From 2fc25fd400a7dbc516af85b116a9a472ca0de1e0 Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Tue, 8 Jul 2025 15:54:46 -0300 Subject: [PATCH 001/134] lib: flag to conditionally modify proto on deprecate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs: https://github.com/nodejs/node/issues/58218 Signed-off-by: RafaelGSS PR-URL: https://github.com/nodejs/node/pull/58928 Reviewed-By: Juan José Arboleda Reviewed-By: Ulises Gascón --- benchmark/util/deprecate.js | 36 ++++++++++++++++++++++++++++++++++++ lib/internal/util.js | 30 +++++++++++++++++------------- 2 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 benchmark/util/deprecate.js diff --git a/benchmark/util/deprecate.js b/benchmark/util/deprecate.js new file mode 100644 index 00000000000000..a94a7606321003 --- /dev/null +++ b/benchmark/util/deprecate.js @@ -0,0 +1,36 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); + +const bench = common.createBenchmark(main, { + n: [1e5], + modifyPrototype: [1, 0], + emitWarningSync: [1, 0], +}, { + flags: ['--expose-internals'], +}); + +function simpleFunction(x) { + return x * 2 + (new Array(1000)).fill(0).map((_, i) => i).reduce((a, b) => a + b, 0); +} + +function main({ n, modifyPrototype, emitWarningSync }) { + const { deprecate } = require('internal/util'); + + const fn = deprecate( + simpleFunction, + 'This function is deprecated', + 'DEP0000', + emitWarningSync, + !!modifyPrototype, + ); + + let sum = 0; + bench.start(); + for (let i = 0; i < n; ++i) { + sum += fn(i); + } + bench.end(n); + assert.ok(sum); +} diff --git a/lib/internal/util.js b/lib/internal/util.js index 7e460735493f10..50863e2fda8952 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -158,7 +158,7 @@ function pendingDeprecate(fn, msg, code) { // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. -function deprecate(fn, msg, code, useEmitSync) { +function deprecate(fn, msg, code, useEmitSync, modifyPrototype = true) { // Lazy-load to avoid a circular dependency. if (validateString === undefined) ({ validateString } = require('internal/validators')); @@ -181,19 +181,23 @@ function deprecate(fn, msg, code, useEmitSync) { return ReflectApply(fn, this, args); } - // The wrapper will keep the same prototype as fn to maintain prototype chain - ObjectSetPrototypeOf(deprecated, fn); - if (fn.prototype) { - // Setting this (rather than using Object.setPrototype, as above) ensures - // that calling the unwrapped constructor gives an instanceof the wrapped - // constructor. - deprecated.prototype = fn.prototype; - } + if (modifyPrototype) { + // The wrapper will keep the same prototype as fn to maintain prototype chain + // Modifying the prototype does alter the object chains, and as observed in + // most cases, it slows the code. + ObjectSetPrototypeOf(deprecated, fn); + if (fn.prototype) { + // Setting this (rather than using Object.setPrototype, as above) ensures + // that calling the unwrapped constructor gives an instanceof the wrapped + // constructor. + deprecated.prototype = fn.prototype; + } - ObjectDefineProperty(deprecated, 'length', { - __proto__: null, - ...ObjectGetOwnPropertyDescriptor(fn, 'length'), - }); + ObjectDefineProperty(deprecated, 'length', { + __proto__: null, + ...ObjectGetOwnPropertyDescriptor(fn, 'length'), + }); + } return deprecated; } From f57ee3d71f22eb6a2591a8c55e87521c38554091 Mon Sep 17 00:00:00 2001 From: alphaleadership <47387699+alphaleadership@users.noreply.github.com> Date: Tue, 8 Jul 2025 22:37:51 +0200 Subject: [PATCH 002/134] net: update net.blocklist to allow file save and file management PR-URL: https://github.com/nodejs/node/pull/58087 Fixes: https://github.com/nodejs/node/issues/56252 Reviewed-By: Ethan Arrowood Reviewed-By: James M Snell --- doc/api/net.md | 32 +++++++ lib/internal/blocklist.js | 126 +++++++++++++++++++++++++++- test/parallel/test-blocklist.js | 72 ++++++++++++++++ test/parallel/test-net-blocklist.js | 1 - 4 files changed, 229 insertions(+), 2 deletions(-) diff --git a/doc/api/net.md b/doc/api/net.md index 5384ad7a34c42c..978c5d2326bc23 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -179,6 +179,38 @@ added: v22.13.0 * `value` {any} Any JS value * Returns `true` if the `value` is a `net.BlockList`. +### `blockList.fromJSON(value)` + +> Stability: 1 - Experimental + + + +```js +const blockList = new net.BlockList(); +const data = [ + 'Subnet: IPv4 192.168.1.0/24', + 'Address: IPv4 10.0.0.5', + 'Range: IPv4 192.168.2.1-192.168.2.10', + 'Range: IPv4 10.0.0.1-10.0.0.10', +]; +blockList.fromJSON(data); +blockList.fromJSON(JSON.stringify(data)); +``` + +* `value` Blocklist.rules + +### `blockList.toJSON()` + +> Stability: 1 - Experimental + + + +* Returns Blocklist.rules + ## Class: `net.SocketAddress` + +> Stability: 1.1 - Active Development + +Enable experimental support for inspector network resources. + ### `--experimental-loader=module` + +> Stability: 1.1 - Active Development + +This feature is only available with the `--experimental-inspector-network-resource` flag enabled. + +The inspector.NetworkResources.put method is used to provide a response for a loadNetworkResource +request issued via the Chrome DevTools Protocol (CDP). +This is typically triggered when a source map is specified by URL, and a DevTools frontend—such as +Chrome—requests the resource to retrieve the source map. + +This method allows developers to predefine the resource content to be served in response to such CDP requests. + +```js +const inspector = require('node:inspector'); +// By preemptively calling put to register the resource, a source map can be resolved when +// a loadNetworkResource request is made from the frontend. +async function setNetworkResources() { + const mapUrl = 'http://localhost:3000/dist/app.js.map'; + const tsUrl = 'http://localhost:3000/src/app.ts'; + const distAppJsMap = await fetch(mapUrl).then((res) => res.text()); + const srcAppTs = await fetch(tsUrl).then((res) => res.text()); + inspector.NetworkResources.put(mapUrl, distAppJsMap); + inspector.NetworkResources.put(tsUrl, srcAppTs); +}; +setNetworkResources().then(() => { + require('./dist/app'); +}); +``` + +For more details, see the official CDP documentation: [Network.loadNetworkResource](https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-loadNetworkResource) + ## Support of breakpoints The Chrome DevTools Protocol [`Debugger` domain][] allows an diff --git a/doc/node.1 b/doc/node.1 index f41323c799ad34..3398c4524aeb53 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -237,6 +237,9 @@ flag is no longer required as WASI is enabled by default. .It Fl -experimental-wasm-modules Enable experimental WebAssembly module support. . +.It Fl -experimental-inspector-network-resource +Enable experimental support for inspector network resources. +. .It Fl -force-context-aware Disable loading native addons that are not context-aware. . diff --git a/lib/inspector.js b/lib/inspector.js index 24a5d62318debc..48daa2ea0c912a 100644 --- a/lib/inspector.js +++ b/lib/inspector.js @@ -39,6 +39,9 @@ const { } = require('internal/validators'); const { isMainThread } = require('worker_threads'); const { _debugEnd } = internalBinding('process_methods'); +const { + put, +} = require('internal/inspector/network_resources'); const { Connection, @@ -221,6 +224,10 @@ const Network = { dataReceived: (params) => broadcastToFrontend('Network.dataReceived', params), }; +const NetworkResources = { + put, +}; + module.exports = { open: inspectorOpen, close: _debugEnd, @@ -229,4 +236,5 @@ module.exports = { console, Session, Network, + NetworkResources, }; diff --git a/lib/internal/inspector/network_resources.js b/lib/internal/inspector/network_resources.js new file mode 100644 index 00000000000000..166b4222cc297f --- /dev/null +++ b/lib/internal/inspector/network_resources.js @@ -0,0 +1,27 @@ +'use strict'; + +const { getOptionValue } = require('internal/options'); +const { validateString } = require('internal/validators'); +const { putNetworkResource } = internalBinding('inspector'); + +/** + * Registers a resource for the inspector using the internal 'putNetworkResource' binding. + * @param {string} url - The URL of the resource. + * @param {string} data - The content of the resource to provide. + */ +function put(url, data) { + if (!getOptionValue('--experimental-inspector-network-resource')) { + process.emitWarning( + 'The --experimental-inspector-network-resource option is not enabled. ' + + 'Please enable it to use the putNetworkResource function'); + return; + } + validateString(url, 'url'); + validateString(data, 'data'); + + putNetworkResource(url, data); +} + +module.exports = { + put, +}; diff --git a/src/inspector/io_agent.cc b/src/inspector/io_agent.cc new file mode 100644 index 00000000000000..749774f5c3144f --- /dev/null +++ b/src/inspector/io_agent.cc @@ -0,0 +1,57 @@ +#include "io_agent.h" +#include +#include +#include +#include +#include "crdtp/dispatch.h" +#include "inspector/network_resource_manager.h" + +namespace node::inspector::protocol { + +void IoAgent::Wire(UberDispatcher* dispatcher) { + frontend_ = std::make_shared(dispatcher->channel()); + IO::Dispatcher::wire(dispatcher, this); +} + +DispatchResponse IoAgent::read(const String& in_handle, + std::optional in_offset, + std::optional in_size, + String* out_data, + bool* out_eof) { + std::string url = in_handle; + std::string txt = network_resource_manager_->Get(url); + std::string_view txt_view(txt); + + int offset = 0; + bool offset_was_specified = false; + if (in_offset.has_value()) { + offset = *in_offset; + offset_was_specified = true; + } else if (offset_map_.find(url) != offset_map_.end()) { + offset = offset_map_[url]; + } + int size = 1 << 20; + if (in_size.has_value()) { + size = *in_size; + } + if (static_cast(offset) < txt_view.length()) { + std::string_view out_view = txt_view.substr(offset, size); + out_data->assign(out_view.data(), out_view.size()); + *out_eof = false; + if (!offset_was_specified) { + offset_map_[url] = offset + size; + } + } else { + *out_data = ""; + *out_eof = true; + } + + return DispatchResponse::Success(); +} + +DispatchResponse IoAgent::close(const String& in_handle) { + std::string url = in_handle; + network_resource_manager_->Erase(url); + return DispatchResponse::Success(); +} +} // namespace node::inspector::protocol diff --git a/src/inspector/io_agent.h b/src/inspector/io_agent.h new file mode 100644 index 00000000000000..4a12311bae32de --- /dev/null +++ b/src/inspector/io_agent.h @@ -0,0 +1,30 @@ +#ifndef SRC_INSPECTOR_IO_AGENT_H_ +#define SRC_INSPECTOR_IO_AGENT_H_ + +#include +#include "inspector/network_resource_manager.h" +#include "node/inspector/protocol/IO.h" + +namespace node::inspector::protocol { + +class IoAgent : public IO::Backend { + public: + explicit IoAgent( + std::shared_ptr network_resource_manager) + : network_resource_manager_(std::move(network_resource_manager)) {} + void Wire(UberDispatcher* dispatcher); + DispatchResponse read(const String& in_handle, + std::optional in_offset, + std::optional in_size, + String* out_data, + bool* out_eof) override; + DispatchResponse close(const String& in_handle) override; + + private: + std::shared_ptr frontend_; + std::unordered_map offset_map_ = + {}; // Maps stream_id to offset + std::shared_ptr network_resource_manager_; +}; +} // namespace node::inspector::protocol +#endif // SRC_INSPECTOR_IO_AGENT_H_ diff --git a/src/inspector/network_agent.cc b/src/inspector/network_agent.cc index 496b5c41a0bfc2..3b5d9615021101 100644 --- a/src/inspector/network_agent.cc +++ b/src/inspector/network_agent.cc @@ -1,8 +1,14 @@ #include "network_agent.h" +#include #include "debug_utils-inl.h" +#include "env-inl.h" +#include "inspector/network_resource_manager.h" #include "inspector/protocol_helper.h" #include "network_inspector.h" +#include "node_metadata.h" #include "util-inl.h" +#include "uv.h" +#include "v8-context.h" #include "v8.h" namespace node { @@ -202,9 +208,15 @@ std::unique_ptr createResponseFromObject( .build(); } -NetworkAgent::NetworkAgent(NetworkInspector* inspector, - v8_inspector::V8Inspector* v8_inspector) - : inspector_(inspector), v8_inspector_(v8_inspector) { +NetworkAgent::NetworkAgent( + NetworkInspector* inspector, + v8_inspector::V8Inspector* v8_inspector, + Environment* env, + std::shared_ptr network_resource_manager) + : inspector_(inspector), + v8_inspector_(v8_inspector), + env_(env), + network_resource_manager_(std::move(network_resource_manager)) { event_notifier_map_["requestWillBeSent"] = &NetworkAgent::requestWillBeSent; event_notifier_map_["responseReceived"] = &NetworkAgent::responseReceived; event_notifier_map_["loadingFailed"] = &NetworkAgent::loadingFailed; @@ -329,10 +341,38 @@ protocol::DispatchResponse NetworkAgent::streamResourceContent( // If the request is finished, remove the entry. requests_.erase(in_requestId); } - return protocol::DispatchResponse::Success(); } +protocol::DispatchResponse NetworkAgent::loadNetworkResource( + const protocol::String& in_url, + std::unique_ptr* + out_resource) { + if (!env_->options()->experimental_inspector_network_resource) { + return protocol::DispatchResponse::ServerError( + "Network resource loading is not enabled. This feature is " + "experimental and requires --experimental-inspector-network-resource " + "flag to be set."); + } + CHECK_NOT_NULL(network_resource_manager_); + std::string data = network_resource_manager_->Get(in_url); + bool found = !data.empty(); + if (found) { + auto result = protocol::Network::LoadNetworkResourcePageResult::create() + .setSuccess(true) + .setStream(in_url) + .build(); + *out_resource = std::move(result); + return protocol::DispatchResponse::Success(); + } else { + auto result = protocol::Network::LoadNetworkResourcePageResult::create() + .setSuccess(false) + .build(); + *out_resource = std::move(result); + return protocol::DispatchResponse::Success(); + } +} + void NetworkAgent::requestWillBeSent(v8::Local context, v8::Local params) { protocol::String request_id; diff --git a/src/inspector/network_agent.h b/src/inspector/network_agent.h index c5303885d61e18..f814c7f5cf6662 100644 --- a/src/inspector/network_agent.h +++ b/src/inspector/network_agent.h @@ -1,9 +1,13 @@ #ifndef SRC_INSPECTOR_NETWORK_AGENT_H_ #define SRC_INSPECTOR_NETWORK_AGENT_H_ +#include "env.h" +#include "io_agent.h" +#include "network_resource_manager.h" #include "node/inspector/protocol/Network.h" #include +#include #include namespace node { @@ -38,8 +42,11 @@ struct RequestEntry { class NetworkAgent : public protocol::Network::Backend { public: - explicit NetworkAgent(NetworkInspector* inspector, - v8_inspector::V8Inspector* v8_inspector); + explicit NetworkAgent( + NetworkInspector* inspector, + v8_inspector::V8Inspector* v8_inspector, + Environment* env, + std::shared_ptr network_resource_manager); void Wire(protocol::UberDispatcher* dispatcher); @@ -60,6 +67,11 @@ class NetworkAgent : public protocol::Network::Backend { const protocol::String& in_requestId, protocol::Binary* out_bufferedData) override; + protocol::DispatchResponse loadNetworkResource( + const protocol::String& in_url, + std::unique_ptr* + out_resource) override; + void emitNotification(v8::Local context, const protocol::String& event, v8::Local params); @@ -89,6 +101,8 @@ class NetworkAgent : public protocol::Network::Backend { v8::Local); std::unordered_map event_notifier_map_; std::map requests_; + Environment* env_; + std::shared_ptr network_resource_manager_; }; } // namespace inspector diff --git a/src/inspector/network_inspector.cc b/src/inspector/network_inspector.cc index e93db7bbe922f6..3a79ba988571ca 100644 --- a/src/inspector/network_inspector.cc +++ b/src/inspector/network_inspector.cc @@ -3,10 +3,15 @@ namespace node { namespace inspector { -NetworkInspector::NetworkInspector(Environment* env, - v8_inspector::V8Inspector* v8_inspector) - : enabled_(false), env_(env) { - network_agent_ = std::make_unique(this, v8_inspector); +NetworkInspector::NetworkInspector( + Environment* env, + v8_inspector::V8Inspector* v8_inspector, + std::shared_ptr network_resource_manager) + : enabled_(false), + env_(env), + network_resource_manager_(std::move(network_resource_manager)) { + network_agent_ = std::make_unique( + this, v8_inspector, env, network_resource_manager_); } NetworkInspector::~NetworkInspector() { network_agent_.reset(); diff --git a/src/inspector/network_inspector.h b/src/inspector/network_inspector.h index 4095a05394cd8a..bcdca254230ea9 100644 --- a/src/inspector/network_inspector.h +++ b/src/inspector/network_inspector.h @@ -1,8 +1,10 @@ #ifndef SRC_INSPECTOR_NETWORK_INSPECTOR_H_ #define SRC_INSPECTOR_NETWORK_INSPECTOR_H_ +#include #include "env.h" #include "network_agent.h" +#include "network_resource_manager.h" namespace node { class Environment; @@ -11,8 +13,10 @@ namespace inspector { class NetworkInspector { public: - explicit NetworkInspector(Environment* env, - v8_inspector::V8Inspector* v8_inspector); + explicit NetworkInspector( + Environment* env, + v8_inspector::V8Inspector* v8_inspector, + std::shared_ptr network_resource_manager); ~NetworkInspector(); void Wire(protocol::UberDispatcher* dispatcher); @@ -32,6 +36,7 @@ class NetworkInspector { bool enabled_; Environment* env_; std::unique_ptr network_agent_; + std::shared_ptr network_resource_manager_; }; } // namespace inspector diff --git a/src/inspector/network_resource_manager.cc b/src/inspector/network_resource_manager.cc new file mode 100644 index 00000000000000..47c625164694ee --- /dev/null +++ b/src/inspector/network_resource_manager.cc @@ -0,0 +1,29 @@ +#include "inspector/network_resource_manager.h" +#include +#include +#include +#include + +namespace node { +namespace inspector { + +void NetworkResourceManager::Put(const std::string& url, + const std::string& data) { + Mutex::ScopedLock lock(mutex_); + resources_[url] = data; +} + +std::string NetworkResourceManager::Get(const std::string& url) { + Mutex::ScopedLock lock(mutex_); + auto it = resources_.find(url); + if (it != resources_.end()) return it->second; + return {}; +} + +void NetworkResourceManager::Erase(const std::string& stream_id) { + Mutex::ScopedLock lock(mutex_); + resources_.erase(stream_id); +} + +} // namespace inspector +} // namespace node diff --git a/src/inspector/network_resource_manager.h b/src/inspector/network_resource_manager.h new file mode 100644 index 00000000000000..10a058ddc48bd4 --- /dev/null +++ b/src/inspector/network_resource_manager.h @@ -0,0 +1,29 @@ +// network_resource_manager.h +#ifndef SRC_INSPECTOR_NETWORK_RESOURCE_MANAGER_H_ +#define SRC_INSPECTOR_NETWORK_RESOURCE_MANAGER_H_ + +#include +#include +#include +#include "node_mutex.h" + +namespace node { +namespace inspector { + +class NetworkResourceManager { + public: + void Put(const std::string& url, const std::string& data); + std::string Get(const std::string& url); + + // Erase resource and mapping by stream id + void Erase(const std::string& stream_id); + + private: + std::unordered_map resources_; + Mutex mutex_; // Protects access to resources_ +}; + +} // namespace inspector +} // namespace node + +#endif // SRC_INSPECTOR_NETWORK_RESOURCE_MANAGER_H_ diff --git a/src/inspector/node_inspector.gypi b/src/inspector/node_inspector.gypi index 176663780afc95..ad81f837e84d76 100644 --- a/src/inspector/node_inspector.gypi +++ b/src/inspector/node_inspector.gypi @@ -36,6 +36,10 @@ 'src/inspector/target_agent.h', 'src/inspector/worker_inspector.cc', 'src/inspector/worker_inspector.h', + 'src/inspector/io_agent.cc', + 'src/inspector/io_agent.h', + 'src/inspector/network_resource_manager.cc', + 'src/inspector/network_resource_manager.h', ], 'node_inspector_generated_sources': [ '<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Forward.h', @@ -51,6 +55,8 @@ '<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Network.h', '<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Target.cpp', '<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/Target.h', + '<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/IO.h', + '<(SHARED_INTERMEDIATE_DIR)/src/node/inspector/protocol/IO.cpp', ], 'node_protocol_files': [ '<(protocol_tool_path)/lib/Forward_h.template', diff --git a/src/inspector/node_protocol.pdl b/src/inspector/node_protocol.pdl index 3608bfd317022c..46631bc20ad081 100644 --- a/src/inspector/node_protocol.pdl +++ b/src/inspector/node_protocol.pdl @@ -180,6 +180,11 @@ experimental domain Network # Request / response headers as keys / values of JSON object. type Headers extends object + type LoadNetworkResourcePageResult extends object + properties + boolean success + optional IO.StreamHandle stream + # Disables network tracking, prevents network events from being sent to the client. command disable @@ -215,6 +220,13 @@ experimental domain Network returns # Data that has been buffered until streaming is enabled. binary bufferedData + # Fetches the resource and returns the content. + command loadNetworkResource + parameters + # URL of the resource to get content for. + string url + returns + LoadNetworkResourcePageResult resource # Fired when page is about to send HTTP request. event requestWillBeSent @@ -321,3 +333,24 @@ experimental domain Target parameters boolean autoAttach boolean waitForDebuggerOnStart +domain IO + type StreamHandle extends string + # Read a chunk of the stream + command read + parameters + # Handle of the stream to read. + StreamHandle handle + # Seek to the specified offset before reading (if not specified, proceed with offset + # following the last read). Some types of streams may only support sequential reads. + optional integer offset + # Maximum number of bytes to read (left upon the agent discretion if not specified). + optional integer size + returns + # Data that were read. + string data + # Set if the end-of-file condition occurred while reading. + boolean eof + command close + parameters + # Handle of the stream to close. + StreamHandle handle diff --git a/src/inspector/worker_inspector.cc b/src/inspector/worker_inspector.cc index fd479181e9566c..58c7d2602b327e 100644 --- a/src/inspector/worker_inspector.cc +++ b/src/inspector/worker_inspector.cc @@ -60,12 +60,14 @@ ParentInspectorHandle::ParentInspectorHandle( const std::string& url, std::shared_ptr parent_thread, bool wait_for_connect, - const std::string& name) + const std::string& name, + std::shared_ptr network_resource_manager) : id_(id), url_(url), parent_thread_(parent_thread), wait_(wait_for_connect), - name_(name) {} + name_(name), + network_resource_manager_(network_resource_manager) {} ParentInspectorHandle::~ParentInspectorHandle() { parent_thread_->Post( @@ -101,10 +103,13 @@ void WorkerManager::WorkerStarted(uint64_t session_id, } std::unique_ptr WorkerManager::NewParentHandle( - uint64_t thread_id, const std::string& url, const std::string& name) { + uint64_t thread_id, + const std::string& url, + const std::string& name, + std::shared_ptr network_resource_manager) { bool wait = !delegates_waiting_on_start_.empty(); return std::make_unique( - thread_id, url, thread_, wait, name); + thread_id, url, thread_, wait, name, network_resource_manager); } void WorkerManager::RemoveAttachDelegate(int id) { diff --git a/src/inspector/worker_inspector.h b/src/inspector/worker_inspector.h index 24403bb1704c40..28a249aea4d91c 100644 --- a/src/inspector/worker_inspector.h +++ b/src/inspector/worker_inspector.h @@ -1,6 +1,7 @@ #ifndef SRC_INSPECTOR_WORKER_INSPECTOR_H_ #define SRC_INSPECTOR_WORKER_INSPECTOR_H_ +#include "inspector/network_resource_manager.h" #if !HAVE_INSPECTOR #error("This header can only be used when inspector is enabled") #endif @@ -54,16 +55,18 @@ struct WorkerInfo { class ParentInspectorHandle { public: - ParentInspectorHandle(uint64_t id, - const std::string& url, - std::shared_ptr parent_thread, - bool wait_for_connect, - const std::string& name); + ParentInspectorHandle( + uint64_t id, + const std::string& url, + std::shared_ptr parent_thread, + bool wait_for_connect, + const std::string& name, + std::shared_ptr network_resource_manager); ~ParentInspectorHandle(); std::unique_ptr NewParentInspectorHandle( uint64_t thread_id, const std::string& url, const std::string& name) { return std::make_unique( - thread_id, url, parent_thread_, wait_, name); + thread_id, url, parent_thread_, wait_, name, network_resource_manager_); } void WorkerStarted(std::shared_ptr worker_thread, bool waiting); @@ -74,6 +77,9 @@ class ParentInspectorHandle { std::unique_ptr Connect( std::unique_ptr delegate, bool prevent_shutdown); + std::shared_ptr GetNetworkResourceManager() { + return network_resource_manager_; + } private: uint64_t id_; @@ -81,6 +87,7 @@ class ParentInspectorHandle { std::shared_ptr parent_thread_; bool wait_; std::string name_; + std::shared_ptr network_resource_manager_; }; class WorkerManager : public std::enable_shared_from_this { @@ -89,7 +96,10 @@ class WorkerManager : public std::enable_shared_from_this { : thread_(thread) {} std::unique_ptr NewParentHandle( - uint64_t thread_id, const std::string& url, const std::string& name); + uint64_t thread_id, + const std::string& url, + const std::string& name, + std::shared_ptr network_resource_manager); void WorkerStarted(uint64_t session_id, const WorkerInfo& info, bool waiting); void WorkerFinished(uint64_t session_id); std::unique_ptr SetAutoAttach( diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index fa6eb29e6e5829..1424cbfb4366f8 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -13,6 +13,7 @@ #include "inspector/worker_agent.h" #include "inspector/worker_inspector.h" #include "inspector_io.h" +#include "node.h" #include "node/inspector/protocol/Protocol.h" #include "node_errors.h" #include "node_internals.h" @@ -238,8 +239,18 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, } runtime_agent_ = std::make_unique(); runtime_agent_->Wire(node_dispatcher_.get()); - network_inspector_ = - std::make_unique(env, inspector.get()); + if (env->options()->experimental_inspector_network_resource) { + io_agent_ = std::make_unique( + env->inspector_agent()->GetNetworkResourceManager()); + io_agent_->Wire(node_dispatcher_.get()); + network_inspector_ = std::make_unique( + env, + inspector.get(), + env->inspector_agent()->GetNetworkResourceManager()); + } else { + network_inspector_ = + std::make_unique(env, inspector.get(), nullptr); + } network_inspector_->Wire(node_dispatcher_.get()); if (env->options()->experimental_worker_inspection) { target_agent_ = std::make_shared(); @@ -405,6 +416,7 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, std::unique_ptr worker_agent_; std::shared_ptr target_agent_; std::unique_ptr network_inspector_; + std::shared_ptr io_agent_; std::unique_ptr delegate_; std::unique_ptr session_; std::unique_ptr node_dispatcher_; @@ -1153,7 +1165,8 @@ std::unique_ptr Agent::GetParentHandle( CHECK_NOT_NULL(client_); if (!parent_handle_) { - return client_->getWorkerManager()->NewParentHandle(thread_id, url, name); + return client_->getWorkerManager()->NewParentHandle( + thread_id, url, name, GetNetworkResourceManager()); } else { return parent_handle_->NewParentInspectorHandle(thread_id, url, name); } @@ -1219,6 +1232,17 @@ std::shared_ptr Agent::GetWorkerManager() { return client_->getWorkerManager(); } +std::shared_ptr Agent::GetNetworkResourceManager() { + if (parent_handle_) { + return parent_handle_->GetNetworkResourceManager(); + } else if (network_resource_manager_) { + return network_resource_manager_; + } else { + network_resource_manager_ = std::make_shared(); + return network_resource_manager_; + } +} + std::string Agent::GetWsUrl() const { if (io_ == nullptr) return ""; diff --git a/src/inspector_agent.h b/src/inspector_agent.h index ad7a8e6c069968..e43dced8f410f3 100644 --- a/src/inspector_agent.h +++ b/src/inspector_agent.h @@ -1,5 +1,6 @@ #pragma once +#include "inspector/network_resource_manager.h" #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #if !HAVE_INSPECTOR @@ -127,6 +128,7 @@ class Agent { std::shared_ptr GetWorkerManager(); inline Environment* env() const { return parent_env_; } + std::shared_ptr GetNetworkResourceManager(); private: void ToggleAsyncHook(v8::Isolate* isolate, v8::Local fn); @@ -153,6 +155,7 @@ class Agent { bool network_tracking_enabled_ = false; bool pending_enable_network_tracking = false; bool pending_disable_network_tracking = false; + std::shared_ptr network_resource_manager_; }; } // namespace inspector diff --git a/src/inspector_js_api.cc b/src/inspector_js_api.cc index 69029247accf5b..64823c68b11e94 100644 --- a/src/inspector_js_api.cc +++ b/src/inspector_js_api.cc @@ -1,4 +1,5 @@ #include "base_object-inl.h" +#include "inspector/network_resource_manager.h" #include "inspector/protocol_helper.h" #include "inspector_agent.h" #include "inspector_io.h" @@ -334,6 +335,18 @@ void Url(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(OneByteString(env->isolate(), url)); } +void PutNetworkResource(const v8::FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + CHECK_GE(args.Length(), 2); + CHECK(args[0]->IsString()); + CHECK(args[1]->IsString()); + + Utf8Value url(env->isolate(), args[0].As()); + Utf8Value data(env->isolate(), args[1].As()); + + env->inspector_agent()->GetNetworkResourceManager()->Put(*url, *data); +} + void Initialize(Local target, Local unused, Local context, void* priv) { Environment* env = Environment::GetCurrent(context); @@ -378,6 +391,7 @@ void Initialize(Local target, Local unused, SetMethodNoSideEffect(context, target, "isEnabled", IsEnabled); SetMethod(context, target, "emitProtocolEvent", EmitProtocolEvent); SetMethod(context, target, "setupNetworkTracking", SetupNetworkTracking); + SetMethod(context, target, "putNetworkResource", PutNetworkResource); Local console_string = FIXED_ONE_BYTE_STRING(isolate, "console"); @@ -420,6 +434,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(JSBindingsConnection::New); registry->Register(JSBindingsConnection::Dispatch); registry->Register(JSBindingsConnection::Disconnect); + registry->Register(PutNetworkResource); } } // namespace inspector diff --git a/src/node_options.cc b/src/node_options.cc index 228fbe645587ab..51c552d157f611 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -650,6 +650,9 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--experimental-worker-inspection", "experimental worker inspection support", &EnvironmentOptions::experimental_worker_inspection); + AddOption("--experimental-inspector-network-resource", + "experimental load network resources via the inspector", + &EnvironmentOptions::experimental_inspector_network_resource); AddOption( "--heap-prof", "Start the V8 heap profiler on start up, and write the heap profile " diff --git a/src/node_options.h b/src/node_options.h index 0b75516eb42692..b62d3201b03e64 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -172,6 +172,7 @@ class EnvironmentOptions : public Options { bool cpu_prof = false; bool experimental_network_inspection = false; bool experimental_worker_inspection = false; + bool experimental_inspector_network_resource = false; std::string heap_prof_dir; std::string heap_prof_name; static const uint64_t kDefaultHeapProfInterval = 512 * 1024; diff --git a/test/fixtures/inspector-network-resource/app.js.map b/test/fixtures/inspector-network-resource/app.js.map new file mode 100644 index 00000000000000..ca4bb9159baeaa --- /dev/null +++ b/test/fixtures/inspector-network-resource/app.js.map @@ -0,0 +1,10 @@ +{ + "version": 3, + "file": "app.js", + "sourceRoot": "", + "sources": [ + "http://localhost:3000/app.ts" + ], + "names": [], + "mappings": ";AAAA,SAAS,GAAG,CAAC,CAAS,EAAE,CAAS;IAC/B,OAAO,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC" +} diff --git a/test/parallel/test-inspector-network-resource.js b/test/parallel/test-inspector-network-resource.js new file mode 100644 index 00000000000000..73620866931c24 --- /dev/null +++ b/test/parallel/test-inspector-network-resource.js @@ -0,0 +1,181 @@ +// Flags: --inspect=0 --experimental-network-inspection +'use strict'; +const common = require('../common'); + +common.skipIfInspectorDisabled(); + +const { NodeInstance } = require('../common/inspector-helper'); +const test = require('node:test'); +const assert = require('node:assert'); +const path = require('path'); +const fs = require('fs'); + +const resourceUrl = 'http://localhost:3000/app.js'; +const resourcePath = path.join(__dirname, '../fixtures/inspector-network-resource/app.js.map'); + +const resourceText = fs.readFileSync(resourcePath, 'utf8'); +const embedPath = resourcePath.replace(/\\/g, '\\\\').replace(/'/g, "\\'"); +const script = ` + const { NetworkResources } = require('node:inspector'); + const fs = require('fs'); + NetworkResources.put('${resourceUrl}', fs.readFileSync('${embedPath}', 'utf8')); + console.log('Network resource loaded:', '${resourceUrl}'); + debugger; +`; + +async function setupSessionAndPauseAtEvalLastLine(script) { + const instance = new NodeInstance([ + '--inspect-wait=0', + '--experimental-inspector-network-resource', + ], script); + const session = await instance.connectInspectorSession(); + await session.send({ method: 'NodeRuntime.enable' }); + await session.waitForNotification('NodeRuntime.waitingForDebugger'); + await session.send({ method: 'Runtime.enable' }); + await session.send({ method: 'Debugger.enable' }); + await session.send({ method: 'Runtime.runIfWaitingForDebugger' }); + await session.waitForNotification('Debugger.paused'); + return { instance, session }; +} + +test('should load and stream a static network resource using loadNetworkResource and IO.read', async () => { + const { session } = await setupSessionAndPauseAtEvalLastLine(script); + const { resource } = await session.send({ + method: 'Network.loadNetworkResource', + params: { url: resourceUrl }, + }); + assert(resource.success, 'Resource should be loaded successfully'); + assert(resource.stream, 'Resource should have a stream handle'); + let result = await session.send({ method: 'IO.read', params: { handle: resource.stream } }); + let data = result.data; + let eof = result.eof; + let content = ''; + while (!eof) { + content += data; + result = await session.send({ method: 'IO.read', params: { handle: resource.stream } }); + data = result.data; + eof = result.eof; + } + content += data; + assert.strictEqual(content, resourceText); + await session.send({ method: 'IO.close', params: { handle: resource.stream } }); + await session.send({ method: 'Debugger.resume' }); + await session.waitForDisconnect(); +}); + +test('should return success: false for missing resource', async () => { + const { session } = await setupSessionAndPauseAtEvalLastLine(script); + const { resource } = await session.send({ + method: 'Network.loadNetworkResource', + params: { url: 'http://localhost:3000/does-not-exist.js' }, + }); + assert.strictEqual(resource.success, false); + assert(!resource.stream, 'No stream should be returned for missing resource'); + await session.send({ method: 'Debugger.resume' }); + await session.waitForDisconnect(); +}); + +test('should error or return empty for wrong stream id', async () => { + const { session } = await setupSessionAndPauseAtEvalLastLine(script); + const { resource } = await session.send({ + method: 'Network.loadNetworkResource', + params: { url: resourceUrl }, + }); + assert(resource.success); + const bogus = '999999'; + const result = await session.send({ method: 'IO.read', params: { handle: bogus } }); + assert(result.eof, 'Should be eof for bogus stream id'); + assert.strictEqual(result.data, ''); + await session.send({ method: 'IO.close', params: { handle: resource.stream } }); + await session.send({ method: 'Debugger.resume' }); + await session.waitForDisconnect(); +}); + +test('should support IO.read with size and offset', async () => { + const { session } = await setupSessionAndPauseAtEvalLastLine(script); + const { resource } = await session.send({ + method: 'Network.loadNetworkResource', + params: { url: resourceUrl }, + }); + assert(resource.success); + assert(resource.stream); + let result = await session.send({ method: 'IO.read', params: { handle: resource.stream, size: 5 } }); + assert.strictEqual(result.data, resourceText.slice(0, 5)); + result = await session.send({ method: 'IO.read', params: { handle: resource.stream, offset: 5, size: 5 } }); + assert.strictEqual(result.data, resourceText.slice(5, 10)); + result = await session.send({ method: 'IO.read', params: { handle: resource.stream, offset: 10 } }); + assert.strictEqual(result.data, resourceText.slice(10)); + await session.send({ method: 'IO.close', params: { handle: resource.stream } }); + await session.send({ method: 'Debugger.resume' }); + await session.waitForDisconnect(); +}); + +test('should load resource put from another thread', async () => { + const workerScript = ` + console.log('this is worker thread'); + debugger; + `; + const script = ` + const { NetworkResources } = require('node:inspector'); + const fs = require('fs'); + NetworkResources.put('${resourceUrl}', fs.readFileSync('${embedPath}', 'utf8')); + const { Worker } = require('worker_threads'); + const worker = new Worker(\`${workerScript}\`, {eval: true}); + `; + const instance = new NodeInstance([ + '--experimental-inspector-network-resource', + '--experimental-worker-inspection', + '--inspect-brk=0', + ], script); + const session = await instance.connectInspectorSession(); + await setupInspector(session); + await session.waitForNotification('Debugger.paused'); + await session.send({ method: 'Debugger.resume' }); + await session.waitForNotification('Target.targetCreated'); + await session.send({ method: 'Target.setAutoAttach', params: { autoAttach: true, waitForDebuggerOnStart: true } }); + let sessionId; + await session.waitForNotification((notification) => { + if (notification.method === 'Target.attachedToTarget') { + sessionId = notification.params.sessionId; + return true; + } + return false; + + }); + await setupInspector(session, sessionId); + + await session.waitForNotification('Debugger.paused'); + + const { resource } = await session.send({ + method: 'Network.loadNetworkResource', + params: { url: resourceUrl, sessionId }, + }); + + assert(resource.success, 'Resource should be loaded successfully'); + assert(resource.stream, 'Resource should have a stream handle'); + let result = await session.send({ method: 'IO.read', params: { handle: resource.stream, sessionId } }); + let data = result.data; + let eof = result.eof; + let content = ''; + while (!eof) { + content += data; + result = await session.send({ method: 'IO.read', params: { handle: resource.stream, sessionId } }); + data = result.data; + eof = result.eof; + } + content += data; + assert.strictEqual(content, resourceText); + await session.send({ method: 'IO.close', params: { handle: resource.stream, sessionId } }); + + await session.send({ method: 'Debugger.resume', sessionId }); + + await session.waitForDisconnect(); + + async function setupInspector(session, sessionId) { + await session.send({ method: 'NodeRuntime.enable', sessionId }); + await session.waitForNotification('NodeRuntime.waitingForDebugger'); + await session.send({ method: 'Runtime.enable', sessionId }); + await session.send({ method: 'Debugger.enable', sessionId }); + await session.send({ method: 'Runtime.runIfWaitingForDebugger', sessionId }); + } +}); diff --git a/typings/internalBinding/inspector.d.ts b/typings/internalBinding/inspector.d.ts index ab32838b2366ca..c0ee57774d87dd 100644 --- a/typings/internalBinding/inspector.d.ts +++ b/typings/internalBinding/inspector.d.ts @@ -33,4 +33,5 @@ export interface InspectorBinding { console: Console; Connection: InspectorConnectionConstructor; MainThreadConnection: InspectorConnectionConstructor; + putNetworkResource: (url: string, resource: string) => void; } From 4a42360fe554afa749ef10188aa3c7dbfd14dc28 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 10 Jul 2025 16:22:51 +0200 Subject: [PATCH 008/134] doc: add scroll margin to links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/58982 Reviewed-By: Claudio Wunder Reviewed-By: Moshe Atlow Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Ulises Gascón Reviewed-By: Tierney Cyren --- doc/api_assets/style.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css index c23e486ef80b82..d314f3d990631b 100644 --- a/doc/api_assets/style.css +++ b/doc/api_assets/style.css @@ -373,6 +373,11 @@ p { padding-bottom: 2rem; } +/* prevent the module-level sticky stability header from overlapping the section headers when clicked */ +#apicontent:has(> .api_stability) a { + scroll-margin-top: 50px; +} + table { border-collapse: collapse; margin: 0 0 1.5rem; @@ -837,6 +842,9 @@ kbd { .api_stability { top: 0; } + #apicontent a { + scroll-margin-top: 0; + } } @media not screen, (max-height: 1000px) { From 1f184513e91248eeb02cf4c8d25dfa9d7c35acd3 Mon Sep 17 00:00:00 2001 From: theanarkh Date: Thu, 10 Jul 2025 23:50:43 +0800 Subject: [PATCH 009/134] dns: support max timeout PR-URL: https://github.com/nodejs/node/pull/58440 Reviewed-By: Luigi Pinca Reviewed-By: Matteo Collina --- doc/api/dns.md | 2 + lib/internal/dns/utils.js | 20 +++-- src/cares_wrap.cc | 30 +++++--- src/cares_wrap.h | 11 +-- .../parallel/test-dns-resolver-max-timeout.js | 77 +++++++++++++++++++ 5 files changed, 118 insertions(+), 22 deletions(-) create mode 100644 test/parallel/test-dns-resolver-max-timeout.js diff --git a/doc/api/dns.md b/doc/api/dns.md index d2d7c85ecb6eb7..bde50619fdf371 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -157,6 +157,8 @@ Create a new resolver. default timeout. * `tries` {integer} The number of tries the resolver will try contacting each name server before giving up. **Default:** `4` + * `maxTimeout` {integer} The max retry timeout, in milliseconds. + **Default:** `0`, disabled. ### `resolver.cancel()` diff --git a/lib/internal/dns/utils.js b/lib/internal/dns/utils.js index 85918f0d43d5c6..32f8794d62ad73 100644 --- a/lib/internal/dns/utils.js +++ b/lib/internal/dns/utils.js @@ -25,6 +25,7 @@ const { validateInt32, validateOneOf, validateString, + validateUint32, } = require('internal/validators'); let binding; function lazyBinding() { @@ -49,6 +50,12 @@ function validateTimeout(options) { return timeout; } +function validateMaxTimeout(options) { + const { maxTimeout = 0 } = { ...options }; + validateUint32(maxTimeout, 'options.maxTimeout'); + return maxTimeout; +} + function validateTries(options) { const { tries = 4 } = { ...options }; validateInt32(tries, 'options.tries', 1); @@ -67,17 +74,18 @@ class ResolverBase { constructor(options = undefined) { const timeout = validateTimeout(options); const tries = validateTries(options); + const maxTimeout = validateMaxTimeout(options); // If we are building snapshot, save the states of the resolver along // the way. if (isBuildingSnapshot()) { - this[kSnapshotStates] = { timeout, tries }; + this[kSnapshotStates] = { timeout, tries, maxTimeout }; } - this[kInitializeHandle](timeout, tries); + this[kInitializeHandle](timeout, tries, maxTimeout); } - [kInitializeHandle](timeout, tries) { + [kInitializeHandle](timeout, tries, maxTimeout) { const { ChannelWrap } = lazyBinding(); - this._handle = new ChannelWrap(timeout, tries); + this._handle = new ChannelWrap(timeout, tries, maxTimeout); } cancel() { @@ -187,8 +195,8 @@ class ResolverBase { } [kDeserializeResolver]() { - const { timeout, tries, localAddress, servers } = this[kSnapshotStates]; - this[kInitializeHandle](timeout, tries); + const { timeout, tries, maxTimeout, localAddress, servers } = this[kSnapshotStates]; + this[kInitializeHandle](timeout, tries, maxTimeout); if (localAddress) { const { ipv4, ipv6 } = localAddress; this._handle.setLocalAddress(ipv4, ipv6); diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index c18a750239c2a2..444b1f73f9e93c 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -787,14 +787,15 @@ Maybe ParseSoaReply(Environment* env, } } // anonymous namespace -ChannelWrap::ChannelWrap( - Environment* env, - Local object, - int timeout, - int tries) +ChannelWrap::ChannelWrap(Environment* env, + Local object, + int timeout, + int tries, + int max_timeout) : AsyncWrap(env, object, PROVIDER_DNSCHANNEL), timeout_(timeout), - tries_(tries) { + tries_(tries), + max_timeout_(max_timeout) { MakeWeak(); Setup(); @@ -808,13 +809,15 @@ void ChannelWrap::MemoryInfo(MemoryTracker* tracker) const { void ChannelWrap::New(const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); - CHECK_EQ(args.Length(), 2); + CHECK_EQ(args.Length(), 3); CHECK(args[0]->IsInt32()); CHECK(args[1]->IsInt32()); + CHECK(args[2]->IsInt32()); const int timeout = args[0].As()->Value(); const int tries = args[1].As()->Value(); + const int max_timeout = args[2].As()->Value(); Environment* env = Environment::GetCurrent(args); - new ChannelWrap(env, args.This(), timeout, tries); + new ChannelWrap(env, args.This(), timeout, tries, max_timeout); } GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env, @@ -879,9 +882,14 @@ void ChannelWrap::Setup() { } /* We do the call to ares_init_option for caller. */ - const int optmask = ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | - ARES_OPT_SOCK_STATE_CB | ARES_OPT_TRIES | - ARES_OPT_QUERY_CACHE; + int optmask = ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | ARES_OPT_SOCK_STATE_CB | + ARES_OPT_TRIES | ARES_OPT_QUERY_CACHE; + + if (max_timeout_ > 0) { + options.maxtimeout = max_timeout_; + optmask |= ARES_OPT_MAXTIMEOUTMS; + } + r = ares_init_options(&channel_, &options, optmask); if (r != ARES_SUCCESS) { diff --git a/src/cares_wrap.h b/src/cares_wrap.h index 081c8e0217a70f..dd62c2f6ff0527 100644 --- a/src/cares_wrap.h +++ b/src/cares_wrap.h @@ -151,11 +151,11 @@ struct NodeAresTask final : public MemoryRetainer { class ChannelWrap final : public AsyncWrap { public: - ChannelWrap( - Environment* env, - v8::Local object, - int timeout, - int tries); + ChannelWrap(Environment* env, + v8::Local object, + int timeout, + int tries, + int max_timeout); ~ChannelWrap() override; static void New(const v8::FunctionCallbackInfo& args); @@ -190,6 +190,7 @@ class ChannelWrap final : public AsyncWrap { bool library_inited_ = false; int timeout_; int tries_; + int max_timeout_; int active_query_count_ = 0; NodeAresTask::List task_list_; }; diff --git a/test/parallel/test-dns-resolver-max-timeout.js b/test/parallel/test-dns-resolver-max-timeout.js new file mode 100644 index 00000000000000..fff1a705ca4116 --- /dev/null +++ b/test/parallel/test-dns-resolver-max-timeout.js @@ -0,0 +1,77 @@ +'use strict'; +const common = require('../common'); +const dnstools = require('../common/dns'); +const dns = require('dns'); +const assert = require('assert'); +const dgram = require('dgram'); + +[ + -1, + 1.1, + NaN, + undefined, + {}, + [], + null, + function() {}, + Symbol(), + true, + Infinity, +].forEach((maxTimeout) => { + try { + new dns.Resolver({ maxTimeout }); + } catch (e) { + assert.ok(/ERR_OUT_OF_RANGE|ERR_INVALID_ARG_TYPE/i.test(e.code)); + } +}); + +const server = dgram.createSocket('udp4'); +const nxdomain = 'nxdomain.org'; +const domain = 'example.org'; +const answers = [{ type: 'A', address: '1.2.3.4', ttl: 123, domain }]; + +server.on('message', common.mustCallAtLeast((msg, { address, port }) => { + const parsed = dnstools.parseDNSPacket(msg); + if (parsed.questions[0].domain === nxdomain) { + return; + } + assert.strictEqual(parsed.questions[0].domain, domain); + server.send(dnstools.writeDNSPacket({ + id: parsed.id, + questions: parsed.questions, + answers: answers, + }), port, address); +}), 1); + +server.bind(0, common.mustCall(async () => { + const address = server.address(); + // Test if the Resolver works as before. + const resolver = new dns.promises.Resolver({ timeout: 1000, tries: 1, maxTimeout: 1000 }); + resolver.setServers([`127.0.0.1:${address.port}`]); + const res = await resolver.resolveAny('example.org'); + assert.strictEqual(res.length, 1); + assert.strictEqual(res.length, answers.length); + assert.strictEqual(res[0].address, answers[0].address); + + // Test that maxTimeout is effective. + // Without maxTimeout, the timeout will keep increasing when retrying. + const timeout1 = await timeout(address, { timeout: 500, tries: 3 }); + // With maxTimeout, the timeout will always be 500 when retrying. + const timeout2 = await timeout(address, { timeout: 500, tries: 3, maxTimeout: 500 }); + console.log(`timeout1: ${timeout1}, timeout2: ${timeout2}`); + assert.strictEqual(timeout1 !== undefined && timeout2 !== undefined, true); + assert.strictEqual(timeout1 > timeout2, true); + server.close(); +})); + +async function timeout(address, options) { + const start = Date.now(); + const resolver = new dns.promises.Resolver(options); + resolver.setServers([`127.0.0.1:${address.port}`]); + try { + await resolver.resolveAny(nxdomain); + } catch (e) { + assert.strictEqual(e.code, 'ETIMEOUT'); + return Date.now() - start; + } +} From cb08a5d43f502c9b3067f85c8ea91238e01e7ac9 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Thu, 10 Jul 2025 20:02:06 +0200 Subject: [PATCH 010/134] doc: add missing `` blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/58995 Reviewed-By: Luigi Pinca Reviewed-By: Juan José Arboleda --- doc/api/assert.md | 2 +- test/common/README.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index fe093bfceda330..9590d213d3d201 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -129,7 +129,7 @@ Legacy assertion mode may have surprising results, especially when using assert.deepEqual(/a/gi, new Date()); ``` -## Class: assert.AssertionError +## Class: `assert.AssertionError` * Extends: {errors.Error} diff --git a/test/common/README.md b/test/common/README.md index a5b90abf1f006f..6fe330d866be8c 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -841,7 +841,7 @@ frames for testing of HTTP/2 endpoints const http2 = require('../common/http2'); ``` -### Class: Frame +### Class: `Frame` The `http2.Frame` is a base class that creates a `Buffer` containing a serialized HTTP/2 frame header. @@ -861,7 +861,7 @@ socket.write(frame.data); The serialized `Buffer` may be retrieved using the `frame.data` property. -### Class: HeadersFrame +### Class: `HeadersFrame` The `http2.HeadersFrame` is a subclass of `http2.Frame` that serializes a `HEADERS` frame. @@ -880,7 +880,7 @@ const frame = new http2.HeadersFrame(id, payload, padlen, final); socket.write(frame.data); ``` -### Class: SettingsFrame +### Class: `SettingsFrame` The `http2.SettingsFrame` is a subclass of `http2.Frame` that serializes an empty `SETTINGS` frame. @@ -1138,7 +1138,7 @@ See the source code for definitions. Please avoid using it in new code - the current usage of this port in tests is being migrated to the original WPT harness, see [the WPT tests README][]. -### Class: WPTRunner +### Class: `WPTRunner` A driver class for running WPT with the WPT harness in a worker thread. From 3e9ed4b08097b075659f2de820317c55b34541c7 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Thu, 10 Jul 2025 19:57:31 +0100 Subject: [PATCH 011/134] doc: add stability index to the `--watch-kill-signal` flag PR-URL: https://github.com/nodejs/node/pull/58997 Reviewed-By: Rafael Gonzaga Reviewed-By: Moshe Atlow Reviewed-By: Luigi Pinca --- doc/api/cli.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/api/cli.md b/doc/api/cli.md index 89e6589c54cbab..b0a391e1b3430d 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -3108,6 +3108,8 @@ added: - v22.18.0 --> +> Stability: 1.1 - Active Development + Customizes the signal sent to the process on watch mode restarts. ```bash From 6a8a73aa35dc3d0733df14335165bec1f22af793 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 13 Jul 2025 21:45:02 +0200 Subject: [PATCH 012/134] tools: ignore CVE mention when linting release proposals PR-URL: https://github.com/nodejs/node/pull/59037 Reviewed-By: Luigi Pinca Reviewed-By: Marco Ippolito --- .github/workflows/lint-release-proposal.yml | 2 +- tools/actions/lint-release-proposal-commit-list.mjs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint-release-proposal.yml b/.github/workflows/lint-release-proposal.yml index 88bbd5d4e9b068..101fa9964f0c73 100644 --- a/.github/workflows/lint-release-proposal.yml +++ b/.github/workflows/lint-release-proposal.yml @@ -39,7 +39,7 @@ jobs: EXPECTED_TRAILER="^$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/pull/[[:digit:]]+\$" echo "Expected trailer format: $EXPECTED_TRAILER" PR_URL="$(git --no-pager log -1 --format='%(trailers:key=PR-URL,valueonly)')" - echo "Actual: $ACTUAL" + echo "Actual: $PR_URL" echo "$PR_URL" | grep -E -q "$EXPECTED_TRAILER" PR_HEAD="$(gh pr view "$PR_URL" --json headRefOid -q .headRefOid)" diff --git a/tools/actions/lint-release-proposal-commit-list.mjs b/tools/actions/lint-release-proposal-commit-list.mjs index b6ec7213bafc0a..b5104a6503e489 100755 --- a/tools/actions/lint-release-proposal-commit-list.mjs +++ b/tools/actions/lint-release-proposal-commit-list.mjs @@ -34,6 +34,7 @@ if (commitListingStart === -1) { // Normalize for consistent comparison commitList = commitList .replaceAll('**(SEMVER-MINOR)** ', '') + .replaceAll(/(?<= - )\*\*\(CVE-\d{4}-\d+\)\*\* (?=\*\*)/g, '') .replaceAll('\\', ''); let expectedNumberOfCommitsLeft = commitList.match(/\n\* \[/g)?.length ?? 0; From 0b840523a24cd04a988a16a1e927df234435bb77 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 15 Jul 2025 00:35:54 +0200 Subject: [PATCH 013/134] doc: remove unused import in `zlib.md` PR-URL: https://github.com/nodejs/node/pull/59041 Reviewed-By: Luigi Pinca Reviewed-By: Antoine du Hamel --- doc/api/zlib.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/api/zlib.md b/doc/api/zlib.md index ded1e96d474bc9..1a94a08fa97b77 100644 --- a/doc/api/zlib.md +++ b/doc/api/zlib.md @@ -74,7 +74,6 @@ import { createReadStream, createWriteStream, } from 'node:fs'; -import process from 'node:process'; import { createGzip } from 'node:zlib'; import { pipeline } from 'node:stream/promises'; From 756c7dd63924396c457680d485eff4f6f64d191d Mon Sep 17 00:00:00 2001 From: Slayer95 Date: Tue, 15 Jul 2025 04:00:32 -0500 Subject: [PATCH 014/134] doc: refine `util.parseArgs` `default` definition The default value is legal by means other than defaulting. PR-URL: https://github.com/nodejs/node/pull/58958 Reviewed-By: Antoine du Hamel --- doc/api/util.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/api/util.md b/doc/api/util.md index 979b5e9e81f1e9..14bbad3250d727 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -1941,10 +1941,12 @@ changes: times. If `true`, all values will be collected in an array. If `false`, values for the option are last-wins. **Default:** `false`. * `short` {string} A single character alias for the option. - * `default` {string | boolean | string\[] | boolean\[]} The default value to - be used if (and only if) the option does not appear in the arguments to be - parsed. It must be of the same type as the `type` property. When `multiple` - is `true`, it must be an array. + * `default` {string | boolean | string\[] | boolean\[]} The value to assign to + the option if it does not appear in the arguments to be parsed. The value + must match the type specified by the `type` property. If `multiple` is + `true`, it must be an array. No default value is applied when the option + does appear in the arguments to be parsed, even if the provided value + is falsy. * `strict` {boolean} Should an error be thrown when unknown arguments are encountered, or when arguments are passed that do not match the `type` configured in `options`. From 1b6b5e72d3794b9a96a32ffd31004bf8bf9a85cc Mon Sep 17 00:00:00 2001 From: Aviv Keller Date: Tue, 15 Jul 2025 13:18:42 -0400 Subject: [PATCH 015/134] doc: fix typed list formatting PR-URL: https://github.com/nodejs/node/pull/59019 Refs: https://github.com/nodejs/api-docs-tooling/issues/348 Reviewed-By: Chemi Atlow Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Claudio Wunder --- doc/api/buffer.md | 22 +++---- doc/api/child_process.md | 24 ++++---- doc/api/cluster.md | 16 ++--- doc/api/crypto.md | 64 +++++++++---------- doc/api/domain.md | 2 +- doc/api/errors.md | 28 ++++----- doc/api/esm.md | 10 +-- doc/api/events.md | 2 +- doc/api/fs.md | 87 +++++++++++++------------- doc/api/globals.md | 22 +++---- doc/api/http.md | 126 +++++++++++++++++++------------------- doc/api/http2.md | 110 ++++++++++++++++----------------- doc/api/https.md | 10 +-- doc/api/inspector.md | 10 +-- doc/api/module.md | 18 +++--- doc/api/modules.md | 32 +++++----- doc/api/net.md | 52 ++++++++-------- doc/api/os.md | 6 +- doc/api/packages.md | 2 +- doc/api/path.md | 8 +-- doc/api/perf_hooks.md | 90 +++++++++++++-------------- doc/api/process.md | 106 ++++++++++++++++---------------- doc/api/punycode.md | 2 +- doc/api/readline.md | 4 +- doc/api/repl.md | 2 +- doc/api/sqlite.md | 24 ++++---- doc/api/stream.md | 54 ++++++++-------- doc/api/test.md | 6 +- doc/api/tls.md | 24 ++++---- doc/api/tracing.md | 4 +- doc/api/tty.md | 4 +- doc/api/url.md | 24 ++++---- doc/api/util.md | 22 +++---- doc/api/vm.md | 14 ++--- doc/api/wasi.md | 2 +- doc/api/worker_threads.md | 22 +++---- doc/api/zlib.md | 2 +- 37 files changed, 527 insertions(+), 530 deletions(-) diff --git a/doc/api/buffer.md b/doc/api/buffer.md index b338811548a7cc..2ba87ea02ff7cc 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -1499,7 +1499,7 @@ console.log(Buffer.isEncoding('')); added: v0.11.3 --> -* {integer} **Default:** `8192` +* Type: {integer} **Default:** `8192` This is the size (in bytes) of pre-allocated internal `Buffer` instances used for pooling. This value may be modified. @@ -1556,7 +1556,7 @@ console.log(buf.toString('utf8')); ### `buf.buffer` -* {ArrayBuffer} The underlying `ArrayBuffer` object based on which this `Buffer` +* Type: {ArrayBuffer} The underlying `ArrayBuffer` object based on which this `Buffer` object is created. This `ArrayBuffer` is not guaranteed to correspond exactly to the original @@ -1584,7 +1584,7 @@ console.log(buffer.buffer === arrayBuffer); ### `buf.byteOffset` -* {integer} The `byteOffset` of the `Buffer`'s underlying `ArrayBuffer` object. +* Type: {integer} The `byteOffset` of the `Buffer`'s underlying `ArrayBuffer` object. When setting `byteOffset` in `Buffer.from(ArrayBuffer, byteOffset, length)`, or sometimes when allocating a `Buffer` smaller than `Buffer.poolSize`, the @@ -2425,7 +2425,7 @@ If `value` is an empty string or empty `Buffer`, `byteOffset` will be returned. added: v0.1.90 --> -* {integer} +* Type: {integer} Returns the number of bytes in `buf`. @@ -5217,7 +5217,7 @@ added: - v18.15.0 --> -* input {Buffer | ArrayBuffer | TypedArray} The input to validate. +* `input` {Buffer | ArrayBuffer | TypedArray} The input to validate. * Returns: {boolean} This function returns `true` if `input` contains only valid ASCII-encoded data, @@ -5233,7 +5233,7 @@ added: - v18.14.0 --> -* input {Buffer | ArrayBuffer | TypedArray} The input to validate. +* `input` {Buffer | ArrayBuffer | TypedArray} The input to validate. * Returns: {boolean} This function returns `true` if `input` contains only valid UTF-8-encoded data, @@ -5247,7 +5247,7 @@ Throws if the `input` is a detached array buffer. added: v0.5.4 --> -* {integer} **Default:** `50` +* Type: {integer} **Default:** `50` Returns the maximum number of bytes that will be returned when `buf.inspect()` is called. This can be overridden by user modules. See @@ -5259,7 +5259,7 @@ Returns the maximum number of bytes that will be returned when added: v3.0.0 --> -* {integer} The largest size allowed for a single `Buffer` instance. +* Type: {integer} The largest size allowed for a single `Buffer` instance. An alias for [`buffer.constants.MAX_LENGTH`][]. @@ -5269,7 +5269,7 @@ An alias for [`buffer.constants.MAX_LENGTH`][]. added: v3.0.0 --> -* {integer} The largest length allowed for a single `string` instance. +* Type: {integer} The largest length allowed for a single `string` instance. An alias for [`buffer.constants.MAX_STRING_LENGTH`][]. @@ -5383,7 +5383,7 @@ changes: 232 - 1 on 64-bit architectures. --> -* {integer} The largest size allowed for a single `Buffer` instance. +* Type: {integer} The largest size allowed for a single `Buffer` instance. On 32-bit architectures, this value currently is 230 - 1 (about 1 GiB). @@ -5400,7 +5400,7 @@ This value is also available as [`buffer.kMaxLength`][]. added: v8.2.0 --> -* {integer} The largest length allowed for a single `string` instance. +* Type: {integer} The largest length allowed for a single `string` instance. Represents the largest `length` that a `string` primitive can have, counted in UTF-16 code units. diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 30c286e837d8f7..b09ccbd4df8da3 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -1602,7 +1602,7 @@ changes: description: The object no longer accidentally exposes native C++ bindings. --> -* {Object} A pipe representing the IPC channel to the child process. +* Type: {Object} A pipe representing the IPC channel to the child process. The `subprocess.channel` property is a reference to the child's IPC channel. If no IPC channel exists, this property is `undefined`. @@ -1631,7 +1631,7 @@ running, and lets it finish even while the channel is open. added: v0.7.2 --> -* {boolean} Set to `false` after `subprocess.disconnect()` is called. +* Type: {boolean} Set to `false` after `subprocess.disconnect()` is called. The `subprocess.connected` property indicates whether it is still possible to send and receive messages from a child process. When `subprocess.connected` is @@ -1660,7 +1660,7 @@ within the child process to close the IPC channel as well. ### `subprocess.exitCode` -* {integer} +* Type: {integer} The `subprocess.exitCode` property indicates the exit code of the child process. If the child process is still running, the field will be `null`. @@ -1783,7 +1783,7 @@ Calls [`subprocess.kill()`][] with `'SIGTERM'`. added: v0.5.10 --> -* {boolean} Set to `true` after `subprocess.kill()` is used to successfully +* Type: {boolean} Set to `true` after `subprocess.kill()` is used to successfully send a signal to the child process. The `subprocess.killed` property indicates whether the child process @@ -1796,7 +1796,7 @@ does not indicate that the child process has been terminated. added: v0.1.90 --> -* {integer|undefined} +* Type: {integer|undefined} Returns the process identifier (PID) of the child process. If the child process fails to spawn due to errors, then the value is `undefined` and `error` is @@ -2094,21 +2094,21 @@ connection to the child. ### `subprocess.signalCode` -* {string|null} +* Type: {string|null} The `subprocess.signalCode` property indicates the signal received by the child process if any, else `null`. ### `subprocess.spawnargs` -* {Array} +* Type: {Array} The `subprocess.spawnargs` property represents the full list of command-line arguments the child process was launched with. ### `subprocess.spawnfile` -* {string} +* Type: {string} The `subprocess.spawnfile` property indicates the executable file name of the child process that is launched. @@ -2126,7 +2126,7 @@ in which the child process is launched. added: v0.1.90 --> -* {stream.Readable|null|undefined} +* Type: {stream.Readable|null|undefined} A `Readable Stream` that represents the child process's `stderr`. @@ -2145,7 +2145,7 @@ if the child process could not be successfully spawned. added: v0.1.90 --> -* {stream.Writable|null|undefined} +* Type: {stream.Writable|null|undefined} A `Writable Stream` that represents the child process's `stdin`. @@ -2167,7 +2167,7 @@ if the child process could not be successfully spawned. added: v0.7.10 --> -* {Array} +* Type: {Array} A sparse array of pipes to the child process, corresponding with positions in the [`stdio`][] option passed to [`child_process.spawn()`][] that have been set @@ -2234,7 +2234,7 @@ not be successfully spawned. added: v0.1.90 --> -* {stream.Readable|null|undefined} +* Type: {stream.Readable|null|undefined} A `Readable Stream` that represents the child process's `stdout`. diff --git a/doc/api/cluster.md b/doc/api/cluster.md index c5946ba8efb6c5..fa9942f4668bdf 100644 --- a/doc/api/cluster.md +++ b/doc/api/cluster.md @@ -450,7 +450,7 @@ if (cluster.isPrimary) { added: v6.0.0 --> -* {boolean} +* Type: {boolean} This property is `true` if the worker exited due to `.disconnect()`. If the worker exited any other way, it is `false`. If the @@ -477,7 +477,7 @@ worker.kill(); added: v0.8.0 --> -* {integer} +* Type: {integer} Each new worker is given its own unique id, this id is stored in the `id`. @@ -595,7 +595,7 @@ it is [`kill()`][]. added: v0.7.0 --> -* {ChildProcess} +* Type: {ChildProcess} All workers are created using [`child_process.fork()`][], the returned object from this function is stored as `.process`. In a worker, the global `process` @@ -860,7 +860,7 @@ Deprecated alias for [`cluster.isPrimary`][]. added: v16.0.0 --> -* {boolean} +* Type: {boolean} True if the process is a primary. This is determined by the `process.env.NODE_UNIQUE_ID`. If `process.env.NODE_UNIQUE_ID` is @@ -872,7 +872,7 @@ undefined, then `isPrimary` is `true`. added: v0.6.0 --> -* {boolean} +* Type: {boolean} True if the process is not a primary (it is the negation of `cluster.isPrimary`). @@ -919,7 +919,7 @@ changes: description: The `stdio` option is supported now. --> -* {Object} +* Type: {Object} * `execArgv` {string\[]} List of string arguments passed to the Node.js executable. **Default:** `process.execArgv`. * `exec` {string} File path to worker file. **Default:** `process.argv[1]`. @@ -1026,7 +1026,7 @@ This can only be called from the primary process. added: v0.7.0 --> -* {Object} +* Type: {Object} A reference to the current worker object. Not available in the primary process. @@ -1060,7 +1060,7 @@ if (cluster.isPrimary) { added: v0.7.0 --> -* {Object} +* Type: {Object} A hash that stores the active worker objects, keyed by `id` field. This makes it easy to loop through all the workers. It is only available in the primary diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 1c74794ec54b90..b8120e5c2fdc74 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1993,15 +1993,15 @@ changes: for RSA-PSS keys. --> -* {Object} - * `modulusLength`: {number} Key size in bits (RSA, DSA). - * `publicExponent`: {bigint} Public exponent (RSA). - * `hashAlgorithm`: {string} Name of the message digest (RSA-PSS). - * `mgf1HashAlgorithm`: {string} Name of the message digest used by +* Type: {Object} + * `modulusLength` {number} Key size in bits (RSA, DSA). + * `publicExponent` {bigint} Public exponent (RSA). + * `hashAlgorithm` {string} Name of the message digest (RSA-PSS). + * `mgf1HashAlgorithm` {string} Name of the message digest used by MGF1 (RSA-PSS). - * `saltLength`: {number} Minimal salt length in bytes (RSA-PSS). - * `divisorLength`: {number} Size of `q` in bits (DSA). - * `namedCurve`: {string} Name of the curve (EC). + * `saltLength` {number} Minimal salt length in bytes (RSA-PSS). + * `divisorLength` {number} Size of `q` in bits (DSA). + * `namedCurve` {string} Name of the curve (EC). This property exists only on asymmetric keys. Depending on the type of the key, this object contains information about the key. None of the information obtained @@ -2039,7 +2039,7 @@ changes: description: Added support for `'ed25519'` and `'ed448'`. --> -* {string} +* Type: {string} For asymmetric keys, this property represents the type of the key. Supported key types are: @@ -2065,7 +2065,7 @@ added: - v16.15.0 --> -* `otherKeyObject`: {KeyObject} A `KeyObject` with which to +* `otherKeyObject` {KeyObject} A `KeyObject` with which to compare `keyObject`. * Returns: {boolean} @@ -2083,27 +2083,27 @@ changes: description: Added support for `'jwk'` format. --> -* `options`: {Object} +* `options` {Object} * Returns: {string | Buffer | Object} For symmetric keys, the following encoding options can be used: -* `format`: {string} Must be `'buffer'` (default) or `'jwk'`. +* `format` {string} Must be `'buffer'` (default) or `'jwk'`. For public keys, the following encoding options can be used: -* `type`: {string} Must be one of `'pkcs1'` (RSA only) or `'spki'`. -* `format`: {string} Must be `'pem'`, `'der'`, or `'jwk'`. +* `type` {string} Must be one of `'pkcs1'` (RSA only) or `'spki'`. +* `format` {string} Must be `'pem'`, `'der'`, or `'jwk'`. For private keys, the following encoding options can be used: -* `type`: {string} Must be one of `'pkcs1'` (RSA only), `'pkcs8'` or +* `type` {string} Must be one of `'pkcs1'` (RSA only), `'pkcs8'` or `'sec1'` (EC only). -* `format`: {string} Must be `'pem'`, `'der'`, or `'jwk'`. -* `cipher`: {string} If specified, the private key will be encrypted with +* `format` {string} Must be `'pem'`, `'der'`, or `'jwk'`. +* `cipher` {string} If specified, the private key will be encrypted with the given `cipher` and `passphrase` using PKCS#5 v2.0 password based encryption. -* `passphrase`: {string | Buffer} The passphrase to use for encryption, see +* `passphrase` {string | Buffer} The passphrase to use for encryption, see `cipher`. The result type depends on the selected encoding format, when PEM the @@ -2129,7 +2129,7 @@ PKCS#1 and SEC1 encryption. added: v11.6.0 --> -* {number} +* Type: {number} For secret keys, this property represents the size of the key in bytes. This property is `undefined` for asymmetric keys. @@ -2142,12 +2142,12 @@ added: v22.10.0 -* `algorithm`: {string|Algorithm|RsaHashedImportParams|EcKeyImportParams|HmacImportParams} +* `algorithm` {string|Algorithm|RsaHashedImportParams|EcKeyImportParams|HmacImportParams} -* `extractable`: {boolean} -* `keyUsages`: {string\[]} See [Key usages][]. +* `extractable` {boolean} +* `keyUsages` {string\[]} See [Key usages][]. * Returns: {CryptoKey} Converts a `KeyObject` instance to a `CryptoKey`. @@ -2158,7 +2158,7 @@ Converts a `KeyObject` instance to a `CryptoKey`. added: v11.6.0 --> -* {string} +* Type: {string} Depending on the type of this `KeyObject`, this property is either `'secret'` for secret (symmetric) keys, `'public'` for public (asymmetric) keys @@ -2997,7 +2997,7 @@ Checks the primality of the `candidate`. added: v6.3.0 --> -* {Object} +* Type: {Object} An object containing commonly used constants for crypto and security related operations. The specific constants currently defined are described in @@ -3408,14 +3408,14 @@ changes: * `key` {Object|string|ArrayBuffer|Buffer|TypedArray|DataView} - * `key`: {string|ArrayBuffer|Buffer|TypedArray|DataView|Object} The key + * `key` {string|ArrayBuffer|Buffer|TypedArray|DataView|Object} The key material, either in PEM, DER, or JWK format. - * `format`: {string} Must be `'pem'`, `'der'`, or '`'jwk'`. + * `format` {string} Must be `'pem'`, `'der'`, or '`'jwk'`. **Default:** `'pem'`. - * `type`: {string} Must be `'pkcs1'`, `'pkcs8'` or `'sec1'`. This option is + * `type` {string} Must be `'pkcs1'`, `'pkcs8'` or `'sec1'`. This option is required only if the `format` is `'der'` and ignored otherwise. - * `passphrase`: {string | Buffer} The passphrase to use for decryption. - * `encoding`: {string} The string encoding to use when `key` is a string. + * `passphrase` {string | Buffer} The passphrase to use for decryption. + * `encoding` {string} The string encoding to use when `key` is a string. * Returns: {KeyObject} @@ -3451,11 +3451,11 @@ changes: * `key` {Object|string|ArrayBuffer|Buffer|TypedArray|DataView} - * `key`: {string|ArrayBuffer|Buffer|TypedArray|DataView|Object} The key + * `key` {string|ArrayBuffer|Buffer|TypedArray|DataView|Object} The key material, either in PEM, DER, or JWK format. - * `format`: {string} Must be `'pem'`, `'der'`, or `'jwk'`. + * `format` {string} Must be `'pem'`, `'der'`, or `'jwk'`. **Default:** `'pem'`. - * `type`: {string} Must be `'pkcs1'` or `'spki'`. This option is + * `type` {string} Must be `'pkcs1'` or `'spki'`. This option is required only if the `format` is `'der'` and ignored otherwise. * `encoding` {string} The string encoding to use when `key` is a string. * Returns: {KeyObject} diff --git a/doc/api/domain.md b/doc/api/domain.md index e986b8ec8527a7..47f97035fca8d6 100644 --- a/doc/api/domain.md +++ b/doc/api/domain.md @@ -287,7 +287,7 @@ To handle the errors that it catches, listen to its `'error'` event. ### `domain.members` -* {Array} +* Type: {Array} An array of timers and event emitters that have been explicitly added to the domain. diff --git a/doc/api/errors.md b/doc/api/errors.md index 51cc1e38eb24a5..c909156d1c8e9a 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -228,7 +228,7 @@ a(); ### `Error.stackTraceLimit` -* {number} +* Type: {number} The `Error.stackTraceLimit` property specifies the number of stack frames collected by a stack trace (whether generated by `new Error().stack` or @@ -246,7 +246,7 @@ not capture any frames. added: v16.9.0 --> -* {any} +* Type: {any} If present, the `error.cause` property is the underlying cause of the `Error`. It is used when catching an error and throwing a new one with a different @@ -285,7 +285,7 @@ console.log(symptom); ### `error.code` -* {string} +* Type: {string} The `error.code` property is a string label that identifies the kind of error. `error.code` is the most stable way to identify an error. It will only change @@ -295,7 +295,7 @@ about specific codes. ### `error.message` -* {string} +* Type: {string} The `error.message` property is the string description of the error as set by calling `new Error(message)`. The `message` passed to the constructor will also @@ -312,7 +312,7 @@ console.error(err.message); ### `error.stack` -* {string} +* Type: {string} The `error.stack` property is a string describing the point in the code at which the `Error` was instantiated. @@ -471,27 +471,27 @@ attempts to read a file that does not exist. ### `error.address` -* {string} +* Type: {string} If present, `error.address` is a string describing the address to which a network connection failed. ### `error.code` -* {string} +* Type: {string} The `error.code` property is a string representing the error code. ### `error.dest` -* {string} +* Type: {string} If present, `error.dest` is the file path destination when reporting a file system error. ### `error.errno` -* {number} +* Type: {number} The `error.errno` property is a negative number which corresponds to the error code defined in [`libuv Error handling`][]. @@ -503,31 +503,31 @@ To get the string representation of the error code, use ### `error.info` -* {Object} +* Type: {Object} If present, `error.info` is an object with details about the error condition. ### `error.message` -* {string} +* Type: {string} `error.message` is a system-provided human-readable description of the error. ### `error.path` -* {string} +* Type: {string} If present, `error.path` is a string containing a relevant invalid pathname. ### `error.port` -* {number} +* Type: {number} If present, `error.port` is the network connection port that is not available. ### `error.syscall` -* {string} +* Type: {string} The `error.syscall` property is a string describing the [syscall][] that failed. diff --git a/doc/api/esm.md b/doc/api/esm.md index 6c11bd1a13ede1..e609083a443e75 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -336,7 +336,7 @@ modules it can be used to load ES modules. ## `import.meta` -* {Object} +* Type: {Object} The `import.meta` meta property is an `Object` that contains the following properties. It is only supported in ES modules. @@ -353,7 +353,7 @@ changes: description: This property is no longer experimental. --> -* {string} The directory name of the current module. +* Type: {string} The directory name of the current module. This is the same as the [`path.dirname()`][] of the [`import.meta.filename`][]. @@ -371,7 +371,7 @@ changes: description: This property is no longer experimental. --> -* {string} The full absolute path and filename of the current module, with +* Type: {string} The full absolute path and filename of the current module, with symlinks resolved. This is the same as the [`url.fileURLToPath()`][] of the [`import.meta.url`][]. @@ -381,7 +381,7 @@ This is the same as the [`url.fileURLToPath()`][] of the [`import.meta.url`][]. ### `import.meta.url` -* {string} The absolute `file:` URL of the module. +* Type: {string} The absolute `file:` URL of the module. This is defined exactly the same as it is in browsers providing the URL of the current module file. @@ -402,7 +402,7 @@ added: > Stability: 1.0 - Early development -* {boolean} `true` when the current module is the entry point of the current process; `false` otherwise. +* Type: {boolean} `true` when the current module is the entry point of the current process; `false` otherwise. Equivalent to `require.main === module` in CommonJS. diff --git a/doc/api/events.md b/doc/api/events.md index 87a52f00985e5a..401e8aeed9513b 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -1984,7 +1984,7 @@ same options as `EventEmitter` and `AsyncResource` themselves. ### `eventemitterasyncresource.asyncResource` -* Type: The underlying {AsyncResource}. +* The underlying {AsyncResource}. The returned `AsyncResource` object has an additional `eventEmitter` property that provides a reference to this `EventEmitterAsyncResource`. diff --git a/doc/api/fs.md b/doc/api/fs.md index a279c648fa23d9..2d542557c4ad26 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -375,7 +375,7 @@ Unlike `filehandle.sync` this method does not flush modified metadata. added: v10.0.0 --> -* {number} The numeric file descriptor managed by the {FileHandle} object. +* Type: {number} The numeric file descriptor managed by the {FileHandle} object. #### `filehandle.read(buffer, offset, length, position)` @@ -1922,7 +1922,7 @@ added: - v16.17.0 --> -* {Object} +* Type: {Object} Returns an object containing commonly used constants for file system operations. The object is the same as `fs.constants`. See [FS constants][] @@ -6379,8 +6379,7 @@ changes: * `target` {string|Buffer|URL} * `path` {string|Buffer|URL} * `type` {string|null} **Default:** `null` - -Returns `undefined`. +* Returns: `undefined`. For detailed information, see the documentation of the asynchronous version of this API: [`fs.symlink()`][]. @@ -6437,8 +6436,7 @@ changes: * `path` {string|Buffer|URL} * `atime` {number|string|Date} * `mtime` {number|string|Date} - -Returns `undefined`. +* Returns: `undefined`. For detailed information, see the documentation of the asynchronous version of this API: [`fs.utimes()`][]. @@ -6489,8 +6487,7 @@ changes: * `flag` {string} See [support of file system `flags`][]. **Default:** `'w'`. * `flush` {boolean} If all data is successfully written to the file, and `flush` is `true`, `fs.fsyncSync()` is used to flush the data. - -Returns `undefined`. +* Returns: `undefined`. The `mode` option only affects the newly created file. See [`fs.open()`][] for more details. @@ -6665,7 +6662,7 @@ Subsequent reads will result in errors. added: v12.12.0 --> -* {string} +* Type: {string} The read-only path of this directory as was provided to [`fs.opendir()`][], [`fs.opendirSync()`][], or [`fsPromises.opendir()`][]. @@ -6863,7 +6860,7 @@ Returns `true` if the {fs.Dirent} object describes a symbolic link. added: v10.10.0 --> -* {string|Buffer} +* Type: {string|Buffer} The file name that this {fs.Dirent} object refers to. The type of this value is determined by the `options.encoding` passed to [`fs.readdir()`][] or @@ -6882,7 +6879,7 @@ changes: description: Marking the API stable. --> -* {string} +* Type: {string} The path to the parent directory of the file this {fs.Dirent} object refers to. @@ -7101,7 +7098,7 @@ Fires immediately after `'open'`. added: v6.4.0 --> -* {number} +* Type: {number} The number of bytes that have been read so far. @@ -7111,7 +7108,7 @@ The number of bytes that have been read so far. added: v0.1.93 --> -* {string|Buffer} +* Type: {string|Buffer} The path to the file the stream is reading from as specified in the first argument to `fs.createReadStream()`. If `path` is passed as a string, then @@ -7127,7 +7124,7 @@ added: - v10.16.0 --> -* {boolean} +* Type: {boolean} This property is `true` if the underlying file has not been opened yet, i.e. before the `'ready'` event is emitted. @@ -7284,49 +7281,49 @@ This method is only valid when using [`fs.lstat()`][]. #### `stats.dev` -* {number|bigint} +* Type: {number|bigint} The numeric identifier of the device containing the file. #### `stats.ino` -* {number|bigint} +* Type: {number|bigint} The file system specific "Inode" number for the file. #### `stats.mode` -* {number|bigint} +* Type: {number|bigint} A bit-field describing the file type and mode. #### `stats.nlink` -* {number|bigint} +* Type: {number|bigint} The number of hard-links that exist for the file. #### `stats.uid` -* {number|bigint} +* Type: {number|bigint} The numeric user identifier of the user that owns the file (POSIX). #### `stats.gid` -* {number|bigint} +* Type: {number|bigint} The numeric group identifier of the group that owns the file (POSIX). #### `stats.rdev` -* {number|bigint} +* Type: {number|bigint} A numeric device identifier if the file represents a device. #### `stats.size` -* {number|bigint} +* Type: {number|bigint} The size of the file in bytes. @@ -7335,13 +7332,13 @@ this will be `0`. #### `stats.blksize` -* {number|bigint} +* Type: {number|bigint} The file system block size for i/o operations. #### `stats.blocks` -* {number|bigint} +* Type: {number|bigint} The number of blocks allocated for this file. @@ -7351,7 +7348,7 @@ The number of blocks allocated for this file. added: v8.1.0 --> -* {number|bigint} +* Type: {number|bigint} The timestamp indicating the last time this file was accessed expressed in milliseconds since the POSIX Epoch. @@ -7362,7 +7359,7 @@ milliseconds since the POSIX Epoch. added: v8.1.0 --> -* {number|bigint} +* Type: {number|bigint} The timestamp indicating the last time this file was modified expressed in milliseconds since the POSIX Epoch. @@ -7373,7 +7370,7 @@ milliseconds since the POSIX Epoch. added: v8.1.0 --> -* {number|bigint} +* Type: {number|bigint} The timestamp indicating the last time the file status was changed expressed in milliseconds since the POSIX Epoch. @@ -7384,7 +7381,7 @@ in milliseconds since the POSIX Epoch. added: v8.1.0 --> -* {number|bigint} +* Type: {number|bigint} The timestamp indicating the creation time of this file expressed in milliseconds since the POSIX Epoch. @@ -7395,7 +7392,7 @@ milliseconds since the POSIX Epoch. added: v12.10.0 --> -* {bigint} +* Type: {bigint} Only present when `bigint: true` is passed into the method that generates the object. @@ -7408,7 +7405,7 @@ nanoseconds since the POSIX Epoch. added: v12.10.0 --> -* {bigint} +* Type: {bigint} Only present when `bigint: true` is passed into the method that generates the object. @@ -7421,7 +7418,7 @@ nanoseconds since the POSIX Epoch. added: v12.10.0 --> -* {bigint} +* Type: {bigint} Only present when `bigint: true` is passed into the method that generates the object. @@ -7434,7 +7431,7 @@ in nanoseconds since the POSIX Epoch. added: v12.10.0 --> -* {bigint} +* Type: {bigint} Only present when `bigint: true` is passed into the method that generates the object. @@ -7447,7 +7444,7 @@ nanoseconds since the POSIX Epoch. added: v0.11.13 --> -* {Date} +* Type: {Date} The timestamp indicating the last time this file was accessed. @@ -7457,7 +7454,7 @@ The timestamp indicating the last time this file was accessed. added: v0.11.13 --> -* {Date} +* Type: {Date} The timestamp indicating the last time this file was modified. @@ -7467,7 +7464,7 @@ The timestamp indicating the last time this file was modified. added: v0.11.13 --> -* {Date} +* Type: {Date} The timestamp indicating the last time the file status was changed. @@ -7477,7 +7474,7 @@ The timestamp indicating the last time the file status was changed. added: v0.11.13 --> -* {Date} +* Type: {Date} The timestamp indicating the creation time of this file. @@ -7569,7 +7566,7 @@ added: - v18.15.0 --> -* {number|bigint} +* Type: {number|bigint} Free blocks available to unprivileged users. @@ -7581,7 +7578,7 @@ added: - v18.15.0 --> -* {number|bigint} +* Type: {number|bigint} Free blocks in file system. @@ -7593,7 +7590,7 @@ added: - v18.15.0 --> -* {number|bigint} +* Type: {number|bigint} Total data blocks in file system. @@ -7605,7 +7602,7 @@ added: - v18.15.0 --> -* {number|bigint} +* Type: {number|bigint} Optimal transfer block size. @@ -7617,7 +7614,7 @@ added: - v18.15.0 --> -* {number|bigint} +* Type: {number|bigint} Free file nodes in file system. @@ -7629,7 +7626,7 @@ added: - v18.15.0 --> -* {number|bigint} +* Type: {number|bigint} Total file nodes in file system. @@ -7641,7 +7638,7 @@ added: - v18.15.0 --> -* {number|bigint} +* Type: {number|bigint} Type of file system. @@ -7723,14 +7720,14 @@ argument to [`fs.createWriteStream()`][]. If `path` is passed as a string, then added: v11.2.0 --> -* {boolean} +* Type: {boolean} This property is `true` if the underlying file has not been opened yet, i.e. before the `'ready'` event is emitted. ### `fs.constants` -* {Object} +* Type: {Object} Returns an object containing commonly used constants for file system operations. diff --git a/doc/api/globals.md b/doc/api/globals.md index 844808d53b7dc6..72e9e32f84c5bb 100644 --- a/doc/api/globals.md +++ b/doc/api/globals.md @@ -104,7 +104,7 @@ changes: description: Added the new optional reason argument. --> -* `reason`: {any} +* `reason` {any} * Returns: {AbortSignal} Returns a new already aborted `AbortSignal`. @@ -238,7 +238,7 @@ See {Blob}. added: v0.1.103 --> -* {Function} +* Type: {Function} Used to handle binary data. See the [buffer section][]. @@ -332,7 +332,7 @@ A browser-compatible implementation of [`CompressionStream`][]. added: v0.1.100 --> -* {Object} +* Type: {Object} Used to print to stdout and stderr. See the [`console`][] section. @@ -567,7 +567,7 @@ added: v0.1.27 > Stability: 3 - Legacy. Use [`globalThis`][] instead. -* {Object} The global namespace object. +* Type: {Object} The global namespace object. In browsers, the top-level scope has traditionally been the global scope. This means that `var something` will define a new global variable, except within @@ -666,7 +666,7 @@ A partial implementation of [`window.navigator`][]. added: v21.0.0 --> -* {number} +* Type: {number} The `navigator.hardwareConcurrency` read-only property returns the number of logical processors available to the current Node.js instance. @@ -681,7 +681,7 @@ console.log(`This process is running on ${navigator.hardwareConcurrency} logical added: v21.2.0 --> -* {string} +* Type: {string} The `navigator.language` read-only property returns a string representing the preferred language of the Node.js instance. The language will be determined by @@ -702,7 +702,7 @@ console.log(`The preferred language of the Node.js instance has the tag '${navig added: v21.2.0 --> -* {Array} +* Type: {Array} The `navigator.languages` read-only property returns an array of strings representing the preferred languages of the Node.js instance. @@ -722,7 +722,7 @@ console.log(`The preferred languages are '${navigator.languages}'`); added: v21.2.0 --> -* {string} +* Type: {string} The `navigator.platform` read-only property returns a string identifying the platform on which the Node.js instance is running. @@ -737,7 +737,7 @@ console.log(`This process is running on ${navigator.platform}`); added: v21.1.0 --> -* {string} +* Type: {string} The `navigator.userAgent` read-only property returns user agent consisting of the runtime name and major version number. @@ -810,7 +810,7 @@ The [`perf_hooks.performance`][] object. added: v0.1.7 --> -* {Object} +* Type: {Object} The process object. See the [`process` object][] section. @@ -1132,7 +1132,7 @@ The WHATWG `URLSearchParams` class. See the [`URLSearchParams`][] section. added: v8.0.0 --> -* {Object} +* Type: {Object} The object that acts as the namespace for all W3C [WebAssembly][webassembly-org] related functionality. See the diff --git a/doc/api/http.md b/doc/api/http.md index 709b956345fba5..0ab2910f9194a9 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -291,7 +291,7 @@ changes: description: The property now has a `null` prototype. --> -* {Object} +* Type: {Object} An object which contains arrays of sockets currently awaiting use by the agent when `keepAlive` is enabled. Do not modify. @@ -332,7 +332,7 @@ that determine socket reusability. added: v0.11.7 --> -* {number} +* Type: {number} By default set to 256. For agents with `keepAlive` enabled, this sets the maximum number of sockets that will be left open in the free @@ -344,7 +344,7 @@ state. added: v0.3.6 --> -* {number} +* Type: {number} By default set to `Infinity`. Determines how many concurrent sockets the agent can have open per origin. Origin is the returned value of [`agent.getName()`][]. @@ -357,7 +357,7 @@ added: - v12.19.0 --> -* {number} +* Type: {number} By default set to `Infinity`. Determines how many concurrent sockets the agent can have open. Unlike `maxSockets`, this parameter applies across all origins. @@ -372,7 +372,7 @@ changes: description: The property now has a `null` prototype. --> -* {Object} +* Type: {Object} An object which contains queues of requests that have not yet been assigned to sockets. Do not modify. @@ -387,7 +387,7 @@ changes: description: The property now has a `null` prototype. --> -* {Object} +* Type: {Object} An object which contains arrays of sockets currently in use by the agent. Do not modify. @@ -836,7 +836,7 @@ changes: > Stability: 0 - Deprecated. Check [`request.destroyed`][] instead. -* {boolean} +* Type: {boolean} The `request.aborted` property will be `true` if the request has been aborted. @@ -850,7 +850,7 @@ deprecated: v13.0.0 > Stability: 0 - Deprecated. Use [`request.socket`][]. -* {stream.Duplex} +* Type: {stream.Duplex} See [`request.socket`][]. @@ -920,7 +920,7 @@ added: - v13.14.0 --> -* {boolean} +* Type: {boolean} Is `true` after [`request.destroy()`][] has been called. @@ -937,7 +937,7 @@ deprecated: > Stability: 0 - Deprecated. Use [`request.writableEnded`][]. -* {boolean} +* Type: {boolean} The `request.finished` property will be `true` if [`request.end()`][] has been called. `request.end()` will automatically be called if the @@ -1069,7 +1069,7 @@ const hasContentType = request.hasHeader('content-type'); ### `request.maxHeadersCount` -* {number} **Default:** `2000` +* Type: {number} **Default:** `2000` Limits maximum response headers count. If set to 0, no limit will be applied. @@ -1079,7 +1079,7 @@ Limits maximum response headers count. If set to 0, no limit will be applied. added: v0.4.0 --> -* {string} The request path. +* Type: {string} The request path. ### `request.method` @@ -1087,7 +1087,7 @@ added: v0.4.0 added: v0.1.97 --> -* {string} The request method. +* Type: {string} The request method. ### `request.host` @@ -1097,7 +1097,7 @@ added: - v12.19.0 --> -* {string} The request host. +* Type: {string} The request host. ### `request.protocol` @@ -1107,7 +1107,7 @@ added: - v12.19.0 --> -* {string} The request protocol. +* Type: {string} The request protocol. ### `request.removeHeader(name)` @@ -1131,7 +1131,7 @@ added: - v12.16.0 --> -* {boolean} Whether the request is send through a reused socket. +* Type: {boolean} Whether the request is send through a reused socket. When sending request through a keep-alive enabled agent, the underlying socket might be reused. But if server closes connection at unfortunate time, client @@ -1306,7 +1306,7 @@ Once a socket is assigned to this request and is connected added: v0.3.0 --> -* {stream.Duplex} +* Type: {stream.Duplex} Reference to the underlying socket. Usually users will not want to access this property. In particular, the socket will not emit `'readable'` events @@ -1362,7 +1362,7 @@ See [`writable.uncork()`][]. added: v12.9.0 --> -* {boolean} +* Type: {boolean} Is `true` after [`request.end()`][] has been called. This property does not indicate whether the data has been flushed, for this use @@ -1374,7 +1374,7 @@ does not indicate whether the data has been flushed, for this use added: v12.7.0 --> -* {boolean} +* Type: {boolean} Is `true` if all data has been flushed to the underlying system, immediately before the [`'finish'`][] event is emitted. @@ -1790,7 +1790,7 @@ changes: description: The default is now set to the minimum between 60000 (60 seconds) or `requestTimeout`. --> -* {number} **Default:** The minimum between [`server.requestTimeout`][] or `60000`. +* Type: {number} **Default:** The minimum between [`server.requestTimeout`][] or `60000`. Limit the amount of time the parser will wait to receive the complete HTTP headers. @@ -1813,7 +1813,7 @@ This method is identical to [`server.listen()`][] from [`net.Server`][]. added: v5.7.0 --> -* {boolean} Indicates whether or not the server is listening for connections. +* Type: {boolean} Indicates whether or not the server is listening for connections. ### `server.maxHeadersCount` @@ -1821,7 +1821,7 @@ added: v5.7.0 added: v0.7.0 --> -* {number} **Default:** `2000` +* Type: {number} **Default:** `2000` Limits maximum incoming headers count. If set to 0, no limit will be applied. @@ -1836,7 +1836,7 @@ changes: from no timeout to 300s (5 minutes). --> -* {number} **Default:** `300000` +* Type: {number} **Default:** `300000` Sets the timeout value in milliseconds for receiving the entire request from the client. @@ -1879,7 +1879,7 @@ explicitly. added: v16.10.0 --> -* {number} Requests per socket. **Default:** 0 (no limit) +* Type: {number} Requests per socket. **Default:** 0 (no limit) The maximum number of requests socket can handle before closing keep alive connection. @@ -1900,7 +1900,7 @@ changes: description: The default timeout changed from 120s to 0 (no timeout). --> -* {number} Timeout in milliseconds. **Default:** 0 (no timeout) +* Type: {number} Timeout in milliseconds. **Default:** 0 (no timeout) The number of milliseconds of inactivity before a socket is presumed to have timed out. @@ -1916,7 +1916,7 @@ value only affects new connections to the server, not any existing connections. added: v8.0.0 --> -* {number} Timeout in milliseconds. **Default:** `5000` (5 seconds). +* Type: {number} Timeout in milliseconds. **Default:** `5000` (5 seconds). The number of milliseconds of inactivity a server needs to wait for additional incoming data, after it has finished writing the last response, before a socket @@ -2012,7 +2012,7 @@ deprecated: v13.0.0 > Stability: 0 - Deprecated. Use [`response.socket`][]. -* {stream.Duplex} +* Type: {stream.Duplex} See [`response.socket`][]. @@ -2065,7 +2065,7 @@ deprecated: > Stability: 0 - Deprecated. Use [`response.writableEnded`][]. -* {boolean} +* Type: {boolean} The `response.finished` property will be `true` if [`response.end()`][] has been called. @@ -2171,7 +2171,7 @@ const hasContentType = response.hasHeader('content-type'); added: v0.9.3 --> -* {boolean} +* Type: {boolean} Boolean (read-only). True if headers were sent, false otherwise. @@ -2195,7 +2195,7 @@ response.removeHeader('Content-Encoding'); added: v15.7.0 --> -* {http.IncomingMessage} +* Type: {http.IncomingMessage} A reference to the original HTTP `request` object. @@ -2205,7 +2205,7 @@ A reference to the original HTTP `request` object. added: v0.7.5 --> -* {boolean} +* Type: {boolean} When true, the Date header will be automatically generated and sent in the response if it is not already present in the headers. Defaults to true. @@ -2292,7 +2292,7 @@ timed out sockets must be handled explicitly. added: v0.3.0 --> -* {stream.Duplex} +* Type: {stream.Duplex} Reference to the underlying socket. Usually users will not want to access this property. In particular, the socket will not emit `'readable'` events @@ -2327,7 +2327,7 @@ type other than {net.Socket}. added: v0.4.0 --> -* {number} **Default:** `200` +* Type: {number} **Default:** `200` When using implicit headers (not calling [`response.writeHead()`][] explicitly), this property controls the status code that will be sent to the client when @@ -2346,7 +2346,7 @@ status code which was sent out. added: v0.11.8 --> -* {string} +* Type: {string} When using implicit headers (not calling [`response.writeHead()`][] explicitly), this property controls the status message that will be sent to the client when @@ -2368,7 +2368,7 @@ added: - v16.18.0 --> -* {boolean} **Default:** `false` +* Type: {boolean} **Default:** `false` If set to `true`, Node.js will check whether the `Content-Length` header value and the size of the body, in bytes, are equal. @@ -2391,7 +2391,7 @@ See [`writable.uncork()`][]. added: v12.9.0 --> -* {boolean} +* Type: {boolean} Is `true` after [`response.end()`][] has been called. This property does not indicate whether the data has been flushed, for this use @@ -2403,7 +2403,7 @@ does not indicate whether the data has been flushed, for this use added: v12.7.0 --> -* {boolean} +* Type: {boolean} Is `true` if all data has been flushed to the underlying system, immediately before the [`'finish'`][] event is emitted. @@ -2662,7 +2662,7 @@ deprecated: > Stability: 0 - Deprecated. Check `message.destroyed` from {stream.Readable}. -* {boolean} +* Type: {boolean} The `message.aborted` property will be `true` if the request has been aborted. @@ -2673,7 +2673,7 @@ been aborted. added: v0.3.0 --> -* {boolean} +* Type: {boolean} The `message.complete` property will be `true` if a complete HTTP message has been received and successfully parsed. @@ -2748,7 +2748,7 @@ changes: on the prototype and is no longer enumerable. --> -* {Object} +* Type: {Object} The request/response headers object. @@ -2786,7 +2786,7 @@ added: - v16.17.0 --> -* {Object} +* Type: {Object} Similar to [`message.headers`][], but there is no join logic and the values are always arrays of strings, even for headers received just once. @@ -2806,7 +2806,7 @@ console.log(request.headersDistinct); added: v0.1.1 --> -* {string} +* Type: {string} In case of server request, the HTTP version sent by the client. In the case of client response, the HTTP version of the connected-to server. @@ -2821,7 +2821,7 @@ Also `message.httpVersionMajor` is the first integer and added: v0.1.1 --> -* {string} +* Type: {string} **Only valid for request obtained from [`http.Server`][].** @@ -2833,7 +2833,7 @@ The request method as a string. Read only. Examples: `'GET'`, `'DELETE'`. added: v0.11.6 --> -* {string\[]} +* Type: {string\[]} The raw request/response headers list exactly as they were received. @@ -2863,7 +2863,7 @@ console.log(request.rawHeaders); added: v0.11.6 --> -* {string\[]} +* Type: {string\[]} The raw request/response trailer keys and values exactly as they were received. Only populated at the `'end'` event. @@ -2886,7 +2886,7 @@ Calls `message.socket.setTimeout(msecs, callback)`. added: v0.3.0 --> -* {stream.Duplex} +* Type: {stream.Duplex} The [`net.Socket`][] object associated with the connection. @@ -2903,7 +2903,7 @@ type other than {net.Socket} or internally nulled. added: v0.1.1 --> -* {number} +* Type: {number} **Only valid for response obtained from [`http.ClientRequest`][].** @@ -2915,7 +2915,7 @@ The 3-digit HTTP response status code. E.G. `404`. added: v0.11.10 --> -* {string} +* Type: {string} **Only valid for response obtained from [`http.ClientRequest`][].** @@ -2928,7 +2928,7 @@ Error`. added: v0.3.0 --> -* {Object} +* Type: {Object} The request/response trailers object. Only populated at the `'end'` event. @@ -2940,7 +2940,7 @@ added: - v16.17.0 --> -* {Object} +* Type: {Object} Similar to [`message.trailers`][], but there is no join logic and the values are always arrays of strings, even for headers received just once. @@ -2952,7 +2952,7 @@ Only populated at the `'end'` event. added: v0.1.90 --> -* {string} +* Type: {string} **Only valid for request obtained from [`http.Server`][].** @@ -3236,7 +3236,7 @@ const hasContentType = outgoingMessage.hasHeader('content-type'); added: v0.9.3 --> -* {boolean} +* Type: {boolean} Read-only. `true` if the headers were sent, otherwise `false`. @@ -3342,7 +3342,7 @@ Once a socket is associated with the message and is connected, added: v0.3.0 --> -* {stream.Duplex} +* Type: {stream.Duplex} Reference to the underlying socket. Usually, users will not want to access this property. @@ -3367,7 +3367,7 @@ added: - v12.16.0 --> -* {number} +* Type: {number} The number of times `outgoingMessage.cork()` has been called. @@ -3377,7 +3377,7 @@ The number of times `outgoingMessage.cork()` has been called. added: v12.9.0 --> -* {boolean} +* Type: {boolean} Is `true` if `outgoingMessage.end()` has been called. This property does not indicate whether the data has been flushed. For that purpose, use @@ -3389,7 +3389,7 @@ not indicate whether the data has been flushed. For that purpose, use added: v12.7.0 --> -* {boolean} +* Type: {boolean} Is `true` if all data has been flushed to the underlying system. @@ -3399,7 +3399,7 @@ Is `true` if all data has been flushed to the underlying system. added: v12.9.0 --> -* {number} +* Type: {number} The `highWaterMark` of the underlying socket if assigned. Otherwise, the default buffer level when [`writable.write()`][] starts returning false (`16384`). @@ -3410,7 +3410,7 @@ buffer level when [`writable.write()`][] starts returning false (`16384`). added: v12.9.0 --> -* {number} +* Type: {number} The number of buffered bytes. @@ -3420,7 +3420,7 @@ The number of buffered bytes. added: v12.9.0 --> -* {boolean} +* Type: {boolean} Always `false`. @@ -3459,7 +3459,7 @@ memory. The `'drain'` event will be emitted when the buffer is free again. added: v0.11.8 --> -* {string\[]} +* Type: {string\[]} A list of the HTTP methods that are supported by the parser. @@ -3469,7 +3469,7 @@ A list of the HTTP methods that are supported by the parser. added: v0.1.22 --> -* {Object} +* Type: {Object} A collection of all the standard HTTP response status codes, and the short description of each. For example, `http.STATUS_CODES[404] === 'Not @@ -3740,7 +3740,7 @@ changes: default. --> -* {http.Agent} +* Type: {http.Agent} Global instance of `Agent` which is used as the default for all HTTP client requests. Diverges from a default `Agent` configuration by having `keepAlive` @@ -3754,7 +3754,7 @@ added: - v10.15.0 --> -* {number} +* Type: {number} Read-only property specifying the maximum allowed size of HTTP headers in bytes. Defaults to 16 KiB. Configurable using the [`--max-http-header-size`][] CLI diff --git a/doc/api/http2.md b/doc/api/http2.md index 7552784a4ca527..b29b2f8a1437b0 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -451,7 +451,7 @@ session.on('timeout', () => { /* .. */ }); added: v9.4.0 --> -* {string|undefined} +* Type: {string|undefined} Value will be `undefined` if the `Http2Session` is not yet connected to a socket, `h2c` if the `Http2Session` is not connected to a `TLSSocket`, or @@ -480,7 +480,7 @@ If specified, the `callback` function is registered as a handler for the added: v9.4.0 --> -* {boolean} +* Type: {boolean} Will be `true` if this `Http2Session` instance has been closed, otherwise `false`. @@ -491,7 +491,7 @@ Will be `true` if this `Http2Session` instance has been closed, otherwise added: v10.0.0 --> -* {boolean} +* Type: {boolean} Will be `true` if this `Http2Session` instance is still connecting, will be set to `false` before emitting `connect` event and/or calling the `http2.connect` @@ -525,7 +525,7 @@ If there are any remaining open `Http2Streams` associated with the added: v8.4.0 --> -* {boolean} +* Type: {boolean} Will be `true` if this `Http2Session` instance has been destroyed and must no longer be used, otherwise `false`. @@ -536,7 +536,7 @@ longer be used, otherwise `false`. added: v9.4.0 --> -* {boolean|undefined} +* Type: {boolean|undefined} Value is `undefined` if the `Http2Session` session socket has not yet been connected, `true` if the `Http2Session` is connected with a `TLSSocket`, @@ -563,7 +563,7 @@ Transmits a `GOAWAY` frame to the connected peer _without_ shutting down the added: v8.4.0 --> -* {HTTP/2 Settings Object} +* Type: {HTTP/2 Settings Object} A prototype-less object describing the current local settings of this `Http2Session`. The local settings are local to _this_ `Http2Session` instance. @@ -574,7 +574,7 @@ A prototype-less object describing the current local settings of this added: v9.4.0 --> -* {string\[]|undefined} +* Type: {string\[]|undefined} If the `Http2Session` is connected to a `TLSSocket`, the `originSet` property will return an `Array` of origins for which the `Http2Session` may be @@ -588,7 +588,7 @@ The `originSet` property is only available when using a secure TLS connection. added: v8.4.0 --> -* {boolean} +* Type: {boolean} Indicates whether the `Http2Session` is currently waiting for acknowledgment of a sent `SETTINGS` frame. Will be `true` after calling the @@ -655,7 +655,7 @@ instance's underlying [`net.Socket`][]. added: v8.4.0 --> -* {HTTP/2 Settings Object} +* Type: {HTTP/2 Settings Object} A prototype-less object describing the current remote settings of this `Http2Session`. The remote settings are set by the _connected_ HTTP/2 peer. @@ -725,7 +725,7 @@ registered as a listener on the `'timeout'` event. added: v8.4.0 --> -* {net.Socket|tls.TLSSocket} +* Type: {net.Socket|tls.TLSSocket} Returns a `Proxy` object that acts as a `net.Socket` (or `tls.TLSSocket`) but limits available methods to ones safe to use with HTTP/2. @@ -747,7 +747,7 @@ added: v8.4.0 Provides miscellaneous information about the current state of the `Http2Session`. -* {Object} +* Type: {Object} * `effectiveLocalWindowSize` {number} The current local (receive) flow control window size for the `Http2Session`. * `effectiveRecvDataLength` {number} The current number of bytes @@ -805,7 +805,7 @@ multiple `SETTINGS` frames while acknowledgment is still pending. added: v8.4.0 --> -* {number} +* Type: {number} The `http2session.type` will be equal to `http2.constants.NGHTTP2_SESSION_SERVER` if this `Http2Session` instance is a @@ -1078,7 +1078,7 @@ changes: `weight` option is deprecated. --> -* `headers` {HTTP/2 Headers Object} | {Array} +* `headers` {HTTP/2 Headers Object|Array} * `options` {Object} * `endStream` {boolean} `true` if the `Http2Stream` _writable_ side should @@ -1366,7 +1366,7 @@ option must be set for this event to be emitted. added: v8.4.0 --> -* {boolean} +* Type: {boolean} Set to `true` if the `Http2Stream` instance was aborted abnormally. When set, the `'aborted'` event will have been emitted. @@ -1379,7 +1379,7 @@ added: - v10.16.0 --> -* {number} +* Type: {number} This property shows the number of characters currently buffered to be written. See [`net.Socket.bufferSize`][] for details. @@ -1410,7 +1410,7 @@ connected HTTP/2 peer. added: v9.4.0 --> -* {boolean} +* Type: {boolean} Set to `true` if the `Http2Stream` instance has been closed. @@ -1420,7 +1420,7 @@ Set to `true` if the `Http2Stream` instance has been closed. added: v8.4.0 --> -* {boolean} +* Type: {boolean} Set to `true` if the `Http2Stream` instance has been destroyed and is no longer usable. @@ -1431,7 +1431,7 @@ usable. added: v10.11.0 --> -* {boolean} +* Type: {boolean} Set to `true` if the `END_STREAM` flag was set in the request or response HEADERS frame received, indicating that no additional data should be received @@ -1443,7 +1443,7 @@ and the readable side of the `Http2Stream` will be closed. added: v8.4.0 --> -* {number|undefined} +* Type: {number|undefined} The numeric stream identifier of this `Http2Stream` instance. Set to `undefined` if the stream identifier has not yet been assigned. @@ -1454,7 +1454,7 @@ if the stream identifier has not yet been assigned. added: v9.4.0 --> -* {boolean} +* Type: {boolean} Set to `true` if the `Http2Stream` instance has not yet been assigned a numeric stream identifier. @@ -1490,7 +1490,7 @@ Updates the priority for this `Http2Stream` instance. added: v8.4.0 --> -* {number} +* Type: {number} Set to the `RST_STREAM` [error code][] reported when the `Http2Stream` is destroyed after either receiving an `RST_STREAM` frame from the connected peer, @@ -1503,7 +1503,7 @@ calling `http2stream.close()`, or `http2stream.destroy()`. Will be added: v9.5.0 --> -* {HTTP/2 Headers Object} +* Type: {HTTP/2 Headers Object} An object containing the outbound headers sent for this `Http2Stream`. @@ -1513,7 +1513,7 @@ An object containing the outbound headers sent for this `Http2Stream`. added: v9.5.0 --> -* {HTTP/2 Headers Object\[]} +* Type: {HTTP/2 Headers Object\[]} An array of objects containing the outbound informational (additional) headers sent for this `Http2Stream`. @@ -1524,7 +1524,7 @@ sent for this `Http2Stream`. added: v9.5.0 --> -* {HTTP/2 Headers Object} +* Type: {HTTP/2 Headers Object} An object containing the outbound trailers sent for this `HttpStream`. @@ -1534,7 +1534,7 @@ An object containing the outbound trailers sent for this `HttpStream`. added: v8.4.0 --> -* {Http2Session} +* Type: {Http2Session} A reference to the `Http2Session` instance that owns this `Http2Stream`. The value will be `undefined` after the `Http2Stream` instance is destroyed. @@ -1588,7 +1588,7 @@ changes: Provides miscellaneous information about the current state of the `Http2Stream`. -* {Object} +* Type: {Object} * `localWindowSize` {number} The number of bytes the connected peer may send for this `Http2Stream` without receiving a `WINDOW_UPDATE`. * `state` {number} A flag indicating the low-level current state of the @@ -1771,7 +1771,7 @@ Sends an additional informational `HEADERS` frame to the connected HTTP/2 peer. added: v8.4.0 --> -* {boolean} +* Type: {boolean} True if headers were sent, false otherwise (read-only). @@ -1781,7 +1781,7 @@ True if headers were sent, false otherwise (read-only). added: v8.4.0 --> -* {boolean} +* Type: {boolean} Read-only property mapped to the `SETTINGS_ENABLE_PUSH` flag of the remote client's most recent `SETTINGS` frame. Will be `true` if the remote peer @@ -2484,7 +2484,7 @@ changes: description: The default timeout changed from 120s to 0 (no timeout). --> -* {number} Timeout in milliseconds. **Default:** 0 (no timeout) +* Type: {number} Timeout in milliseconds. **Default:** 0 (no timeout) The number of milliseconds of inactivity before a socket is presumed to have timed out. @@ -2753,7 +2753,7 @@ changes: description: The default timeout changed from 120s to 0 (no timeout). --> -* {number} Timeout in milliseconds. **Default:** 0 (no timeout) +* Type: {number} Timeout in milliseconds. **Default:** 0 (no timeout) The number of milliseconds of inactivity before a socket is presumed to have timed out. @@ -3384,7 +3384,7 @@ added: - v14.18.0 --> -* {symbol} +* Type: {symbol} This symbol can be set as a property on the HTTP/2 headers object with an array value in order to provide a list of headers considered sensitive. @@ -3948,7 +3948,7 @@ Just like `'end'`, this event occurs only once per response. added: v10.1.0 --> -* {boolean} +* Type: {boolean} The `request.aborted` property will be `true` if the request has been aborted. @@ -3959,7 +3959,7 @@ been aborted. added: v8.4.0 --> -* {string} +* Type: {string} The request authority pseudo header field. Because HTTP/2 allows requests to set either `:authority` or `host`, this value is derived from @@ -3972,7 +3972,7 @@ to set either `:authority` or `host`, this value is derived from added: v12.10.0 --> -* {boolean} +* Type: {boolean} The `request.complete` property will be `true` if the request has been completed, aborted, or destroyed. @@ -3986,7 +3986,7 @@ deprecated: v13.0.0 > Stability: 0 - Deprecated. Use [`request.socket`][]. -* {net.Socket|tls.TLSSocket} +* Type: {net.Socket|tls.TLSSocket} See [`request.socket`][]. @@ -4010,7 +4010,7 @@ It does nothing if the stream was already destroyed. added: v8.4.0 --> -* {Object} +* Type: {Object} The request/response headers object. @@ -4044,7 +4044,7 @@ assert(request.url); // Fails because the :path header has been removed added: v8.4.0 --> -* {string} +* Type: {string} In case of server request, the HTTP version sent by the client. In the case of client response, the HTTP version of the connected-to server. Returns @@ -4059,7 +4059,7 @@ Also `message.httpVersionMajor` is the first integer and added: v8.4.0 --> -* {string} +* Type: {string} The request method as a string. Read-only. Examples: `'GET'`, `'DELETE'`. @@ -4069,7 +4069,7 @@ The request method as a string. Read-only. Examples: `'GET'`, `'DELETE'`. added: v8.4.0 --> -* {string\[]} +* Type: {string\[]} The raw request/response headers list exactly as they were received. @@ -4099,7 +4099,7 @@ console.log(request.rawHeaders); added: v8.4.0 --> -* {string\[]} +* Type: {string\[]} The raw request/response trailer keys and values exactly as they were received. Only populated at the `'end'` event. @@ -4110,7 +4110,7 @@ received. Only populated at the `'end'` event. added: v8.4.0 --> -* {string} +* Type: {string} The request scheme pseudo header field indicating the scheme portion of the target URL. @@ -4140,7 +4140,7 @@ events, timed out sockets must be handled explicitly. added: v8.4.0 --> -* {net.Socket|tls.TLSSocket} +* Type: {net.Socket|tls.TLSSocket} Returns a `Proxy` object that acts as a `net.Socket` (or `tls.TLSSocket`) but applies getters, setters, and methods based on HTTP/2 logic. @@ -4167,7 +4167,7 @@ authentication details. added: v8.4.0 --> -* {Http2Stream} +* Type: {Http2Stream} The [`Http2Stream`][] object backing the request. @@ -4177,7 +4177,7 @@ The [`Http2Stream`][] object backing the request. added: v8.4.0 --> -* {Object} +* Type: {Object} The request/response trailers object. Only populated at the `'end'` event. @@ -4187,7 +4187,7 @@ The request/response trailers object. Only populated at the `'end'` event. added: v8.4.0 --> -* {string} +* Type: {string} Request URL string. This contains only the URL that is present in the actual HTTP request. If the request is: @@ -4314,7 +4314,7 @@ deprecated: v13.0.0 > Stability: 0 - Deprecated. Use [`response.socket`][]. -* {net.Socket|tls.TLSSocket} +* Type: {net.Socket|tls.TLSSocket} See [`response.socket`][]. @@ -4380,7 +4380,7 @@ deprecated: > Stability: 0 - Deprecated. Use [`response.writableEnded`][]. -* {boolean} +* Type: {boolean} Boolean value that indicates whether the response has completed. Starts as `false`. After [`response.end()`][] executes, the value will be `true`. @@ -4469,7 +4469,7 @@ const hasContentType = response.hasHeader('content-type'); added: v8.4.0 --> -* {boolean} +* Type: {boolean} True if headers were sent, false otherwise (read-only). @@ -4493,7 +4493,7 @@ response.removeHeader('Content-Encoding'); added: v15.7.0 --> -* {http2.Http2ServerRequest} +* Type: {http2.Http2ServerRequest} A reference to the original HTTP2 `request` object. @@ -4503,7 +4503,7 @@ A reference to the original HTTP2 `request` object. added: v8.4.0 --> -* {boolean} +* Type: {boolean} When true, the Date header will be automatically generated and sent in the response if it is not already present in the headers. Defaults to true. @@ -4576,7 +4576,7 @@ events, timed out sockets must be handled explicitly. added: v8.4.0 --> -* {net.Socket|tls.TLSSocket} +* Type: {net.Socket|tls.TLSSocket} Returns a `Proxy` object that acts as a `net.Socket` (or `tls.TLSSocket`) but applies getters, setters, and methods based on HTTP/2 logic. @@ -4619,7 +4619,7 @@ const server = http2.createServer((req, res) => { added: v8.4.0 --> -* {number} +* Type: {number} When using implicit headers (not calling [`response.writeHead()`][] explicitly), this property controls the status code that will be sent to the client when @@ -4638,7 +4638,7 @@ status code which was sent out. added: v8.4.0 --> -* {string} +* Type: {string} Status message is not supported by HTTP/2 (RFC 7540 8.1.2.4). It returns an empty string. @@ -4649,7 +4649,7 @@ an empty string. added: v8.4.0 --> -* {Http2Stream} +* Type: {Http2Stream} The [`Http2Stream`][] object backing the response. @@ -4659,7 +4659,7 @@ The [`Http2Stream`][] object backing the response. added: v12.9.0 --> -* {boolean} +* Type: {boolean} Is `true` after [`response.end()`][] has been called. This property does not indicate whether the data has been flushed, for this use diff --git a/doc/api/https.md b/doc/api/https.md index 86b7fd0be1cdf9..29c60135e42718 100644 --- a/doc/api/https.md +++ b/doc/api/https.md @@ -166,7 +166,7 @@ See [`server.closeIdleConnections()`][] in the `node:http` module. added: v11.3.0 --> -* {number} **Default:** `60000` +* Type: {number} **Default:** `60000` See [`server.headersTimeout`][] in the `node:http` module. @@ -177,7 +177,7 @@ This method is identical to [`server.listen()`][] from [`net.Server`][]. ### `server.maxHeadersCount` -* {number} **Default:** `2000` +* Type: {number} **Default:** `2000` See [`server.maxHeadersCount`][] in the `node:http` module. @@ -192,7 +192,7 @@ changes: from no timeout to 300s (5 minutes). --> -* {number} **Default:** `300000` +* Type: {number} **Default:** `300000` See [`server.requestTimeout`][] in the `node:http` module. @@ -218,7 +218,7 @@ changes: description: The default timeout changed from 120s to 0 (no timeout). --> -* {number} **Default:** 0 (no timeout) +* Type: {number} **Default:** 0 (no timeout) See [`server.timeout`][] in the `node:http` module. @@ -228,7 +228,7 @@ See [`server.timeout`][] in the `node:http` module. added: v8.0.0 --> -* {number} **Default:** `5000` (5 seconds) +* Type: {number} **Default:** `5000` (5 seconds) See [`server.keepAliveTimeout`][] in the `node:http` module. diff --git a/doc/api/inspector.md b/doc/api/inspector.md index 4ad68c1bfff466..518ad1688a9f78 100644 --- a/doc/api/inspector.md +++ b/doc/api/inspector.md @@ -64,7 +64,7 @@ command. added: v8.0.0 --> -* {Object} The notification message object +* Type: {Object} The notification message object Emitted when any notification from the V8 Inspector is received. @@ -85,7 +85,7 @@ It is also possible to subscribe only to notifications with specific method: added: v8.0.0 --> -* {Object} The notification message object +* Type: {Object} The notification message object Emitted when an inspector notification is received that has its method field set to the `` value. @@ -243,7 +243,7 @@ command. added: v8.0.0 --> -* {Object} The notification message object +* Type: {Object} The notification message object Emitted when any notification from the V8 Inspector is received. @@ -264,7 +264,7 @@ It is also possible to subscribe only to notifications with specific method: added: v8.0.0 --> -* {Object} The notification message object +* Type: {Object} The notification message object Emitted when an inspector notification is received that has its method field set to the `` value. @@ -420,7 +420,7 @@ are closed. Once all connections are closed, deactivates the inspector. ### `inspector.console` -* {Object} An object to send messages to the remote inspector console. +* Type: {Object} An object to send messages to the remote inspector console. ```js require('node:inspector').console.log('a message'); diff --git a/doc/api/module.md b/doc/api/module.md index 0fad98bc1422de..8bb7fba96ca5eb 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -8,7 +8,7 @@ added: v0.3.7 ## The `Module` object -* {Object} +* Type: {Object} Provides general utility methods when interacting with instances of `Module`, the [`module`][] variable often seen in [CommonJS][] modules. Accessed @@ -23,7 +23,7 @@ added: - v6.13.0 --> -* {string\[]} +* Type: {string\[]} A list of the names of all modules provided by Node.js. Can be used to verify if a module is maintained by a third party or not. @@ -1821,13 +1821,13 @@ Creates a new `sourceMap` instance. `payload` is an object with keys matching the [Source map format][]: -* `file`: {string} -* `version`: {number} -* `sources`: {string\[]} -* `sourcesContent`: {string\[]} -* `names`: {string\[]} -* `mappings`: {string} -* `sourceRoot`: {string} +* `file` {string} +* `version` {number} +* `sources` {string\[]} +* `sourcesContent` {string\[]} +* `names` {string\[]} +* `mappings` {string} +* `sourceRoot` {string} `lineLengths` is an optional array of the length of each line in the generated code. diff --git a/doc/api/modules.md b/doc/api/modules.md index 3cf0f4a928b53d..898413d2c702a7 100644 --- a/doc/api/modules.md +++ b/doc/api/modules.md @@ -764,7 +764,7 @@ added: v0.1.27 -* {string} +* Type: {string} The directory name of the current module. This is the same as the [`path.dirname()`][] of the [`__filename`][]. @@ -786,7 +786,7 @@ added: v0.0.1 -* {string} +* Type: {string} The file name of the current module. This is the current module file's absolute path with symlinks resolved. @@ -825,7 +825,7 @@ added: v0.1.12 -* {Object} +* Type: {Object} A reference to the `module.exports` that is shorter to type. See the section about the [exports shortcut][] for details on when to use @@ -839,7 +839,7 @@ added: v0.1.16 -* {module} +* Type: {module} A reference to the current module, see the section about the [`module` object][]. In particular, `module.exports` is used for defining what @@ -882,7 +882,7 @@ const crypto = require('node:crypto'); added: v0.3.0 --> -* {Object} +* Type: {Object} Modules are cached in this object when they are required. By deleting a key value from this object, the next `require` will reload the module. @@ -916,7 +916,7 @@ deprecated: v0.10.6 > Stability: 0 - Deprecated -* {Object} +* Type: {Object} Instruct `require` on how to handle certain file extensions. @@ -940,7 +940,7 @@ extensions gets slower with each registered extension. added: v0.1.17 --> -* {module | undefined} +* Type: {module | undefined} The `Module` object representing the entry script loaded when the Node.js process launched, or `undefined` if the entry point of the program is not a @@ -1022,7 +1022,7 @@ added: v0.1.16 -* {Object} +* Type: {Object} In each module, the `module` free variable is a reference to the object representing the current module. For convenience, `module.exports` is @@ -1035,7 +1035,7 @@ a global but rather local to each module. added: v0.1.16 --> -* {module\[]} +* Type: {module\[]} The module objects required for the first time by this one. @@ -1045,7 +1045,7 @@ The module objects required for the first time by this one. added: v0.1.16 --> -* {Object} +* Type: {Object} The `module.exports` object is created by the `Module` system. Sometimes this is not acceptable; many want their module to be an instance of some class. To do @@ -1149,7 +1149,7 @@ function require(/* ... */) { added: v0.1.16 --> -* {string} +* Type: {string} The fully resolved filename of the module. @@ -1159,7 +1159,7 @@ The fully resolved filename of the module. added: v0.1.16 --> -* {string} +* Type: {string} The identifier for the module. Typically this is the fully resolved filename. @@ -1181,7 +1181,7 @@ added: added: v0.1.16 --> -* {boolean} +* Type: {boolean} Whether or not the module is done loading, or is in the process of loading. @@ -1198,7 +1198,7 @@ deprecated: > Stability: 0 - Deprecated: Please use [`require.main`][] and > [`module.children`][] instead. -* {module | null | undefined} +* Type: {module | null | undefined} The module that first required this one, or `null` if the current module is the entry point of the current process, or `undefined` if the module was loaded by @@ -1210,7 +1210,7 @@ something that is not a CommonJS module (E.G.: REPL or `import`). added: v11.14.0 --> -* {string} +* Type: {string} The directory name of the module. This is usually the same as the [`path.dirname()`][] of the [`module.id`][]. @@ -1221,7 +1221,7 @@ The directory name of the module. This is usually the same as the added: v0.4.0 --> -* {string\[]} +* Type: {string\[]} The search paths for the module. diff --git a/doc/api/net.md b/doc/api/net.md index 978c5d2326bc23..ba49daecf13043 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -244,7 +244,7 @@ added: - v14.18.0 --> -* Type {string} +* Type: {string} ### `socketaddress.family` @@ -254,7 +254,7 @@ added: - v14.18.0 --> -* Type {string} Either `'ipv4'` or `'ipv6'`. +* Type: {string} Either `'ipv4'` or `'ipv6'`. ### `socketaddress.flowlabel` @@ -264,7 +264,7 @@ added: - v14.18.0 --> -* Type {number} +* Type: {number} ### `socketaddress.port` @@ -274,7 +274,7 @@ added: - v14.18.0 --> -* Type {number} +* Type: {number} ### `SocketAddress.parse(input)` @@ -322,7 +322,7 @@ event is not emitted until all connections are ended. added: v0.1.90 --> -* {net.Socket} The connection object +* Type: {net.Socket} The connection object Emitted when a new connection is made. `socket` is an instance of `net.Socket`. @@ -333,7 +333,7 @@ Emitted when a new connection is made. `socket` is an instance of added: v0.1.90 --> -* {Error} +* Type: {Error} Emitted when an error occurs. Unlike [`net.Socket`][], the [`'close'`][] event will **not** be emitted directly following this event unless @@ -648,7 +648,7 @@ may cause the `net.Server` to also listen on the [unspecified IPv4 address][] added: v5.7.0 --> -* {boolean} Indicates whether or not the server is listening for connections. +* Type: {boolean} Indicates whether or not the server is listening for connections. ### `server.maxConnections` @@ -661,7 +661,7 @@ changes: connections. Previously, it was interpreted as `Infinity`. --> -* {integer} +* Type: {integer} When the number of connections reaches the `server.maxConnections` threshold: @@ -678,7 +678,7 @@ with [`child_process.fork()`][]. added: v22.12.0 --> -* {boolean} +* Type: {boolean} Set this property to `true` to begin closing connections once the number of connections reaches the \[`server.maxConnections`]\[] threshold. This setting is only effective in cluster mode. @@ -846,7 +846,7 @@ in [`socket.connect(options)`][]. added: v0.1.90 --> -* {Buffer|string} +* Type: {Buffer|string} Emitted when data is received. The argument `data` will be a `Buffer` or `String`. Encoding of data is set by [`socket.setEncoding()`][]. @@ -887,7 +887,7 @@ FIN packet back). added: v0.1.90 --> -* {Error} +* Type: {Error} Emitted when an error occurs. The `'close'` event will be called directly following this event. @@ -958,7 +958,7 @@ added: - v18.18.0 --> -* {string\[]} +* Type: {string\[]} This property is only present if the family autoselection algorithm is enabled in [`socket.connect(options)`][] and it is an array of the addresses that have been attempted. @@ -976,7 +976,7 @@ deprecated: > Stability: 0 - Deprecated: Use [`writable.writableLength`][] instead. -* {integer} +* Type: {integer} This property shows the number of characters buffered for writing. The buffer may contain strings whose length after encoding is not yet known. So this number @@ -999,7 +999,7 @@ Users who experience large or growing `bufferSize` should attempt to added: v0.5.3 --> -* {integer} +* Type: {integer} The amount of received bytes. @@ -1009,7 +1009,7 @@ The amount of received bytes. added: v0.5.3 --> -* {integer} +* Type: {integer} The amount of bytes sent. @@ -1168,7 +1168,7 @@ called with `{port: port, host: host}` as `options`. added: v6.1.0 --> -* {boolean} +* Type: {boolean} If `true`, [`socket.connect(options[, connectListener])`][`socket.connect(options)`] was @@ -1194,7 +1194,7 @@ See [`writable.destroy()`][] for further details. ### `socket.destroyed` -* {boolean} Indicates if the connection is destroyed or not. Once a +* Type: {boolean} Indicates if the connection is destroyed or not. Once a connection is destroyed no further data can be transferred using it. See [`writable.destroyed`][] for further details. @@ -1231,7 +1231,7 @@ See [`writable.end()`][] for further details. added: v0.9.6 --> -* {string} +* Type: {string} The string representation of the local IP address the remote client is connecting on. For example, in a server listening on `'0.0.0.0'`, if a client @@ -1244,7 +1244,7 @@ connects on `'192.168.1.1'`, the value of `socket.localAddress` would be added: v0.9.6 --> -* {integer} +* Type: {integer} The numeric representation of the local port. For example, `80` or `21`. @@ -1256,7 +1256,7 @@ added: - v16.18.0 --> -* {string} +* Type: {string} The string representation of the local IP family. `'IPv4'` or `'IPv6'`. @@ -1275,7 +1275,7 @@ added: - v10.16.0 --> -* {boolean} +* Type: {boolean} This is `true` if the socket is not connected yet, either because `.connect()` has not yet been called or because it is still in the process of connecting @@ -1299,7 +1299,7 @@ If the socket is `ref`ed calling `ref` again will have no effect. added: v0.5.10 --> -* {string} +* Type: {string} The string representation of the remote IP address. For example, `'74.125.127.100'` or `'2001:4860:a005::68'`. Value may be `undefined` if @@ -1311,7 +1311,7 @@ the socket is destroyed (for example, if the client disconnected). added: v0.11.14 --> -* {string} +* Type: {string} The string representation of the remote IP family. `'IPv4'` or `'IPv6'`. Value may be `undefined` if the socket is destroyed (for example, if the client disconnected). @@ -1322,7 +1322,7 @@ the socket is destroyed (for example, if the client disconnected). added: v0.5.10 --> -* {integer} +* Type: {integer} The numeric representation of the remote port. For example, `80` or `21`. Value may be `undefined` if the socket is destroyed (for example, if the client disconnected). @@ -1453,7 +1453,7 @@ The optional `callback` parameter will be added as a one-time listener for the added: v10.7.0 --> -* {number|undefined} +* Type: {number|undefined} The socket timeout in milliseconds as set by [`socket.setTimeout()`][]. It is `undefined` if a timeout has not been set. @@ -1500,7 +1500,7 @@ information. added: v0.5.0 --> -* {string} +* Type: {string} This property represents the state of the connection as a string. diff --git a/doc/api/os.md b/doc/api/os.md index a367a8c4aa0234..882deab45042d8 100644 --- a/doc/api/os.md +++ b/doc/api/os.md @@ -23,7 +23,7 @@ const os = require('node:os'); added: v0.7.8 --> -* {string} +* Type: {string} The operating system-specific end-of-line marker. @@ -66,7 +66,7 @@ The return value is equivalent to [`process.arch`][]. added: v6.3.0 --> -* {Object} +* Type: {Object} Contains commonly used operating system-specific constants for error codes, process signals, and so on. The specific constants defined are described in @@ -161,7 +161,7 @@ added: - v14.18.0 --> -* {string} +* Type: {string} The platform-specific file path of the null device. diff --git a/doc/api/packages.md b/doc/api/packages.md index 08fd12a4e19c87..af25beb82a7fe8 100644 --- a/doc/api/packages.md +++ b/doc/api/packages.md @@ -1103,7 +1103,7 @@ changes: description: Implement conditional exports. --> -* Type: {Object} | {string} | {string\[]} +* Type: {Object|string|string\[]} ```json { diff --git a/doc/api/path.md b/doc/api/path.md index e26506a8a47b33..9111684633eedd 100644 --- a/doc/api/path.md +++ b/doc/api/path.md @@ -114,7 +114,7 @@ and is not a string. added: v0.9.3 --> -* {string} +* Type: {string} Provides the platform-specific path delimiter: @@ -499,7 +499,7 @@ changes: description: Exposed as `require('path/posix')`. --> -* {Object} +* Type: {Object} The `path.posix` property provides access to POSIX specific implementations of the `path` methods. @@ -593,7 +593,7 @@ A [`TypeError`][] is thrown if any of the arguments is not a string. added: v0.7.9 --> -* {string} +* Type: {string} Provides the platform-specific path segment separator: @@ -644,7 +644,7 @@ changes: description: Exposed as `require('path/win32')`. --> -* {Object} +* Type: {Object} The `path.win32` property provides access to Windows-specific implementations of the `path` methods. diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index fccaac5e730ca6..585f42053369dc 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -369,7 +369,7 @@ Performance Timeline manually with `performance.clearMeasures`. added: v8.5.0 --> -* {PerformanceNodeTiming} +* Type: {PerformanceNodeTiming} _This property is an extension by Node.js. It is not available in Web browsers._ @@ -414,7 +414,7 @@ By default the max buffer size is set to 250. added: v8.5.0 --> -* {number} +* Type: {number} The [`timeOrigin`][] specifies the high resolution millisecond timestamp at which the current `node` process began, measured in Unix time. @@ -541,7 +541,7 @@ changes: `PerformanceEntry` object as the receiver. --> -* {number} +* Type: {number} The total number of milliseconds elapsed for this entry. This value will not be meaningful for all Performance Entry types. @@ -557,7 +557,7 @@ changes: `PerformanceEntry` object as the receiver. --> -* {string} +* Type: {string} The type of the performance entry. It may be one of: @@ -583,7 +583,7 @@ changes: `PerformanceEntry` object as the receiver. --> -* {string} +* Type: {string} The name of the performance entry. @@ -598,7 +598,7 @@ changes: `PerformanceEntry` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp marking the starting time of the Performance Entry. @@ -626,7 +626,7 @@ changes: `PerformanceMark` object as the receiver. --> -* {any} +* Type: {any} Additional detail specified when creating with `Performance.mark()` method. @@ -655,7 +655,7 @@ changes: `PerformanceMeasure` object as the receiver. --> -* {any} +* Type: {any} Additional detail specified when creating with `Performance.measure()` method. @@ -684,7 +684,7 @@ changes: `PerformanceNodeEntry` object as the receiver. --> -* {any} +* Type: {any} Additional detail specific to the `entryType`. @@ -703,7 +703,7 @@ changes: > Stability: 0 - Deprecated: Use `performanceNodeEntry.detail` instead. -* {number} +* Type: {number} When `performanceEntry.entryType` is equal to `'gc'`, the `performance.flags` property contains additional information about garbage collection operation. @@ -730,7 +730,7 @@ changes: > Stability: 0 - Deprecated: Use `performanceNodeEntry.detail` instead. -* {number} +* Type: {number} When `performanceEntry.entryType` is equal to `'gc'`, the `performance.kind` property identifies the type of garbage collection operation that occurred. @@ -871,7 +871,7 @@ is not exposed to users. added: v8.5.0 --> -* {number} +* Type: {number} The high resolution millisecond timestamp at which the Node.js process completed bootstrapping. If bootstrapping has not yet finished, the property @@ -883,7 +883,7 @@ has the value of -1. added: v8.5.0 --> -* {number} +* Type: {number} The high resolution millisecond timestamp at which the Node.js environment was initialized. @@ -896,7 +896,7 @@ added: - v12.19.0 --> -* {number} +* Type: {number} The high resolution millisecond timestamp of the amount of time the event loop has been idle within the event loop's event provider (e.g. `epoll_wait`). This @@ -910,7 +910,7 @@ value of 0. added: v8.5.0 --> -* {number} +* Type: {number} The high resolution millisecond timestamp at which the Node.js event loop exited. If the event loop has not yet exited, the property has the value of -1. @@ -922,7 +922,7 @@ It can only have a value of not -1 in a handler of the [`'exit'`][] event. added: v8.5.0 --> -* {number} +* Type: {number} The high resolution millisecond timestamp at which the Node.js event loop started. If the event loop has not yet started (e.g., in the first tick of the @@ -934,7 +934,7 @@ main script), the property has the value of -1. added: v8.5.0 --> -* {number} +* Type: {number} The high resolution millisecond timestamp at which the Node.js process was initialized. @@ -979,7 +979,7 @@ setImmediate(() => { added: v8.5.0 --> -* {number} +* Type: {number} The high resolution millisecond timestamp at which the V8 platform was initialized. @@ -1012,7 +1012,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp at immediately before dispatching the `fetch` request. If the resource is not intercepted by a worker the property @@ -1031,7 +1031,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp that represents the start time of the fetch which initiates the redirect. @@ -1049,7 +1049,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp that will be created immediately after receiving the last byte of the response of the last redirect. @@ -1067,7 +1067,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp immediately before the Node.js starts to fetch the resource. @@ -1085,7 +1085,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp immediately before the Node.js starts the domain name lookup for the resource. @@ -1103,7 +1103,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp representing the time immediately after the Node.js finished the domain name lookup for the resource. @@ -1121,7 +1121,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp representing the time immediately before Node.js starts to establish the connection to the server to retrieve @@ -1140,7 +1140,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp representing the time immediately after Node.js finishes establishing the connection to the server to retrieve @@ -1159,7 +1159,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp representing the time immediately before Node.js starts the handshake process to secure the current connection. @@ -1177,7 +1177,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp representing the time immediately before Node.js receives the first byte of the response from the server. @@ -1195,7 +1195,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} The high resolution millisecond timestamp representing the time immediately after Node.js receives the last byte of the resource or immediately before @@ -1214,7 +1214,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} A number representing the size (in octets) of the fetched resource. The size includes the response header fields plus the response payload body. @@ -1232,7 +1232,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} A number representing the size (in octets) received from the fetch (HTTP or cache), of the payload body, before removing any applied @@ -1251,7 +1251,7 @@ changes: `PerformanceResourceTiming` object as the receiver. --> -* {number} +* Type: {number} A number representing the size (in octets) received from the fetch (HTTP or cache), of the message body, after removing any applied @@ -1285,7 +1285,7 @@ added: v8.5.0 added: v16.0.0 --> -* {string\[]} +* Type: {string\[]} Get supported types. @@ -1787,7 +1787,7 @@ added: - v16.14.0 --> -* {number} +* Type: {number} The number of samples recorded by the histogram. @@ -1799,7 +1799,7 @@ added: - v16.14.0 --> -* {bigint} +* Type: {bigint} The number of samples recorded by the histogram. @@ -1809,7 +1809,7 @@ The number of samples recorded by the histogram. added: v11.10.0 --> -* {number} +* Type: {number} The number of times the event loop delay exceeded the maximum 1 hour event loop delay threshold. @@ -1822,7 +1822,7 @@ added: - v16.14.0 --> -* {bigint} +* Type: {bigint} The number of times the event loop delay exceeded the maximum 1 hour event loop delay threshold. @@ -1833,7 +1833,7 @@ loop delay threshold. added: v11.10.0 --> -* {number} +* Type: {number} The maximum recorded event loop delay. @@ -1845,7 +1845,7 @@ added: - v16.14.0 --> -* {bigint} +* Type: {bigint} The maximum recorded event loop delay. @@ -1855,7 +1855,7 @@ The maximum recorded event loop delay. added: v11.10.0 --> -* {number} +* Type: {number} The mean of the recorded event loop delays. @@ -1865,7 +1865,7 @@ The mean of the recorded event loop delays. added: v11.10.0 --> -* {number} +* Type: {number} The minimum recorded event loop delay. @@ -1877,7 +1877,7 @@ added: - v16.14.0 --> -* {bigint} +* Type: {bigint} The minimum recorded event loop delay. @@ -1911,7 +1911,7 @@ Returns the value at the given percentile. added: v11.10.0 --> -* {Map} +* Type: {Map} Returns a `Map` object detailing the accumulated percentile distribution. @@ -1923,7 +1923,7 @@ added: - v16.14.0 --> -* {Map} +* Type: {Map} Returns a `Map` object detailing the accumulated percentile distribution. @@ -1941,7 +1941,7 @@ Resets the collected histogram data. added: v11.10.0 --> -* {number} +* Type: {number} The standard deviation of the recorded event loop delays. diff --git a/doc/api/process.md b/doc/api/process.md index 144187a24b7cc3..f2e0aa55f393cf 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -825,7 +825,7 @@ This feature is not available in [`Worker`][] threads. added: v10.10.0 --> -* {Set} +* Type: {Set} The `process.allowedNodeEnvironmentFlags` property is a special, read-only `Set` of flags allowable within the [`NODE_OPTIONS`][] @@ -888,7 +888,7 @@ contain what _would have_ been allowable. added: v0.5.0 --> -* {string} +* Type: {string} The operating system CPU architecture for which the Node.js binary was compiled. Possible values are: `'arm'`, `'arm64'`, `'ia32'`, `'loong64'`, `'mips'`, @@ -912,7 +912,7 @@ console.log(`This processor architecture is ${arch}`); added: v0.1.27 --> -* {string\[]} +* Type: {string\[]} The `process.argv` property returns an array containing the command-line arguments passed when the Node.js process was launched. The first element will @@ -963,7 +963,7 @@ Would generate the output: added: v6.4.0 --> -* {string} +* Type: {string} The `process.argv0` property stores a read-only copy of the original value of `argv[0]` passed when Node.js starts. @@ -986,7 +986,7 @@ changes: description: Change stability index for this feature from Experimental to Stable. --> -* {number} +* Type: {number} Gets the amount of free memory that is still available to the process (in bytes). @@ -1004,7 +1004,7 @@ changes: description: The object no longer accidentally exposes native C++ bindings. --> -* {Object} +* Type: {Object} If the Node.js process was spawned with an IPC channel (see the [Child Process][] documentation), the `process.channel` @@ -1088,7 +1088,7 @@ changes: description: Modifying process.config has been deprecated. --> -* {Object} +* Type: {Object} The `process.config` property returns a frozen `Object` containing the JavaScript representation of the configure options used to compile the current @@ -1131,7 +1131,7 @@ An example of the possible output looks like: added: v0.7.2 --> -* {boolean} +* Type: {boolean} If the Node.js process is spawned with an IPC channel (see the [Child Process][] and [Cluster][] documentation), the `process.connected` property will return @@ -1156,7 +1156,7 @@ changes: description: Aligned return value with `uv_get_constrained_memory`. --> -* {number} +* Type: {number} Gets the amount of memory available to the process (in bytes) based on limits imposed by the OS. If there is no such constraint, or the constraint @@ -1243,7 +1243,7 @@ console.log(`Current directory: ${cwd()}`); added: v0.7.2 --> -* {number} +* Type: {number} The port used by the Node.js debugger when enabled. @@ -1591,7 +1591,7 @@ changes: description: Implicit conversion of variable value to string is deprecated. --> -* {Object} +* Type: {Object} The `process.env` property returns an object containing the user environment. See environ(7). @@ -1719,7 +1719,7 @@ unlike the main thread. added: v0.7.7 --> -* {string\[]} +* Type: {string\[]} The `process.execArgv` property returns the set of Node.js-specific command-line options passed when the Node.js process was launched. These options do not @@ -1755,7 +1755,7 @@ threads with this property. added: v0.1.100 --> -* {string} +* Type: {string} The `process.execPath` property returns the absolute pathname of the executable that started the Node.js process. Symbolic links, if any, are resolved. @@ -1912,7 +1912,7 @@ changes: represents an integer. --> -* {integer|string|null|undefined} The exit code. For string type, only +* Type: {integer|string|null|undefined} The exit code. For string type, only integer strings (e.g.,'1') are allowed. **Default:** `undefined`. A number which will be the process exit code, when the process either @@ -1948,7 +1948,7 @@ $ node --input-type=module -e 'process.exitCode = 9; await new Promise(() => {}) added: v12.0.0 --> -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build is caching builtin modules. @@ -1958,7 +1958,7 @@ A boolean value that is `true` if the current Node.js build is caching builtin m added: v0.5.5 --> -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build is a debug build. @@ -1968,7 +1968,7 @@ A boolean value that is `true` if the current Node.js build is a debug build. added: v11.10.0 --> -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build includes the inspector. @@ -1982,7 +1982,7 @@ deprecated: v22.13.0 > Stability: 0 - Deprecated. This property is always true, and any checks based on it are > redundant. -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build includes support for IPv6. @@ -1994,7 +1994,7 @@ Since all Node.js builds have IPv6 support, this value is always `true`. added: v22.10.0 --> -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build supports [loading ECMAScript modules using `require()`][]. @@ -2005,7 +2005,7 @@ A boolean value that is `true` if the current Node.js build supports added: v0.5.3 --> -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build includes support for TLS. @@ -2018,7 +2018,7 @@ deprecated: v22.13.0 > Stability: 0 - Deprecated. Use `process.features.tls` instead. -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build includes support for ALPN in TLS. @@ -2034,7 +2034,7 @@ deprecated: v22.13.0 > Stability: 0 - Deprecated. Use `process.features.tls` instead. -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build includes support for OCSP in TLS. @@ -2050,7 +2050,7 @@ deprecated: v22.13.0 > Stability: 0 - Deprecated. Use `process.features.tls` instead. -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build includes support for SNI in TLS. @@ -2065,7 +2065,7 @@ added: v22.10.0 > Stability: 1.1 - Active development -* {boolean|string} +* Type: {boolean|string} A value that is `"strip"` by default, `"transform"` if Node.js is run with `--experimental-transform-types`, and `false` if @@ -2081,7 +2081,7 @@ deprecated: v22.13.0 > Stability: 0 - Deprecated. This property is always true, and any checks based on it are > redundant. -* {boolean} +* Type: {boolean} A boolean value that is `true` if the current Node.js build includes support for libuv. @@ -2778,7 +2778,7 @@ deprecated: v14.0.0 > Stability: 0 - Deprecated: Use [`require.main`][] instead. -* {Object} +* Type: {Object} The `process.mainModule` property provides an alternative way of retrieving [`require.main`][]. The difference is that if the main module changes at @@ -3137,7 +3137,7 @@ needed, use `queueMicrotask()`. added: v0.8.0 --> -* {boolean} +* Type: {boolean} The `process.noDeprecation` property indicates whether the `--no-deprecation` flag is set on the current Node.js process. See the documentation for @@ -3151,7 +3151,7 @@ flag's behavior. added: v20.0.0 --> -* {Object} +* Type: {Object} This API is available through the [`--permission`][] flag. @@ -3198,7 +3198,7 @@ process.permission.has('fs.read'); added: v0.1.15 --> -* {integer} +* Type: {integer} The `process.pid` property returns the PID of the process. @@ -3220,7 +3220,7 @@ console.log(`This process is pid ${pid}`); added: v0.1.16 --> -* {string} +* Type: {string} The `process.platform` property returns a string identifying the operating system platform for which the Node.js binary was compiled. @@ -3260,7 +3260,7 @@ added: - v6.13.0 --> -* {integer} +* Type: {integer} The `process.ppid` property returns the PID of the parent of the current process. @@ -3306,7 +3306,7 @@ changes: description: The `lts` property is now supported. --> -* {Object} +* Type: {Object} The `process.release` property returns an `Object` containing metadata related to the current release, including URLs for the source tarball and headers-only @@ -3362,7 +3362,7 @@ changes: description: This API is no longer experimental. --> -* {Object} +* Type: {Object} `process.report` is an object whose methods are used to generate diagnostic reports for the current process. Additional documentation is available in the @@ -3376,7 +3376,7 @@ added: - v12.17.0 --> -* {boolean} +* Type: {boolean} Write reports in a compact format, single-line JSON, more easily consumable by log processing systems than the default multi-line format designed for @@ -3406,7 +3406,7 @@ changes: description: This API is no longer experimental. --> -* {string} +* Type: {string} Directory where the report is written. The default value is the empty string, indicating that reports are written to the current working directory of the @@ -3436,7 +3436,7 @@ changes: description: This API is no longer experimental. --> -* {string} +* Type: {string} Filename where the report is written. If set to the empty string, the output filename will be comprised of a timestamp, PID, and sequence number. The default @@ -3514,7 +3514,7 @@ changes: description: This API is no longer experimental. --> -* {boolean} +* Type: {boolean} If `true`, a diagnostic report is generated on fatal errors, such as out of memory errors or failed C++ assertions. @@ -3543,7 +3543,7 @@ changes: description: This API is no longer experimental. --> -* {boolean} +* Type: {boolean} If `true`, a diagnostic report is generated when the process receives the signal specified by `process.report.signal`. @@ -3572,7 +3572,7 @@ changes: description: This API is no longer experimental. --> -* {boolean} +* Type: {boolean} If `true`, a diagnostic report is generated on uncaught exception. @@ -3594,7 +3594,7 @@ console.log(`Report on exception: ${report.reportOnUncaughtException}`); added: v22.13.0 --> -* {boolean} +* Type: {boolean} If `true`, a diagnostic report is generated without the environment variables. @@ -3610,7 +3610,7 @@ changes: description: This API is no longer experimental. --> -* {string} +* Type: {string} The signal used to trigger the creation of a diagnostic report. Defaults to `'SIGUSR2'`. @@ -4082,14 +4082,14 @@ added: > Stability: 1 - Experimental: Use [`module.getSourceMapsSupport()`][] instead. -* {boolean} +* Type: {boolean} The `process.sourceMapsEnabled` property returns whether the [Source Map][] support for stack traces is enabled. ## `process.stderr` -* {Stream} +* Type: {Stream} The `process.stderr` property returns a stream connected to `stderr` (fd `2`). It is a [`net.Socket`][] (which is a [Duplex][] @@ -4101,7 +4101,7 @@ a [Writable][] stream. ### `process.stderr.fd` -* {number} +* Type: {number} This property refers to the value of underlying file descriptor of `process.stderr`. The value is fixed at `2`. In [`Worker`][] threads, @@ -4109,7 +4109,7 @@ this field does not exist. ## `process.stdin` -* {Stream} +* Type: {Stream} The `process.stdin` property returns a stream connected to `stdin` (fd `0`). It is a [`net.Socket`][] (which is a [Duplex][] @@ -4128,7 +4128,7 @@ must call `process.stdin.resume()` to read from it. Note also that calling ### `process.stdin.fd` -* {number} +* Type: {number} This property refers to the value of underlying file descriptor of `process.stdin`. The value is fixed at `0`. In [`Worker`][] threads, @@ -4136,7 +4136,7 @@ this field does not exist. ## `process.stdout` -* {Stream} +* Type: {Stream} The `process.stdout` property returns a stream connected to `stdout` (fd `1`). It is a [`net.Socket`][] (which is a [Duplex][] @@ -4162,7 +4162,7 @@ stdin.pipe(stdout); ### `process.stdout.fd` -* {number} +* Type: {number} This property refers to the value of underlying file descriptor of `process.stdout`. The value is fixed at `1`. In [`Worker`][] threads, @@ -4222,7 +4222,7 @@ See the [TTY][] documentation for more information. added: v0.9.12 --> -* {boolean} +* Type: {boolean} The initial value of `process.throwDeprecation` indicates whether the `--throw-deprecation` flag is set on the current Node.js process. @@ -4253,7 +4253,7 @@ Thrown: added: v0.1.104 --> -* {string} +* Type: {string} The `process.title` property returns the current process title (i.e. returns the current value of `ps`). Assigning a new value to `process.title` modifies @@ -4278,7 +4278,7 @@ Services Manager. added: v0.8.0 --> -* {boolean} +* Type: {boolean} The `process.traceDeprecation` property indicates whether the `--trace-deprecation` flag is set on the current Node.js process. See the @@ -4378,7 +4378,7 @@ seconds. added: v0.1.3 --> -* {string} +* Type: {string} The `process.version` property contains the Node.js version string. @@ -4412,7 +4412,7 @@ changes: description: The `icu` property is now supported. --> -* {Object} +* Type: {Object} The `process.versions` property returns an object listing the version strings of Node.js and its dependencies. `process.versions.modules` indicates the current diff --git a/doc/api/punycode.md b/doc/api/punycode.md index f2e9bc09fbbb00..31d331926b7758 100644 --- a/doc/api/punycode.md +++ b/doc/api/punycode.md @@ -155,7 +155,7 @@ punycode.ucs2.encode([0x1D306]); // '\uD834\uDF06' added: v0.6.1 --> -* {string} +* Type: {string} Returns a string identifying the current [Punycode.js][] version number. diff --git a/doc/api/readline.md b/doc/api/readline.md index 05f9e169219743..cc91846f609a49 100644 --- a/doc/api/readline.md +++ b/doc/api/readline.md @@ -435,7 +435,7 @@ changes: description: Value will always be a string, never undefined. --> -* {string} +* Type: {string} The current input data being processed by node. @@ -471,7 +471,7 @@ process.stdin.on('keypress', (c, k) => { added: v0.1.98 --> -* {number|undefined} +* Type: {number|undefined} The cursor position relative to `rl.line`. diff --git a/doc/api/repl.md b/doc/api/repl.md index fae055a656fad3..ea585f261992e0 100644 --- a/doc/api/repl.md +++ b/doc/api/repl.md @@ -671,7 +671,7 @@ deprecated: v22.16.0 > Stability: 0 - Deprecated. Use [`module.builtinModules`][] instead. -* {string\[]} +* Type: {string\[]} A list of the names of some Node.js modules, e.g., `'http'`. diff --git a/doc/api/sqlite.md b/doc/api/sqlite.md index 61ceab3a22b739..65ca654c70d1b3 100644 --- a/doc/api/sqlite.md +++ b/doc/api/sqlite.md @@ -308,7 +308,7 @@ wrapper around [`sqlite3_create_function_v2()`][]. added: v22.15.0 --> -* {boolean} Whether the database is currently open or not. +* Type: {boolean} Whether the database is currently open or not. ### `database.isTransaction` @@ -316,7 +316,7 @@ added: v22.15.0 added: v22.16.0 --> -* {boolean} Whether the database is currently within a transaction. This method +* Type: {boolean} Whether the database is currently within a transaction. This method is a wrapper around [`sqlite3_get_autocommit()`][]. ### `database.open()` @@ -502,19 +502,19 @@ added: v22.16.0 * Returns: {Array} An array of objects. Each object corresponds to a column in the prepared statement, and contains the following properties: - * `column`: {string|null} The unaliased name of the column in the origin + * `column` {string|null} The unaliased name of the column in the origin table, or `null` if the column is the result of an expression or subquery. This property is the result of [`sqlite3_column_origin_name()`][]. - * `database`: {string|null} The unaliased name of the origin database, or + * `database` {string|null} The unaliased name of the origin database, or `null` if the column is the result of an expression or subquery. This property is the result of [`sqlite3_column_database_name()`][]. - * `name`: {string} The name assigned to the column in the result set of a + * `name` {string} The name assigned to the column in the result set of a `SELECT` statement. This property is the result of [`sqlite3_column_name()`][]. - * `table`: {string|null} The unaliased name of the origin table, or `null` if + * `table` {string|null} The unaliased name of the origin table, or `null` if the column is the result of an expression or subquery. This property is the result of [`sqlite3_column_table_name()`][]. - * `type`: {string|null} The declared data type of the column, or `null` if the + * `type` {string|null} The declared data type of the column, or `null` if the column is the result of an expression or subquery. This property is the result of [`sqlite3_column_decltype()`][]. @@ -527,7 +527,7 @@ prepared statement. added: v22.5.0 --> -* {string} The source SQL expanded to include parameter values. +* Type: {string} The source SQL expanded to include parameter values. The source SQL text of the prepared statement with parameter placeholders replaced by the values that were used during the most recent @@ -596,12 +596,12 @@ changes: * `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or more values to bind to anonymous parameters. * Returns: {Object} - * `changes`: {number|bigint} The number of rows modified, inserted, or deleted + * `changes` {number|bigint} The number of rows modified, inserted, or deleted by the most recently completed `INSERT`, `UPDATE`, or `DELETE` statement. This field is either a number or a `BigInt` depending on the prepared statement's configuration. This property is the result of [`sqlite3_changes64()`][]. - * `lastInsertRowid`: {number|bigint} The most recently inserted rowid. This + * `lastInsertRowid` {number|bigint} The most recently inserted rowid. This field is either a number or a `BigInt` depending on the prepared statement's configuration. This property is the result of [`sqlite3_last_insert_rowid()`][]. @@ -668,7 +668,7 @@ supported at all times. added: v22.5.0 --> -* {string} The source SQL used to create this prepared statement. +* Type: {string} The source SQL used to create this prepared statement. The source SQL text of the prepared statement. This property is a wrapper around [`sqlite3_sql()`][]. @@ -752,7 +752,7 @@ console.log('Backup completed', totalPagesTransferred); added: v22.13.0 --> -* {Object} +* Type: {Object} An object containing commonly used constants for SQLite operations. diff --git a/doc/api/stream.md b/doc/api/stream.md index 7bc15ae9a27cbb..aba2532d3be9af 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -568,7 +568,7 @@ function writeOneMillionTimes(writer, data, encoding, callback) { added: v0.9.4 --> -* {Error} +* Type: {Error} The `'error'` event is emitted if an error occurred while writing or piping data. The listener callback is passed a single `Error` argument when called. @@ -732,7 +732,7 @@ but instead implement [`writable._destroy()`][writable-_destroy]. added: v18.0.0 --> -* {boolean} +* Type: {boolean} Is `true` after `'close'` has been emitted. @@ -742,7 +742,7 @@ Is `true` after `'close'` has been emitted. added: v8.0.0 --> -* {boolean} +* Type: {boolean} Is `true` after [`writable.destroy()`][writable-destroy] has been called. @@ -864,7 +864,7 @@ See also: [`writable.cork()`][]. added: v11.4.0 --> -* {boolean} +* Type: {boolean} Is `true` if it is safe to call [`writable.write()`][stream-write], which means the stream has not been destroyed, errored, or ended. @@ -881,7 +881,7 @@ changes: description: Marking the API stable. --> -* {boolean} +* Type: {boolean} Returns whether the stream was destroyed or errored before emitting `'finish'`. @@ -891,7 +891,7 @@ Returns whether the stream was destroyed or errored before emitting `'finish'`. added: v12.9.0 --> -* {boolean} +* Type: {boolean} Is `true` after [`writable.end()`][] has been called. This property does not indicate whether the data has been flushed, for this use @@ -905,7 +905,7 @@ added: - v12.16.0 --> -* {integer} +* Type: {integer} Number of times [`writable.uncork()`][stream-uncork] needs to be called in order to fully uncork the stream. @@ -917,7 +917,7 @@ added: v18.0.0 --> -* {Error} +* Type: {Error} Returns error if the stream has been destroyed with an error. @@ -927,7 +927,7 @@ Returns error if the stream has been destroyed with an error. added: v12.6.0 --> -* {boolean} +* Type: {boolean} Is set to `true` immediately before the [`'finish'`][] event is emitted. @@ -937,7 +937,7 @@ Is set to `true` immediately before the [`'finish'`][] event is emitted. added: v9.3.0 --> -* {number} +* Type: {number} Return the value of `highWaterMark` passed when creating this `Writable`. @@ -947,7 +947,7 @@ Return the value of `highWaterMark` passed when creating this `Writable`. added: v9.4.0 --> -* {number} +* Type: {number} This property contains the number of bytes (or objects) in the queue ready to be written. The value provides introspection data regarding @@ -961,7 +961,7 @@ added: - v14.17.0 --> -* {boolean} +* Type: {boolean} Is `true` if the stream's buffer has been full and stream will emit `'drain'`. @@ -971,7 +971,7 @@ Is `true` if the stream's buffer has been full and stream will emit `'drain'`. added: v12.3.0 --> -* {boolean} +* Type: {boolean} Getter for the property `objectMode` of a given `Writable` stream. @@ -1279,7 +1279,7 @@ readable.on('end', () => { added: v0.9.4 --> -* {Error} +* Type: {Error} The `'error'` event may be emitted by a `Readable` implementation at any time. Typically, this may occur if the underlying stream is unable to generate data @@ -1408,7 +1408,7 @@ Implementors should not override this method, but instead implement added: v18.0.0 --> -* {boolean} +* Type: {boolean} Is `true` after `'close'` has been emitted. @@ -1418,7 +1418,7 @@ Is `true` after `'close'` has been emitted. added: v8.0.0 --> -* {boolean} +* Type: {boolean} Is `true` after [`readable.destroy()`][readable-destroy] has been called. @@ -1628,7 +1628,7 @@ been emitted will return `null`. No runtime error will be raised. added: v11.4.0 --> -* {boolean} +* Type: {boolean} Is `true` if it is safe to call [`readable.read()`][stream-read], which means the stream has not been destroyed or emitted `'error'` or `'end'`. @@ -1643,7 +1643,7 @@ changes: description: Marking the API stable. --> -* {boolean} +* Type: {boolean} Returns whether the stream was destroyed or errored before emitting `'end'`. @@ -1659,7 +1659,7 @@ changes: description: Marking the API stable. --> -* {boolean} +* Type: {boolean} Returns whether `'data'` has been emitted. @@ -1669,7 +1669,7 @@ Returns whether `'data'` has been emitted. added: v12.7.0 --> -* {null|string} +* Type: {null|string} Getter for the property `encoding` of a given `Readable` stream. The `encoding` property can be set using the [`readable.setEncoding()`][] method. @@ -1680,7 +1680,7 @@ property can be set using the [`readable.setEncoding()`][] method. added: v12.9.0 --> -* {boolean} +* Type: {boolean} Becomes `true` when [`'end'`][] event is emitted. @@ -1691,7 +1691,7 @@ added: v18.0.0 --> -* {Error} +* Type: {Error} Returns error if the stream has been destroyed with an error. @@ -1701,7 +1701,7 @@ Returns error if the stream has been destroyed with an error. added: v9.4.0 --> -* {boolean} +* Type: {boolean} This property reflects the current state of a `Readable` stream as described in the [Three states][] section. @@ -1712,7 +1712,7 @@ in the [Three states][] section. added: v9.3.0 --> -* {number} +* Type: {number} Returns the value of `highWaterMark` passed when creating this `Readable`. @@ -1722,7 +1722,7 @@ Returns the value of `highWaterMark` passed when creating this `Readable`. added: v9.4.0 --> -* {number} +* Type: {number} This property contains the number of bytes (or objects) in the queue ready to be read. The value provides introspection data regarding @@ -1734,7 +1734,7 @@ the status of the `highWaterMark`. added: v12.3.0 --> -* {boolean} +* Type: {boolean} Getter for the property `objectMode` of a given `Readable` stream. @@ -2656,7 +2656,7 @@ Examples of `Duplex` streams include: added: v0.9.4 --> -* {boolean} +* Type: {boolean} If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, diff --git a/doc/api/test.md b/doc/api/test.md index e6b44518823ebb..9a141297473229 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -1287,7 +1287,7 @@ changes: * `forceExit`: {boolean} Configures the test runner to exit the process once all known tests have finished executing even if the event loop would otherwise remain active. **Default:** `false`. - * `globPatterns`: {Array} An array containing the list of glob patterns to + * `globPatterns` {Array} An array containing the list of glob patterns to match test files. This option cannot be used together with `files`. **Default:** matching files from [test runner execution model][]. * `inspectPort` {number|Function} Sets inspector port of test child process. @@ -1300,7 +1300,7 @@ changes: `'process'`, each test file is run in a separate child process. If set to `'none'`, all test files run in the current process. **Default:** `'process'`. - * `only`: {boolean} If truthy, the test context will only run tests that + * `only` {boolean} If truthy, the test context will only run tests that have the `only` option set * `setup` {Function} A function that accepts the `TestsStream` instance and can be used to setup listeners before any tests are run. @@ -1816,7 +1816,7 @@ added: - v18.13.0 --> -* {Array} +* Type: {Array} A getter that returns a copy of the internal array used to track calls to the mock. Each entry in the array is an object with the following properties. diff --git a/doc/api/tls.md b/doc/api/tls.md index bff3e464232084..db0131550e7802 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -1070,7 +1070,7 @@ property is set only when `tlsSocket.authorized === false`. added: v0.11.4 --> -* {boolean} +* Type: {boolean} This property is `true` if the peer certificate was signed by one of the CAs specified when creating the `tls.TLSSocket` instance, otherwise `false`. @@ -1421,7 +1421,7 @@ See the OpenSSL [`SSL_get_version`][] documentation for more information. added: v0.11.4 --> -* {Buffer} +* Type: {Buffer} Returns the TLS session data or `undefined` if no session was negotiated. On the client, the data can be provided to the `session` option of @@ -1452,7 +1452,7 @@ for more information. added: v0.11.4 --> -* {Buffer} +* Type: {Buffer} For a client, returns the TLS session ticket if one is available, or `undefined`. For a server, always returns `undefined`. @@ -1490,7 +1490,7 @@ See [Session Resumption][] for more information. added: v0.11.4 --> -* {string} +* Type: {string} Returns the string representation of the local IP address. @@ -1500,7 +1500,7 @@ Returns the string representation of the local IP address. added: v0.11.4 --> -* {integer} +* Type: {integer} Returns the numeric representation of the local port. @@ -1510,7 +1510,7 @@ Returns the numeric representation of the local port. added: v0.11.4 --> -* {string} +* Type: {string} Returns the string representation of the remote IP address. For example, `'74.125.127.100'` or `'2001:4860:a005::68'`. @@ -1521,7 +1521,7 @@ Returns the string representation of the remote IP address. For example, added: v0.11.4 --> -* {string} +* Type: {string} Returns the string representation of the remote IP family. `'IPv4'` or `'IPv6'`. @@ -1531,7 +1531,7 @@ Returns the string representation of the remote IP family. `'IPv4'` or `'IPv6'`. added: v0.11.4 --> -* {integer} +* Type: {integer} Returns the numeric representation of the remote port. For example, `443`. @@ -2399,7 +2399,7 @@ console.log(tls.getCiphers()); // ['aes128-gcm-sha256', 'aes128-sha', ...] added: v12.3.0 --> -* {string\[]} +* Type: {string\[]} An immutable array of strings representing the root certificates (in PEM format) from the bundled Mozilla CA store as supplied by the current Node.js version. @@ -2432,7 +2432,7 @@ information. added: v11.4.0 --> -* {string} The default value of the `maxVersion` option of +* Type: {string} The default value of the `maxVersion` option of [`tls.createSecureContext()`][]. It can be assigned any of the supported TLS protocol versions, `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. **Default:** `'TLSv1.3'`, unless changed using CLI options. Using @@ -2446,7 +2446,7 @@ added: v11.4.0 added: v11.4.0 --> -* {string} The default value of the `minVersion` option of +* Type: {string} The default value of the `minVersion` option of [`tls.createSecureContext()`][]. It can be assigned any of the supported TLS protocol versions, `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Versions before TLSv1.2 may require downgrading the [OpenSSL Security Level][]. @@ -2464,7 +2464,7 @@ added: - v18.16.0 --> -* {string} The default value of the `ciphers` option of +* Type: {string} The default value of the `ciphers` option of [`tls.createSecureContext()`][]. It can be assigned any of the supported OpenSSL ciphers. Defaults to the content of `crypto.constants.defaultCoreCipherList`, unless changed using CLI options diff --git a/doc/api/tracing.md b/doc/api/tracing.md index 1b18243a5ad1d3..61c29dd1763393 100644 --- a/doc/api/tracing.md +++ b/doc/api/tracing.md @@ -147,7 +147,7 @@ set of enabled trace event categories. added: v10.0.0 --> -* {string} +* Type: {string} A comma-separated list of the trace event categories covered by this `Tracing` object. @@ -210,7 +210,7 @@ Enables this `Tracing` object for the set of categories covered by the added: v10.0.0 --> -* {boolean} `true` only if the `Tracing` object has been enabled. +* Type: {boolean} `true` only if the `Tracing` object has been enabled. ### `trace_events.createTracing(options)` diff --git a/doc/api/tty.md b/doc/api/tty.md index 1139355ed0f280..a7c4c3a48d8707 100644 --- a/doc/api/tty.md +++ b/doc/api/tty.md @@ -110,7 +110,7 @@ changes: * `fd` {number} A file descriptor associated with a TTY. * `options` {Object} Options passed to parent `net.Socket`, see `options` of [`net.Socket` constructor][]. -* Returns {tty.ReadStream} +* Returns: {tty.ReadStream} Creates a `ReadStream` for `fd` associated with a TTY. @@ -121,7 +121,7 @@ added: v0.5.8 --> * `fd` {number} A file descriptor associated with a TTY. -* Returns {tty.WriteStream} +* Returns: {tty.WriteStream} Creates a `WriteStream` for `fd` associated with a TTY. diff --git a/doc/api/url.md b/doc/api/url.md index 9d39e3cb9e26d2..205ae77ba0f175 100644 --- a/doc/api/url.md +++ b/doc/api/url.md @@ -207,7 +207,7 @@ myURL = new URL('foo:Example.com/', 'https://example.org/'); #### `url.hash` -* {string} +* Type: {string} Gets and sets the fragment portion of the URL. @@ -228,7 +228,7 @@ percent-encode may vary somewhat from what the [`url.parse()`][] and #### `url.host` -* {string} +* Type: {string} Gets and sets the host portion of the URL. @@ -246,7 +246,7 @@ Invalid host values assigned to the `host` property are ignored. #### `url.hostname` -* {string} +* Type: {string} Gets and sets the host name portion of the URL. The key difference between `url.host` and `url.hostname` is that `url.hostname` does _not_ include the @@ -272,7 +272,7 @@ Invalid host name values assigned to the `hostname` property are ignored. #### `url.href` -* {string} +* Type: {string} Gets and sets the serialized URL. @@ -306,7 +306,7 @@ changes: returns `'null'` for it. --> -* {string} +* Type: {string} Gets the read-only serialization of the URL's origin. @@ -327,7 +327,7 @@ console.log(idnURL.hostname); #### `url.password` -* {string} +* Type: {string} Gets and sets the password portion of the URL. @@ -348,7 +348,7 @@ percent-encode may vary somewhat from what the [`url.parse()`][] and #### `url.pathname` -* {string} +* Type: {string} Gets and sets the path portion of the URL. @@ -376,7 +376,7 @@ changes: description: The scheme "gopher" is no longer special. --> -* {string} +* Type: {string} Gets and sets the port portion of the URL. @@ -459,7 +459,7 @@ console.log(myURL.port); #### `url.protocol` -* {string} +* Type: {string} Gets and sets the protocol portion of the URL. @@ -524,7 +524,7 @@ According to the WHATWG URL Standard, special protocol schemes are `ftp`, #### `url.search` -* {string} +* Type: {string} Gets and sets the serialized query portion of the URL. @@ -545,7 +545,7 @@ and [`url.format()`][] methods would produce. #### `url.searchParams` -* {URLSearchParams} +* Type: {URLSearchParams} Gets the [`URLSearchParams`][] object representing the query parameters of the URL. This property is read-only but the `URLSearchParams` object it provides @@ -572,7 +572,7 @@ console.log(myURL.search); // prints ?foo=%7Ebar #### `url.username` -* {string} +* Type: {string} Gets and sets the username portion of the URL. diff --git a/doc/api/util.md b/doc/api/util.md index 14bbad3250d727..0258377f03fcc9 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -185,7 +185,7 @@ let log = debuglog('internals', (debug) => { added: v14.9.0 --> -* {boolean} +* Type: {boolean} The `util.debuglog().enabled` getter is used to create a test that can be used in conditionals based on the existence of the `NODE_DEBUG` environment variable. @@ -1466,7 +1466,7 @@ changes: description: This is now defined as a shared symbol. --> -* {symbol} that can be used to declare custom inspect functions. +* Type: {symbol} that can be used to declare custom inspect functions. In addition to being accessible through `util.inspect.custom`, this symbol is [registered globally][global symbol registry] and can be @@ -1607,7 +1607,7 @@ console.log(String(myMIME)); ### `mime.type` -* {string} +* Type: {string} Gets and sets the type portion of the MIME. @@ -1639,7 +1639,7 @@ console.log(String(myMIME)); ### `mime.subtype` -* {string} +* Type: {string} Gets and sets the subtype portion of the MIME. @@ -1671,7 +1671,7 @@ console.log(String(myMIME)); ### `mime.essence` -* {string} +* Type: {string} Gets the essence of the MIME. This property is read only. Use `mime.type` or `mime.subtype` to alter the MIME. @@ -1704,7 +1704,7 @@ console.log(String(myMIME)); ### `mime.params` -* {MIMEParams} +* Type: {MIMEParams} Gets the [`MIMEParams`][] object representing the parameters of the MIME. This property is read-only. See @@ -2353,7 +2353,7 @@ changes: description: This is now defined as a shared symbol. --> -* {symbol} that can be used to declare custom promisified variants of functions, +* Type: {symbol} that can be used to declare custom promisified variants of functions, see [Custom promisified functions][]. In addition to being accessible through `util.promisify.custom`, this @@ -2596,20 +2596,20 @@ If `textDecoder.fatal` is `true`, decoding errors that occur will result in a ### `textDecoder.encoding` -* {string} +* Type: {string} The encoding supported by the `TextDecoder` instance. ### `textDecoder.fatal` -* {boolean} +* Type: {boolean} The value will be `true` if decoding errors result in a `TypeError` being thrown. ### `textDecoder.ignoreBOM` -* {boolean} +* Type: {boolean} The value will be `true` if the decoding result will include the byte order mark. @@ -2666,7 +2666,7 @@ const { read, written } = encoder.encodeInto(src, dest); ### `textEncoder.encoding` -* {string} +* Type: {string} The encoding supported by the `TextEncoder` instance. Always set to `'utf-8'`. diff --git a/doc/api/vm.md b/doc/api/vm.md index 958e17f299e481..309f24fabdce32 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -120,7 +120,7 @@ any global object; rather, it is bound before each run, just for that run. added: v5.7.0 --> -* {boolean|undefined} +* Type: {boolean|undefined} When `cachedData` is supplied to create the `vm.Script`, this value will be set to either `true` or `false` depending on acceptance of the data by V8. @@ -369,7 +369,7 @@ added: - v18.13.0 --> -* {string|undefined} +* Type: {string|undefined} When the script is compiled from a source that contains a source map magic comment, this property will be set to the URL of the source map. @@ -585,7 +585,7 @@ the ECMAScript specification. ### `module.error` -* {any} +* Type: {any} If the `module.status` is `'errored'`, this property contains the exception thrown by the module during evaluation. If the status is anything else, @@ -626,7 +626,7 @@ Record][]s in the ECMAScript specification. ### `module.identifier` -* {string} +* Type: {string} The identifier of the current module, as set in the constructor. @@ -701,7 +701,7 @@ Record][]s in the ECMAScript specification. ### `module.namespace` -* {Object} +* Type: {Object} The namespace object of the module. This is only available after linking (`module.link()`) has completed. @@ -711,7 +711,7 @@ specification. ### `module.status` -* {string} +* Type: {string} The current status of the module. Will be one of: @@ -1063,7 +1063,7 @@ added: - v20.12.0 --> -* {Object} +* Type: {Object} Returns an object containing commonly used constants for VM operations. diff --git a/doc/api/wasi.md b/doc/api/wasi.md index 9b67d9a942b60a..21d0febcb1e1b7 100644 --- a/doc/api/wasi.md +++ b/doc/api/wasi.md @@ -251,7 +251,7 @@ added: - v12.16.0 --> -* {Object} +* Type: {Object} `wasiImport` is an object that implements the WASI system call API. This object should be passed as the `wasi_snapshot_preview1` import during the instantiation diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index 5afeaaa9c17fd7..305ffce2193e45 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -164,7 +164,7 @@ if (isMainThread) { added: v22.14.0 --> -* {boolean} +* Type: {boolean} Is `true` if this code is running inside of an internal [`Worker`][] thread (e.g the loader thread). @@ -206,7 +206,7 @@ console.log(isInternalThread); // false added: v10.5.0 --> -* {boolean} +* Type: {boolean} Is `true` if this code is not running inside of a [`Worker`][] thread. @@ -427,7 +427,7 @@ events using it. added: v10.5.0 --> -* {null|MessagePort} +* Type: {null|MessagePort} If this thread is a [`Worker`][], this is a [`MessagePort`][] allowing communication with the parent thread. Messages sent using @@ -636,7 +636,7 @@ added: - v12.16.0 --> -* {Object} +* Type: {Object} * `maxYoungGenerationSizeMb` {number} * `maxOldGenerationSizeMb` {number} * `codeRangeSizeMb` {number} @@ -654,7 +654,7 @@ If this is used in the main thread, its value is an empty object. added: v11.14.0 --> -* {symbol} +* Type: {symbol} A special value that can be passed as the `env` option of the [`Worker`][] constructor, to indicate that the current thread and the Worker thread should @@ -709,7 +709,7 @@ instances spawned from the current context. added: v10.5.0 --> -* {integer} +* Type: {integer} An integer identifier for the current thread. On the corresponding worker object (if there is any), it is available as [`worker.threadId`][]. @@ -1755,7 +1755,7 @@ added: - v12.16.0 --> -* {Object} +* Type: {Object} * `maxYoungGenerationSizeMb` {number} * `maxOldGenerationSizeMb` {number} * `codeRangeSizeMb` {number} @@ -1773,7 +1773,7 @@ If the worker has stopped, the return value is an empty object. added: v10.5.0 --> -* {stream.Readable} +* Type: {stream.Readable} This is a readable stream which contains data written to [`process.stderr`][] inside the worker thread. If `stderr: true` was not passed to the @@ -1786,7 +1786,7 @@ inside the worker thread. If `stderr: true` was not passed to the added: v10.5.0 --> -* {null|stream.Writable} +* Type: {null|stream.Writable} If `stdin: true` was passed to the [`Worker`][] constructor, this is a writable stream. The data written to this stream will be made available in @@ -1798,7 +1798,7 @@ the worker thread as [`process.stdin`][]. added: v10.5.0 --> -* {stream.Readable} +* Type: {stream.Readable} This is a readable stream which contains data written to [`process.stdout`][] inside the worker thread. If `stdout: true` was not passed to the @@ -1830,7 +1830,7 @@ Returns a Promise for the exit code that is fulfilled when the added: v10.5.0 --> -* {integer} +* Type: {integer} An integer identifier for the referenced thread. Inside the worker thread, it is available as [`require('node:worker_threads').threadId`][]. diff --git a/doc/api/zlib.md b/doc/api/zlib.md index 1a94a08fa97b77..25b125959a592d 100644 --- a/doc/api/zlib.md +++ b/doc/api/zlib.md @@ -1004,7 +1004,7 @@ expose values under these names. added: v10.0.0 --> -* {number} +* Type: {number} The `zlib.bytesWritten` property specifies the number of bytes written to the engine, before the bytes are processed (compressed or decompressed, From 0b5613f9fe38fd0f500d0bd147fa7d442189c7e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 00:40:46 +0000 Subject: [PATCH 016/134] doc: run license-builder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/59056 Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell Reviewed-By: Filip Skokan Reviewed-By: Darshan Sen Reviewed-By: Moshe Atlow Reviewed-By: Rafael Gonzaga Reviewed-By: Luigi Pinca Reviewed-By: Tobias Nießen Reviewed-By: Ulises Gascón --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index ac9e2ef9b13f5d..a003c6e1a27301 100644 --- a/LICENSE +++ b/LICENSE @@ -2100,7 +2100,7 @@ The externally maintained libraries used by Node.js are: - inspector_protocol, located at deps/inspector_protocol, is licensed as follows: """ - // Copyright 2016 The Chromium Authors. All rights reserved. + // Copyright 2016 The Chromium Authors. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are From 7d747aeac8994542666a92e783cc483f46304980 Mon Sep 17 00:00:00 2001 From: Haram Jeong <91401364+haramj@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:44:22 +0900 Subject: [PATCH 017/134] doc: clarify ERR_FS_FILE_TOO_LARGE to reflect fs.readFile() I/O limit PR-URL: https://github.com/nodejs/node/pull/59050 Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: LiviaMedeiros --- doc/api/errors.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index c909156d1c8e9a..952394745140c1 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1368,8 +1368,10 @@ Path is a directory. ### `ERR_FS_FILE_TOO_LARGE` -An attempt has been made to read a file whose size is larger than the maximum -allowed size for a `Buffer`. +An attempt was made to read a file larger than the supported 2 GiB limit for +`fs.readFile()`. This is not a limitation of `Buffer`, but an internal I/O constraint. +For handling larger files, consider using `fs.createReadStream()` to read the +file in chunks. From d0f40f3a3ac78c423757f84adf9f03d48481d3f2 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 16 Jul 2025 10:57:22 +0200 Subject: [PATCH 018/134] tools,test: enforce best practices to detect never settling promises PR-URL: https://github.com/nodejs/node/pull/58992 Reviewed-By: Luigi Pinca --- test/es-module/test-require-module-tla-retry-import-2.js | 2 +- test/es-module/test-require-module-tla-retry-import.js | 2 +- test/es-module/test-vm-main-context-default-loader-eval.js | 2 +- test/es-module/test-vm-main-context-default-loader.js | 2 +- test/eslint.config_partial.mjs | 4 ++++ test/module-hooks/test-module-hooks-load-esm-mock.js | 2 +- test/module-hooks/test-module-hooks-load-esm.js | 2 +- test/parallel/test-crypto-async-sign-verify.js | 4 ++-- test/parallel/test-fs-open.js | 2 +- test/parallel/test-stream-readable-async-iterators.js | 2 +- test/parallel/test-vm-context-dont-contextify.js | 2 +- 11 files changed, 15 insertions(+), 11 deletions(-) diff --git a/test/es-module/test-require-module-tla-retry-import-2.js b/test/es-module/test-require-module-tla-retry-import-2.js index aa9c344dd398d7..2ca8e07449c2fa 100644 --- a/test/es-module/test-require-module-tla-retry-import-2.js +++ b/test/es-module/test-require-module-tla-retry-import-2.js @@ -23,4 +23,4 @@ async function test() { } // Run the test twice to check consistency after caching. -test().then(common.mustCall(test)).catch(common.mustNotCall()); +test().then(common.mustCall(test)); diff --git a/test/es-module/test-require-module-tla-retry-import.js b/test/es-module/test-require-module-tla-retry-import.js index 70f918fa4f463f..80b289fdfc8c43 100644 --- a/test/es-module/test-require-module-tla-retry-import.js +++ b/test/es-module/test-require-module-tla-retry-import.js @@ -22,4 +22,4 @@ async function test() { } // Run the test twice to check consistency after caching. -test().then(common.mustCall(test)).catch(common.mustNotCall()); +test().then(common.mustCall(test)); diff --git a/test/es-module/test-vm-main-context-default-loader-eval.js b/test/es-module/test-vm-main-context-default-loader-eval.js index 3226c3512f4887..7bde86ba551b6c 100644 --- a/test/es-module/test-vm-main-context-default-loader-eval.js +++ b/test/es-module/test-vm-main-context-default-loader-eval.js @@ -70,4 +70,4 @@ async function main() { } } -main().catch(common.mustNotCall()); +main().then(common.mustCall()); diff --git a/test/es-module/test-vm-main-context-default-loader.js b/test/es-module/test-vm-main-context-default-loader.js index 9e45bbd9a12a4e..d2ac6021df3837 100644 --- a/test/es-module/test-vm-main-context-default-loader.js +++ b/test/es-module/test-vm-main-context-default-loader.js @@ -116,4 +116,4 @@ async function main() { } } -main().catch(common.mustNotCall()); +main().then(common.mustCall()); diff --git a/test/eslint.config_partial.mjs b/test/eslint.config_partial.mjs index b91112deee704f..fdbab827359620 100644 --- a/test/eslint.config_partial.mjs +++ b/test/eslint.config_partial.mjs @@ -91,6 +91,10 @@ export default [ selector: "ExpressionStatement>CallExpression:matches([callee.name='rejects'], [callee.object.name='assert'][callee.property.name='rejects'])", message: 'Calling `assert.rejects` without `await` or `.then(common.mustCall())` will not detect never-settling promises.', }, + { + selector: 'CallExpression[callee.property.name="catch"]>:first-child:matches(CallExpression[callee.object.name="common"][callee.property.name="mustNotCall"], CallExpression[callee.name="mustNotCall"])', + message: 'Calling `.catch(common.mustNotCall())` will not detect never-settling promises. Use `.then(common.mustCall())` instead.', + }, ], // Stylistic rules. diff --git a/test/module-hooks/test-module-hooks-load-esm-mock.js b/test/module-hooks/test-module-hooks-load-esm-mock.js index 88941b5d685f07..26bb01385014f7 100644 --- a/test/module-hooks/test-module-hooks-load-esm-mock.js +++ b/test/module-hooks/test-module-hooks-load-esm-mock.js @@ -48,4 +48,4 @@ function hook(code, filename) { assert.deepStrictEqual({ ...bar }, { $key: 'bar-esm' }); } -})().catch(common.mustNotCall()); +})().then(common.mustCall()); diff --git a/test/module-hooks/test-module-hooks-load-esm.js b/test/module-hooks/test-module-hooks-load-esm.js index 88941b5d685f07..26bb01385014f7 100644 --- a/test/module-hooks/test-module-hooks-load-esm.js +++ b/test/module-hooks/test-module-hooks-load-esm.js @@ -48,4 +48,4 @@ function hook(code, filename) { assert.deepStrictEqual({ ...bar }, { $key: 'bar-esm' }); } -})().catch(common.mustNotCall()); +})().then(common.mustCall()); diff --git a/test/parallel/test-crypto-async-sign-verify.js b/test/parallel/test-crypto-async-sign-verify.js index b35dd08e6c4979..7a5e72b1e8e498 100644 --- a/test/parallel/test-crypto-async-sign-verify.js +++ b/test/parallel/test-crypto-async-sign-verify.js @@ -138,9 +138,9 @@ test('dsa_public.pem', 'dsa_private.pem', 'sha256', false, verify('sha256', data, publicKey, signature), verify('sha256', data, publicKey, signature), verify('sha256', data, publicKey, signature), - ]).then(common.mustCall()); + ]); }) - .catch(common.mustNotCall()); + .then(common.mustCall()); } { diff --git a/test/parallel/test-fs-open.js b/test/parallel/test-fs-open.js index 56157b0183de63..2d9243955e662d 100644 --- a/test/parallel/test-fs-open.js +++ b/test/parallel/test-fs-open.js @@ -53,7 +53,7 @@ async function promise() { await (await fs.promises.open(__filename, 'r')).close(); } -promise().then(common.mustCall()).catch(common.mustNotCall()); +promise().then(common.mustCall()); assert.throws( () => fs.open(__filename, 'r', 'boom', common.mustNotCall()), diff --git a/test/parallel/test-stream-readable-async-iterators.js b/test/parallel/test-stream-readable-async-iterators.js index 28975de405133f..beece038772a34 100644 --- a/test/parallel/test-stream-readable-async-iterators.js +++ b/test/parallel/test-stream-readable-async-iterators.js @@ -690,7 +690,7 @@ async function tests() { const it = r[Symbol.asyncIterator](); const p = it.return(); r.emit('close'); - p.then(common.mustCall()).catch(common.mustNotCall()); + p.then(common.mustCall()); } { diff --git a/test/parallel/test-vm-context-dont-contextify.js b/test/parallel/test-vm-context-dont-contextify.js index d75fc1438d364a..ae9fb676067999 100644 --- a/test/parallel/test-vm-context-dont-contextify.js +++ b/test/parallel/test-vm-context-dont-contextify.js @@ -182,4 +182,4 @@ function checkFrozen(context) { const promise = script.runInContext(context); assert.strictEqual(await promise, namespace); } -})().catch(common.mustNotCall()); +})().then(common.mustCall()); From 0b93ca3d198497c1ac2463da25426d022a2f7c6c Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Wed, 16 Jul 2025 06:16:52 -0300 Subject: [PATCH 019/134] doc: add RafaelGSS as steward July 25 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/59078 Reviewed-By: Richard Lau Reviewed-By: Marco Ippolito Reviewed-By: Chengzhong Wu Reviewed-By: Ulises Gascón --- doc/contributing/security-release-process.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/contributing/security-release-process.md b/doc/contributing/security-release-process.md index 6c2f8a3a6e2400..676d8fd408909a 100644 --- a/doc/contributing/security-release-process.md +++ b/doc/contributing/security-release-process.md @@ -37,6 +37,7 @@ The current security stewards are documented in the main Node.js | NodeSource | Rafael | 2024-Jul-08 | | NodeSource | Rafael | 2025-Jan-21 | | NodeSource | Rafael | 2025-May-14 | +| NodeSource | Rafael | 2025-July-15 | | Datadog | Bryan | | | IBM | Joe | | | Platformatic | Matteo | | From 0f0ce631169ee828b7e046c5704993062a49cb0b Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Thu, 17 Jul 2025 19:50:49 -0300 Subject: [PATCH 020/134] build: remove suppressions.supp We have removed the UBSan workflow and there's no ongoing initiative to bring it back. PR-URL: https://github.com/nodejs/node/pull/59079 Reviewed-By: Richard Lau Reviewed-By: Marco Ippolito Reviewed-By: Luigi Pinca --- suppressions.supp | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 suppressions.supp diff --git a/suppressions.supp b/suppressions.supp deleted file mode 100644 index 9dc89fb83df5b4..00000000000000 --- a/suppressions.supp +++ /dev/null @@ -1,6 +0,0 @@ -vptr:deps/icu-small/source/common/uloc_tag.cpp -vptr:deps/icu-small/source/common/unistr.cpp -shift-base:deps/v8/src/wasm/decoder.h -vptr:deps/icu-small/source/common/sharedobject.cpp -vptr:deps/icu-small/source/i18n/coll.cpp -nonnull-attribute:deps/v8/src/snapshot/snapshot-source-sink.h From 4a12f5d83b0f0caef854f374a85e0fb67682e573 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 18 Jul 2025 01:46:25 +0200 Subject: [PATCH 021/134] test: mark test-inspector-network-fetch as flaky on Windows PR-URL: https://github.com/nodejs/node/pull/59091 Refs: https://github.com/nodejs/node/issues/59090 Reviewed-By: Chengzhong Wu Reviewed-By: Ryuhei Shima Reviewed-By: Filip Skokan --- test/parallel/parallel.status | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 6303908ce180db..32afd621533fdc 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -32,6 +32,8 @@ test-async-context-frame: PASS, FLAKY test-runner-run-watch: PASS, FLAKY # https://github.com/nodejs/node/issues/56794 test-fs-cp: PASS, FLAKY +# https://github.com/nodejs/node/issues/59090 +test-inspector-network-fetch: PASS, FLAKY # https://github.com/nodejs/node/issues/56751 test-without-async-context-frame: PASS, FLAKY From ff6be2ed5d2efed412429b164e2f7a74aed42435 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Fri, 18 Jul 2025 13:45:52 +0100 Subject: [PATCH 022/134] node-api,doc: update links to ecma262 with section names Section numbers can change over time. Use the section names as the link text for better readability. Also, use https://tc39.es/ecma262/ as the unified host of living version of ECMA-262. PR-URL: https://github.com/nodejs/node/pull/59087 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Vladimir Morozov --- doc/api/n-api.md | 149 +++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 76 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 211bd73ed4cf1e..d16ff2ec29d498 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -446,7 +446,7 @@ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) { ## Environment life cycle APIs -[Section 8.7][] of the [ECMAScript Language Specification][] defines the concept +[Section Agents][] of the [ECMAScript Language Specification][] defines the concept of an "Agent" as a self-contained environment in which JavaScript code runs. Multiple such Agents may be started and terminated either concurrently or in sequence by the process. @@ -2139,7 +2139,7 @@ API. ## Working with JavaScript values Node-API exposes a set of APIs to create all types of JavaScript values. -Some of these types are documented under [Section 6][] +Some of these types are documented under [Section language types][] of the [ECMAScript Language Specification][]. Fundamentally, these APIs are used to do one of the following: @@ -2245,7 +2245,7 @@ typedef enum { ``` Describes the type of a `napi_value`. This generally corresponds to the types -described in [Section 6.1][] of the ECMAScript Language Specification. +described in [Section language types][] of the ECMAScript Language Specification. In addition to types in that section, `napi_valuetype` can also represent `Function`s and `Object`s with external data. @@ -2272,7 +2272,7 @@ typedef enum { This represents the underlying binary scalar datatype of the `TypedArray`. Elements of this enum correspond to -[Section 22.2][] of the [ECMAScript Language Specification][]. +[Section TypedArray objects][] of the [ECMAScript Language Specification][]. ### Object creation functions @@ -2294,7 +2294,7 @@ Returns `napi_ok` if the API succeeded. This API returns a Node-API value corresponding to a JavaScript `Array` type. JavaScript arrays are described in -[Section 22.1][] of the ECMAScript Language Specification. +[Section Array objects][] of the ECMAScript Language Specification. #### `napi_create_array_with_length` @@ -2324,7 +2324,7 @@ directly read and/or written via C, consider using [`napi_create_external_arraybuffer`][]. JavaScript arrays are described in -[Section 22.1][] of the ECMAScript Language Specification. +[Section Array objects][] of the ECMAScript Language Specification. #### `napi_create_arraybuffer` @@ -2359,7 +2359,7 @@ written to directly from native code. To write to this buffer from JavaScript, a typed array or `DataView` object would need to be created. JavaScript `ArrayBuffer` objects are described in -[Section 24.1][] of the ECMAScript Language Specification. +[Section ArrayBuffer objects][] of the ECMAScript Language Specification. #### `napi_create_buffer` @@ -2442,7 +2442,7 @@ ECMAScript aligns with POSIX time specification. This API allocates a JavaScript `Date` object. JavaScript `Date` objects are described in -[Section 20.3][] of the ECMAScript Language Specification. +[Section Date objects][] of the ECMAScript Language Specification. #### `napi_create_external` @@ -2531,7 +2531,7 @@ The API adds a `napi_finalize` callback which will be called when the JavaScript object just created has been garbage collected. JavaScript `ArrayBuffer`s are described in -[Section 24.1][] of the ECMAScript Language Specification. +[Section ArrayBuffer objects][] of the ECMAScript Language Specification. #### `napi_create_external_buffer` @@ -2602,7 +2602,7 @@ Returns `napi_ok` if the API succeeded. This API allocates a default JavaScript `Object`. It is the equivalent of doing `new Object()` in JavaScript. -The JavaScript `Object` type is described in [Section 6.1.7][] of the +The JavaScript `Object` type is described in [Section object type][] of the ECMAScript Language Specification. #### `napi_create_symbol` @@ -2627,7 +2627,7 @@ Returns `napi_ok` if the API succeeded. This API creates a JavaScript `symbol` value from a UTF8-encoded C string. -The JavaScript `symbol` type is described in [Section 19.4][] +The JavaScript `symbol` type is described in [Section symbol type][] of the ECMAScript Language Specification. #### `node_api_symbol_for` @@ -2659,7 +2659,7 @@ This API searches in the global registry for an existing symbol with the given description. If the symbol already exists it will be returned, otherwise a new symbol will be created in the registry. -The JavaScript `symbol` type is described in [Section 19.4][] of the ECMAScript +The JavaScript `symbol` type is described in [Section symbol type][] of the ECMAScript Language Specification. #### `napi_create_typedarray` @@ -2698,7 +2698,7 @@ be <= the size in bytes of the array passed in. If not, a `RangeError` exception is raised. JavaScript `TypedArray` objects are described in -[Section 22.2][] of the ECMAScript Language Specification. +[Section TypedArray objects][] of the ECMAScript Language Specification. #### `node_api_create_buffer_from_arraybuffer` @@ -2763,7 +2763,7 @@ size in bytes of the array passed in. If not, a `RangeError` exception is raised. JavaScript `DataView` objects are described in -[Section 24.3][] of the ECMAScript Language Specification. +[Section DataView objects][] of the ECMAScript Language Specification. ### Functions to convert from C types to Node-API @@ -2788,7 +2788,7 @@ This API is used to convert from the C `int32_t` type to the JavaScript `number` type. The JavaScript `number` type is described in -[Section 6.1.6][] of the ECMAScript Language Specification. +[Section number type][] of the ECMAScript Language Specification. #### `napi_create_uint32` @@ -2811,7 +2811,7 @@ This API is used to convert from the C `uint32_t` type to the JavaScript `number` type. The JavaScript `number` type is described in -[Section 6.1.6][] of the ECMAScript Language Specification. +[Section number type][] of the ECMAScript Language Specification. #### `napi_create_int64` @@ -2833,7 +2833,7 @@ Returns `napi_ok` if the API succeeded. This API is used to convert from the C `int64_t` type to the JavaScript `number` type. -The JavaScript `number` type is described in [Section 6.1.6][] +The JavaScript `number` type is described in [Section number type][] of the ECMAScript Language Specification. Note the complete range of `int64_t` cannot be represented with full precision in JavaScript. Integer values outside the range of [`Number.MIN_SAFE_INTEGER`][] `-(2**53 - 1)` - @@ -2860,7 +2860,7 @@ This API is used to convert from the C `double` type to the JavaScript `number` type. The JavaScript `number` type is described in -[Section 6.1.6][] of the ECMAScript Language Specification. +[Section number type][] of the ECMAScript Language Specification. #### `napi_create_bigint_int64` @@ -2960,7 +2960,7 @@ This API creates a JavaScript `string` value from an ISO-8859-1-encoded C string. The native string is copied. The JavaScript `string` type is described in -[Section 6.1.4][] of the ECMAScript Language Specification. +[Section string type][] of the ECMAScript Language Specification. #### `node_api_create_external_string_latin1` @@ -3011,7 +3011,7 @@ string. The native string may not be copied and must thus exist for the entire life cycle of the JavaScript value. The JavaScript `string` type is described in -[Section 6.1.4][] of the ECMAScript Language Specification. +[Section string type][] of the ECMAScript Language Specification. #### `napi_create_string_utf16` @@ -3039,7 +3039,7 @@ This API creates a JavaScript `string` value from a UTF16-LE-encoded C string. The native string is copied. The JavaScript `string` type is described in -[Section 6.1.4][] of the ECMAScript Language Specification. +[Section string type][] of the ECMAScript Language Specification. #### `node_api_create_external_string_utf16` @@ -3090,7 +3090,7 @@ The native string may not be copied and must thus exist for the entire life cycle of the JavaScript value. The JavaScript `string` type is described in -[Section 6.1.4][] of the ECMAScript Language Specification. +[Section string type][] of the ECMAScript Language Specification. #### `napi_create_string_utf8` @@ -3118,7 +3118,7 @@ This API creates a JavaScript `string` value from a UTF8-encoded C string. The native string is copied. The JavaScript `string` type is described in -[Section 6.1.4][] of the ECMAScript Language Specification. +[Section string type][] of the ECMAScript Language Specification. ### Functions to create optimized property keys @@ -3165,7 +3165,7 @@ subsequent calls to this function with the same `str` pointer may benefit from a in the creation of the requested `napi_value`, depending on the engine. The JavaScript `string` type is described in -[Section 6.1.4][] of the ECMAScript Language Specification. +[Section string type][] of the ECMAScript Language Specification. #### `node_api_create_property_key_utf16` @@ -3197,7 +3197,7 @@ a UTF16-LE-encoded C string to be used as a property key for objects. The native string is copied. The JavaScript `string` type is described in -[Section 6.1.4][] of the ECMAScript Language Specification. +[Section string type][] of the ECMAScript Language Specification. #### `node_api_create_property_key_utf8` @@ -3227,7 +3227,7 @@ a UTF8-encoded C string to be used as a property key for objects. The native string is copied. The JavaScript `string` type is described in -[Section 6.1.4][] of the ECMAScript Language Specification. +[Section string type][] of the ECMAScript Language Specification. ### Functions to convert from Node-API to C types @@ -3253,7 +3253,7 @@ Returns `napi_ok` if the API succeeded. This API returns the length of an array. -`Array` length is described in [Section 22.1.4.1][] of the ECMAScript Language +`Array` length is described in [Section Array instance length][] of the ECMAScript Language Specification. #### `napi_get_arraybuffer_info` @@ -3862,8 +3862,7 @@ This API returns the Undefined object. ## Working with JavaScript values and abstract operations Node-API exposes a set of APIs to perform some abstract operations on JavaScript -values. Some of these operations are documented under [Section 7][] -of the [ECMAScript Language Specification][]. +values. These APIs support doing one of the following: @@ -3892,7 +3891,7 @@ napi_status napi_coerce_to_bool(napi_env env, Returns `napi_ok` if the API succeeded. This API implements the abstract operation `ToBoolean()` as defined in -[Section 7.1.2][] of the ECMAScript Language Specification. +[Section ToBoolean][] of the ECMAScript Language Specification. ### `napi_coerce_to_number` @@ -3914,7 +3913,7 @@ napi_status napi_coerce_to_number(napi_env env, Returns `napi_ok` if the API succeeded. This API implements the abstract operation `ToNumber()` as defined in -[Section 7.1.3][] of the ECMAScript Language Specification. +[Section ToNumber][] of the ECMAScript Language Specification. This function potentially runs JS code if the passed-in value is an object. @@ -3938,7 +3937,7 @@ napi_status napi_coerce_to_object(napi_env env, Returns `napi_ok` if the API succeeded. This API implements the abstract operation `ToObject()` as defined in -[Section 7.1.13][] of the ECMAScript Language Specification. +[Section ToObject][] of the ECMAScript Language Specification. ### `napi_coerce_to_string` @@ -3960,7 +3959,7 @@ napi_status napi_coerce_to_string(napi_env env, Returns `napi_ok` if the API succeeded. This API implements the abstract operation `ToString()` as defined in -[Section 7.1.13][] of the ECMAScript Language Specification. +[Section ToString][] of the ECMAScript Language Specification. This function potentially runs JS code if the passed-in value is an object. @@ -3985,7 +3984,7 @@ Returns `napi_ok` if the API succeeded. `value` is not an External value. This API represents behavior similar to invoking the `typeof` Operator on -the object as defined in [Section 12.5.5][] of the ECMAScript Language +the object as defined in [Section typeof operator][] of the ECMAScript Language Specification. However, there are some differences: 1. It has support for detecting an External value. @@ -4018,7 +4017,7 @@ napi_status napi_instanceof(napi_env env, Returns `napi_ok` if the API succeeded. This API represents invoking the `instanceof` Operator on the object as -defined in [Section 12.10.4][] of the ECMAScript Language Specification. +defined in [Section instanceof operator][] of the ECMAScript Language Specification. ### `napi_is_array` @@ -4038,7 +4037,7 @@ napi_status napi_is_array(napi_env env, napi_value value, bool* result) Returns `napi_ok` if the API succeeded. This API represents invoking the `IsArray` operation on the object -as defined in [Section 7.2.2][] of the ECMAScript Language Specification. +as defined in [Section IsArray][] of the ECMAScript Language Specification. ### `napi_is_arraybuffer` @@ -4182,7 +4181,7 @@ napi_status napi_strict_equals(napi_env env, Returns `napi_ok` if the API succeeded. This API represents the invocation of the Strict Equality algorithm as -defined in [Section 7.2.14][] of the ECMAScript Language Specification. +defined in [Section IsStrctEqual][] of the ECMAScript Language Specification. ### `napi_detach_arraybuffer` @@ -4211,7 +4210,7 @@ detachable. For example, V8 requires that the `ArrayBuffer` be external, that is, created with [`napi_create_external_arraybuffer`][]. This API represents the invocation of the `ArrayBuffer` detach operation as -defined in [Section 24.1.1.3][] of the ECMAScript Language Specification. +defined in [Section detachArrayBuffer][] of the ECMAScript Language Specification. ### `napi_is_detached_arraybuffer` @@ -4238,14 +4237,13 @@ Returns `napi_ok` if the API succeeded. The `ArrayBuffer` is considered detached if its internal data is `null`. This API represents the invocation of the `ArrayBuffer` `IsDetachedBuffer` -operation as defined in [Section 24.1.1.2][] of the ECMAScript Language +operation as defined in [Section isDetachedBuffer][] of the ECMAScript Language Specification. ## Working with JavaScript properties Node-API exposes a set of APIs to get and set properties on JavaScript -objects. Some of these types are documented under [Section 7][] of the -[ECMAScript Language Specification][]. +objects. Properties in JavaScript are represented as a tuple of a key and a value. Fundamentally, all property keys in Node-API can be represented in one of the @@ -4415,7 +4413,7 @@ typedef enum { `napi_property_attributes` are flags used to control the behavior of properties set on a JavaScript object. Other than `napi_static` they correspond to the -attributes listed in [Section 6.1.7.1][] +attributes listed in [Section property attributes][] of the [ECMAScript Language Specification][]. They can be one or more of the following bitflags: @@ -4424,7 +4422,7 @@ They can be one or more of the following bitflags: * `napi_writable`: The property is writable. * `napi_enumerable`: The property is enumerable. * `napi_configurable`: The property is configurable as defined in - [Section 6.1.7.1][] of the [ECMAScript Language Specification][]. + [Section property attributes][] of the [ECMAScript Language Specification][]. * `napi_static`: The property will be defined as a static property on a class as opposed to an instance property, which is the default. This is used only by [`napi_define_class`][]. It is ignored by `napi_define_properties`. @@ -4850,7 +4848,7 @@ This method allows the efficient definition of multiple properties on a given object. The properties are defined using property descriptors (see [`napi_property_descriptor`][]). Given an array of such property descriptors, this API will set the properties on the object one at a time, as defined by -`DefineOwnProperty()` (described in [Section 9.1.6][] of the ECMA-262 +`DefineOwnProperty()` (described in [Section DefineOwnProperty][] of the ECMA-262 specification). #### `napi_object_freeze` @@ -5078,7 +5076,7 @@ be associated with the resulting JavaScript function (which is returned in the `result` parameter) and freed whenever the function is garbage-collected by passing both the JavaScript function and the data to [`napi_add_finalizer`][]. -JavaScript `Function`s are described in [Section 19.2][] of the ECMAScript +JavaScript `Function`s are described in [Section Function objects][] of the ECMAScript Language Specification. ### `napi_get_cb_info` @@ -6148,7 +6146,7 @@ increased the external memory. ## Promises Node-API provides facilities for creating `Promise` objects as described in -[Section 25.4][] of the ECMA specification. It implements promises as a pair of +[Section Promise objects][] of the ECMA specification. It implements promises as a pair of objects. When a promise is created by `napi_create_promise()`, a "deferred" object is created and returned alongside the `Promise`. The deferred object is bound to the created `Promise` and is the only means to resolve or reject the @@ -6734,7 +6732,7 @@ the add-on's file name during loading. [C++ Addons]: addons.md [CMake]: https://cmake.org [CMake.js]: https://github.com/cmake-js/cmake-js -[ECMAScript Language Specification]: https://tc39.github.io/ecma262/ +[ECMAScript Language Specification]: https://tc39.es/ecma262/ [Error handling]: #error-handling [GCC]: https://gcc.gnu.org [GYP]: https://gyp.gsrc.io @@ -6744,40 +6742,39 @@ the add-on's file name during loading. [Node-API Media]: https://github.com/nodejs/abi-stable-node/blob/HEAD/node-api-media.md [Object lifetime management]: #object-lifetime-management [Object wrap]: #object-wrap -[Section 12.10.4]: https://tc39.github.io/ecma262/#sec-instanceofoperator -[Section 12.5.5]: https://tc39.github.io/ecma262/#sec-typeof-operator -[Section 19.2]: https://tc39.github.io/ecma262/#sec-function-objects -[Section 19.4]: https://tc39.github.io/ecma262/#sec-symbol-objects -[Section 20.3]: https://tc39.github.io/ecma262/#sec-date-objects -[Section 22.1]: https://tc39.github.io/ecma262/#sec-array-objects -[Section 22.1.4.1]: https://tc39.github.io/ecma262/#sec-properties-of-array-instances-length -[Section 22.2]: https://tc39.github.io/ecma262/#sec-typedarray-objects -[Section 24.1]: https://tc39.github.io/ecma262/#sec-arraybuffer-objects -[Section 24.1.1.2]: https://tc39.es/ecma262/#sec-isdetachedbuffer -[Section 24.1.1.3]: https://tc39.es/ecma262/#sec-detacharraybuffer -[Section 24.3]: https://tc39.github.io/ecma262/#sec-dataview-objects -[Section 25.4]: https://tc39.github.io/ecma262/#sec-promise-objects -[Section 6]: https://tc39.github.io/ecma262/#sec-ecmascript-data-types-and-values -[Section 6.1]: https://tc39.github.io/ecma262/#sec-ecmascript-language-types -[Section 6.1.4]: https://tc39.github.io/ecma262/#sec-ecmascript-language-types-string-type -[Section 6.1.6]: https://tc39.github.io/ecma262/#sec-ecmascript-language-types-number-type -[Section 6.1.7]: https://tc39.github.io/ecma262/#sec-object-type -[Section 6.1.7.1]: https://tc39.github.io/ecma262/#table-2 -[Section 7]: https://tc39.github.io/ecma262/#sec-abstract-operations -[Section 7.1.13]: https://tc39.github.io/ecma262/#sec-toobject -[Section 7.1.2]: https://tc39.github.io/ecma262/#sec-toboolean -[Section 7.1.3]: https://tc39.github.io/ecma262/#sec-tonumber -[Section 7.2.14]: https://tc39.github.io/ecma262/#sec-strict-equality-comparison -[Section 7.2.2]: https://tc39.github.io/ecma262/#sec-isarray -[Section 8.7]: https://tc39.es/ecma262/#sec-agents -[Section 9.1.6]: https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc +[Section Agents]: https://tc39.es/ecma262/#sec-agents +[Section Array instance length]: https://tc39.es/ecma262/#sec-properties-of-array-instances-length +[Section Array objects]: https://tc39.es/ecma262/#sec-array-objects +[Section ArrayBuffer objects]: https://tc39.es/ecma262/#sec-arraybuffer-objects +[Section DataView objects]: https://tc39.es/ecma262/#sec-dataview-objects +[Section Date objects]: https://tc39.es/ecma262/#sec-date-objects +[Section DefineOwnProperty]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc +[Section Function objects]: https://tc39.es/ecma262/#sec-function-objects +[Section IsArray]: https://tc39.es/ecma262/#sec-isarray +[Section IsStrctEqual]: https://tc39.es/ecma262/#sec-strict-equality-comparison +[Section Promise objects]: https://tc39.es/ecma262/#sec-promise-objects +[Section ToBoolean]: https://tc39.es/ecma262/#sec-toboolean +[Section ToNumber]: https://tc39.es/ecma262/#sec-tonumber +[Section ToObject]: https://tc39.es/ecma262/#sec-toobject +[Section ToString]: https://tc39.es/ecma262/#sec-tostring +[Section TypedArray objects]: https://tc39.es/ecma262/#sec-typedarray-objects +[Section detachArrayBuffer]: https://tc39.es/ecma262/#sec-detacharraybuffer +[Section instanceof operator]: https://tc39.es/ecma262/#sec-instanceofoperator +[Section isDetachedBuffer]: https://tc39.es/ecma262/#sec-isdetachedbuffer +[Section language types]: https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values +[Section number type]: https://tc39.es/ecma262/#sec-ecmascript-language-types-number-type +[Section object type]: https://tc39.es/ecma262/#sec-object-type +[Section property attributes]: https://tc39.es/ecma262/#sec-property-attributes +[Section string type]: https://tc39.es/ecma262/#sec-ecmascript-language-types-string-type +[Section symbol type]: https://tc39.es/ecma262/#sec-ecmascript-language-types-symbol-type +[Section typeof operator]: https://tc39.es/ecma262/#sec-typeof-operator [Travis CI]: https://travis-ci.org [Visual Studio]: https://visualstudio.microsoft.com [Working with JavaScript properties]: #working-with-javascript-properties [Xcode]: https://developer.apple.com/xcode/ [`'uncaughtException'`]: process.md#event-uncaughtexception -[`Number.MAX_SAFE_INTEGER`]: https://tc39.github.io/ecma262/#sec-number.max_safe_integer -[`Number.MIN_SAFE_INTEGER`]: https://tc39.github.io/ecma262/#sec-number.min_safe_integer +[`Number.MAX_SAFE_INTEGER`]: https://tc39.es/ecma262/#sec-number.max_safe_integer +[`Number.MIN_SAFE_INTEGER`]: https://tc39.es/ecma262/#sec-number.min_safe_integer [`Worker`]: worker_threads.md#class-worker [`async_hooks.executionAsyncResource()`]: async_hooks.md#async_hooksexecutionasyncresource [`build_with_cmake`]: https://github.com/nodejs/node-addon-examples/tree/main/src/8-tooling/build_with_cmake From cda1dab6e2722159da3999856c01d4f511025c62 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 18 Jul 2025 21:57:53 +0200 Subject: [PATCH 023/134] crypto: add tls.setDefaultCACertificates() This API allows dynamically configuring CA certificates that will be used by the Node.js TLS clients by default. Once called, the provided certificates will become the default CA certificate list returned by `tls.getCACertificates('default')` and used by TLS connections that don't specify their own CA certificates. This function only affects the current Node.js thread. PR-URL: https://github.com/nodejs/node/pull/58822 Reviewed-By: Matteo Collina Reviewed-By: Tim Perry Reviewed-By: Ethan Arrowood --- doc/api/tls.md | 48 +++++ lib/tls.js | 32 +++ src/crypto/crypto_context.cc | 196 ++++++++++++++++-- test/common/tls.js | 32 +++ .../es-modules/custom-condition/load.cjs | 6 + test/fixtures/tls-extra-ca-override.js | 50 +++++ ...t-default-ca-certificates-append-fetch.mjs | 54 +++++ ...lt-ca-certificates-append-https-request.js | 71 +++++++ ...et-default-ca-certificates-array-buffer.js | 39 ++++ ...t-tls-set-default-ca-certificates-basic.js | 58 ++++++ ...t-tls-set-default-ca-certificates-error.js | 41 ++++ ...-default-ca-certificates-extra-override.js | 19 ++ ...set-default-ca-certificates-mixed-types.js | 46 ++++ ...ault-ca-certificates-precedence-bundled.js | 53 +++++ ...efault-ca-certificates-precedence-empty.js | 51 +++++ ...ls-set-default-ca-certificates-recovery.js | 43 ++++ ...et-default-ca-certificates-reset-fetch.mjs | 47 +++++ ...ult-ca-certificates-reset-https-request.js | 62 ++++++ ...fault-ca-certificates-append-system-ca.mjs | 49 +++++ ...efault-ca-certificates-override-system.mjs | 87 ++++++++ ...ult-ca-certificates-system-combinations.js | 58 ++++++ 21 files changed, 1128 insertions(+), 14 deletions(-) create mode 100644 test/fixtures/es-modules/custom-condition/load.cjs create mode 100644 test/fixtures/tls-extra-ca-override.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-append-fetch.mjs create mode 100644 test/parallel/test-tls-set-default-ca-certificates-append-https-request.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-array-buffer.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-basic.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-error.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-extra-override.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-mixed-types.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-precedence-bundled.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-precedence-empty.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-recovery.js create mode 100644 test/parallel/test-tls-set-default-ca-certificates-reset-fetch.mjs create mode 100644 test/parallel/test-tls-set-default-ca-certificates-reset-https-request.js create mode 100644 test/system-ca/test-set-default-ca-certificates-append-system-ca.mjs create mode 100644 test/system-ca/test-set-default-ca-certificates-override-system.mjs create mode 100644 test/system-ca/test-set-default-ca-certificates-system-combinations.js diff --git a/doc/api/tls.md b/doc/api/tls.md index db0131550e7802..984b45be7ebd1d 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -2342,6 +2342,54 @@ openssl pkcs12 -certpbe AES-256-CBC -export -out client-cert.pem \ The server can be tested by connecting to it using the example client from [`tls.connect()`][]. +## `tls.setDefaultCACertificates(certs)` + + + +* `certs` {string\[]|ArrayBufferView\[]} An array of CA certificates in PEM format. + +Sets the default CA certificates used by Node.js TLS clients. If the provided +certificates are parsed successfully, they will become the default CA +certificate list returned by [`tls.getCACertificates()`][] and used +by subsequent TLS connections that don't specify their own CA certificates. +The certificates will be deduplicated before being set as the default. + +This function only affects the current Node.js thread. Previous +sessions cached by the HTTPS agent won't be affected by this change, so +this method should be called before any unwanted cachable TLS connections are +made. + +To use system CA certificates as the default: + +```cjs +const tls = require('node:tls'); +tls.setDefaultCACertificates(tls.getCACertificates('system')); +``` + +```mjs +import tls from 'node:tls'; +tls.setDefaultCACertificates(tls.getCACertificates('system')); +``` + +This function completely replaces the default CA certificate list. To add additional +certificates to the existing defaults, get the current certificates and append to them: + +```cjs +const tls = require('node:tls'); +const currentCerts = tls.getCACertificates('default'); +const additionalCerts = ['-----BEGIN CERTIFICATE-----\n...']; +tls.setDefaultCACertificates([...currentCerts, ...additionalCerts]); +``` + +```mjs +import tls from 'node:tls'; +const currentCerts = tls.getCACertificates('default'); +const additionalCerts = ['-----BEGIN CERTIFICATE-----\n...']; +tls.setDefaultCACertificates([...currentCerts, ...additionalCerts]); +``` + ## `tls.getCACertificates([type])` + +* `previousValue` {Object} A previous return value from calling + `process.cpuUsage()` +* Returns: {Object} + * `user` {integer} + * `system` {integer} + +The `process.threadCpuUsage()` method returns the user and system CPU time usage of +the current worker thread, in an object with properties `user` and `system`, whose +values are microsecond values (millionth of a second). + +The result of a previous call to `process.threadCpuUsage()` can be passed as the +argument to the function, to get a diff reading. + ## `process.title` + +* Returns: {Promise} + +This method returns a `Promise` that will resolve to an object identical to [`process.threadCpuUsage()`][], +or reject with an [`ERR_WORKER_NOT_RUNNING`][] error if the worker is no longer running. +This methods allows the statistics to be observed from outside the actual thread. + ### `worker.getHeapSnapshot([options])` -* `type`: {string} The intended use of the generated secret key. Currently +* `type` {string} The intended use of the generated secret key. Currently accepted values are `'hmac'` and `'aes'`. -* `options`: {Object} - * `length`: {number} The bit length of the key to generate. This must be a +* `options` {Object} + * `length` {number} The bit length of the key to generate. This must be a value greater than 0. * If `type` is `'hmac'`, the minimum is 8, and the maximum length is 231-1. If the value is not a multiple of 8, the generated key will be truncated to `Math.floor(length / 8)`. * If `type` is `'aes'`, the length must be one of `128`, `192`, or `256`. -* `callback`: {Function} - * `err`: {Error} - * `key`: {KeyObject} +* `callback` {Function} + * `err` {Error} + * `key` {KeyObject} Asynchronously generates a new random secret key of the given `length`. The `type` will determine which validations will be performed on the `length`. @@ -3661,30 +3661,30 @@ changes: produce key objects if no encoding was specified. --> -* `type`: {string} Must be `'rsa'`, `'rsa-pss'`, `'dsa'`, `'ec'`, `'ed25519'`, +* `type` {string} Must be `'rsa'`, `'rsa-pss'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`, `'x25519'`, `'x448'`, or `'dh'`. -* `options`: {Object} - * `modulusLength`: {number} Key size in bits (RSA, DSA). - * `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`. - * `hashAlgorithm`: {string} Name of the message digest (RSA-PSS). - * `mgf1HashAlgorithm`: {string} Name of the message digest used by +* `options` {Object} + * `modulusLength` {number} Key size in bits (RSA, DSA). + * `publicExponent` {number} Public exponent (RSA). **Default:** `0x10001`. + * `hashAlgorithm` {string} Name of the message digest (RSA-PSS). + * `mgf1HashAlgorithm` {string} Name of the message digest used by MGF1 (RSA-PSS). - * `saltLength`: {number} Minimal salt length in bytes (RSA-PSS). - * `divisorLength`: {number} Size of `q` in bits (DSA). - * `namedCurve`: {string} Name of the curve to use (EC). - * `prime`: {Buffer} The prime parameter (DH). - * `primeLength`: {number} Prime length in bits (DH). - * `generator`: {number} Custom generator (DH). **Default:** `2`. - * `groupName`: {string} Diffie-Hellman group name (DH). See + * `saltLength` {number} Minimal salt length in bytes (RSA-PSS). + * `divisorLength` {number} Size of `q` in bits (DSA). + * `namedCurve` {string} Name of the curve to use (EC). + * `prime` {Buffer} The prime parameter (DH). + * `primeLength` {number} Prime length in bits (DH). + * `generator` {number} Custom generator (DH). **Default:** `2`. + * `groupName` {string} Diffie-Hellman group name (DH). See [`crypto.getDiffieHellman()`][]. - * `paramEncoding`: {string} Must be `'named'` or `'explicit'` (EC). + * `paramEncoding` {string} Must be `'named'` or `'explicit'` (EC). **Default:** `'named'`. - * `publicKeyEncoding`: {Object} See [`keyObject.export()`][]. - * `privateKeyEncoding`: {Object} See [`keyObject.export()`][]. -* `callback`: {Function} - * `err`: {Error} - * `publicKey`: {string | Buffer | KeyObject} - * `privateKey`: {string | Buffer | KeyObject} + * `publicKeyEncoding` {Object} See [`keyObject.export()`][]. + * `privateKeyEncoding` {Object} See [`keyObject.export()`][]. +* `callback` {Function} + * `err` {Error} + * `publicKey` {string | Buffer | KeyObject} + * `privateKey` {string | Buffer | KeyObject} Generates a new asymmetric key pair of the given `type`. RSA, RSA-PSS, DSA, EC, Ed25519, Ed448, X25519, X448, and DH are currently supported. @@ -3775,29 +3775,29 @@ changes: produce key objects if no encoding was specified. --> -* `type`: {string} Must be `'rsa'`, `'rsa-pss'`, `'dsa'`, `'ec'`, `'ed25519'`, +* `type` {string} Must be `'rsa'`, `'rsa-pss'`, `'dsa'`, `'ec'`, `'ed25519'`, `'ed448'`, `'x25519'`, `'x448'`, or `'dh'`. -* `options`: {Object} - * `modulusLength`: {number} Key size in bits (RSA, DSA). - * `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`. - * `hashAlgorithm`: {string} Name of the message digest (RSA-PSS). - * `mgf1HashAlgorithm`: {string} Name of the message digest used by +* `options` {Object} + * `modulusLength` {number} Key size in bits (RSA, DSA). + * `publicExponent` {number} Public exponent (RSA). **Default:** `0x10001`. + * `hashAlgorithm` {string} Name of the message digest (RSA-PSS). + * `mgf1HashAlgorithm` {string} Name of the message digest used by MGF1 (RSA-PSS). - * `saltLength`: {number} Minimal salt length in bytes (RSA-PSS). - * `divisorLength`: {number} Size of `q` in bits (DSA). - * `namedCurve`: {string} Name of the curve to use (EC). - * `prime`: {Buffer} The prime parameter (DH). - * `primeLength`: {number} Prime length in bits (DH). - * `generator`: {number} Custom generator (DH). **Default:** `2`. - * `groupName`: {string} Diffie-Hellman group name (DH). See + * `saltLength` {number} Minimal salt length in bytes (RSA-PSS). + * `divisorLength` {number} Size of `q` in bits (DSA). + * `namedCurve` {string} Name of the curve to use (EC). + * `prime` {Buffer} The prime parameter (DH). + * `primeLength` {number} Prime length in bits (DH). + * `generator` {number} Custom generator (DH). **Default:** `2`. + * `groupName` {string} Diffie-Hellman group name (DH). See [`crypto.getDiffieHellman()`][]. - * `paramEncoding`: {string} Must be `'named'` or `'explicit'` (EC). + * `paramEncoding` {string} Must be `'named'` or `'explicit'` (EC). **Default:** `'named'`. - * `publicKeyEncoding`: {Object} See [`keyObject.export()`][]. - * `privateKeyEncoding`: {Object} See [`keyObject.export()`][]. + * `publicKeyEncoding` {Object} See [`keyObject.export()`][]. + * `privateKeyEncoding` {Object} See [`keyObject.export()`][]. * Returns: {Object} - * `publicKey`: {string | Buffer | KeyObject} - * `privateKey`: {string | Buffer | KeyObject} + * `publicKey` {string | Buffer | KeyObject} + * `privateKey` {string | Buffer | KeyObject} Generates a new asymmetric key pair of the given `type`. RSA, RSA-PSS, DSA, EC, Ed25519, Ed448, X25519, X448, and DH are currently supported. @@ -3866,10 +3866,10 @@ it will be a buffer containing the data encoded as DER. added: v15.0.0 --> -* `type`: {string} The intended use of the generated secret key. Currently +* `type` {string} The intended use of the generated secret key. Currently accepted values are `'hmac'` and `'aes'`. -* `options`: {Object} - * `length`: {number} The bit length of the key to generate. +* `options` {Object} + * `length` {number} The bit length of the key to generate. * If `type` is `'hmac'`, the minimum is 8, and the maximum length is 231-1. If the value is not a multiple of 8, the generated key will be truncated to `Math.floor(length / 8)`. @@ -4010,10 +4010,10 @@ the process unresponsive. added: v15.0.0 --> -* `nameOrNid`: {string|number} The name or nid of the cipher to query. -* `options`: {Object} - * `keyLength`: {number} A test key length. - * `ivLength`: {number} A test IV length. +* `nameOrNid` {string|number} The name or nid of the cipher to query. +* `options` {Object} + * `keyLength` {number} A test key length. + * `ivLength` {number} A test IV length. * Returns: {Object} * `name` {string} The name of the cipher * `nid` {number} The nid of the cipher diff --git a/doc/api/diagnostics_channel.md b/doc/api/diagnostics_channel.md index 0aeef6c65c5db1..fe0d28fc29d281 100644 --- a/doc/api/diagnostics_channel.md +++ b/doc/api/diagnostics_channel.md @@ -1106,35 +1106,35 @@ for the sync error and one for the async error. > Stability: 1 - Experimental -`console.log` +##### Event: `'console.log'` * `args` {any\[]} Emitted when `console.log()` is called. Receives and array of the arguments passed to `console.log()`. -`console.info` +##### Event: `'console.info'` * `args` {any\[]} Emitted when `console.info()` is called. Receives and array of the arguments passed to `console.info()`. -`console.debug` +##### Event: `'console.debug'` * `args` {any\[]} Emitted when `console.debug()` is called. Receives and array of the arguments passed to `console.debug()`. -`console.warn` +##### Event: `'console.warn'` * `args` {any\[]} Emitted when `console.warn()` is called. Receives and array of the arguments passed to `console.warn()`. -`console.error` +##### Event: `'console.error'` * `args` {any\[]} @@ -1145,34 +1145,34 @@ passed to `console.error()`. > Stability: 1 - Experimental -`http.client.request.created` +##### Event: `'http.client.request.created'` * `request` {http.ClientRequest} Emitted when client creates a request object. Unlike `http.client.request.start`, this event is emitted before the request has been sent. -`http.client.request.start` +##### Event: `'http.client.request.start'` * `request` {http.ClientRequest} Emitted when client starts a request. -`http.client.request.error` +##### Event: `'http.client.request.error'` * `request` {http.ClientRequest} * `error` {Error} Emitted when an error occurs during a client request. -`http.client.response.finish` +##### Event: `'http.client.response.finish'` * `request` {http.ClientRequest} * `response` {http.IncomingMessage} Emitted when client receives a response. -`http.server.request.start` +##### Event: `'http.server.request.start'` * `request` {http.IncomingMessage} * `response` {http.ServerResponse} @@ -1181,7 +1181,7 @@ Emitted when client receives a response. Emitted when server receives a request. -`http.server.response.created` +##### Event: `'http.server.response.created'` * `request` {http.IncomingMessage} * `response` {http.ServerResponse} @@ -1189,7 +1189,7 @@ Emitted when server receives a request. Emitted when server creates a response. The event is emitted before the response is sent. -`http.server.response.finish` +##### Event: `'http.server.response.finish'` * `request` {http.IncomingMessage} * `response` {http.ServerResponse} @@ -1202,28 +1202,28 @@ Emitted when server sends a response. > Stability: 1 - Experimental -`http2.client.stream.created` +##### Event: `'http2.client.stream.created'` * `stream` {ClientHttp2Stream} * `headers` {HTTP/2 Headers Object} Emitted when a stream is created on the client. -`http2.client.stream.start` +##### Event: `'http2.client.stream.start'` * `stream` {ClientHttp2Stream} * `headers` {HTTP/2 Headers Object} Emitted when a stream is started on the client. -`http2.client.stream.error` +##### Event: `'http2.client.stream.error'` * `stream` {ClientHttp2Stream} * `error` {Error} Emitted when an error occurs during the processing of a stream on the client. -`http2.client.stream.finish` +##### Event: `'http2.client.stream.finish'` * `stream` {ClientHttp2Stream} * `headers` {HTTP/2 Headers Object} @@ -1231,35 +1231,35 @@ Emitted when an error occurs during the processing of a stream on the client. Emitted when a stream is received on the client. -`http2.client.stream.close` +##### Event: `'http2.client.stream.close'` * `stream` {ClientHttp2Stream} Emitted when a stream is closed on the client. The HTTP/2 error code used when closing the stream can be retrieved using the `stream.rstCode` property. -`http2.server.stream.created` +##### Event: `'http2.server.stream.created'` * `stream` {ServerHttp2Stream} * `headers` {HTTP/2 Headers Object} Emitted when a stream is created on the server. -`http2.server.stream.start` +##### Event: `'http2.server.stream.start'` * `stream` {ServerHttp2Stream} * `headers` {HTTP/2 Headers Object} Emitted when a stream is started on the server. -`http2.server.stream.error` +##### Event: `'http2.server.stream.error'` * `stream` {ServerHttp2Stream} * `error` {Error} Emitted when an error occurs during the processing of a stream on the server. -`http2.server.stream.finish` +##### Event: `'http2.server.stream.finish'` * `stream` {ServerHttp2Stream} * `headers` {HTTP/2 Headers Object} @@ -1267,7 +1267,7 @@ Emitted when an error occurs during the processing of a stream on the server. Emitted when a stream is sent on the server. -`http2.server.stream.close` +##### Event: `'http2.server.stream.close'` * `stream` {ServerHttp2Stream} @@ -1278,52 +1278,52 @@ closing the stream can be retrieved using the `stream.rstCode` property. > Stability: 1 - Experimental -`module.require.start` +##### Event: `'module.require.start'` * `event` {Object} containing the following properties - * `id` - Argument passed to `require()`. Module name. - * `parentFilename` - Name of the module that attempted to require(id). + * `id` Argument passed to `require()`. Module name. + * `parentFilename` Name of the module that attempted to require(id). Emitted when `require()` is executed. See [`start` event][]. -`module.require.end` +##### Event: `'module.require.end'` * `event` {Object} containing the following properties - * `id` - Argument passed to `require()`. Module name. - * `parentFilename` - Name of the module that attempted to require(id). + * `id` Argument passed to `require()`. Module name. + * `parentFilename` Name of the module that attempted to require(id). Emitted when a `require()` call returns. See [`end` event][]. -`module.require.error` +##### Event: `'module.require.error'` * `event` {Object} containing the following properties - * `id` - Argument passed to `require()`. Module name. - * `parentFilename` - Name of the module that attempted to require(id). + * `id` Argument passed to `require()`. Module name. + * `parentFilename` Name of the module that attempted to require(id). * `error` {Error} Emitted when a `require()` throws an error. See [`error` event][]. -`module.import.asyncStart` +##### Event: `'module.import.asyncStart'` * `event` {Object} containing the following properties - * `id` - Argument passed to `import()`. Module name. - * `parentURL` - URL object of the module that attempted to import(id). + * `id` Argument passed to `import()`. Module name. + * `parentURL` URL object of the module that attempted to import(id). Emitted when `import()` is invoked. See [`asyncStart` event][]. -`module.import.asyncEnd` +##### Event: `'module.import.asyncEnd'` * `event` {Object} containing the following properties - * `id` - Argument passed to `import()`. Module name. - * `parentURL` - URL object of the module that attempted to import(id). + * `id` Argument passed to `import()`. Module name. + * `parentURL` URL object of the module that attempted to import(id). Emitted when `import()` has completed. See [`asyncEnd` event][]. -`module.import.error` +##### Event: `'module.import.error'` * `event` {Object} containing the following properties - * `id` - Argument passed to `import()`. Module name. - * `parentURL` - URL object of the module that attempted to import(id). + * `id` Argument passed to `import()`. Module name. + * `parentURL` URL object of the module that attempted to import(id). * `error` {Error} Emitted when a `import()` throws an error. See [`error` event][]. @@ -1332,32 +1332,32 @@ Emitted when a `import()` throws an error. See [`error` event][]. > Stability: 1 - Experimental -`net.client.socket` +##### Event: `'net.client.socket'` * `socket` {net.Socket|tls.TLSSocket} Emitted when a new TCP or pipe client socket connection is created. -`net.server.socket` +##### Event: `'net.server.socket'` * `socket` {net.Socket} Emitted when a new TCP or pipe connection is received. -`tracing:net.server.listen:asyncStart` +##### Event: `'tracing:net.server.listen:asyncStart'` * `server` {net.Server} * `options` {Object} Emitted when [`net.Server.listen()`][] is invoked, before the port or pipe is actually setup. -`tracing:net.server.listen:asyncEnd` +##### Event: `'tracing:net.server.listen:asyncEnd'` * `server` {net.Server} Emitted when [`net.Server.listen()`][] has completed and thus the server is ready to accept connection. -`tracing:net.server.listen:error` +##### Event: `'tracing:net.server.listen:error'` * `server` {net.Server} * `error` {Error} @@ -1368,7 +1368,7 @@ Emitted when [`net.Server.listen()`][] is returning an error. > Stability: 1 - Experimental -`udp.socket` +##### Event: `'udp.socket'` * `socket` {dgram.Socket} @@ -1382,13 +1382,13 @@ Emitted when a new UDP socket is created. added: v16.18.0 --> -`child_process` +##### Event: `'child_process'` * `process` {ChildProcess} Emitted when a new process is created. -`execve` +##### Event: `'execve'` * `execPath` {string} * `args` {string\[]} @@ -1404,16 +1404,15 @@ Emitted when [`process.execve()`][] is invoked. added: v16.18.0 --> -`worker_threads` +##### Event: `'worker_threads'` -* `worker` [`Worker`][] +* `worker` {Worker} Emitted when a new thread is created. [TracingChannel Channels]: #tracingchannel-channels [`'uncaughtException'`]: process.md#event-uncaughtexception [`TracingChannel`]: #class-tracingchannel -[`Worker`]: worker_threads.md#class-worker [`asyncEnd` event]: #asyncendevent [`asyncStart` event]: #asyncstartevent [`channel.bindStore(store)`]: #channelbindstorestore-transform diff --git a/doc/api/dns.md b/doc/api/dns.md index bde50619fdf371..a8c7cb51c58218 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -852,14 +852,10 @@ changes: `ERR_INVALID_CALLBACK`. --> - - * `hostname` {string} * `callback` {Function} * `err` {Error} - * `records` \ - - + * `records` {string\[]} Uses the DNS protocol to resolve text queries (`TXT` records) for the `hostname`. The `records` argument passed to the `callback` function is a diff --git a/doc/api/events.md b/doc/api/events.md index 401e8aeed9513b..2308baf3a00314 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -1099,7 +1099,7 @@ changes: description: No longer experimental. --> -* `err` Error +* `err` {Error} * `eventName` {string|symbol} * `...args` {any} @@ -1600,7 +1600,7 @@ changes: description: No longer experimental. --> -Value: {boolean} +* Type: {boolean} Change the default `captureRejections` option on all new `EventEmitter` objects. @@ -1618,7 +1618,7 @@ changes: description: No longer experimental. --> -Value: `Symbol.for('nodejs.rejection')` +* Type: {symbol} `Symbol.for('nodejs.rejection')` See how to write a custom [rejection handler][rejection]. @@ -1679,12 +1679,12 @@ changes: * `eventName` {string|symbol} The name of the event being listened for * `options` {Object} * `signal` {AbortSignal} Can be used to cancel awaiting events. - * `close` - {string\[]} Names of events that will end the iteration. - * `highWaterMark` - {integer} **Default:** `Number.MAX_SAFE_INTEGER` + * `close` {string\[]} Names of events that will end the iteration. + * `highWaterMark` {integer} **Default:** `Number.MAX_SAFE_INTEGER` The high watermark. The emitter is paused every time the size of events being buffered is higher than it. Supported only on emitters implementing `pause()` and `resume()` methods. - * `lowWaterMark` - {integer} **Default:** `1` + * `lowWaterMark` {integer} **Default:** `1` The low watermark. The emitter is resumed every time the size of events being buffered is lower than it. Supported only on emitters implementing `pause()` and `resume()` methods. @@ -1984,7 +1984,7 @@ same options as `EventEmitter` and `AsyncResource` themselves. ### `eventemitterasyncresource.asyncResource` -* The underlying {AsyncResource}. +* Type: {AsyncResource} The underlying {AsyncResource}. The returned `AsyncResource` object has an additional `eventEmitter` property that provides a reference to this `EventEmitterAsyncResource`. diff --git a/doc/api/http2.md b/doc/api/http2.md index b29b2f8a1437b0..7131693ee2b012 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -2920,7 +2920,7 @@ changes: and trailing whitespace validation for HTTP/2 header field names and values as per [RFC-9113](https://www.rfc-editor.org/rfc/rfc9113.html#section-8.2.1). **Default:** `true`. - * ...: Any [`net.createServer()`][] option can be provided. + * `...options` {Object} Any [`net.createServer()`][] option can be provided. * `onRequestHandler` {Function} See [Compatibility API][] * Returns: {Http2Server} @@ -3083,8 +3083,8 @@ changes: settings types, which are included in the `customSettings`-property of the received remoteSettings. Please see the `customSettings`-property of the `Http2Settings` object for more information, on the allowed setting types. - * ...: Any [`tls.createServer()`][] options can be provided. For - servers, the identity options (`pfx` or `key`/`cert`) are usually required. + * `...options` {Object} Any [`tls.createServer()`][] options can be provided. + For servers, the identity options (`pfx` or `key`/`cert`) are usually required. * `origins` {string\[]} An array of origin strings to send within an `ORIGIN` frame immediately following creation of a new server `Http2Session`. * `unknownProtocolTimeout` {number} Specifies a timeout in milliseconds that @@ -3245,7 +3245,8 @@ changes: * `createConnection` {Function} An optional callback that receives the `URL` instance passed to `connect` and the `options` object, and returns any [`Duplex`][] stream that is to be used as the connection for this session. - * ...: Any [`net.connect()`][] or [`tls.connect()`][] options can be provided. + * `...options` {Object} Any [`net.connect()`][] or [`tls.connect()`][] options + can be provided. * `unknownProtocolTimeout` {number} Specifies a timeout in milliseconds that a server should wait when an [`'unknownProtocol'`][] event is emitted. If the socket has not been destroyed by that time the server will destroy it. @@ -3370,8 +3371,7 @@ added: --> * `socket` {stream.Duplex} -* `options` {Object} - * ...: Any [`http2.createServer()`][] option can be provided. +* `options` {Object} Any [`http2.createServer()`][] option can be provided. * Returns: {ServerHttp2Session} Create an HTTP/2 server session from an existing socket. diff --git a/doc/api/inspector.md b/doc/api/inspector.md index 518ad1688a9f78..b4685a72214895 100644 --- a/doc/api/inspector.md +++ b/doc/api/inspector.md @@ -79,7 +79,7 @@ session.on('inspectorNotification', (message) => console.log(message.method)); It is also possible to subscribe only to notifications with specific method: -#### Event: ``; +#### Event: `` - - * Type: {string} The directory name of the current module. This is the same as the @@ -784,8 +782,6 @@ console.log(path.dirname(__filename)); added: v0.0.1 --> - - * Type: {string} The file name of the current module. This is the current module file's absolute @@ -823,8 +819,6 @@ References to `__filename` within `b.js` will return added: v0.1.12 --> - - * Type: {Object} A reference to the `module.exports` that is shorter to type. @@ -837,8 +831,6 @@ See the section about the [exports shortcut][] for details on when to use added: v0.1.16 --> - - * Type: {module} A reference to the current module, see the section about the @@ -851,8 +843,6 @@ a module exports and makes available through `require()`. added: v0.1.13 --> - - * `id` {string} module name or path * Returns: {any} exported module content @@ -1018,8 +1008,6 @@ Returns an array containing the paths searched during resolution of `request` or added: v0.1.16 --> - - * Type: {Object} diff --git a/doc/api/stream.md b/doc/api/stream.md index aba2532d3be9af..2ca927466affd6 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -62,10 +62,10 @@ functions for streams that return `Promise` objects rather than using callbacks. The API is accessible via `require('node:stream/promises')` or `require('node:stream').promises`. -### `stream.pipeline(source[, ...transforms], destination[, options])` - ### `stream.pipeline(streams[, options])` +### `stream.pipeline(source[, ...transforms], destination[, options])` + * `options` {Object} - * `ALPNProtocols`: {string\[]|Buffer\[]|TypedArray\[]|DataView\[]|Buffer| + * `ALPNProtocols` {string\[]|Buffer\[]|TypedArray\[]|DataView\[]|Buffer| TypedArray|DataView} An array of strings, `Buffer`s, `TypedArray`s, or `DataView`s, or a single `Buffer`, `TypedArray`, or `DataView` containing the supported ALPN @@ -2210,7 +2210,7 @@ changes: e.g. `0x05hello0x05world`, where the first byte is the length of the next protocol name. Passing an array is usually much simpler, e.g. `['hello', 'world']`. (Protocols should be ordered by their priority.) - * `ALPNCallback`: {Function} If set, this will be called when a + * `ALPNCallback` {Function} If set, this will be called when a client opens a connection using the ALPN extension. One argument will be passed to the callback: an object containing `servername` and `protocols` fields, respectively containing the server name from @@ -2249,7 +2249,7 @@ changes: If `callback` is called with a falsy `ctx` argument, the default secure context of the server will be used. If `SNICallback` wasn't provided the default callback with high-level API will be used (see below). - * `ticketKeys`: {Buffer} 48-bytes of cryptographically strong pseudorandom + * `ticketKeys` {Buffer} 48-bytes of cryptographically strong pseudorandom data. See [Session Resumption][] for more information. * `pskCallback` {Function} For TLS-PSK negotiation, see [Pre-shared keys][]. * `pskIdentityHint` {string} optional hint to send to a client to help diff --git a/doc/api/util.md b/doc/api/util.md index 0258377f03fcc9..38c996434021b3 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -338,8 +338,8 @@ added: v22.15.0 * `expected` {Array|string} The second value to compare * Returns: {Array} An array of difference entries. Each entry is an array with two elements: - * Index 0: {number} Operation code: `-1` for delete, `0` for no-op/unchanged, `1` for insert - * Index 1: {string} The value associated with the operation + * `0` {number} Operation code: `-1` for delete, `0` for no-op/unchanged, `1` for insert + * `1` {string} The value associated with the operation * Algorithm complexity: O(N\*D), where: @@ -1295,19 +1295,19 @@ ignored, if not supported. * `reset` - Resets all (color) modifiers to their defaults * **bold** - Make text bold * _italic_ - Make text italic -* underline - Make text underlined +* underline - Make text underlined * ~~strikethrough~~ - Puts a horizontal line through the center of the text (Alias: `strikeThrough`, `crossedout`, `crossedOut`) * `hidden` - Prints the text, but makes it invisible (Alias: conceal) * dim - Decreased color intensity (Alias: `faint`) -* overlined - Make text overlined +* overlined - Make text overlined * blink - Hides and shows the text in an interval -* inverse - Swap foreground and +* inverse - Swap foreground and background colors (Alias: `swapcolors`, `swapColors`) * doubleunderline - Make text double underlined (Alias: `doubleUnderline`) -* framed - Draw a frame around the text +* framed - Draw a frame around the text #### Foreground colors diff --git a/doc/api/webcrypto.md b/doc/api/webcrypto.md index 0bf068bcd8157f..e7595455de21a1 100644 --- a/doc/api/webcrypto.md +++ b/doc/api/webcrypto.md @@ -553,9 +553,9 @@ added: v15.0.0 added: v15.0.0 --> -* `algorithm`: {RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams} -* `key`: {CryptoKey} -* `data`: {ArrayBuffer|TypedArray|DataView|Buffer} +* `algorithm` {RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams} +* `key` {CryptoKey} +* `data` {ArrayBuffer|TypedArray|DataView|Buffer} * Returns: {Promise} Fulfills with an {ArrayBuffer} upon success. Using the method and parameters specified in `algorithm` and the keying @@ -588,9 +588,9 @@ changes: -* `algorithm`: {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params} -* `baseKey`: {CryptoKey} -* `length`: {number|null} **Default:** `null` +* `algorithm` {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params} +* `baseKey` {CryptoKey} +* `length` {number|null} **Default:** `null` * Returns: {Promise} Fulfills with an {ArrayBuffer} upon success. @@ -628,11 +628,11 @@ changes: -* `algorithm`: {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params} -* `baseKey`: {CryptoKey} -* `derivedKeyAlgorithm`: {string|Algorithm|HmacImportParams|AesDerivedKeyParams} -* `extractable`: {boolean} -* `keyUsages`: {string\[]} See [Key usages][]. +* `algorithm` {EcdhKeyDeriveParams|HkdfParams|Pbkdf2Params} +* `baseKey` {CryptoKey} +* `derivedKeyAlgorithm` {string|Algorithm|HmacImportParams|AesDerivedKeyParams} +* `extractable` {boolean} +* `keyUsages` {string\[]} See [Key usages][]. * Returns: {Promise} Fulfills with a {CryptoKey} upon success. @@ -660,8 +660,8 @@ The algorithms currently supported include: added: v15.0.0 --> -* `algorithm`: {string|Algorithm} -* `data`: {ArrayBuffer|TypedArray|DataView|Buffer} +* `algorithm` {string|Algorithm} +* `data` {ArrayBuffer|TypedArray|DataView|Buffer} * Returns: {Promise} Fulfills with an {ArrayBuffer} upon success. Using the method identified by `algorithm`, `subtle.digest()` attempts to @@ -684,9 +684,9 @@ whose value is one of the above. added: v15.0.0 --> -* `algorithm`: {RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams} -* `key`: {CryptoKey} -* `data`: {ArrayBuffer|TypedArray|DataView|Buffer} +* `algorithm` {RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams} +* `key` {CryptoKey} +* `data` {ArrayBuffer|TypedArray|DataView|Buffer} * Returns: {Promise} Fulfills with an {ArrayBuffer} upon success. Using the method and parameters specified by `algorithm` and the keying @@ -717,8 +717,8 @@ changes: description: Removed `'NODE-DSA'` JWK export. --> -* `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. -* `key`: {CryptoKey} +* `format` {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. +* `key` {CryptoKey} * Returns: {Promise} Fulfills with an {ArrayBuffer|Object} upon success. Exports the given key into the specified format, if supported. @@ -756,12 +756,12 @@ added: v15.0.0 -* `algorithm`: {string|Algorithm|RsaHashedKeyGenParams|EcKeyGenParams|HmacKeyGenParams|AesKeyGenParams} +* `algorithm` {string|Algorithm|RsaHashedKeyGenParams|EcKeyGenParams|HmacKeyGenParams|AesKeyGenParams} -* `extractable`: {boolean} -* `keyUsages`: {string\[]} See [Key usages][]. +* `extractable` {boolean} +* `keyUsages` {string\[]} See [Key usages][]. * Returns: {Promise} Fulfills with a {CryptoKey|CryptoKeyPair} upon success. Using the method and parameters provided in `algorithm`, `subtle.generateKey()` @@ -805,17 +805,17 @@ changes: description: Removed `'NODE-DSA'` JWK import. --> -* `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. -* `keyData`: {ArrayBuffer|TypedArray|DataView|Buffer|Object} +* `format` {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. +* `keyData` {ArrayBuffer|TypedArray|DataView|Buffer|Object} -* `algorithm`: {string|Algorithm|RsaHashedImportParams|EcKeyImportParams|HmacImportParams} +* `algorithm` {string|Algorithm|RsaHashedImportParams|EcKeyImportParams|HmacImportParams} -* `extractable`: {boolean} -* `keyUsages`: {string\[]} See [Key usages][]. +* `extractable` {boolean} +* `keyUsages` {string\[]} See [Key usages][]. * Returns: {Promise} Fulfills with a {CryptoKey} upon success. The `subtle.importKey()` method attempts to interpret the provided `keyData` @@ -860,9 +860,9 @@ changes: -* `algorithm`: {string|Algorithm|RsaPssParams|EcdsaParams|Ed448Params} -* `key`: {CryptoKey} -* `data`: {ArrayBuffer|TypedArray|DataView|Buffer} +* `algorithm` {string|Algorithm|RsaPssParams|EcdsaParams|Ed448Params} +* `key` {CryptoKey} +* `data` {ArrayBuffer|TypedArray|DataView|Buffer} * Returns: {Promise} Fulfills with an {ArrayBuffer} upon success. @@ -887,19 +887,19 @@ The algorithms currently supported include: added: v15.0.0 --> -* `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. -* `wrappedKey`: {ArrayBuffer|TypedArray|DataView|Buffer} -* `unwrappingKey`: {CryptoKey} +* `format` {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. +* `wrappedKey` {ArrayBuffer|TypedArray|DataView|Buffer} +* `unwrappingKey` {CryptoKey} -* `unwrapAlgo`: {string|Algorithm|RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams} -* `unwrappedKeyAlgo`: {string|Algorithm|RsaHashedImportParams|EcKeyImportParams|HmacImportParams} +* `unwrapAlgo` {string|Algorithm|RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams} +* `unwrappedKeyAlgo` {string|Algorithm|RsaHashedImportParams|EcKeyImportParams|HmacImportParams} -* `extractable`: {boolean} -* `keyUsages`: {string\[]} See [Key usages][]. +* `extractable` {boolean} +* `keyUsages` {string\[]} See [Key usages][]. * Returns: {Promise} Fulfills with a {CryptoKey} upon success. In cryptography, "wrapping a key" refers to exporting and then encrypting the @@ -950,10 +950,10 @@ changes: -* `algorithm`: {string|Algorithm|RsaPssParams|EcdsaParams|Ed448Params} -* `key`: {CryptoKey} -* `signature`: {ArrayBuffer|TypedArray|DataView|Buffer} -* `data`: {ArrayBuffer|TypedArray|DataView|Buffer} +* `algorithm` {string|Algorithm|RsaPssParams|EcdsaParams|Ed448Params} +* `key` {CryptoKey} +* `signature` {ArrayBuffer|TypedArray|DataView|Buffer} +* `data` {ArrayBuffer|TypedArray|DataView|Buffer} * Returns: {Promise} Fulfills with a {boolean} upon success. @@ -980,10 +980,10 @@ added: v15.0.0 -* `format`: {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. -* `key`: {CryptoKey} -* `wrappingKey`: {CryptoKey} -* `wrapAlgo`: {string|Algorithm|RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams} +* `format` {string} Must be one of `'raw'`, `'pkcs8'`, `'spki'`, or `'jwk'`. +* `key` {CryptoKey} +* `wrappingKey` {CryptoKey} +* `wrapAlgo` {string|Algorithm|RsaOaepParams|AesCtrParams|AesCbcParams|AesGcmParams} * Returns: {Promise} Fulfills with an {ArrayBuffer} upon success. diff --git a/doc/api/webstreams.md b/doc/api/webstreams.md index 7e37235315eba5..70f1167ebef662 100644 --- a/doc/api/webstreams.md +++ b/doc/api/webstreams.md @@ -805,7 +805,7 @@ queue. added: v16.5.0 --> -* `chunk`: {Buffer|TypedArray|DataView} +* `chunk` {Buffer|TypedArray|DataView} Appends a new chunk of data to the {ReadableStream}'s queue. @@ -1075,7 +1075,7 @@ Releases this writer's lock on the underlying {ReadableStream}. added: v16.5.0 --> -* `chunk`: {any} +* `chunk` {any} * Returns: A promise fulfilled with `undefined`. Appends a new chunk of data to the {WritableStream}'s queue. From cbb0a8eb136e3b7996e78eb9f43415c9a7df45c4 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Fri, 11 Jul 2025 10:07:44 +0800 Subject: [PATCH 073/134] doc: add note on process memoryUsage Co-authored-by: Joyee Cheung PR-URL: https://github.com/nodejs/node/pull/59026 Reviewed-By: Joyee Cheung Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Luigi Pinca --- doc/api/process.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/api/process.md b/doc/api/process.md index 1dcef4393544b2..fb9e9099225244 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -2861,6 +2861,13 @@ The `process.memoryUsage()` method iterates over each page to gather information about memory usage which might be slow depending on the program memory allocations. +### A note on process memoryUsage + +On Linux or other systems where glibc is commonly used, an application may have sustained +`rss` growth despite stable `heapTotal` due to fragmentation caused by the glibc `malloc` +implementation. See [nodejs/node#21973][] on how to switch to an alternative `malloc` +implementation to address the performance issue. + ## `process.memoryUsage.rss()` + +Type: Documentation-only + +The `node:_http_agent`, `node:_http_client`, `node:_http_common`, `node:_http_incoming`, +`node:_http_outgoing` and `node:_http_server` modules are deprecated as they should be considered +an internal nodejs implementation rather than a public facing API, use `node:http` instead. + [DEP0142]: #dep0142-repl_builtinlibs [NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf [RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3 From a100cce3796e4c527a9190b37550f2a1b3521853 Mon Sep 17 00:00:00 2001 From: Ethan Arrowood Date: Fri, 1 Aug 2025 22:25:35 -0600 Subject: [PATCH 093/134] test: deflake stream-readable-to-web test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Luigi Pinca PR-URL: https://github.com/nodejs/node/pull/58948 Fixes: https://github.com/nodejs/node/issues/58949 Reviewed-By: Matteo Collina Reviewed-By: Mattias Buelens Reviewed-By: Juan José Arboleda Reviewed-By: Luigi Pinca Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Daeyeon Jeong --- test/parallel/test-stream-readable-to-web.js | 62 ------------------ test/parallel/test-stream-readable-to-web.mjs | 64 +++++++++++++++++++ 2 files changed, 64 insertions(+), 62 deletions(-) delete mode 100644 test/parallel/test-stream-readable-to-web.js create mode 100644 test/parallel/test-stream-readable-to-web.mjs diff --git a/test/parallel/test-stream-readable-to-web.js b/test/parallel/test-stream-readable-to-web.js deleted file mode 100644 index 753672b509c173..00000000000000 --- a/test/parallel/test-stream-readable-to-web.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; -const common = require('../common'); -if (!common.hasCrypto) { common.skip('missing crypto'); } - -const { Readable } = require('stream'); -const process = require('process'); -const { randomBytes } = require('crypto'); -const assert = require('assert'); - -// Based on: https://github.com/nodejs/node/issues/46347#issuecomment-1413886707 -// edit: make it cross-platform as /dev/urandom is not available on Windows -{ - let currentMemoryUsage = process.memoryUsage().arrayBuffers; - - // We initialize a stream, but not start consuming it - const randomNodeStream = new Readable({ - read(size) { - randomBytes(size, (err, buffer) => { - if (err) { - // If an error occurs, emit an 'error' event - this.emit('error', err); - return; - } - - // Push the random bytes to the stream - this.push(buffer); - }); - } - }); - // after 2 seconds, it'll get converted to web stream - let randomWebStream; - - // We check memory usage every second - // since it's a stream, it shouldn't be higher than the chunk size - const reportMemoryUsage = () => { - const { arrayBuffers } = process.memoryUsage(); - currentMemoryUsage = arrayBuffers; - - assert(currentMemoryUsage <= 256 * 1024 * 1024); - }; - setInterval(reportMemoryUsage, 1000); - - // after 1 second we use Readable.toWeb - // memory usage should stay pretty much the same since it's still a stream - setTimeout(() => { - randomWebStream = Readable.toWeb(randomNodeStream); - }, 1000); - - // after 2 seconds we start consuming the stream - // memory usage will grow, but the old chunks should be garbage-collected pretty quickly - setTimeout(async () => { - // eslint-disable-next-line no-unused-vars - for await (const _ of randomWebStream) { - // Do nothing, just let the stream flow - } - }, 2000); - - setTimeout(() => { - // Test considered passed if we don't crash - process.exit(0); - }, 5000); -} diff --git a/test/parallel/test-stream-readable-to-web.mjs b/test/parallel/test-stream-readable-to-web.mjs new file mode 100644 index 00000000000000..8ff9f2fb16ed1c --- /dev/null +++ b/test/parallel/test-stream-readable-to-web.mjs @@ -0,0 +1,64 @@ +import { mustCall } from '../common/index.mjs'; +import { Readable } from 'node:stream'; +import { memoryUsage } from 'node:process'; +import assert from 'node:assert'; +import { setImmediate } from 'node:timers/promises'; + +// Based on: https://github.com/nodejs/node/issues/46347#issuecomment-1413886707 +// edit: make it cross-platform as /dev/urandom is not available on Windows + +const MAX_MEM = 256 * 1024 * 1024; // 256 MiB + +function checkMemoryUsage() { + assert(memoryUsage().arrayBuffers < MAX_MEM); +} + +const MAX_BUFFERS = 1000; +let buffersCreated = 0; + +const randomNodeStream = new Readable({ + read(size) { + if (buffersCreated >= MAX_BUFFERS) { + this.push(null); + return; + } + + this.push(Buffer.alloc(size)); + buffersCreated++; + } +}); + +randomNodeStream.on('error', (err) => { + assert.fail(err); +}); + +// Before doing anything, make sure memory usage is okay +checkMemoryUsage(); + +// Create stream and check memory usage remains okay + +const randomWebStream = Readable.toWeb(randomNodeStream); + +checkMemoryUsage(); + +let timeout; +try { + // Wait two seconds before consuming the stream to see if memory usage increases + timeout = setTimeout(mustCall(async () => { + // Did the stream leak memory? + checkMemoryUsage(); + // eslint-disable-next-line no-unused-vars + for await (const _ of randomWebStream) { + // Yield event loop to allow garbage collection + await setImmediate(); + // consume the stream + // check memory usage remains okay + checkMemoryUsage(); + } + }), 2000); +} catch (err) { + if (timeout) { + clearTimeout(timeout); + } + assert.fail(err); +} From 6dbda6cb25c598ac3e9870254f68412b78f61872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sat, 2 Aug 2025 07:43:00 +0200 Subject: [PATCH 094/134] typings: improve internal binding types - Add typings for `async_context_frame`, `icu`, and `sea` bindings - Add a few missing exports on other bindings - Add a few missing primordials PR-URL: https://github.com/nodejs/node/pull/59176 Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Yagiz Nizipli --- typings/globals.d.ts | 7 +++++++ .../internalBinding/async_context_frame.d.ts | 4 ++++ typings/internalBinding/constants.d.ts | 3 +++ typings/internalBinding/http_parser.d.ts | 13 ++++++++++++- typings/internalBinding/icu.d.ts | 18 ++++++++++++++++++ typings/internalBinding/sea.d.ts | 5 +++++ typings/internalBinding/symbols.d.ts | 2 ++ typings/internalBinding/util.d.ts | 19 +++++++++++++++++++ typings/primordials.d.ts | 3 +++ 9 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 typings/internalBinding/async_context_frame.d.ts create mode 100644 typings/internalBinding/icu.d.ts create mode 100644 typings/internalBinding/sea.d.ts diff --git a/typings/globals.d.ts b/typings/globals.d.ts index e978602d5f3d82..e10b00863ea78b 100644 --- a/typings/globals.d.ts +++ b/typings/globals.d.ts @@ -1,3 +1,4 @@ +import { AsyncContextFrameBinding } from './internalBinding/async_context_frame'; import { AsyncWrapBinding } from './internalBinding/async_wrap'; import { BlobBinding } from './internalBinding/blob'; import { ConfigBinding } from './internalBinding/config'; @@ -7,10 +8,12 @@ import { HttpParserBinding } from './internalBinding/http_parser'; import { InspectorBinding } from './internalBinding/inspector'; import { FsBinding } from './internalBinding/fs'; import { FsDirBinding } from './internalBinding/fs_dir'; +import { ICUBinding } from './internalBinding/icu'; import { MessagingBinding } from './internalBinding/messaging'; import { OptionsBinding } from './internalBinding/options'; import { OSBinding } from './internalBinding/os'; import { ProcessBinding } from './internalBinding/process'; +import { SeaBinding } from './internalBinding/sea'; import { SerdesBinding } from './internalBinding/serdes'; import { SymbolsBinding } from './internalBinding/symbols'; import { TimersBinding } from './internalBinding/timers'; @@ -23,6 +26,7 @@ import { ModulesBinding } from './internalBinding/modules'; import { ZlibBinding } from './internalBinding/zlib'; interface InternalBindingMap { + async_context_frame: AsyncContextFrameBinding; async_wrap: AsyncWrapBinding; blob: BlobBinding; config: ConfigBinding; @@ -31,12 +35,14 @@ interface InternalBindingMap { fs: FsBinding; fs_dir: FsDirBinding; http_parser: HttpParserBinding; + icu: ICUBinding; inspector: InspectorBinding; messaging: MessagingBinding; modules: ModulesBinding; options: OptionsBinding; os: OSBinding; process: ProcessBinding; + sea: SeaBinding; serdes: SerdesBinding; symbols: SymbolsBinding; timers: TimersBinding; @@ -61,6 +67,7 @@ declare global { | Int8Array | Int16Array | Int32Array + | Float16Array | Float32Array | Float64Array | BigUint64Array diff --git a/typings/internalBinding/async_context_frame.d.ts b/typings/internalBinding/async_context_frame.d.ts new file mode 100644 index 00000000000000..e7387b57653fd1 --- /dev/null +++ b/typings/internalBinding/async_context_frame.d.ts @@ -0,0 +1,4 @@ +export interface AsyncContextFrameBinding { + getContinuationPreservedEmbedderData(): unknown, + setContinuationPreservedEmbedderData(frame: unknown): void, +} diff --git a/typings/internalBinding/constants.d.ts b/typings/internalBinding/constants.d.ts index 75d2dcc65e8ea7..3c29df44c13303 100644 --- a/typings/internalBinding/constants.d.ts +++ b/typings/internalBinding/constants.d.ts @@ -287,6 +287,9 @@ export interface ConstantsBinding { BROTLI_ENCODE: 9; ZSTD_COMPRESS: 10; ZSTD_DECOMPRESS: 11; + ZSTD_e_continue: 0; + ZSTD_e_flush: 1; + ZSTD_e_end: 2; Z_MIN_WINDOWBITS: 8; Z_MAX_WINDOWBITS: 15; Z_DEFAULT_WINDOWBITS: 15; diff --git a/typings/internalBinding/http_parser.d.ts b/typings/internalBinding/http_parser.d.ts index 5ab5651b637176..124bdd5af2f152 100644 --- a/typings/internalBinding/http_parser.d.ts +++ b/typings/internalBinding/http_parser.d.ts @@ -2,6 +2,15 @@ declare namespace InternalHttpParserBinding { type Buffer = Uint8Array; type Stream = object; + class ConnectionsList { + constructor(); + + all(): HTTPParser[]; + idle(): HTTPParser[]; + active(): HTTPParser[]; + expired(): HTTPParser[]; + } + class HTTPParser { static REQUEST: 1; static RESPONSE: 2; @@ -40,6 +49,8 @@ declare namespace InternalHttpParserBinding { } export interface HttpParserBinding { - methods: string[]; + ConnectionsList: typeof InternalHttpParserBinding.ConnectionsList; HTTPParser: typeof InternalHttpParserBinding.HTTPParser; + allMethods: string[]; + methods: string[]; } diff --git a/typings/internalBinding/icu.d.ts b/typings/internalBinding/icu.d.ts new file mode 100644 index 00000000000000..7a688a5f08233e --- /dev/null +++ b/typings/internalBinding/icu.d.ts @@ -0,0 +1,18 @@ +export interface ICUBinding { + Converter: object; + decode( + converter: object, + input: ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + flags: number, + fromEncoding: string, + ): string; + getConverter(label: string, flags: number): object | undefined; + getStringWidth(value: string, ambiguousAsFullWidth?: boolean, expandEmojiSequence?: boolean): number; + hasConverter(label: string): boolean; + icuErrName(status: number): string; + transcode( + input: ArrayBufferView | ArrayBuffer | SharedArrayBuffer, + fromEncoding: string, + toEncoding: string, + ): Buffer | number; +} diff --git a/typings/internalBinding/sea.d.ts b/typings/internalBinding/sea.d.ts new file mode 100644 index 00000000000000..15f4430d87d1b4 --- /dev/null +++ b/typings/internalBinding/sea.d.ts @@ -0,0 +1,5 @@ +export interface SeaBinding { + getAsset(key: string): ArrayBuffer | undefined; + isExperimentalSeaWarningNeeded(): boolean; + isSea(): boolean; +} diff --git a/typings/internalBinding/symbols.d.ts b/typings/internalBinding/symbols.d.ts index 96310970d5cdee..8f754b283c0351 100644 --- a/typings/internalBinding/symbols.d.ts +++ b/typings/internalBinding/symbols.d.ts @@ -1,5 +1,6 @@ export const async_id_symbol: unique symbol; export const handle_onclose_symbol: unique symbol; +export const imported_cjs_symbol: unique symbol; export const no_message_symbol: unique symbol; export const messaging_deserialize_symbol: unique symbol; export const messaging_transfer_symbol: unique symbol; @@ -13,6 +14,7 @@ export const trigger_async_id_symbol: unique symbol; export interface SymbolsBinding { async_id_symbol: typeof async_id_symbol; handle_onclose_symbol: typeof handle_onclose_symbol; + imported_cjs_symbol: typeof imported_cjs_symbol; no_message_symbol: typeof no_message_symbol; messaging_deserialize_symbol: typeof messaging_deserialize_symbol; messaging_transfer_symbol: typeof messaging_transfer_symbol; diff --git a/typings/internalBinding/util.d.ts b/typings/internalBinding/util.d.ts index 34b4b31c1d8abd..2a68699283debe 100644 --- a/typings/internalBinding/util.d.ts +++ b/typings/internalBinding/util.d.ts @@ -45,4 +45,23 @@ export interface UtilBinding { guessHandleType(fd: number): 'TCP' | 'TTY' | 'UDP' | 'FILE' | 'PIPE' | 'UNKNOWN'; parseEnv(content: string): Record; styleText(format: Array | string, text: string): string; + isInsideNodeModules(frameLimit: number, defaultValue: unknown): boolean; + + constants: { + kPending: 0; + kFulfilled: 1; + kRejected: 2; + kExiting: 0; + kExitCode: 1; + kHasExitCode: 2; + ALL_PROPERTIES: 0; + ONLY_WRITABLE: 1; + ONLY_ENUMERABLE: 2; + ONLY_CONFIGURABLE: 4; + SKIP_STRINGS: 8; + SKIP_SYMBOLS: 16; + kDisallowCloneAndTransfer: 0; + kTransferable: 1; + kCloneable: 2; + }; } diff --git a/typings/primordials.d.ts b/typings/primordials.d.ts index 87ac2552287308..c8bf95d1f2cfc8 100644 --- a/typings/primordials.d.ts +++ b/typings/primordials.d.ts @@ -279,6 +279,7 @@ declare namespace primordials { export const FunctionPrototypeApply: UncurryThis export const FunctionPrototypeBind: UncurryThis export const FunctionPrototypeCall: UncurryThis + export const FunctionPrototypeSymbolHasInstance: UncurryMethod export const FunctionPrototypeToString: UncurryThis export import Int16Array = globalThis.Int16Array; export const Int16ArrayPrototype: typeof Int16Array.prototype @@ -370,6 +371,8 @@ declare namespace primordials { export const RegExpPrototypeGetSource: UncurryGetter; export const RegExpPrototypeGetSticky: UncurryGetter; export const RegExpPrototypeGetUnicode: UncurryGetter; + export const RegExpPrototypeSymbolReplace: UncurryMethod + export const RegExpPrototypeSymbolSplit: UncurryMethod export import Set = globalThis.Set; export const SetLength: typeof Set.length export const SetName: typeof Set.name From 212263a3055a89e838b84c53c0b3c71fddcec2a5 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sat, 2 Aug 2025 12:58:21 +0200 Subject: [PATCH 095/134] doc: clarify release candidate stability index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/59295 Reviewed-By: Antoine du Hamel Reviewed-By: James M Snell Reviewed-By: Rafael Gonzaga Reviewed-By: Jacob Smith Reviewed-By: Michaël Zasso Reviewed-By: Ruy Adorno Reviewed-By: Luigi Pinca Reviewed-By: Beth Griggs Reviewed-By: Claudio Wunder --- doc/api/documentation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api/documentation.md b/doc/api/documentation.md index c6edb13ad613cd..6938ac40a21374 100644 --- a/doc/api/documentation.md +++ b/doc/api/documentation.md @@ -41,9 +41,9 @@ The stability indexes are as follows: > minimum viability. > * 1.2 - Release candidate. Experimental features at this stage are hopefully > ready to become stable. No further breaking changes are anticipated but may -> still occur in response to user feedback. We encourage user testing and -> feedback so that we can know that this feature is ready to be marked as -> stable. +> still occur in response to user feedback or the features' underlying +> specification development. We encourage user testing and feedback so that +> we can know that this feature is ready to be marked as stable. > > Experimental features leave the experimental status typically either by > graduating to stable, or are removed without a deprecation cycle. From cd857a97b5bb42495d74b5ef940575514af73be1 Mon Sep 17 00:00:00 2001 From: hotpineapple <77835382+hotpineapple@users.noreply.github.com> Date: Sat, 2 Aug 2025 20:31:47 +0900 Subject: [PATCH 096/134] lib: use validateString refactor validation code using validate function PR-URL: https://github.com/nodejs/node/pull/59296 Reviewed-By: Ethan Arrowood Reviewed-By: Luigi Pinca Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Filip Skokan --- lib/_http_client.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index 00b59f357fa45d..0935191b3efc8b 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -78,6 +78,7 @@ const { const { validateInteger, validateBoolean, + validateString, } = require('internal/validators'); const { getTimerDuration } = require('internal/timers'); const { @@ -218,12 +219,11 @@ function ClientRequest(input, options, cb) { delete optsWithoutSignal.signal; } let method = options.method; - const methodIsString = (typeof method === 'string'); - if (method !== null && method !== undefined && !methodIsString) { - throw new ERR_INVALID_ARG_TYPE('options.method', 'string', method); + if (method != null) { + validateString(method, 'options.method'); } - if (methodIsString && method) { + if (method) { if (!checkIsHttpToken(method)) { throw new ERR_INVALID_HTTP_TOKEN('Method', method); } From 70a586261f22c5c83c8fd64d45566f027a4c2cb7 Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Sat, 2 Aug 2025 10:59:50 -0300 Subject: [PATCH 097/134] meta: add tsc and build team as codeowners building.md PR-URL: https://github.com/nodejs/node/pull/59298 Reviewed-By: Antoine du Hamel Reviewed-By: Marco Ippolito Reviewed-By: Ruy Adorno Reviewed-By: Darshan Sen Reviewed-By: Chengzhong Wu Reviewed-By: Matteo Collina Reviewed-By: Luigi Pinca --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cc363c492a5c4f..5ef23759b3e18e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -18,6 +18,7 @@ /doc/contributing/**/* @nodejs/tsc /GOVERNANCE.md @nodejs/tsc /SECURITY.md @nodejs/tsc +/BUILDING.md @nodejs/build @nodejs/tsc /LICENSE @nodejs/tsc /onboarding.md @nodejs/tsc From 68bec19f767255cb16d06242e117c737029c1bf7 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sat, 2 Aug 2025 07:23:15 -0700 Subject: [PATCH 098/134] test: add known issue test for fs.cpSync dereference bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs: https://github.com/nodejs/node/issues/58939 PR-URL: https://github.com/nodejs/node/pull/58941 Reviewed-By: Juan José Arboleda Reviewed-By: Luigi Pinca --- .../test-fs-cp-sync-dereference.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 test/known_issues/test-fs-cp-sync-dereference.js diff --git a/test/known_issues/test-fs-cp-sync-dereference.js b/test/known_issues/test-fs-cp-sync-dereference.js new file mode 100644 index 00000000000000..fbb07a8f781520 --- /dev/null +++ b/test/known_issues/test-fs-cp-sync-dereference.js @@ -0,0 +1,39 @@ +'use strict'; + +// Refs: https://github.com/nodejs/node/issues/58939 +// +// The cpSync function is not correctly handling the `dereference` option. +// In this test, both the cp and cpSync functions are attempting to copy +// a file over a symlinked directory. In the cp case it works fine. In the +// cpSync case it fails with an error. + +const common = require('../common'); + +const { + cp, + cpSync, + mkdirSync, + symlinkSync, + writeFileSync, +} = require('fs'); + +const { + join, +} = require('path'); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +const pathA = join(tmpdir.path, 'a'); +const pathB = join(tmpdir.path, 'b'); +const pathC = join(tmpdir.path, 'c'); +const pathD = join(tmpdir.path, 'd'); + +writeFileSync(pathA, 'file a'); +mkdirSync(pathB); +symlinkSync(pathB, pathC, 'dir'); +symlinkSync(pathB, pathD, 'dir'); + +cp(pathA, pathD, { dereference: false }, common.mustSucceed()); + +cpSync(pathA, pathC, { dereference: false }); From 946eab8d77e82706f8da4b1119d406517fa306c8 Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Sat, 2 Aug 2025 14:39:16 -0300 Subject: [PATCH 099/134] lib: handle superscript variants on windows device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows recognizes the 8-bit [ISO/IEC 8859-1](https://en.wikipedia.org/wiki/ISO/IEC_8859-1) superscript digits ¹, ², and ³ as digits and treats them as valid parts of COM# and LPT# device names, making them reserved in every directory. Signed-off-by: RafaelGSS PR-URL: https://github.com/nodejs/node/pull/59261 Reviewed-By: Robert Nagy Reviewed-By: Filip Skokan Reviewed-By: Matteo Collina --- lib/path.js | 2 ++ test/parallel/test-path-win32-normalize-device-names.js | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/lib/path.js b/lib/path.js index d39f67e75cd6b0..722e1ea27cf0a0 100644 --- a/lib/path.js +++ b/lib/path.js @@ -74,6 +74,8 @@ const WINDOWS_RESERVED_NAMES = [ 'CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9', + 'COM\xb9', 'COM\xb2', 'COM\xb3', + 'LPT\xb9', 'LPT\xb2', 'LPT\xb3', ]; function isWindowsReservedName(path, colonIndex) { diff --git a/test/parallel/test-path-win32-normalize-device-names.js b/test/parallel/test-path-win32-normalize-device-names.js index 927bc5cec8a2e5..2c6dcf142a2674 100644 --- a/test/parallel/test-path-win32-normalize-device-names.js +++ b/test/parallel/test-path-win32-normalize-device-names.js @@ -45,10 +45,18 @@ const normalizeDeviceNameTests = [ { input: 'COM1:', expected: '.\\COM1:.' }, { input: 'COM9:', expected: '.\\COM9:.' }, + { input: 'COM¹:', expected: '.\\COM¹:.' }, + { input: 'COM²:', expected: '.\\COM²:.' }, + { input: 'COM³:', expected: '.\\COM³:.' }, { input: 'COM1:.\\..\\..\\foo', expected: '.\\COM1:..\\..\\foo' }, + { input: 'COM¹:.\\..\\..\\foo', expected: '.\\COM¹:..\\..\\foo' }, { input: 'LPT1:', expected: '.\\LPT1:.' }, + { input: 'LPT¹:', expected: '.\\LPT¹:.' }, + { input: 'LPT²:', expected: '.\\LPT²:.' }, + { input: 'LPT³:', expected: '.\\LPT³:.' }, { input: 'LPT9:', expected: '.\\LPT9:.' }, { input: 'LPT1:.\\..\\..\\foo', expected: '.\\LPT1:..\\..\\foo' }, + { input: 'LPT¹:.\\..\\..\\foo', expected: '.\\LPT¹:..\\..\\foo' }, { input: 'LpT5:/another/path', expected: '.\\LpT5:another\\path' }, { input: 'C:\\foo', expected: 'C:\\foo' }, From a46ed50350c8264be9aa83655a32e85f6bd5dd32 Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Sat, 2 Aug 2025 15:23:28 -0300 Subject: [PATCH 100/134] doc: clarify the need of compiler compatible with c++20 Very often someone appear in the #node-core slack channel asking for guidance on this compilation error PR-URL: https://github.com/nodejs/node/pull/59297 Reviewed-By: Jacob Smith Reviewed-By: Luigi Pinca --- BUILDING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/BUILDING.md b/BUILDING.md index cedf2cb5e88d1e..d264bf79f3aab7 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -281,6 +281,11 @@ export CXX=g++-12 make -j4 ``` +> \[!IMPORTANT] +> If you face a compilation error during this process such as +> `error: no matching conversion for functional-style cast from 'unsigned int' to 'TypeIndex'` +> Make sure to use a `g++` or `clang` version compatible with C++20. + We can speed up the builds by using [Ninja](https://ninja-build.org/). For more information, see [Building Node.js with Ninja](doc/contributing/building-node-with-ninja.md). From 7f767a2e38d8b4fadcfbbfd4f2c20e024e9cc33a Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Sun, 3 Aug 2025 10:27:14 +0200 Subject: [PATCH 101/134] =?UTF-8?q?doc:=20correct=20orthography=20`eg.`=20?= =?UTF-8?q?=E2=86=92=20`e.g.`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/59329 Reviewed-By: Michaël Zasso Reviewed-By: Edy Silva Reviewed-By: James M Snell Reviewed-By: Rafael Gonzaga Reviewed-By: Luigi Pinca Reviewed-By: Zeyu "Alex" Yang --- doc/contributing/investigating-native-memory-leaks.md | 2 +- tools/msvs/msi/nodemsi/product.wxs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/contributing/investigating-native-memory-leaks.md b/doc/contributing/investigating-native-memory-leaks.md index 4d565fe031244f..6639617b54c53c 100644 --- a/doc/contributing/investigating-native-memory-leaks.md +++ b/doc/contributing/investigating-native-memory-leaks.md @@ -396,7 +396,7 @@ call: } ``` -Create a file (eg. `node-12.14.1.supp`) with the contents of the suppression +Create a file (e.g. `node-12.14.1.supp`) with the contents of the suppression records, and run Valgrind with the suppression file previously created: ```bash diff --git a/tools/msvs/msi/nodemsi/product.wxs b/tools/msvs/msi/nodemsi/product.wxs index ff66ade6816aaa..a0100cc564405f 100644 --- a/tools/msvs/msi/nodemsi/product.wxs +++ b/tools/msvs/msi/nodemsi/product.wxs @@ -41,7 +41,7 @@ - + From 438cb11a155e5b7c37049fac262d434cfbb96c51 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sun, 3 Aug 2025 13:31:39 +0200 Subject: [PATCH 102/134] test: update WPT resources,WebCryptoAPI,webstorage PR-URL: https://github.com/nodejs/node/pull/59311 Refs: https://github.com/nodejs/node/issues/58987 Refs: https://github.com/nodejs/node/issues/59310 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/fixtures/wpt/README.md | 8 +- ...rves_bits_curve448.tentative.https.any.js} | 0 ...rves_keys_curve448.tentative.https.any.js} | 0 ... => failures_Ed448.tentative.https.any.js} | 0 ...s => failures_X448.tentative.https.any.js} | 0 ...=> successes_Ed448.tentative.https.any.js} | 0 ... => successes_X448.tentative.https.any.js} | 0 .../wpt/WebCryptoAPI/getRandomValues.any.js | 6 +- ...kp_importKey_Ed448.tentative.https.any.js} | 0 ...okp_importKey_X448.tentative.https.any.js} | 0 ...Key_failures_Ed448.tentative.https.any.js} | 0 ...tKey_failures_X448.tentative.https.any.js} | 0 ... => eddsa_curve448.tentative.https.any.js} | 0 test/fixtures/wpt/resources/channel.sub.js | 2 +- .../fixtures/wpt/resources/check-layout-th.js | 3 +- test/fixtures/wpt/resources/check-layout.js | 245 --- .../declarative-shadow-dom-polyfill.js | 25 - .../wpt/resources/idlharness-shadowrealm.js | 61 - test/fixtures/wpt/resources/idlharness.js | 31 +- .../wpt/resources/out-of-scope-test.js | 5 + .../wpt/resources/testdriver-actions.js | 4 +- .../resources/testdriver-actions.js.headers | 2 + test/fixtures/wpt/resources/testdriver.js | 1366 ++++++++++++++++- ...rness-shadowrealm-audioworkletprocessor.js | 52 + .../testharness-shadowrealm-inner.js | 38 + .../testharness-shadowrealm-outer.js | 151 ++ test/fixtures/wpt/resources/testharness.js | 656 +++++--- .../wpt/resources/testharnessreport.js | 25 - .../wpt/resources/web-bluetooth-bidi-test.js | 408 +++++ test/fixtures/wpt/versions.json | 6 +- ...e_local_setitem_quotaexceedederr.window.js | 12 +- ...session_setitem_quotaexceedederr.window.js | 12 +- .../wpt/webstorage/symbol-props.window.js | 6 +- test/wpt/status/WebCryptoAPI.cjs | 16 + test/wpt/status/webstorage.json | 25 + 35 files changed, 2571 insertions(+), 594 deletions(-) rename test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/{cfrg_curves_bits_curve448.https.any.js => cfrg_curves_bits_curve448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/{cfrg_curves_keys_curve448.https.any.js => cfrg_curves_keys_curve448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/generateKey/{failures_Ed448.https.any.js => failures_Ed448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/generateKey/{failures_X448.https.any.js => failures_X448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/generateKey/{successes_Ed448.https.any.js => successes_Ed448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/generateKey/{successes_X448.https.any.js => successes_X448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/import_export/{okp_importKey_Ed448.https.any.js => okp_importKey_Ed448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/import_export/{okp_importKey_X448.https.any.js => okp_importKey_X448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/import_export/{okp_importKey_failures_Ed448.https.any.js => okp_importKey_failures_Ed448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/import_export/{okp_importKey_failures_X448.https.any.js => okp_importKey_failures_X448.tentative.https.any.js} (100%) rename test/fixtures/wpt/WebCryptoAPI/sign_verify/{eddsa_curve448.https.any.js => eddsa_curve448.tentative.https.any.js} (100%) delete mode 100644 test/fixtures/wpt/resources/check-layout.js delete mode 100644 test/fixtures/wpt/resources/declarative-shadow-dom-polyfill.js delete mode 100644 test/fixtures/wpt/resources/idlharness-shadowrealm.js create mode 100644 test/fixtures/wpt/resources/out-of-scope-test.js create mode 100644 test/fixtures/wpt/resources/testdriver-actions.js.headers create mode 100644 test/fixtures/wpt/resources/testharness-shadowrealm-audioworkletprocessor.js create mode 100644 test/fixtures/wpt/resources/testharness-shadowrealm-inner.js create mode 100644 test/fixtures/wpt/resources/testharness-shadowrealm-outer.js create mode 100644 test/fixtures/wpt/resources/web-bluetooth-bidi-test.js diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 1b452347e5d2a3..672f1653b91275 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -26,16 +26,16 @@ Last update: - interfaces: https://github.com/web-platform-tests/wpt/tree/e1b27be06b/interfaces - performance-timeline: https://github.com/web-platform-tests/wpt/tree/94caab7038/performance-timeline - resource-timing: https://github.com/web-platform-tests/wpt/tree/22d38586d0/resource-timing -- resources: https://github.com/web-platform-tests/wpt/tree/1e140d63ec/resources +- resources: https://github.com/web-platform-tests/wpt/tree/1d2c5fb36a/resources - streams: https://github.com/web-platform-tests/wpt/tree/bc9dcbbf1a/streams - url: https://github.com/web-platform-tests/wpt/tree/a23788b77a/url - user-timing: https://github.com/web-platform-tests/wpt/tree/5ae85bf826/user-timing - wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/cde25e7e3c/wasm/jsapi - wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi -- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/ab08796857/WebCryptoAPI -- webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/a370aad338/webidl/ecmascript-binding/es-exceptions +- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/1d2c5fb36a/WebCryptoAPI +- webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/2f96fa1996/webidl/ecmascript-binding/es-exceptions - webmessaging/broadcastchannel: https://github.com/web-platform-tests/wpt/tree/6495c91853/webmessaging/broadcastchannel -- webstorage: https://github.com/web-platform-tests/wpt/tree/1291340aaa/webstorage +- webstorage: https://github.com/web-platform-tests/wpt/tree/1d2c5fb36a/webstorage [Web Platform Tests]: https://github.com/web-platform-tests/wpt [`git node wpt`]: https://github.com/nodejs/node-core-utils/blob/main/docs/git-node.md#git-node-wpt diff --git a/test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_bits_curve448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_bits_curve448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_bits_curve448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_bits_curve448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_keys_curve448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_keys_curve448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_keys_curve448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/derive_bits_keys/cfrg_curves_keys_curve448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/generateKey/failures_Ed448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/generateKey/failures_Ed448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/generateKey/failures_Ed448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/generateKey/failures_Ed448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/generateKey/failures_X448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/generateKey/failures_X448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/generateKey/failures_X448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/generateKey/failures_X448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/generateKey/successes_Ed448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/generateKey/successes_Ed448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/generateKey/successes_Ed448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/generateKey/successes_Ed448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/generateKey/successes_X448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/generateKey/successes_X448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/generateKey/successes_X448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/generateKey/successes_X448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/getRandomValues.any.js b/test/fixtures/wpt/WebCryptoAPI/getRandomValues.any.js index 574134eb76dcd8..aecd38efd60bac 100644 --- a/test/fixtures/wpt/WebCryptoAPI/getRandomValues.any.js +++ b/test/fixtures/wpt/WebCryptoAPI/getRandomValues.any.js @@ -60,9 +60,9 @@ for (const array of arrays) { test(function() { const maxlength = 65536 / ctor.BYTES_PER_ELEMENT; - assert_throws_dom("QuotaExceededError", function() { - self.crypto.getRandomValues(new ctor(maxlength + 1)) - }, "crypto.getRandomValues length over 65536") + assert_throws_quotaexceedederror(() => { + self.crypto.getRandomValues(new ctor(maxlength + 1)); + }, null, null, "crypto.getRandomValues length over 65536"); }, "Large length: " + array); test(function() { diff --git a/test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_Ed448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_Ed448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_Ed448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_Ed448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_X448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_X448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_X448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_X448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_failures_Ed448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_failures_Ed448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_failures_Ed448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_failures_Ed448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_failures_X448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_failures_X448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_failures_X448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/import_export/okp_importKey_failures_X448.tentative.https.any.js diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa_curve448.https.any.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa_curve448.tentative.https.any.js similarity index 100% rename from test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa_curve448.https.any.js rename to test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa_curve448.tentative.https.any.js diff --git a/test/fixtures/wpt/resources/channel.sub.js b/test/fixtures/wpt/resources/channel.sub.js index d93b3b3091947d..370d4f5905e3fa 100644 --- a/test/fixtures/wpt/resources/channel.sub.js +++ b/test/fixtures/wpt/resources/channel.sub.js @@ -511,7 +511,7 @@ * * @param {SendChannel|string} [dest] - Either a SendChannel * to the destination, or the UUID of the destination. If - * omitted, a new UUID is generated, which can be used when + * ommitted, a new UUID is generated, which can be used when * constructing the URL for the global. * */ diff --git a/test/fixtures/wpt/resources/check-layout-th.js b/test/fixtures/wpt/resources/check-layout-th.js index f14ca3246b8ea2..2965a25d146a1f 100644 --- a/test/fixtures/wpt/resources/check-layout-th.js +++ b/test/fixtures/wpt/resources/check-layout-th.js @@ -218,6 +218,7 @@ window.checkLayout = function(selectorList, callDone = true) nodes = Array.prototype.slice.call(nodes); var checkedLayout = false; Array.prototype.forEach.call(nodes, function(node) { + const title = node.title ? `: ${node.title}` : ''; test(function(t) { var container = node.parentNode.className == 'container' ? node.parentNode : node; var prefix = @@ -240,7 +241,7 @@ window.checkLayout = function(selectorList, callDone = true) } checkedLayout |= !passed; } - }, selectorList + ' ' + String(++testNumber)); + }, `${selectorList} ${++testNumber}${title}`); }); if (!checkedLayout) { console.error("No valid data-* attributes found in selector list : " + selectorList); diff --git a/test/fixtures/wpt/resources/check-layout.js b/test/fixtures/wpt/resources/check-layout.js deleted file mode 100644 index 8634481497d701..00000000000000 --- a/test/fixtures/wpt/resources/check-layout.js +++ /dev/null @@ -1,245 +0,0 @@ -(function() { - -function insertAfter(nodeToAdd, referenceNode) -{ - if (referenceNode == document.body) { - document.body.appendChild(nodeToAdd); - return; - } - - if (referenceNode.nextSibling) - referenceNode.parentNode.insertBefore(nodeToAdd, referenceNode.nextSibling); - else - referenceNode.parentNode.appendChild(nodeToAdd); -} - -function positionedAncestor(node) -{ - var ancestor = node.parentNode; - while (getComputedStyle(ancestor).position == 'static') - ancestor = ancestor.parentNode; - return ancestor; -} - -function checkSubtreeExpectedValues(parent, failures) -{ - var checkedLayout = checkExpectedValues(parent, failures); - Array.prototype.forEach.call(parent.childNodes, function(node) { - checkedLayout |= checkSubtreeExpectedValues(node, failures); - }); - return checkedLayout; -} - -function checkAttribute(output, node, attribute) -{ - var result = node.getAttribute && node.getAttribute(attribute); - output.checked |= !!result; - return result; -} - -function checkExpectedValues(node, failures) -{ - var output = { checked: false }; - var expectedWidth = checkAttribute(output, node, "data-expected-width"); - if (expectedWidth) { - if (isNaN(expectedWidth) || Math.abs(node.offsetWidth - expectedWidth) >= 1) - failures.push("Expected " + expectedWidth + " for width, but got " + node.offsetWidth + ". "); - } - - var expectedHeight = checkAttribute(output, node, "data-expected-height"); - if (expectedHeight) { - if (isNaN(expectedHeight) || Math.abs(node.offsetHeight - expectedHeight) >= 1) - failures.push("Expected " + expectedHeight + " for height, but got " + node.offsetHeight + ". "); - } - - var expectedOffset = checkAttribute(output, node, "data-offset-x"); - if (expectedOffset) { - if (isNaN(expectedOffset) || Math.abs(node.offsetLeft - expectedOffset) >= 1) - failures.push("Expected " + expectedOffset + " for offsetLeft, but got " + node.offsetLeft + ". "); - } - - var expectedOffset = checkAttribute(output, node, "data-offset-y"); - if (expectedOffset) { - if (isNaN(expectedOffset) || Math.abs(node.offsetTop - expectedOffset) >= 1) - failures.push("Expected " + expectedOffset + " for offsetTop, but got " + node.offsetTop + ". "); - } - - var expectedOffset = checkAttribute(output, node, "data-positioned-offset-x"); - if (expectedOffset) { - var actualOffset = node.getBoundingClientRect().left - positionedAncestor(node).getBoundingClientRect().left; - if (isNaN(expectedOffset) || Math.abs(actualOffset - expectedOffset) >= 1) - failures.push("Expected " + expectedOffset + " for getBoundingClientRect().left offset, but got " + actualOffset + ". "); - } - - var expectedOffset = checkAttribute(output, node, "data-positioned-offset-y"); - if (expectedOffset) { - var actualOffset = node.getBoundingClientRect().top - positionedAncestor(node).getBoundingClientRect().top; - if (isNaN(expectedOffset) || Math.abs(actualOffset - expectedOffset) >= 1) - failures.push("Expected " + expectedOffset + " for getBoundingClientRect().top offset, but got " + actualOffset + ". "); - } - - var expectedWidth = checkAttribute(output, node, "data-expected-client-width"); - if (expectedWidth) { - if (isNaN(expectedWidth) || Math.abs(node.clientWidth - expectedWidth) >= 1) - failures.push("Expected " + expectedWidth + " for clientWidth, but got " + node.clientWidth + ". "); - } - - var expectedHeight = checkAttribute(output, node, "data-expected-client-height"); - if (expectedHeight) { - if (isNaN(expectedHeight) || Math.abs(node.clientHeight - expectedHeight) >= 1) - failures.push("Expected " + expectedHeight + " for clientHeight, but got " + node.clientHeight + ". "); - } - - var expectedWidth = checkAttribute(output, node, "data-expected-scroll-width"); - if (expectedWidth) { - if (isNaN(expectedWidth) || Math.abs(node.scrollWidth - expectedWidth) >= 1) - failures.push("Expected " + expectedWidth + " for scrollWidth, but got " + node.scrollWidth + ". "); - } - - var expectedHeight = checkAttribute(output, node, "data-expected-scroll-height"); - if (expectedHeight) { - if (isNaN(expectedHeight) || Math.abs(node.scrollHeight - expectedHeight) >= 1) - failures.push("Expected " + expectedHeight + " for scrollHeight, but got " + node.scrollHeight + ". "); - } - - var expectedOffset = checkAttribute(output, node, "data-total-x"); - if (expectedOffset) { - var totalLeft = node.clientLeft + node.offsetLeft; - if (isNaN(expectedOffset) || Math.abs(totalLeft - expectedOffset) >= 1) - failures.push("Expected " + expectedOffset + " for clientLeft+offsetLeft, but got " + totalLeft + ", clientLeft: " + node.clientLeft + ", offsetLeft: " + node.offsetLeft + ". "); - } - - var expectedOffset = checkAttribute(output, node, "data-total-y"); - if (expectedOffset) { - var totalTop = node.clientTop + node.offsetTop; - if (isNaN(expectedOffset) || Math.abs(totalTop - expectedOffset) >= 1) - failures.push("Expected " + expectedOffset + " for clientTop+offsetTop, but got " + totalTop + ", clientTop: " + node.clientTop + ", + offsetTop: " + node.offsetTop + ". "); - } - - var expectedDisplay = checkAttribute(output, node, "data-expected-display"); - if (expectedDisplay) { - var actualDisplay = getComputedStyle(node).display; - if (actualDisplay != expectedDisplay) - failures.push("Expected " + expectedDisplay + " for display, but got " + actualDisplay + ". "); - } - - var expectedPaddingTop = checkAttribute(output, node, "data-expected-padding-top"); - if (expectedPaddingTop) { - var actualPaddingTop = getComputedStyle(node).paddingTop; - // Trim the unit "px" from the output. - actualPaddingTop = actualPaddingTop.substring(0, actualPaddingTop.length - 2); - if (actualPaddingTop != expectedPaddingTop) - failures.push("Expected " + expectedPaddingTop + " for padding-top, but got " + actualPaddingTop + ". "); - } - - var expectedPaddingBottom = checkAttribute(output, node, "data-expected-padding-bottom"); - if (expectedPaddingBottom) { - var actualPaddingBottom = getComputedStyle(node).paddingBottom; - // Trim the unit "px" from the output. - actualPaddingBottom = actualPaddingBottom.substring(0, actualPaddingBottom.length - 2); - if (actualPaddingBottom != expectedPaddingBottom) - failures.push("Expected " + expectedPaddingBottom + " for padding-bottom, but got " + actualPaddingBottom + ". "); - } - - var expectedPaddingLeft = checkAttribute(output, node, "data-expected-padding-left"); - if (expectedPaddingLeft) { - var actualPaddingLeft = getComputedStyle(node).paddingLeft; - // Trim the unit "px" from the output. - actualPaddingLeft = actualPaddingLeft.substring(0, actualPaddingLeft.length - 2); - if (actualPaddingLeft != expectedPaddingLeft) - failures.push("Expected " + expectedPaddingLeft + " for padding-left, but got " + actualPaddingLeft + ". "); - } - - var expectedPaddingRight = checkAttribute(output, node, "data-expected-padding-right"); - if (expectedPaddingRight) { - var actualPaddingRight = getComputedStyle(node).paddingRight; - // Trim the unit "px" from the output. - actualPaddingRight = actualPaddingRight.substring(0, actualPaddingRight.length - 2); - if (actualPaddingRight != expectedPaddingRight) - failures.push("Expected " + expectedPaddingRight + " for padding-right, but got " + actualPaddingRight + ". "); - } - - var expectedMarginTop = checkAttribute(output, node, "data-expected-margin-top"); - if (expectedMarginTop) { - var actualMarginTop = getComputedStyle(node).marginTop; - // Trim the unit "px" from the output. - actualMarginTop = actualMarginTop.substring(0, actualMarginTop.length - 2); - if (actualMarginTop != expectedMarginTop) - failures.push("Expected " + expectedMarginTop + " for margin-top, but got " + actualMarginTop + ". "); - } - - var expectedMarginBottom = checkAttribute(output, node, "data-expected-margin-bottom"); - if (expectedMarginBottom) { - var actualMarginBottom = getComputedStyle(node).marginBottom; - // Trim the unit "px" from the output. - actualMarginBottom = actualMarginBottom.substring(0, actualMarginBottom.length - 2); - if (actualMarginBottom != expectedMarginBottom) - failures.push("Expected " + expectedMarginBottom + " for margin-bottom, but got " + actualMarginBottom + ". "); - } - - var expectedMarginLeft = checkAttribute(output, node, "data-expected-margin-left"); - if (expectedMarginLeft) { - var actualMarginLeft = getComputedStyle(node).marginLeft; - // Trim the unit "px" from the output. - actualMarginLeft = actualMarginLeft.substring(0, actualMarginLeft.length - 2); - if (actualMarginLeft != expectedMarginLeft) - failures.push("Expected " + expectedMarginLeft + " for margin-left, but got " + actualMarginLeft + ". "); - } - - var expectedMarginRight = checkAttribute(output, node, "data-expected-margin-right"); - if (expectedMarginRight) { - var actualMarginRight = getComputedStyle(node).marginRight; - // Trim the unit "px" from the output. - actualMarginRight = actualMarginRight.substring(0, actualMarginRight.length - 2); - if (actualMarginRight != expectedMarginRight) - failures.push("Expected " + expectedMarginRight + " for margin-right, but got " + actualMarginRight + ". "); - } - - return output.checked; -} - -window.checkLayout = function(selectorList, outputContainer) -{ - var result = true; - if (!selectorList) { - document.body.appendChild(document.createTextNode("You must provide a CSS selector of nodes to check.")); - return; - } - var nodes = document.querySelectorAll(selectorList); - nodes = Array.prototype.slice.call(nodes); - nodes.reverse(); - var checkedLayout = false; - Array.prototype.forEach.call(nodes, function(node) { - var failures = []; - checkedLayout |= checkExpectedValues(node.parentNode, failures); - checkedLayout |= checkSubtreeExpectedValues(node, failures); - - var container = node.parentNode.className == 'container' ? node.parentNode : node; - - var pre = document.createElement('pre'); - if (failures.length) { - pre.className = 'FAIL'; - result = false; - } - pre.appendChild(document.createTextNode(failures.length ? "FAIL:\n" + failures.join('\n') + '\n\n' + container.outerHTML : "PASS")); - - var referenceNode = container; - if (outputContainer) { - if (!outputContainer.lastChild) { - // Inserting a text node so we have something to insertAfter. - outputContainer.textContent = " "; - } - referenceNode = outputContainer.lastChild; - } - insertAfter(pre, referenceNode); - }); - - if (!checkedLayout) { - document.body.appendChild(document.createTextNode("FAIL: No valid data-* attributes found in selector list : " + selectorList)); - return false; - } - - return result; -} - -})(); diff --git a/test/fixtures/wpt/resources/declarative-shadow-dom-polyfill.js b/test/fixtures/wpt/resources/declarative-shadow-dom-polyfill.js deleted file mode 100644 index 99a3e911eb6336..00000000000000 --- a/test/fixtures/wpt/resources/declarative-shadow-dom-polyfill.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Polyfill for attaching shadow trees for declarative Shadow DOM for - * implementations that do not support declarative Shadow DOM. - * - * Note: this polyfill will feature-detect the native feature, and do nothing - * if supported. - * - * See: https://github.com/whatwg/html/pull/5465 - * - * root: The root of the subtree in which to upgrade shadow roots - * - */ - -function polyfill_declarative_shadow_dom(root) { - if (HTMLTemplateElement.prototype.hasOwnProperty('shadowRootMode')) - return; - root.querySelectorAll("template[shadowrootmode]").forEach(template => { - const mode = template.getAttribute("shadowrootmode"); - const delegatesFocus = template.hasAttribute("shadowrootdelegatesfocus"); - const shadowRoot = template.parentNode.attachShadow({ mode, delegatesFocus }); - shadowRoot.appendChild(template.content); - template.remove(); - polyfill_declarative_shadow_dom(shadowRoot); - }); -} diff --git a/test/fixtures/wpt/resources/idlharness-shadowrealm.js b/test/fixtures/wpt/resources/idlharness-shadowrealm.js deleted file mode 100644 index 9484ca6f512ad0..00000000000000 --- a/test/fixtures/wpt/resources/idlharness-shadowrealm.js +++ /dev/null @@ -1,61 +0,0 @@ -// TODO: it would be nice to support `idl_array.add_objects` -function fetch_text(url) { - return fetch(url).then(function (r) { - if (!r.ok) { - throw new Error("Error fetching " + url + "."); - } - return r.text(); - }); -} - -/** - * idl_test_shadowrealm is a promise_test wrapper that handles the fetching of the IDL, and - * running the code in a `ShadowRealm`, avoiding repetitive boilerplate. - * - * @see https://github.com/tc39/proposal-shadowrealm - * @param {String[]} srcs Spec name(s) for source idl files (fetched from - * /interfaces/{name}.idl). - * @param {String[]} deps Spec name(s) for dependency idl files (fetched - * from /interfaces/{name}.idl). Order is important - dependencies from - * each source will only be included if they're already know to be a - * dependency (i.e. have already been seen). - */ -function idl_test_shadowrealm(srcs, deps) { - promise_setup(async t => { - const realm = new ShadowRealm(); - // https://github.com/web-platform-tests/wpt/issues/31996 - realm.evaluate("globalThis.self = globalThis; undefined;"); - - realm.evaluate(` - globalThis.self.GLOBAL = { - isWindow: function() { return false; }, - isWorker: function() { return false; }, - isShadowRealm: function() { return true; }, - }; undefined; - `); - const specs = await Promise.all(srcs.concat(deps).map(spec => { - return fetch_text("/interfaces/" + spec + ".idl"); - })); - const idls = JSON.stringify(specs); - await new Promise( - realm.evaluate(`(resolve,reject) => { - (async () => { - await import("/resources/testharness.js"); - await import("/resources/WebIDLParser.js"); - await import("/resources/idlharness.js"); - const idls = ${idls}; - const idl_array = new IdlArray(); - for (let i = 0; i < ${srcs.length}; i++) { - idl_array.add_idls(idls[i]); - } - for (let i = ${srcs.length}; i < ${srcs.length + deps.length}; i++) { - idl_array.add_dependency_idls(idls[i]); - } - idl_array.test(); - })().then(resolve, (e) => reject(e.toString())); - }`) - ); - await fetch_tests_from_shadow_realm(realm); - }); -} -// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker: diff --git a/test/fixtures/wpt/resources/idlharness.js b/test/fixtures/wpt/resources/idlharness.js index 056fcdd4a1076a..2eb710c1827cda 100644 --- a/test/fixtures/wpt/resources/idlharness.js +++ b/test/fixtures/wpt/resources/idlharness.js @@ -566,6 +566,7 @@ IdlArray.prototype.is_json_type = function(type) case "Uint8ClampedArray": case "BigInt64Array": case "BigUint64Array": + case "Float16Array": case "Float32Array": case "Float64Array": case "ArrayBuffer": @@ -733,7 +734,7 @@ IdlArray.prototype.test = function() Object.getOwnPropertyNames(this.members).forEach(function(memberName) { var member = this.members[memberName]; - if (!(member instanceof IdlInterface)) { + if (!(member instanceof IdlInterface || member instanceof IdlNamespace)) { return; } @@ -782,6 +783,10 @@ IdlArray.prototype.merge_partials = function() } testedPartials.set(parsed_idl.name, partialTestCount); + if (!self.shouldRunSubTest(partialTestName)) { + return; + } + if (!parsed_idl.untested) { test(function () { assert_true(originalExists, `Original ${parsed_idl.type} should be defined`); @@ -809,7 +814,7 @@ IdlArray.prototype.merge_partials = function() { // Special-case "Exposed". Must be a subset of original interface's exposure. // Exposed on a partial is the equivalent of having the same Exposed on all nested members. - // See https://github.com/heycam/webidl/issues/154 for discrepancy between Exposed and + // See https://github.com/heycam/webidl/issues/154 for discrepency between Exposed and // other extended attributes on partial interfaces. const exposureAttr = parsed_idl.extAttrs.find(a => a.name === "Exposed"); if (exposureAttr) { @@ -870,6 +875,7 @@ IdlArray.prototype.merge_mixins = function() { const lhs = parsed_idl.target; const rhs = parsed_idl.includes; + const testName = lhs + " includes " + rhs + ": member names are unique"; var errStr = lhs + " includes " + rhs + ", but "; if (!(lhs in this.members)) throw errStr + lhs + " is undefined."; @@ -877,7 +883,7 @@ IdlArray.prototype.merge_mixins = function() if (!(rhs in this.members)) throw errStr + rhs + " is undefined."; if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface."; - if (this.members[rhs].members.length) { + if (this.members[rhs].members.length && self.shouldRunSubTest(testName)) { test(function () { var clash = this.members[rhs].members.find(function(member) { return this.members[lhs].members.find(function(m) { @@ -891,7 +897,7 @@ IdlArray.prototype.merge_mixins = function() this.members[lhs].members.push(new IdlInterfaceMember(member)); }.bind(this)); assert_true(!clash, "member " + (clash && clash.name) + " is unique"); - }.bind(this), lhs + " includes " + rhs + ": member names are unique"); + }.bind(this), testName); } } this.includes = []; @@ -1420,7 +1426,7 @@ IdlInterface.prototype.test = function() if (!this.untested) { subsetTestByKey(this.name, test, function() { - assert_false(this.name in self); + assert_false(this.name in self, this.name + " interface should not exist"); }.bind(this), this.name + " interface: existence and properties of interface object"); } return; @@ -3450,6 +3456,17 @@ IdlNamespace.prototype.test_self = function () IdlNamespace.prototype.test = function () { + // If the namespace object is not exposed, only test that. Members can't be + // tested either + if (!this.exposed) { + if (!this.untested) { + subsetTestByKey(this.name, test, function() { + assert_false(this.name in self, this.name + " namespace should not exist"); + }.bind(this), this.name + " namespace: existence and properties of namespace object"); + } + return; + } + if (!this.untested) { this.test_self(); } @@ -3497,7 +3514,7 @@ function idl_test(srcs, deps, idl_setup_func) { "require-exposed" ]; return Promise.all( - srcs.concat(deps).map(fetch_spec)) + srcs.concat(deps).map(globalThis.fetch_spec)) .then(function(results) { const astArray = results.map(result => WebIDL2.parse(result.idl, { sourceName: result.spec }) @@ -3538,9 +3555,11 @@ function idl_test(srcs, deps, idl_setup_func) { }); }, 'idl_test setup'); } +globalThis.idl_test = idl_test; /** * fetch_spec is a shorthand for a Promise that fetches the spec's content. + * Note: ShadowRealm-specific implementation in testharness-shadowrealm-inner.js */ function fetch_spec(spec) { var url = '/interfaces/' + spec + '.idl'; diff --git a/test/fixtures/wpt/resources/out-of-scope-test.js b/test/fixtures/wpt/resources/out-of-scope-test.js new file mode 100644 index 00000000000000..ce24124646dc83 --- /dev/null +++ b/test/fixtures/wpt/resources/out-of-scope-test.js @@ -0,0 +1,5 @@ +// Testing that the resolution is correct using `resolve`, as you can't import +// the same module twice. +window.outscope_test_result = import.meta.resolve("a"); +window.outscope_test_result2 = import.meta.resolve("../resources/log.sub.js?name=E"); + diff --git a/test/fixtures/wpt/resources/testdriver-actions.js b/test/fixtures/wpt/resources/testdriver-actions.js index e550ff0b1dc903..edb4759954d4c3 100644 --- a/test/fixtures/wpt/resources/testdriver-actions.js +++ b/test/fixtures/wpt/resources/testdriver-actions.js @@ -32,7 +32,7 @@ * await actions.send(); * * @param {number} [defaultTickDuration] - The default duration of a - * tick. Be default this is set to 16ms, which is one frame time + * tick. Be default this is set ot 16ms, which is one frame time * based on 60Hz display. */ function Actions(defaultTickDuration=16) { @@ -290,7 +290,7 @@ }, /** - * Create a keyDown event for the current default key source + * Create a keyUp event for the current default key source * * @param {String} key - Key to release * @param {String?} sourceName - Named key source to use or null for the default key source diff --git a/test/fixtures/wpt/resources/testdriver-actions.js.headers b/test/fixtures/wpt/resources/testdriver-actions.js.headers new file mode 100644 index 00000000000000..5e8f640c6659d1 --- /dev/null +++ b/test/fixtures/wpt/resources/testdriver-actions.js.headers @@ -0,0 +1,2 @@ +Content-Type: text/javascript; charset=utf-8 +Cache-Control: max-age=3600 diff --git a/test/fixtures/wpt/resources/testdriver.js b/test/fixtures/wpt/resources/testdriver.js index ddf723cb3ee8a5..5b390dedeb72bb 100644 --- a/test/fixtures/wpt/resources/testdriver.js +++ b/test/fixtures/wpt/resources/testdriver.js @@ -3,6 +3,26 @@ var idCounter = 0; let testharness_context = null; + const features = (() => { + function getFeatures(scriptSrc) { + try { + const url = new URL(scriptSrc); + return url.searchParams.getAll('feature'); + } catch (e) { + return []; + } + } + + return getFeatures(document?.currentScript?.src ?? ''); + })(); + + function assertBidiIsEnabled(){ + if (!features.includes('bidi')) { + throw new Error( + "`?feature=bidi` is missing when importing testdriver.js but the test is using WebDriver BiDi APIs"); + } + } + function getInViewCenterPoint(rect) { var left = Math.max(0, rect.left); var right = Math.min(window.innerWidth, rect.right); @@ -49,6 +69,924 @@ * @namespace {test_driver} */ window.test_driver = { + /** + Represents `WebDriver BiDi `_ protocol. + */ + bidi: { + /** + * @typedef {(String|WindowProxy)} Context A browsing context. Can + * be specified by its ID (a string) or using a `WindowProxy` + * object. + */ + /** + * `bluetooth `_ module. + */ + bluetooth: { + /** + * Handle a bluetooth device prompt with the given params. Matches the + * `bluetooth.handleRequestDevicePrompt + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.handleRequestDevicePrompt({ + * prompt: "pmt-e0a234b", + * accept: true, + * device: "dvc-9b3b872" + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.prompt - The id of a bluetooth device prompt. + * Matches the + * `bluetooth.HandleRequestDevicePromptParameters:prompt `_ + * value. + * @param {bool} params.accept - Whether to accept a bluetooth device prompt. + * Matches the + * `bluetooth.HandleRequestDevicePromptAcceptParameters:accept `_ + * value. + * @param {string} params.device - The device id from a bluetooth device + * prompt to be accepted. Matches the + * `bluetooth.HandleRequestDevicePromptAcceptParameters:device `_ + * value. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the bluetooth device prompt should be handled. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the bluetooth device prompt + * is handled, or rejected if the operation fails. + */ + handle_request_device_prompt: function(params) { + return window.test_driver_internal.bidi.bluetooth + .handle_request_device_prompt(params); + }, + /** + * Creates a simulated bluetooth adapter with the given params. Matches the + * `bluetooth.simulateAdapter `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_adapter({ + * state: "powered-on" + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.state The state of the simulated bluetooth adapter. + * Matches the + * `bluetooth.SimulateAdapterParameters:state `_ + * value. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the simulated bluetooth adapter should be set. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the simulated bluetooth adapter is created + * and set, or rejected if the operation fails. + */ + simulate_adapter: function (params) { + return window.test_driver_internal.bidi.bluetooth.simulate_adapter(params); + }, + /** + * Disables the bluetooth simulation with the given params. Matches the + * `bluetooth.disableSimulation `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.disable_simulation(); + * + * @param {object} params - Parameters for the command. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context to disable the simulation for. If not provided, the + * current browsing context is used. + * @returns {Promise} fulfilled after the simulation is disabled, or rejected if + * the operation fails. + */ + disable_simulation: function (params) { + return window.test_driver_internal.bidi.bluetooth.disable_simulation(params); + }, + /** + * Creates a simulated bluetooth peripheral with the given params. + * Matches the + * `bluetooth.simulatePreconnectedPeripheral `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulatePreconnectedPeripheral({ + * "address": "09:09:09:09:09:09", + * "name": "Some Device", + * "manufacturerData": [{key: 17, data: "AP8BAX8="}], + * "knownServiceUuids": [ + * "12345678-1234-5678-9abc-def123456789", + * ], + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.address - The address of the simulated + * bluetooth peripheral. Matches the + * `bluetooth.SimulatePreconnectedPeripheralParameters:address `_ + * value. + * @param {string} params.name - The name of the simulated bluetooth + * peripheral. Matches the + * `bluetooth.SimulatePreconnectedPeripheralParameters:name `_ + * value. + * @param {Array.ManufacturerData} params.manufacturerData - The manufacturerData of the + * simulated bluetooth peripheral. Matches the + * `bluetooth.SimulatePreconnectedPeripheralParameters:manufacturerData `_ + * value. + * @param {string} params.knownServiceUuids - The knownServiceUuids of + * the simulated bluetooth peripheral. Matches the + * `bluetooth.SimulatePreconnectedPeripheralParameters:knownServiceUuids `_ + * value. + * @param {Context} [params.context] The optional context parameter + * specifies in which browsing context the simulated bluetooth peripheral should be + * set. If not provided, the current browsing context is used. + * @returns {Promise} fulfilled after the simulated bluetooth peripheral is created + * and set, or rejected if the operation fails. + */ + simulate_preconnected_peripheral: function(params) { + return window.test_driver_internal.bidi.bluetooth + .simulate_preconnected_peripheral(params); + }, + /** + * Simulates a GATT connection response for a given peripheral. + * Matches the `bluetooth.simulateGattConnectionResponse + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_gatt_connection_response({ + * "address": "09:09:09:09:09:09", + * "code": 0x0 + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.address - The address of the simulated + * bluetooth peripheral. Matches the + * `bluetooth.SimulateGattConnectionResponseParameters:peripheral `_ + * value. + * @param {number} params.code - The response code for a GATT connection attempted. + * Matches the + * `bluetooth.SimulateGattConnectionResponseParameters:code `_ + * value. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the GATT connection response should be simulated. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the GATT connection response + * is simulated, or rejected if the operation fails. + */ + simulate_gatt_connection_response: function(params) { + return window.test_driver_internal.bidi.bluetooth + .simulate_gatt_connection_response(params); + }, + /** + * Simulates a GATT disconnection for a given peripheral. + * Matches the `bluetooth.simulateGattDisconnection + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_gatt_disconnection({ + * "address": "09:09:09:09:09:09", + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.address - The address of the simulated + * bluetooth peripheral. Matches the + * `bluetooth.SimulateGattDisconnectionParameters:address `_ + * value. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the GATT disconnection should be simulated. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the GATT disconnection + * is simulated, or rejected if the operation fails. + */ + simulate_gatt_disconnection: function(params) { + return window.test_driver_internal.bidi.bluetooth + .simulate_gatt_disconnection(params); + }, + /** + * Simulates a GATT service. + * Matches the `bluetooth.simulateService + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_service({ + * "address": "09:09:09:09:09:09", + * "uuid": "0000180d-0000-1000-8000-00805f9b34fb", + * "type": "add" + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.address - The address of the simulated bluetooth peripheral this service belongs to. + * Matches the + * `bluetooth.SimulateServiceParameters:address `_ + * value. + * @param {string} params.uuid - The uuid of the simulated GATT service. + * Matches the + * `bluetooth.SimulateServiceParameters:address `_ + * value. + * @param {string} params.type - The type of the GATT service simulation, either "add" or "remove". + * Matches the + * `bluetooth.SimulateServiceParameters:address `_ + * value. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the GATT service should be simulated. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the GATT service + * is simulated, or rejected if the operation fails. + */ + simulate_service: function(params) { + return window.test_driver_internal.bidi.bluetooth + .simulate_service(params); + }, + /** + * Simulates a GATT characteristic. + * Matches the `bluetooth.simulateCharacteristic + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_characteristic({ + * "address": "09:09:09:09:09:09", + * "serviceUuid": "0000180d-0000-1000-8000-00805f9b34fb", + * "characteristicUuid": "00002a21-0000-1000-8000-00805f9b34fb", + * "characteristicProperties": { + * "read": true, + * "write": true, + * "notify": true + * }, + * "type": "add" + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.address - The address of the simulated bluetooth peripheral the characterisitc belongs to. + * Matches the + * `bluetooth.SimulateCharacteristicParameters:address `_ + * value. + * @param {string} params.serviceUuid - The uuid of the simulated GATT service the characterisitc belongs to. + * Matches the + * `bluetooth.SimulateCharacteristicParameters:address `_ + * value. + * @param {string} params.characteristicUuid - The uuid of the simulated GATT characteristic. + * Matches the + * `bluetooth.SimulateCharacteristicParameters:address `_ + * value. + * @param {string} params.characteristicProperties - The properties of the simulated GATT characteristic. + * Matches the + * `bluetooth.SimulateCharacteristicParameters:address `_ + * value. + * @param {string} params.type - The type of the GATT characterisitc simulation, either "add" or "remove". + * Matches the + * `bluetooth.SimulateCharacteristicParameters:address `_ + * value. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the GATT characteristic should be simulated. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the GATT characteristic + * is simulated, or rejected if the operation fails. + */ + simulate_characteristic: function(params) { + return window.test_driver_internal.bidi.bluetooth + .simulate_characteristic(params); + }, + /** + * Simulates a GATT characteristic response. + * Matches the `bluetooth.simulateCharacteristicResponse + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_characteristic({ + * "address": "09:09:09:09:09:09", + * "serviceUuid": "0000180d-0000-1000-8000-00805f9b34fb", + * "characteristicUuid": "00002a21-0000-1000-8000-00805f9b34fb", + * "type": "read", + * "code": 0, + * "data": [1, 2] + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.address - The address of the simulated + * bluetooth peripheral. Matches the + * `bluetooth.SimulateCharacteristicResponseParameters:address `_ + * value. + * @param {string} params.serviceUuid - The uuid of the simulated GATT service the characterisitc belongs to. + * Matches the + * `bluetooth.SimulateCharacteristicResponseParameters:address `_ + * value. + * @param {string} params.characteristicUuid - The uuid of the simulated characteristic. + * Matches the + * `bluetooth.SimulateCharacteristicResponseParameters:address `_ + * value. + * @param {string} params.type - The type of the simulated GATT characteristic operation." + * Can be "read", "write", "subscribe-to-notifications" or "unsubscribe-from-notifications". + * Matches the + * `bluetooth.SimulateCharacteristicResponseParameters:address `_ + * value. + * @param {string} params.code - The simulated GATT characteristic response code. + * Matches the + * `bluetooth.SimulateCharacteristicResponseParameters:address `_ + * value.* + * @param {string} params.data - The data along with the simulated GATT characteristic response. + * Matches the + * `bluetooth.SimulateCharacteristicResponseParameters:address `_ + * value.** + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the GATT characteristic belongs to. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the GATT characteristic + * is simulated, or rejected if the operation fails. + */ + simulate_characteristic_response: function(params) { + return window.test_driver_internal.bidi.bluetooth + .simulate_characteristic_response(params); + }, + /** + * Simulates a GATT descriptor. + * Matches the `bluetooth.simulateDescriptor + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_descriptor({ + * "address": "09:09:09:09:09:09", + * "serviceUuid": "0000180d-0000-1000-8000-00805f9b34fb", + * "characteristicUuid": "00002a21-0000-1000-8000-00805f9b34fb", + * "descriptorUuid": "00002901-0000-1000-8000-00805f9b34fb", + * "type": "add" + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.address - The address of the simulated bluetooth peripheral the descriptor belongs to. + * Matches the + * `bluetooth.SimulateDescriptorParameters:address `_ + * value. + * @param {string} params.serviceUuid - The uuid of the simulated GATT service the descriptor belongs to. + * Matches the + * `bluetooth.SimulateDescriptorParameters:address `_ + * value. + * @param {string} params.characteristicUuid - The uuid of the simulated GATT characterisitc the descriptor belongs to. + * Matches the + * `bluetooth.SimulateDescriptorParameters:address `_ + * value. + * @param {string} params.descriptorUuid - The uuid of the simulated GATT descriptor. + * Matches the + * `bluetooth.SimulateDescriptorParameters:address `_ + * value.* + * @param {string} params.type - The type of the GATT descriptor simulation, either "add" or "remove". + * Matches the + * `bluetooth.SimulateDescriptorParameters:address `_ + * value. + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the GATT descriptor should be simulated. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the GATT descriptor + * is simulated, or rejected if the operation fails. + */ + simulate_descriptor: function(params) { + return window.test_driver_internal.bidi.bluetooth + .simulate_descriptor(params); + }, + /** + * Simulates a GATT descriptor response. + * Matches the `bluetooth.simulateDescriptorResponse + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.bluetooth.simulate_descriptor_response({ + * "address": "09:09:09:09:09:09", + * "serviceUuid": "0000180d-0000-1000-8000-00805f9b34fb", + * "characteristicUuid": "00002a21-0000-1000-8000-00805f9b34fb", + * "descriptorUuid": "00002901-0000-1000-8000-00805f9b34fb", + * "type": "read", + * "code": 0, + * "data": [1, 2] + * }); + * + * @param {object} params - Parameters for the command. + * @param {string} params.address - The address of the simulated bluetooth peripheral the descriptor belongs to. + * Matches the + * `bluetooth.SimulateDescriptorResponseParameters:address `_ + * value. + * @param {string} params.serviceUuid - The uuid of the simulated GATT service the descriptor belongs to. + * Matches the + * `bluetooth.SimulateDescriptorResponseParameters:address `_ + * value. + * @param {string} params.characteristicUuid - The uuid of the simulated GATT characterisitc the descriptor belongs to. + * Matches the + * `bluetooth.SimulateDescriptorResponseParameters:address `_ + * value. + * @param {string} params.descriptorUuid - The uuid of the simulated GATT descriptor. + * Matches the + * `bluetooth.SimulateDescriptorResponseParameters:address `_ + * value. + * @param {string} params.type - The type of the simulated GATT descriptor operation. + * Matches the + * `bluetooth.SimulateDescriptorResponseParameters:address `_ + * value. + * @param {string} params.code - The simulated GATT descriptor response code. + * Matches the + * `bluetooth.SimulateDescriptorResponseParameters:address `_ + * value.* + * @param {string} params.data - The data along with the simulated GATT descriptor response. + * Matches the + * `bluetooth.SimulateDescriptorResponseParameters:address `_ + * value.** + * @param {Context} [params.context] The optional context parameter specifies in + * which browsing context the GATT descriptor belongs to. If not + * provided, the current browsing context is used. + * @returns {Promise} fulfilled after the GATT descriptor response + * is simulated, or rejected if the operation fails. + */ + simulate_descriptor_response: function(params) { + return window.test_driver_internal.bidi.bluetooth + .simulate_descriptor_response(params); + }, + /** + * `bluetooth.RequestDevicePromptUpdatedParameters `_ + * event. + */ + request_device_prompt_updated: { + /** + * @typedef {object} RequestDevicePromptUpdated + * `bluetooth.RequestDevicePromptUpdatedParameters `_ + * event. + */ + + /** + * Subscribes to the event. Events will be emitted only if + * there is a subscription for the event. This method does + * not add actual listeners. To listen to the event, use the + * `on` or `once` methods. The buffered events will be + * emitted before the command promise is resolved. + * + * @param {object} [params] Parameters for the subscription. + * @param {null|Array.<(Context)>} [params.contexts] The + * optional contexts parameter specifies which browsing + * contexts to subscribe to the event on. It should be + * either an array of Context objects, or null. If null, the + * event will be subscribed to globally. If omitted, the + * event will be subscribed to on the current browsing + * context. + * @returns {Promise<(function(): Promise)>} Callback + * for unsubscribing from the created subscription. + */ + subscribe: async function(params = {}) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.bluetooth + .request_device_prompt_updated.subscribe(params); + }, + /** + * Adds an event listener for the event. + * + * @param {function(RequestDevicePromptUpdated): void} callback The + * callback to be called when the event is emitted. The + * callback is called with the event object as a parameter. + * @returns {function(): void} A function that removes the + * added event listener when called. + */ + on: function(callback) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.bluetooth + .request_device_prompt_updated.on(callback); + }, + /** + * Adds an event listener for the event that is only called + * once and removed afterward. + * + * @return {Promise} The promise which + * is resolved with the event object when the event is emitted. + */ + once: function() { + assertBidiIsEnabled(); + return new Promise(resolve => { + const remove_handler = + window.test_driver_internal.bidi.bluetooth + .request_device_prompt_updated.on(event => { + resolve(event); + remove_handler(); + }); + }); + }, + }, + /** + * `bluetooth.GattConnectionAttemptedParameters `_ + * event. + */ + gatt_connection_attempted: { + /** + * @typedef {object} GattConnectionAttempted + * `bluetooth.GattConnectionAttempted `_ + * event. + */ + + /** + * Subscribes to the event. Events will be emitted only if + * there is a subscription for the event. This method does + * not add actual listeners. To listen to the event, use the + * `on` or `once` methods. The buffered events will be + * emitted before the command promise is resolved. + * + * @param {object} [params] Parameters for the subscription. + * @param {null|Array.<(Context)>} [params.contexts] The + * optional contexts parameter specifies which browsing + * contexts to subscribe to the event on. It should be + * either an array of Context objects, or null. If null, the + * event will be subscribed to globally. If omitted, the + * event will be subscribed to on the current browsing + * context. + * @returns {Promise<(function(): Promise)>} Callback + * for unsubscribing from the created subscription. + */ + subscribe: async function(params = {}) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.bluetooth + .gatt_connection_attempted.subscribe(params); + }, + /** + * Adds an event listener for the event. + * + * @param {function(GattConnectionAttempted): void} callback The + * callback to be called when the event is emitted. The + * callback is called with the event object as a parameter. + * @returns {function(): void} A function that removes the + * added event listener when called. + */ + on: function(callback) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.bluetooth + .gatt_connection_attempted.on(callback); + }, + /** + * Adds an event listener for the event that is only called + * once and removed afterward. + * + * @return {Promise} The promise which + * is resolved with the event object when the event is emitted. + */ + once: function() { + assertBidiIsEnabled(); + return new Promise(resolve => { + const remove_handler = + window.test_driver_internal.bidi.bluetooth + .gatt_connection_attempted.on(event => { + resolve(event); + remove_handler(); + }); + }); + }, + }, + /** + * `bluetooth.CharacteristicEventGeneratedParameters `_ + * event. + */ + characteristic_event_generated: { + /** + * @typedef {object} CharacteristicEventGenerated + * `bluetooth.CharacteristicEventGenerated `_ + * event. + */ + + /** + * Subscribes to the event. Events will be emitted only if + * there is a subscription for the event. This method does + * not add actual listeners. To listen to the event, use the + * `on` or `once` methods. The buffered events will be + * emitted before the command promise is resolved. + * + * @param {object} [params] Parameters for the subscription. + * @param {null|Array.<(Context)>} [params.contexts] The + * optional contexts parameter specifies which browsing + * contexts to subscribe to the event on. It should be + * either an array of Context objects, or null. If null, the + * event will be subscribed to globally. If omitted, the + * event will be subscribed to on the current browsing + * context. + * @returns {Promise<(function(): Promise)>} Callback + * for unsubscribing from the created subscription. + */ + subscribe: async function(params = {}) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.bluetooth + .characteristic_event_generated.subscribe(params); + }, + /** + * Adds an event listener for the event. + * + * @param {function(CharacteristicEventGenerated): void} callback The + * callback to be called when the event is emitted. The + * callback is called with the event object as a parameter. + * @returns {function(): void} A function that removes the + * added event listener when called. + */ + on: function(callback) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.bluetooth + .characteristic_event_generated.on(callback); + }, + /** + * Adds an event listener for the event that is only called + * once and removed afterward. + * + * @return {Promise} The promise which + * is resolved with the event object when the event is emitted. + */ + once: function() { + assertBidiIsEnabled(); + return new Promise(resolve => { + const remove_handler = + window.test_driver_internal.bidi.bluetooth + .characteristic_event_generated.on(event => { + resolve(event); + remove_handler(); + }); + }); + }, + }, + /** + * `bluetooth.DescriptorEventGeneratedParameters `_ + * event. + */ + descriptor_event_generated: { + /** + * @typedef {object} DescriptorEventGenerated + * `bluetooth.DescriptorEventGenerated `_ + * event. + */ + + /** + * Subscribes to the event. Events will be emitted only if + * there is a subscription for the event. This method does + * not add actual listeners. To listen to the event, use the + * `on` or `once` methods. The buffered events will be + * emitted before the command promise is resolved. + * + * @param {object} [params] Parameters for the subscription. + * @param {null|Array.<(Context)>} [params.contexts] The + * optional contexts parameter specifies which browsing + * contexts to subscribe to the event on. It should be + * either an array of Context objects, or null. If null, the + * event will be subscribed to globally. If omitted, the + * event will be subscribed to on the current browsing + * context. + * @returns {Promise<(function(): Promise)>} Callback + * for unsubscribing from the created subscription. + */ + subscribe: async function(params = {}) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.bluetooth + .descriptor_event_generated.subscribe(params); + }, + /** + * Adds an event listener for the event. + * + * @param {function(DescriptorEventGenerated): void} callback The + * callback to be called when the event is emitted. The + * callback is called with the event object as a parameter. + * @returns {function(): void} A function that removes the + * added event listener when called. + */ + on: function(callback) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.bluetooth + .descriptor_event_generated.on(callback); + }, + /** + * Adds an event listener for the event that is only called + * once and removed afterward. + * + * @return {Promise} The promise which + * is resolved with the event object when the event is emitted. + */ + once: function() { + assertBidiIsEnabled(); + return new Promise(resolve => { + const remove_handler = + window.test_driver_internal.bidi.bluetooth + .descriptor_event_generated.on(event => { + resolve(event); + remove_handler(); + }); + }); + }, + } + }, + /** + * `emulation `_ module. + */ + emulation: { + /** + * Overrides the geolocation coordinates for the specified + * browsing contexts. + * Matches the `emulation.setGeolocationOverride + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.emulation.set_geolocation_override({ + * coordinates: { + * latitude: 52.51, + * longitude: 13.39, + * accuracy: 0.5, + * altitude: 34, + * altitudeAccuracy: 0.75, + * heading: 180, + * speed: 2.77 + * } + * }); + * + * @param {object} params - Parameters for the command. + * @param {null|object} params.coordinates - The optional + * geolocation coordinates to set. Matches the + * `emulation.GeolocationCoordinates `_ + * value. If null or omitted and the `params.error` is set, the + * emulation will be removed. Mutually exclusive with + * `params.error`. + * @param {object} params.error - The optional + * geolocation error to emulate. Matches the + * `emulation.GeolocationPositionError `_ + * value. Mutually exclusive with `params.coordinates`. + * @param {null|Array.<(Context)>} [params.contexts] The + * optional contexts parameter specifies which browsing contexts + * to set the geolocation override on. It should be either an + * array of Context objects (window or browsing context id), or + * null. If null or omitted, the override will be set on the + * current browsing context. + * @returns {Promise} Resolves when the geolocation + * override is successfully set. + */ + set_geolocation_override: function (params) { + // Ensure the bidi feature is enabled before calling the internal method + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.emulation.set_geolocation_override( + params); + }, + /** + * Overrides the locale for the specified browsing contexts. + * Matches the `emulation.setLocaleOverride + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.emulation.set_locale_override({ + * locale: 'de-DE' + * }); + * + * @param {object} params - Parameters for the command. + * @param {null|string} params.locale - The optional + * locale to set. + * @param {null|Array.<(Context)>} [params.contexts] The + * optional contexts parameter specifies which browsing contexts + * to set the locale override on. It should be either an array + * of Context objects (window or browsing context id), or null. + * If null or omitted, the override will be set on the current + * browsing context. + * @returns {Promise} Resolves when the locale override + * is successfully set. + */ + set_locale_override: function (params) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.emulation.set_locale_override( + params); + }, + /** + * Overrides the screen orientation for the specified browsing + * contexts. + * Matches the `emulation.setScreenOrientationOverride + * `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.emulation.set_screen_orientation_override({ + * screenOrientation: { + * natural: 'portrait', + * type: 'landscape-secondary' + * } + * }); + * + * @param {object} params - Parameters for the command. + * @param {null|object} params.screenOrientation - The optional + * screen orientation. Matches the + * `emulation.ScreenOrientation `_ + * type. If null or omitted, the override will be removed. + * @param {null|Array.<(Context)>} [params.contexts] The + * optional contexts parameter specifies which browsing contexts + * to set the screen orientation override on. It should be + * either an array of Context objects (window or browsing + * context id), or null. If null or omitted, the override will + * be set on the current browsing context. + * @returns {Promise} Resolves when the screen orientation + * override is successfully set. + */ + set_screen_orientation_override: function (params) { + // Ensure the bidi feature is enabled before calling the internal method + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.emulation.set_screen_orientation_override( + params); + }, + }, + /** + * `log `_ module. + */ + log: { + entry_added: { + /** + * @typedef {object} LogEntryAdded `log.entryAdded `_ event. + */ + + /** + * Subscribes to the event. Events will be emitted only if + * there is a subscription for the event. This method does + * not add actual listeners. To listen to the event, use the + * `on` or `once` methods. The buffered events will be + * emitted before the command promise is resolved. + * + * @param {object} [params] Parameters for the subscription. + * @param {null|Array.<(Context)>} [params.contexts] The + * optional contexts parameter specifies which browsing + * contexts to subscribe to the event on. It should be + * either an array of Context objects, or null. If null, the + * event will be subscribed to globally. If omitted, the + * event will be subscribed to on the current browsing + * context. + * @returns {Promise<(function(): Promise)>} Callback + * for unsubscribing from the created subscription. + */ + subscribe: async function (params = {}) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.log.entry_added.subscribe(params); + }, + /** + * Adds an event listener for the event. + * + * @param {function(LogEntryAdded): void} callback The + * callback to be called when the event is emitted. The + * callback is called with the event object as a parameter. + * @returns {function(): void} A function that removes the + * added event listener when called. + */ + on: function (callback) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.log.entry_added.on(callback); + }, + /** + * Adds an event listener for the event that is only called + * once and removed afterward. + * + * @return {Promise} The promise which is resolved + * with the event object when the event is emitted. + */ + once: function () { + assertBidiIsEnabled(); + return new Promise(resolve => { + const remove_handler = window.test_driver_internal.bidi.log.entry_added.on( + event => { + resolve(event); + remove_handler(); + }); + }); + }, + } + }, + /** + * `permissions `_ module. + */ + permissions: { + /** + * Sets the state of a permission + * + * This function causes permission requests and queries for the status + * of a certain permission type (e.g. "push", or "background-fetch") to + * always return ``state`` for the specific origin. + * + * Matches the `permissions.setPermission `_ + * WebDriver BiDi command. + * + * @example + * await test_driver.bidi.permissions.set_permission({ + * {name: "geolocation"}, + * state: "granted", + * }); + * + * @param {object} params - Parameters for the command. + * @param {PermissionDescriptor} params.descriptor - a `PermissionDescriptor + * `_ + * or derived object. + * @param {PermissionState} params.state - a `PermissionState + * `_ + * value. + * @param {string} [params.origin] - an optional `origin` string to set the + * permission for. If omitted, the permission is set for the + * current window's origin. + * @returns {Promise} fulfilled after the permission is set, or rejected if setting + * the permission fails. + */ + set_permission: function (params) { + assertBidiIsEnabled(); + return window.test_driver_internal.bidi.permissions.set_permission( + params); + } + } + }, + /** * Set the context in which testharness.js is loaded * @@ -112,8 +1050,8 @@ let wait_click = new Promise(resolve => button.addEventListener("click", resolve)); return test_driver.click(button) - .then(wait_click) - .then(function() { + .then(() => wait_click) + .then(() => { button.remove(); if (typeof action === "function") { @@ -124,11 +1062,10 @@ }, /** - * Triggers a user-initiated click + * Triggers a user-initiated mouse click. * - * If ``element`` isn't inside the - * viewport, it will be scrolled into view before the click - * occurs. + * If ``element`` isn't inside the viewport, it will be + * scrolled into view before the click occurs. * * If ``element`` is from a different browsing context, the * command will be run in that context. @@ -322,7 +1259,7 @@ /** * Minimizes the browser window. * - * Matches the the behaviour of the `Minimize + * Matches the behaviour of the `Minimize * `_ * WebDriver command * @@ -357,6 +1294,25 @@ return window.test_driver_internal.set_window_rect(rect, context); }, + /** + * Gets a rect with the size and position on the screen from the current window state. + * + * Matches the behaviour of the `Get Window Rect + * `_ + * WebDriver command + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the window rect is returned, or rejected + * in cases the WebDriver command returns errors. Returns a + * `WindowRect `_ + */ + get_window_rect: function(context=null) { + return window.test_driver_internal.get_window_rect(context); + }, + /** * Send a sequence of actions * @@ -647,7 +1603,7 @@ * * This function places `Secure Payment * Confirmation `_ into - * an automated 'autoaccept' or 'autoreject' mode, to allow testing + * an automated 'autoAccept' or 'autoReject' mode, to allow testing * without user interaction with the transaction UX prompt. * * Matches the `Set SPC Transaction Mode @@ -667,8 +1623,8 @@ * @param {String} mode - The `transaction mode * `_ * to set. Must be one of "``none``", - * "``autoaccept``", or - * "``autoreject``". + * "``autoAccept``", or + * "``autoReject``". * @param {WindowProxy} context - Browsing context in which * to run the call, or null for the current * browsing context. @@ -680,6 +1636,42 @@ return window.test_driver_internal.set_spc_transaction_mode(mode, context); }, + /** + * Sets the current registration automation mode for Register Protocol Handlers. + * + * This function places `Register Protocol Handlers + * `_ into + * an automated 'autoAccept' or 'autoReject' mode, to allow testing + * without user interaction with the transaction UX prompt. + * + * Matches the `Set Register Protocol Handler Mode + * `_ + * WebDriver command. + * + * @example + * await test_driver.set_rph_registration_mode("autoAccept"); + * test.add_cleanup(() => { + * return test_driver.set_rph_registration_mode("none"); + * }); + * + * navigator.registerProtocolHandler('web+soup', 'soup?url=%s'); + * + * @param {String} mode - The `registration mode + * `_ + * to set. Must be one of "``none``", + * "``autoAccept``", or + * "``autoReject``". + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the transaction mode has been set, + * or rejected if setting the mode fails. + */ + set_rph_registration_mode: function(mode, context=null) { + return window.test_driver_internal.set_rph_registration_mode(mode, context); + }, + /** * Cancels the Federated Credential Management dialog * @@ -968,6 +1960,215 @@ */ get_virtual_sensor_information: function(sensor_type, context=null) { return window.test_driver_internal.get_virtual_sensor_information(sensor_type, context); + }, + + /** + * Overrides device posture set by hardware. + * + * Matches the `Set device posture + * `_ + * WebDriver command. + * + * @param {String} posture - A `DevicePostureType + * `_ + * either "continuous" or "folded". + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled when device posture is set. + * Rejected in case the WebDriver command errors out + * (including if a device posture of the given type + * does not exist). + */ + set_device_posture: function(posture, context=null) { + return window.test_driver_internal.set_device_posture(posture, context); + }, + + /** + * Removes device posture override and returns device posture control + * back to hardware. + * + * Matches the `Clear device posture + * `_ + * WebDriver command. + * + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled after the device posture override has + * been removed. Rejected in case the WebDriver + * command errors out. + */ + clear_device_posture: function(context=null) { + return window.test_driver_internal.clear_device_posture(context); + }, + + /** + * Runs the `bounce tracking timer algorithm + * `_, + * which removes all hosts from the stateful bounce tracking map, without + * regard for the bounce tracking grace period and returns a list of the + * deleted hosts. + * + * Matches the `Run Bounce Tracking Mitigations + * `_ + * WebDriver command. + * + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * @returns {Promise} Fulfilled after the bounce tracking timer + * algorithm has finished running. Returns an array + * of all hosts that were in the stateful bounce + * tracking map before deletion occurred. + */ + run_bounce_tracking_mitigations: function (context = null) { + return window.test_driver_internal.run_bounce_tracking_mitigations(context); + }, + + /** + * Creates a virtual pressure source. + * + * Matches the `Create virtual pressure source + * `_ + * WebDriver command. + * + * @param {String} source_type - A `virtual pressure source type + * `_ + * such as "cpu". + * @param {Object} [metadata={}] - Optional parameters described + * in `Create virtual pressure source + * `_. + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled when virtual pressure source is created. + * Rejected in case the WebDriver command errors out + * (including if a virtual pressure source of the + * same type already exists). + */ + create_virtual_pressure_source: function(source_type, metadata={}, context=null) { + return window.test_driver_internal.create_virtual_pressure_source(source_type, metadata, context); + }, + + /** + * Causes a virtual pressure source to report a new reading. + * + * Matches the `Update virtual pressure source + * `_ + * WebDriver command. + * + * @param {String} source_type - A `virtual pressure source type + * `_ + * such as "cpu". + * @param {String} sample - A `virtual pressure state + * `_ + * such as "critical". + * @param {number} own_contribution_estimate - Optional, A `virtual own contribution estimate` + * `_ + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled after the reading update reaches the + * virtual pressure source. Rejected in case the + * WebDriver command errors out (including if a + * virtual pressure source of the given type does not + * exist). + */ + update_virtual_pressure_source: function(source_type, sample, own_contribution_estimate, context=null) { + return window.test_driver_internal.update_virtual_pressure_source(source_type, sample, own_contribution_estimate, context); + }, + + /** + * Removes created virtual pressure source. + * + * Matches the `Delete virtual pressure source + * `_ + * WebDriver command. + * + * @param {String} source_type - A `virtual pressure source type + * `_ + * such as "cpu". + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled after the virtual pressure source has + * been removed or if a pressure source of the given + * type does not exist. Rejected in case the + * WebDriver command errors out. + */ + remove_virtual_pressure_source: function(source_type, context=null) { + return window.test_driver_internal.remove_virtual_pressure_source(source_type, context); + }, + + /** + * Sets which hashes are considered k-anonymous for the Protected + * Audience interest group with specified `owner` and `name`. + * + * Matches the `Set Protected Audience K-Anonymity + * + * WebDriver command. + * + * @param {String} owner - Origin of the owner of the interest group + * to modify + * @param {String} name - Name of the interest group to modify + * @param {Array} hashes - An array of strings, each of which is a + * base64 ecoded hash to consider k-anonymous. + * + * @returns {Promise} Fulfilled after the k-anonymity status for the + * specified Protected Audience interest group has + * been updated. + * + */ + set_protected_audience_k_anonymity: function(owner, name, hashes, context = null) { + return window.test_driver_internal.set_protected_audience_k_anonymity(owner, name, hashes, context); + }, + + /** + * Overrides the display features provided by the hardware so the viewport segments + * can be emulated. + * + * Matches the `Set display features + * `_ + * WebDriver command. + * + * @param {Array} features - An array of `DisplayFeatureOverride + * `. + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled when the display features are set. + * Rejected in case the WebDriver command errors out + * (including if the array is malformed). + */ + set_display_features: function(features, context=null) { + return window.test_driver_internal.set_display_features(features, context); + }, + + /** + * Removes display features override and returns the control + * back to hardware. + * + * Matches the `Clear display features + * `_ + * WebDriver command. + * + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled after the display features override has + * been removed. Rejected in case the WebDriver + * command errors out. + */ + clear_display_features: function(context=null) { + return window.test_driver_internal.clear_display_features(context); } }; @@ -980,6 +2181,99 @@ */ in_automation: false, + bidi: { + bluetooth: { + handle_request_device_prompt: function() { + throw new Error( + 'bidi.bluetooth.handle_request_device_prompt is not implemented by testdriver-vendor.js'); + }, + simulate_adapter: function () { + throw new Error( + "bidi.bluetooth.simulate_adapter is not implemented by testdriver-vendor.js"); + }, + disable_simulation: function () { + throw new Error( + "bidi.bluetooth.disable_simulation is not implemented by testdriver-vendor.js"); + }, + simulate_preconnected_peripheral: function() { + throw new Error( + 'bidi.bluetooth.simulate_preconnected_peripheral is not implemented by testdriver-vendor.js'); + }, + request_device_prompt_updated: { + async subscribe() { + throw new Error( + 'bidi.bluetooth.request_device_prompt_updated.subscribe is not implemented by testdriver-vendor.js'); + }, + on() { + throw new Error( + 'bidi.bluetooth.request_device_prompt_updated.on is not implemented by testdriver-vendor.js'); + } + }, + gatt_connection_attempted: { + async subscribe() { + throw new Error( + 'bidi.bluetooth.gatt_connection_attempted.subscribe is not implemented by testdriver-vendor.js'); + }, + on() { + throw new Error( + 'bidi.bluetooth.gatt_connection_attempted.on is not implemented by testdriver-vendor.js'); + } + }, + characteristic_event_generated: { + async subscribe() { + throw new Error( + 'bidi.bluetooth.characteristic_event_generated.subscribe is not implemented by testdriver-vendor.js'); + }, + on() { + throw new Error( + 'bidi.bluetooth.characteristic_event_generated.on is not implemented by testdriver-vendor.js'); + } + }, + descriptor_event_generated: { + async subscribe() { + throw new Error( + 'bidi.bluetooth.descriptor_event_generated.subscribe is not implemented by testdriver-vendor.js'); + }, + on() { + throw new Error( + 'bidi.bluetooth.descriptor_event_generated.on is not implemented by testdriver-vendor.js'); + } + } + }, + emulation: { + set_geolocation_override: function (params) { + throw new Error( + "bidi.emulation.set_geolocation_override is not implemented by testdriver-vendor.js"); + }, + set_locale_override: function (params) { + throw new Error( + "bidi.emulation.set_locale_override is not implemented by testdriver-vendor.js"); + }, + set_screen_orientation_override: function (params) { + throw new Error( + "bidi.emulation.set_screen_orientation_override is not implemented by testdriver-vendor.js"); + } + }, + log: { + entry_added: { + async subscribe() { + throw new Error( + "bidi.log.entry_added.subscribe is not implemented by testdriver-vendor.js"); + }, + on() { + throw new Error( + "bidi.log.entry_added.on is not implemented by testdriver-vendor.js"); + } + } + }, + permissions: { + async set_permission() { + throw new Error( + "bidi.permissions.set_permission() is not implemented by testdriver-vendor.js"); + } + } + }, + async click(element, coords) { if (this.in_automation) { throw new Error("click() is not implemented by testdriver-vendor.js"); @@ -1002,6 +2296,14 @@ throw new Error("get_named_cookie() is not implemented by testdriver-vendor.js"); }, + async get_computed_role(element) { + throw new Error("get_computed_role is a testdriver.js function which cannot be run in this context."); + }, + + async get_computed_name(element) { + throw new Error("get_computed_name is a testdriver.js function which cannot be run in this context."); + }, + async send_keys(element, keys) { if (this.in_automation) { throw new Error("send_keys() is not implemented by testdriver-vendor.js"); @@ -1046,6 +2348,10 @@ throw new Error("set_window_rect() is not implemented by testdriver-vendor.js"); }, + async get_window_rect(context=null) { + throw new Error("get_window_rect() is not implemented by testdriver-vendor.js"); + }, + async action_sequence(actions, context=null) { throw new Error("action_sequence() is not implemented by testdriver-vendor.js"); }, @@ -1094,6 +2400,10 @@ throw new Error("set_spc_transaction_mode() is not implemented by testdriver-vendor.js"); }, + set_rph_registration_mode: function(mode, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + async cancel_fedcm_dialog(context=null) { throw new Error("cancel_fedcm_dialog() is not implemented by testdriver-vendor.js"); }, @@ -1140,6 +2450,42 @@ async get_virtual_sensor_information(sensor_type, context=null) { throw new Error("get_virtual_sensor_information() is not implemented by testdriver-vendor.js"); + }, + + async set_device_posture(posture, context=null) { + throw new Error("set_device_posture() is not implemented by testdriver-vendor.js"); + }, + + async clear_device_posture(context=null) { + throw new Error("clear_device_posture() is not implemented by testdriver-vendor.js"); + }, + + async run_bounce_tracking_mitigations(context=null) { + throw new Error("run_bounce_tracking_mitigations() is not implemented by testdriver-vendor.js"); + }, + + async create_virtual_pressure_source(source_type, metadata={}, context=null) { + throw new Error("create_virtual_pressure_source() is not implemented by testdriver-vendor.js"); + }, + + async update_virtual_pressure_source(source_type, sample, own_contribution_estimate, context=null) { + throw new Error("update_virtual_pressure_source() is not implemented by testdriver-vendor.js"); + }, + + async remove_virtual_pressure_source(source_type, context=null) { + throw new Error("remove_virtual_pressure_source() is not implemented by testdriver-vendor.js"); + }, + + async set_protected_audience_k_anonymity(owner, name, hashes, context=null) { + throw new Error("set_protected_audience_k_anonymity() is not implemented by testdriver-vendor.js"); + }, + + async set_display_features(features, context=null) { + throw new Error("set_display_features() is not implemented by testdriver-vendor.js"); + }, + + async clear_display_features(context=null) { + throw new Error("clear_display_features() is not implemented by testdriver-vendor.js"); } }; })(); diff --git a/test/fixtures/wpt/resources/testharness-shadowrealm-audioworkletprocessor.js b/test/fixtures/wpt/resources/testharness-shadowrealm-audioworkletprocessor.js new file mode 100644 index 00000000000000..a87d9130908f86 --- /dev/null +++ b/test/fixtures/wpt/resources/testharness-shadowrealm-audioworkletprocessor.js @@ -0,0 +1,52 @@ +/** + * AudioWorkletProcessor intended for hosting a ShadowRealm and running a test + * inside of that ShadowRealm. + */ +globalThis.TestRunner = class TestRunner extends AudioWorkletProcessor { + constructor() { + super(); + this.createShadowRealmAndStartTests(); + } + + /** + * Fetch adaptor function intended as a drop-in replacement for fetchAdaptor() + * (see testharness-shadowrealm-outer.js), but it does not assume fetch() is + * present in the realm. Instead, it relies on setupFakeFetchOverMessagePort() + * having been called on the port on the other side of this.port's channel. + */ + fetchOverPortExecutor(resource) { + return (resolve, reject) => { + const listener = (event) => { + if (typeof event.data !== "string" || !event.data.startsWith("fetchResult::")) { + return; + } + + const result = event.data.slice("fetchResult::".length); + if (result.startsWith("success::")) { + resolve(result.slice("success::".length)); + } else { + reject(result.slice("fail::".length)); + } + + this.port.removeEventListener("message", listener); + } + this.port.addEventListener("message", listener); + this.port.start(); + this.port.postMessage(`fetchRequest::${resource}`); + } + } + + /** + * Async method, which is patched over in + * (test).any.audioworklet-shadowrealm.js; see serve.py + */ + async createShadowRealmAndStartTests() { + throw new Error("Forgot to overwrite this method!"); + } + + /** Overrides AudioWorkletProcessor.prototype.process() */ + process() { + return false; + } +}; +registerProcessor("test-runner", TestRunner); diff --git a/test/fixtures/wpt/resources/testharness-shadowrealm-inner.js b/test/fixtures/wpt/resources/testharness-shadowrealm-inner.js new file mode 100644 index 00000000000000..a9bdf9fc76ceea --- /dev/null +++ b/test/fixtures/wpt/resources/testharness-shadowrealm-inner.js @@ -0,0 +1,38 @@ +// testharness file with ShadowRealm utilities to be imported inside ShadowRealm + +/** + * Set up all properties on the ShadowRealm's global object that tests will + * expect to be present. + * + * @param {string} queryString - string to use as value for location.search, + * used for subsetting some tests + * @param {function} fetchAdaptor - a function that takes a resource URI and + * returns a function which itself takes a (resolve, reject) pair from the + * hosting realm, and calls resolve with the text result of fetching the + * resource, or reject with a string indicating the error that occurred + */ +globalThis.setShadowRealmGlobalProperties = function (queryString, fetchAdaptor) { + globalThis.fetch_json = (resource) => { + const executor = fetchAdaptor(resource); + return new Promise(executor).then((s) => JSON.parse(s)); + }; + + // Used only by idlharness.js + globalThis.fetch_spec = (spec) => { + const resource = `/interfaces/${spec}.idl`; + const executor = fetchAdaptor(resource); + return new Promise(executor).then( + idl => ({ spec, idl }), + () => { + throw new IdlHarnessError(`Error fetching ${resource}.`); + }); + } + + globalThis.location = { search: queryString }; +}; + +globalThis.GLOBAL = { + isWindow: function() { return false; }, + isWorker: function() { return false; }, + isShadowRealm: function() { return true; }, +}; diff --git a/test/fixtures/wpt/resources/testharness-shadowrealm-outer.js b/test/fixtures/wpt/resources/testharness-shadowrealm-outer.js new file mode 100644 index 00000000000000..1affa72c2c56a2 --- /dev/null +++ b/test/fixtures/wpt/resources/testharness-shadowrealm-outer.js @@ -0,0 +1,151 @@ +// testharness file with ShadowRealm utilities to be imported in the realm +// hosting the ShadowRealm + +/** + * Convenience function for evaluating some async code in the ShadowRealm and + * waiting for the result. + * + * In case of error, this function intentionally exposes the stack trace (if it + * is available) to the hosting realm, for debugging purposes. + * + * @param {ShadowRealm} realm - the ShadowRealm to evaluate the code in + * @param {string} asyncBody - the code to evaluate; will be put in the body of + * an async function, and must return a value explicitly if a value is to be + * returned to the hosting realm. + */ +globalThis.shadowRealmEvalAsync = function (realm, asyncBody) { + return new Promise(realm.evaluate(` + (resolve, reject) => { + (async () => { + ${asyncBody} + })().then(resolve, (e) => reject(e.toString() + "\\n" + (e.stack || ""))); + } + `)); +}; + +/** + * Convenience adaptor function for fetch() that can be passed to + * setShadowRealmGlobalProperties() (see testharness-shadowrealm-inner.js). + * Used to adapt the hosting realm's fetch(), if present, to fetch a resource + * and pass its text through the callable boundary to the ShadowRealm. + */ +globalThis.fetchAdaptor = (resource) => (resolve, reject) => { + fetch(resource) + .then(res => res.text()) + .then(resolve, (e) => reject(e.toString())); +}; + +let workerMessagePortPromise; +/** + * Used when the hosting realm is a worker. This value is a Promise that + * resolves to a function that posts a message to the worker's message port, + * just like postMessage(). The message port is only available asynchronously in + * SharedWorkers and ServiceWorkers. + */ +globalThis.getPostMessageFunc = async function () { + if (typeof postMessage === "function") { + return postMessage; // postMessage available directly in dedicated worker + } + + if (workerMessagePortPromise) { + return await workerMessagePortPromise; + } + + throw new Error("getPostMessageFunc is intended for Worker scopes"); +} + +// Port available asynchronously in shared worker, but not via an async func +let savedResolver; +if (globalThis.constructor.name === "SharedWorkerGlobalScope") { + workerMessagePortPromise = new Promise((resolve) => { + savedResolver = resolve; + }); + addEventListener("connect", function (event) { + const port = event.ports[0]; + savedResolver(port.postMessage.bind(port)); + }); +} else if (globalThis.constructor.name === "ServiceWorkerGlobalScope") { + workerMessagePortPromise = new Promise((resolve) => { + savedResolver = resolve; + }); + addEventListener("message", (e) => { + if (typeof e.data === "object" && e.data !== null && e.data.type === "connect") { + const client = e.source; + savedResolver(client.postMessage.bind(client)); + } + }); +} + +/** + * Used when the hosting realm does not permit dynamic import, e.g. in + * ServiceWorkers or AudioWorklets. Requires an adaptor function such as + * fetchAdaptor() above, or an equivalent if fetch() is not present in the + * hosting realm. + * + * @param {ShadowRealm} realm - the ShadowRealm in which to setup a + * fakeDynamicImport() global function. + * @param {function} adaptor - an adaptor function that does what fetchAdaptor() + * does. + */ +globalThis.setupFakeDynamicImportInShadowRealm = function(realm, adaptor) { + function fetchModuleTextExecutor(url) { + return (resolve, reject) => { + new Promise(adaptor(url)) + .then(text => realm.evaluate(text + ";\nundefined")) + .then(resolve, (e) => reject(e.toString())); + } + } + + realm.evaluate(` + (fetchModuleTextExecutor) => { + globalThis.fakeDynamicImport = function (url) { + return new Promise(fetchModuleTextExecutor(url)); + } + } + `)(fetchModuleTextExecutor); +}; + +/** + * Used when the hosting realm does not expose fetch(), i.e. in worklets. The + * port on the other side of the channel needs to send messages starting with + * 'fetchRequest::' and listen for messages starting with 'fetchResult::'. See + * testharness-shadowrealm-audioworkletprocessor.js. + * + * @param {port} MessagePort - the message port on which to listen for fetch + * requests + */ +globalThis.setupFakeFetchOverMessagePort = function (port) { + port.addEventListener("message", (event) => { + if (typeof event.data !== "string" || !event.data.startsWith("fetchRequest::")) { + return; + } + + fetch(event.data.slice("fetchRequest::".length)) + .then(res => res.text()) + .then( + text => port.postMessage(`fetchResult::success::${text}`), + error => port.postMessage(`fetchResult::fail::${error}`), + ); + }); + port.start(); +} + +/** + * Returns a message suitable for posting with postMessage() that will signal to + * the test harness that the tests are finished and there was an error in the + * setup code. + * + * @param {message} any - error + */ +globalThis.createSetupErrorResult = function (message) { + return { + type: "complete", + tests: [], + asserts: [], + status: { + status: 1, // TestsStatus.ERROR, + message: String(message), + stack: typeof message === "object" && message !== null && "stack" in message ? message.stack : undefined, + }, + }; +}; diff --git a/test/fixtures/wpt/resources/testharness.js b/test/fixtures/wpt/resources/testharness.js index 126ae96423bc83..f495b62458ba75 100644 --- a/test/fixtures/wpt/resources/testharness.js +++ b/test/fixtures/wpt/resources/testharness.js @@ -88,10 +88,15 @@ status: harness_status.structured_clone(), asserts: asserts.map(assert => assert.structured_clone())}); }] - } + }; on_event(window, 'load', function() { + setTimeout(() => { this_obj.all_loaded = true; + if (tests.all_done()) { + tests.complete(); + } + },0); }); on_event(window, 'message', function(event) { @@ -198,7 +203,7 @@ } }); this.message_events = new_events; - } + }; WindowTestEnvironment.prototype.next_default_test_name = function() { var suffix = this.name_counter > 0 ? " " + this.name_counter : ""; @@ -220,8 +225,8 @@ WindowTestEnvironment.prototype.test_timeout = function() { var metas = document.getElementsByTagName("meta"); for (var i = 0; i < metas.length; i++) { - if (metas[i].name == "timeout") { - if (metas[i].content == "long") { + if (metas[i].name === "timeout") { + if (metas[i].content === "long") { return settings.harness_timeout.long; } break; @@ -482,7 +487,7 @@ this.all_loaded = false; this.on_loaded_callback = null; Promise.resolve().then(function() { - this.all_loaded = true + this.all_loaded = true; if (this.on_loaded_callback) { this.on_loaded_callback(); } @@ -558,7 +563,7 @@ // The worker object may be from another execution context, // so do not use instanceof here. return 'ServiceWorker' in global_scope && - Object.prototype.toString.call(worker) == '[object ServiceWorker]'; + Object.prototype.toString.call(worker) === '[object ServiceWorker]'; } var seen_func_name = Object.create(null); @@ -600,7 +605,7 @@ /** * @callback TestFunction - * @param {Test} test - The test currently being run. + * @param {Test} test - The test currnetly being run. * @param {Any[]} args - Additional args to pass to function. * */ @@ -805,7 +810,7 @@ return bring_promise_to_current_realm(promise) .then(test.unreached_func("Should have rejected: " + description)) .catch(function(e) { - assert_throws_js_impl(constructor, function() { throw e }, + assert_throws_js_impl(constructor, function() { throw e; }, description, "promise_rejects_js"); }); } @@ -852,16 +857,64 @@ promise = promiseOrConstructor; description = descriptionOrPromise; assert(maybeDescription === undefined, - "Too many args pased to no-constructor version of promise_rejects_dom"); + "Too many args passed to no-constructor version of promise_rejects_dom, or accidentally explicitly passed undefined"); } return bring_promise_to_current_realm(promise) .then(test.unreached_func("Should have rejected: " + description)) .catch(function(e) { - assert_throws_dom_impl(type, function() { throw e }, description, + assert_throws_dom_impl(type, function() { throw e; }, description, "promise_rejects_dom", constructor); }); } +/** + * Assert that a `Promise` is rejected with a `QuotaExceededError` with the + * expected values. + * + * For the remaining arguments, there are two ways of calling + * `promise_rejects_quotaexceedederror`: + * + * 1) If the `QuotaExceededError` is expected to come from the + * current global, the second argument should be the promise + * expected to reject, the third and a fourth the expected + * `requested` and `quota` property values, and the fifth, + * optional, argument is the assertion description. + * + * 2) If the `QuotaExceededError` is expected to come from some + * other global, the second argument should be the + * `QuotaExceededError` constructor from that global, the third + * argument should be the promise expected to reject, the fourth + * and fifth the expected `requested` and `quota` property + * values, and the sixth, optional, argument is the assertion + * description. + * + */ + function promise_rejects_quotaexceedederror(test, promiseOrConstructor, requestedOrPromise, quotaOrRequested, descriptionOrQuota, maybeDescription) + { + let constructor, promise, requested, quota, description; + if (typeof promiseOrConstructor === "function" && + promiseOrConstructor.name === "QuotaExceededError") { + constructor = promiseOrConstructor; + promise = requestedOrPromise; + requested = quotaOrRequested; + quota = descriptionOrQuota; + description = maybeDescription; + } else { + constructor = self.QuotaExceededError; + promise = promiseOrConstructor; + requested = requestedOrPromise; + quota = quotaOrRequested; + description = descriptionOrQuota; + assert(maybeDescription === undefined, + "Too many args passed to no-constructor version of promise_rejects_quotaexceedederror"); + } + return bring_promise_to_current_realm(promise) + .then(test.unreached_func("Should have rejected: " + description)) + .catch(function(e) { + assert_throws_quotaexceedederror_impl(function() { throw e; }, requested, quota, description, "promise_rejects_quotaexceedederror", constructor); + }); + } + /** * Assert that a Promise is rejected with the provided value. * @@ -876,7 +929,7 @@ return bring_promise_to_current_realm(promise) .then(test.unreached_func("Should have rejected: " + description)) .catch(function(e) { - assert_throws_exactly_impl(exception, function() { throw e }, + assert_throws_exactly_impl(exception, function() { throw e; }, description, "promise_rejects_exactly"); }); } @@ -902,7 +955,7 @@ */ function EventWatcher(test, watchedNode, eventTypes, timeoutPromise) { - if (typeof eventTypes == 'string') { + if (typeof eventTypes === 'string') { eventTypes = [eventTypes]; } @@ -967,7 +1020,7 @@ if (waitingFor) { return Promise.reject('Already waiting for an event or events'); } - if (typeof types == 'string') { + if (typeof types === 'string') { types = [types]; } if (options && options.record && options.record === 'all') { @@ -982,7 +1035,7 @@ // This should always fail, otherwise we should have // resolved the promise. - assert_true(waitingFor.types.length == 0, + assert_true(waitingFor.types.length === 0, 'Timed out waiting for ' + waitingFor.types.join(', ')); var result = recordedEvents; recordedEvents = null; @@ -1006,13 +1059,13 @@ /** * Stop listening for events */ - function stop_watching() { + this.stop_watching = function() { for (var i = 0; i < eventTypes.length; i++) { watchedNode.removeEventListener(eventTypes[i], eventHandler, false); } }; - test._add_cleanup(stop_watching); + test._add_cleanup(this.stop_watching); return this; } @@ -1089,7 +1142,7 @@ { if (typeof func !== "function") { tests.set_status(tests.status.ERROR, - "promise_test invoked without a function"); + "`promise_setup` invoked without a function"); tests.complete(); return; } @@ -1127,7 +1180,7 @@ * * Typically this function is called implicitly on page load; it's * only necessary for users to call this when either the - * ``explicit_done`` or ``single_page`` properties have been set + * ``explicit_done`` or ``single_test`` properties have been set * via the :js:func:`setup` function. * * For single page tests this marks the test as complete and sets its status. @@ -1196,6 +1249,23 @@ object.addEventListener(event, callback, false); } + // Internal helper function to provide timeout-like functionality in + // environments where there is no setTimeout(). (No timeout ID or + // clearTimeout().) + function fake_set_timeout(callback, delay) { + var p = Promise.resolve(); + var start = Date.now(); + var end = start + delay; + function check() { + if ((end - Date.now()) > 0) { + p.then(check); + } else { + callback(); + } + } + p.then(check); + } + /** * Global version of :js:func:`Test.step_timeout` for use in single page tests. * @@ -1207,7 +1277,8 @@ function step_timeout(func, timeout) { var outer_this = this; var args = Array.prototype.slice.call(arguments, 2); - return setTimeout(function() { + var local_set_timeout = typeof global_scope.setTimeout === "undefined" ? fake_set_timeout : setTimeout; + return local_set_timeout(function() { func.apply(outer_this, args); }, timeout * tests.timeout_multiplier); } @@ -1217,6 +1288,7 @@ expose(promise_test, 'promise_test'); expose(promise_rejects_js, 'promise_rejects_js'); expose(promise_rejects_dom, 'promise_rejects_dom'); + expose(promise_rejects_quotaexceedederror, 'promise_rejects_quotaexceedederror'); expose(promise_rejects_exactly, 'promise_rejects_exactly'); expose(generate_tests, 'generate_tests'); expose(setup, 'setup'); @@ -1307,6 +1379,15 @@ "0xffff": "uffff", }; + const formatEscapeMap = { + "\\": "\\\\", + '"': '\\"' + }; + for (const p in replacements) { + formatEscapeMap[String.fromCharCode(p)] = "\\" + replacements[p]; + } + const formatEscapePattern = new RegExp(`[${Object.keys(formatEscapeMap).map(k => k === "\\" ? "\\\\" : k).join("")}]`, "g"); + /** * Convert a value to a nice, human-readable string * @@ -1357,12 +1438,7 @@ switch (typeof val) { case "string": - val = val.replace(/\\/g, "\\\\"); - for (var p in replacements) { - var replace = "\\" + replacements[p]; - val = val.replace(RegExp(String.fromCharCode(p), "g"), replace); - } - return '"' + val.replace(/"/g, '\\"') + '"'; + return '"' + val.replace(formatEscapePattern, match => formatEscapeMap[match]) + '"'; case "boolean": case "undefined": return String(val); @@ -1373,6 +1449,8 @@ return "-0"; } return String(val); + case "bigint": + return String(val) + 'n'; case "object": if (val === null) { return "null"; @@ -1396,11 +1474,11 @@ case Node.COMMENT_NODE: return "Comment node "; case Node.DOCUMENT_NODE: - return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children"); + return "Document node with " + val.childNodes.length + (val.childNodes.length === 1 ? " child" : " children"); case Node.DOCUMENT_TYPE_NODE: return "DocumentType node"; case Node.DOCUMENT_FRAGMENT_NODE: - return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children"); + return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length === 1 ? " child" : " children"); default: return "Node object of unknown type"; } @@ -1744,20 +1822,25 @@ /** * Assert that ``actual`` is a number less than ``expected``. * - * @param {number} actual - Test value. - * @param {number} expected - Number that ``actual`` must be less than. + * @param {number|bigint} actual - Test value. + * @param {number|bigint} expected - Value that ``actual`` must be less than. * @param {string} [description] - Description of the condition being tested. */ function assert_less_than(actual, expected, description) { /* - * Test if a primitive number is less than another + * Test if a primitive number (or bigint) is less than another */ - assert(typeof actual === "number", + assert(typeof actual === "number" || typeof actual === "bigint", "assert_less_than", description, "expected a number but got a ${type_actual}", {type_actual:typeof actual}); + assert(typeof actual === typeof expected, + "assert_less_than", description, + "expected a ${type_expected} but got a ${type_actual}", + {type_expected:typeof expected, type_actual:typeof actual}); + assert(actual < expected, "assert_less_than", description, "expected a number less than ${expected} but got ${actual}", @@ -1768,20 +1851,25 @@ /** * Assert that ``actual`` is a number greater than ``expected``. * - * @param {number} actual - Test value. - * @param {number} expected - Number that ``actual`` must be greater than. + * @param {number|bigint} actual - Test value. + * @param {number|bigint} expected - Value that ``actual`` must be greater than. * @param {string} [description] - Description of the condition being tested. */ function assert_greater_than(actual, expected, description) { /* - * Test if a primitive number is greater than another + * Test if a primitive number (or bigint) is greater than another */ - assert(typeof actual === "number", + assert(typeof actual === "number" || typeof actual === "bigint", "assert_greater_than", description, "expected a number but got a ${type_actual}", {type_actual:typeof actual}); + assert(typeof actual === typeof expected, + "assert_greater_than", description, + "expected a ${type_expected} but got a ${type_actual}", + {type_expected:typeof expected, type_actual:typeof actual}); + assert(actual > expected, "assert_greater_than", description, "expected a number greater than ${expected} but got ${actual}", @@ -1793,21 +1881,31 @@ * Assert that ``actual`` is a number greater than ``lower`` and less * than ``upper`` but not equal to either. * - * @param {number} actual - Test value. - * @param {number} lower - Number that ``actual`` must be greater than. - * @param {number} upper - Number that ``actual`` must be less than. + * @param {number|bigint} actual - Test value. + * @param {number|bigint} lower - Value that ``actual`` must be greater than. + * @param {number|bigint} upper - Value that ``actual`` must be less than. * @param {string} [description] - Description of the condition being tested. */ function assert_between_exclusive(actual, lower, upper, description) { /* - * Test if a primitive number is between two others + * Test if a primitive number (or bigint) is between two others */ - assert(typeof actual === "number", + assert(typeof lower === typeof upper, + "assert_between_exclusive", description, + "expected lower (${type_lower}) and upper (${type_upper}) types to match (test error)", + {type_lower:typeof lower, type_upper:typeof upper}); + + assert(typeof actual === "number" || typeof actual === "bigint", "assert_between_exclusive", description, "expected a number but got a ${type_actual}", {type_actual:typeof actual}); + assert(typeof actual === typeof lower, + "assert_between_exclusive", description, + "expected a ${type_lower} but got a ${type_actual}", + {type_lower:typeof lower, type_actual:typeof actual}); + assert(actual > lower && actual < upper, "assert_between_exclusive", description, "expected a number greater than ${lower} " + @@ -1819,21 +1917,26 @@ /** * Assert that ``actual`` is a number less than or equal to ``expected``. * - * @param {number} actual - Test value. - * @param {number} expected - Number that ``actual`` must be less + * @param {number|bigint} actual - Test value. + * @param {number|bigint} expected - Value that ``actual`` must be less * than or equal to. * @param {string} [description] - Description of the condition being tested. */ function assert_less_than_equal(actual, expected, description) { /* - * Test if a primitive number is less than or equal to another + * Test if a primitive number (or bigint) is less than or equal to another */ - assert(typeof actual === "number", + assert(typeof actual === "number" || typeof actual === "bigint", "assert_less_than_equal", description, "expected a number but got a ${type_actual}", {type_actual:typeof actual}); + assert(typeof actual === typeof expected, + "assert_less_than_equal", description, + "expected a ${type_expected} but got a ${type_actual}", + {type_expected:typeof expected, type_actual:typeof actual}); + assert(actual <= expected, "assert_less_than_equal", description, "expected a number less than or equal to ${expected} but got ${actual}", @@ -1844,21 +1947,26 @@ /** * Assert that ``actual`` is a number greater than or equal to ``expected``. * - * @param {number} actual - Test value. - * @param {number} expected - Number that ``actual`` must be greater + * @param {number|bigint} actual - Test value. + * @param {number|bigint} expected - Value that ``actual`` must be greater * than or equal to. * @param {string} [description] - Description of the condition being tested. */ function assert_greater_than_equal(actual, expected, description) { /* - * Test if a primitive number is greater than or equal to another + * Test if a primitive number (or bigint) is greater than or equal to another */ - assert(typeof actual === "number", + assert(typeof actual === "number" || typeof actual === "bigint", "assert_greater_than_equal", description, "expected a number but got a ${type_actual}", {type_actual:typeof actual}); + assert(typeof actual === typeof expected, + "assert_greater_than_equal", description, + "expected a ${type_expected} but got a ${type_actual}", + {type_expected:typeof expected, type_actual:typeof actual}); + assert(actual >= expected, "assert_greater_than_equal", description, "expected a number greater than or equal to ${expected} but got ${actual}", @@ -1870,21 +1978,31 @@ * Assert that ``actual`` is a number greater than or equal to ``lower`` and less * than or equal to ``upper``. * - * @param {number} actual - Test value. - * @param {number} lower - Number that ``actual`` must be greater than or equal to. - * @param {number} upper - Number that ``actual`` must be less than or equal to. + * @param {number|bigint} actual - Test value. + * @param {number|bigint} lower - Value that ``actual`` must be greater than or equal to. + * @param {number|bigint} upper - Value that ``actual`` must be less than or equal to. * @param {string} [description] - Description of the condition being tested. */ function assert_between_inclusive(actual, lower, upper, description) { /* - * Test if a primitive number is between to two others or equal to either of them + * Test if a primitive number (or bigint) is between to two others or equal to either of them */ - assert(typeof actual === "number", + assert(typeof lower === typeof upper, + "assert_between_inclusive", description, + "expected lower (${type_lower}) and upper (${type_upper}) types to match (test error)", + {type_lower:typeof lower, type_upper:typeof upper}); + + assert(typeof actual === "number" || typeof actual === "bigint", "assert_between_inclusive", description, "expected a number but got a ${type_actual}", {type_actual:typeof actual}); + assert(typeof actual === typeof lower, + "assert_between_inclusive", description, + "expected a ${type_lower} but got a ${type_actual}", + {type_lower:typeof lower, type_actual:typeof actual}); + assert(actual >= lower && actual <= upper, "assert_between_inclusive", description, "expected a number greater than or equal to ${lower} " + @@ -2009,30 +2127,46 @@ /** - * Assert that ``object`` has a property named ``property_name`` and that the property is readonly. + * Assert that ``object`` has a property named ``property_name`` and that the property is not writable or has no setter. * - * Note: The implementation tries to update the named property, so - * any side effects of updating will be triggered. Users are - * encouraged to instead inspect the property descriptor of ``property_name`` on ``object``. - * - * @param {Object} object - Object that should have the given property in its prototype chain. + * @param {Object} object - Object that should have the given (not necessarily own) property. * @param {string} property_name - Expected property name. * @param {string} [description] - Description of the condition being tested. */ function assert_readonly(object, property_name, description) { - var initial_value = object[property_name]; - try { - //Note that this can have side effects in the case where - //the property has PutForwards - object[property_name] = initial_value + "a"; //XXX use some other value here? - assert(same_value(object[property_name], initial_value), - "assert_readonly", description, - "changing property ${p} succeeded", - {p:property_name}); - } finally { - object[property_name] = initial_value; - } + assert(property_name in object, + "assert_readonly", description, + "property ${p} not found", + {p:property_name}); + + let desc; + while (object && (desc = Object.getOwnPropertyDescriptor(object, property_name)) === undefined) { + object = Object.getPrototypeOf(object); + } + + assert(desc !== undefined, + "assert_readonly", description, + "could not find a descriptor for property ${p}", + {p:property_name}); + + if (desc.hasOwnProperty("value")) { + // We're a data property descriptor + assert(desc.writable === false, "assert_readonly", description, + "descriptor [[Writable]] expected false got ${actual}", {actual:desc.writable}); + } else if (desc.hasOwnProperty("get") || desc.hasOwnProperty("set")) { + // We're an accessor property descriptor + assert(desc.set === undefined, "assert_readonly", description, + "property ${p} is an accessor property with a [[Set]] attribute, cannot test readonly-ness", + {p:property_name}); + } else { + // We're a generic property descriptor + // This shouldn't happen, because Object.getOwnPropertyDescriptor + // forwards the return value of [[GetOwnProperty]] (P), which must + // be a fully populated Property Descriptor or Undefined. + assert(false, "assert_readonly", description, + "Object.getOwnPropertyDescriptor must return a fully populated property descriptor"); + } } expose_assert(assert_readonly, "assert_readonly"); @@ -2078,7 +2212,7 @@ {func:func}); // Basic sanity-check on the passed-in constructor - assert(typeof constructor == "function", + assert(typeof constructor === "function", assertion_type, description, "${constructor} is not a constructor", {constructor:constructor}); @@ -2151,9 +2285,9 @@ func = funcOrConstructor; description = descriptionOrFunc; assert(maybeDescription === undefined, - "Too many args pased to no-constructor version of assert_throws_dom"); + "Too many args passed to no-constructor version of assert_throws_dom, or accidentally explicitly passed undefined"); } - assert_throws_dom_impl(type, func, description, "assert_throws_dom", constructor) + assert_throws_dom_impl(type, func, description, "assert_throws_dom", constructor); } expose_assert(assert_throws_dom, "assert_throws_dom"); @@ -2186,8 +2320,8 @@ {func:func}); // Sanity-check our type - assert(typeof type == "number" || - typeof type == "string", + assert(typeof type === "number" || + typeof type === "string", assertion_type, description, "${type} is not a number or string", {type:type}); @@ -2211,7 +2345,6 @@ NETWORK_ERR: 'NetworkError', ABORT_ERR: 'AbortError', URL_MISMATCH_ERR: 'URLMismatchError', - QUOTA_EXCEEDED_ERR: 'QuotaExceededError', TIMEOUT_ERR: 'TimeoutError', INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError', DATA_CLONE_ERR: 'DataCloneError' @@ -2236,7 +2369,6 @@ NetworkError: 19, AbortError: 20, URLMismatchError: 21, - QuotaExceededError: 22, TimeoutError: 23, InvalidNodeTypeError: 24, DataCloneError: 25, @@ -2267,12 +2399,19 @@ if (typeof type === "number") { if (type === 0) { throw new AssertionError('Test bug: ambiguous DOMException code 0 passed to assert_throws_dom()'); - } else if (!(type in code_name_map)) { + } + if (type === 22) { + throw new AssertionError('Test bug: QuotaExceededError needs to be tested for using assert_throws_quotaexceedederror()'); + } + if (!(type in code_name_map)) { throw new AssertionError('Test bug: unrecognized DOMException code "' + type + '" passed to assert_throws_dom()'); } name = code_name_map[type]; required_props.code = type; } else if (typeof type === "string") { + if (name === "QuotaExceededError") { + throw new AssertionError('Test bug: QuotaExceededError needs to be tested for using assert_throws_quotaexceedederror()'); + } name = type in codename_name_map ? codename_name_map[type] : type; if (!(name in name_code_map)) { throw new AssertionError('Test bug: unrecognized DOMException code name or name "' + type + '" passed to assert_throws_dom()'); @@ -2307,6 +2446,137 @@ } } + /** + * Assert a `QuotaExceededError` with the expected values is thrown. + * + * There are two ways of calling `assert_throws_quotaexceedederror`: + * + * 1) If the `QuotaExceededError` is expected to come from the + * current global, the first argument should be the function + * expected to throw, the second and a third the expected + * `requested` and `quota` property values, and the fourth, + * optional, argument is the assertion description. + * + * 2) If the `QuotaExceededError` is expected to come from some + * other global, the first argument should be the + * `QuotaExceededError` constructor from that global, the second + * argument should be the function expected to throw, the third + * and fourth the expected `requested` and `quota` property + * values, and the fifth, optional, argument is the assertion + * description. + * + * For the `requested` and `quota` values, instead of `null` or a + * number, the caller can provide a function which determines + * whether the value is acceptable by returning a boolean. + * + */ + function assert_throws_quotaexceedederror(funcOrConstructor, requestedOrFunc, quotaOrRequested, descriptionOrQuota, maybeDescription) + { + let constructor, func, requested, quota, description; + if (funcOrConstructor.name === "QuotaExceededError") { + constructor = funcOrConstructor; + func = requestedOrFunc; + requested = quotaOrRequested; + quota = descriptionOrQuota; + description = maybeDescription; + } else { + constructor = self.QuotaExceededError; + func = funcOrConstructor; + requested = requestedOrFunc; + quota = quotaOrRequested; + description = descriptionOrQuota; + assert(maybeDescription === undefined, + "Too many args passed to no-constructor version of assert_throws_quotaexceedederror"); + } + assert_throws_quotaexceedederror_impl(func, requested, quota, description, "assert_throws_quotaexceedederror", constructor); + } + expose_assert(assert_throws_quotaexceedederror, "assert_throws_quotaexceedederror"); + + /** + * Similar to `assert_throws_quotaexceedederror` but allows + * specifying the assertion type + * (`"assert_throws_quotaexceedederror"` or + * `"promise_rejects_quotaexceedederror"`, in practice). The + * `constructor` argument must be the `QuotaExceededError` + * constructor from the global we expect the exception to come from. + */ + function assert_throws_quotaexceedederror_impl(func, requested, quota, description, assertion_type, constructor) + { + try { + func.call(this); + assert(false, assertion_type, description, "${func} did not throw", + {func}); + } catch (e) { + if (e instanceof AssertionError) { + throw e; + } + + // Basic sanity-checks on the thrown exception. + assert(typeof e === "object", + assertion_type, description, + "${func} threw ${e} with type ${type}, not an object", + {func, e, type:typeof e}); + + assert(e !== null, + assertion_type, description, + "${func} threw null, not an object", + {func}); + + // Sanity-check our requested and quota. + assert(requested === null || + typeof requested === "number" || + typeof requested === "function", + assertion_type, description, + "${requested} is not null, a number, or a function", + {requested}); + assert(quota === null || + typeof quota === "number" || + typeof quota === "function", + assertion_type, description, + "${quota} is not null or a number", + {quota}); + + const required_props = { + code: 22, + name: "QuotaExceededError" + }; + if (typeof requested !== "function") { + required_props.requested = requested; + } + if (typeof quota !== "function") { + required_props.quota = quota; + } + + for (const [prop, expected] of Object.entries(required_props)) { + assert(prop in e && e[prop] == expected, + assertion_type, description, + "${func} threw ${e} that is not a correct QuotaExceededError: property ${prop} is equal to ${actual}, expected ${expected}", + {func, e, prop, actual:e[prop], expected}); + } + + if (typeof requested === "function") { + assert(requested(e.requested), + assertion_type, description, + "${func} threw ${e} that is not a correct QuotaExceededError: requested value ${requested} did not pass the requested predicate", + {func, e, requested}); + } + if (typeof quota === "function") { + assert(quota(e.quota), + assertion_type, description, + "${func} threw ${e} that is not a correct QuotaExceededError: quota value ${quota} did not pass the quota predicate", + {func, e, quota}); + } + + // Check that the exception is from the right global. This check is last + // so more specific, and more informative, checks on the properties can + // happen in case a totally incorrect exception is thrown. + assert(e.constructor === constructor, + assertion_type, description, + "${func} threw an exception from the wrong global", + {func}); + } + } + /** * Assert the provided value is thrown. * @@ -2416,7 +2686,7 @@ function assert_implements(condition, description) { assert(!!condition, "assert_implements", description); } - expose_assert(assert_implements, "assert_implements") + expose_assert(assert_implements, "assert_implements"); /** * Assert that an optional feature is implemented, based on a 'truthy' condition. @@ -2530,11 +2800,11 @@ 2: "Timeout", 3: "Not Run", 4: "Optional Feature Unsupported", - } + }; Test.prototype.format_status = function() { return this.status_formats[this.status]; - } + }; Test.prototype.structured_clone = function() { @@ -2715,7 +2985,8 @@ Test.prototype.step_timeout = function(func, timeout) { var test_this = this; var args = Array.prototype.slice.call(arguments, 2); - return setTimeout(this.step_func(function() { + var local_set_timeout = typeof global_scope.setTimeout === "undefined" ? fake_set_timeout : setTimeout; + return local_set_timeout(this.step_func(function() { return func.apply(test_this, args); }), timeout * tests.timeout_multiplier); }; @@ -2746,6 +3017,7 @@ var timeout_full = timeout * tests.timeout_multiplier; var remaining = Math.ceil(timeout_full / interval); var test_this = this; + var local_set_timeout = typeof global_scope.setTimeout === 'undefined' ? fake_set_timeout : setTimeout; const step = test_this.step_func((result) => { if (result) { @@ -2756,7 +3028,7 @@ "Timed out waiting on condition"); } remaining--; - setTimeout(wait_for_inner, interval); + local_set_timeout(wait_for_inner, interval); } }); @@ -2842,7 +3114,7 @@ return new Promise(resolve => { this.step_wait_func(cond, resolve, description, timeout, interval); }); - } + }; /* * Private method for registering cleanup functions. `testharness.js` @@ -3075,7 +3347,7 @@ throw new Error("AbortController is not supported in this browser"); } return this._abortController.signal; - } + }; /** * A RemoteTest object mirrors a Test object on a remote worker. The @@ -3151,11 +3423,11 @@ function(callback) { callback(); }); - } + }; RemoteTest.prototype.format_status = function() { return Test.prototype.status_formats[this.status]; - } + }; /* * A RemoteContext listens for test events from a remote test context, such @@ -3427,7 +3699,7 @@ this.all_done_callbacks = []; this.hide_test_state = false; - this.pending_remotes = []; + this.remotes = []; this.current_test = null; this.asserts_run = []; @@ -3469,26 +3741,26 @@ for (var p in properties) { if (properties.hasOwnProperty(p)) { var value = properties[p]; - if (p == "allow_uncaught_exception") { + if (p === "allow_uncaught_exception") { this.allow_uncaught_exception = value; - } else if (p == "explicit_done" && value) { + } else if (p === "explicit_done" && value) { this.wait_for_finish = true; - } else if (p == "explicit_timeout" && value) { + } else if (p === "explicit_timeout" && value) { this.timeout_length = null; if (this.timeout_id) { clearTimeout(this.timeout_id); } - } else if (p == "single_test" && value) { + } else if (p === "single_test" && value) { this.set_file_is_test(); - } else if (p == "timeout_multiplier") { + } else if (p === "timeout_multiplier") { this.timeout_multiplier = value; if (this.timeout_length) { this.timeout_length *= this.timeout_multiplier; } - } else if (p == "hide_test_state") { + } else if (p === "hide_test_state") { this.hide_test_state = value; - } else if (p == "output") { + } else if (p === "output") { this.output = value; } else if (p === "debug") { settings.debug = value; @@ -3581,11 +3853,14 @@ Tests.prototype.push = function(test) { + if (this.phase === this.phases.COMPLETE) { + return; + } if (this.phase < this.phases.HAVE_TESTS) { this.start(); } this.num_pending++; - test.index = this.tests.push(test); + test.index = this.tests.push(test) - 1; this.notify_test_state(test); }; @@ -3598,11 +3873,11 @@ }; Tests.prototype.all_done = function() { - return (this.tests.length > 0 || this.pending_remotes.length > 0) && + return (this.tests.length > 0 || this.remotes.length > 0) && test_environment.all_loaded && (this.num_pending === 0 || this.is_aborted) && !this.wait_for_finish && !this.processing_callbacks && - !this.pending_remotes.some(function(w) { return w.running; }); + !this.remotes.some(function(w) { return w.running; }); }; Tests.prototype.start = function() { @@ -3671,7 +3946,8 @@ function(test, testDone) { if (test.phase === test.phases.INITIAL) { - test.phase = test.phases.COMPLETE; + test.phase = test.phases.HAS_RESULT; + test.done(); testDone(); } else { add_test_done_callback(test, testDone); @@ -3682,14 +3958,14 @@ }; Tests.prototype.set_assert = function(assert_name, args) { - this.asserts_run.push(new AssertRecord(this.current_test, assert_name, args)) - } + this.asserts_run.push(new AssertRecord(this.current_test, assert_name, args)); + }; Tests.prototype.set_assert_status = function(index, status, stack) { let assert_record = this.asserts_run[index]; assert_record.status = status; assert_record.stack = stack; - } + }; /** * Update the harness status to reflect an unrecoverable harness error that @@ -3831,7 +4107,7 @@ } var remoteContext = this.create_remote_worker(worker); - this.pending_remotes.push(remoteContext); + this.remotes.push(remoteContext); return remoteContext.done; }; @@ -3854,7 +4130,7 @@ } var remoteContext = this.create_remote_window(remote); - this.pending_remotes.push(remoteContext); + this.remotes.push(remoteContext); return remoteContext.done; }; @@ -4066,8 +4342,8 @@ } else { var root = output_document.documentElement; var is_html = (root && - root.namespaceURI == "http://www.w3.org/1999/xhtml" && - root.localName == "html"); + root.namespaceURI === "http://www.w3.org/1999/xhtml" && + root.localName === "html"); var is_svg = (output_document.defaultView && "SVGSVGElement" in output_document.defaultView && root instanceof output_document.defaultView.SVGSVGElement); @@ -4169,11 +4445,7 @@ status ], ], - ["button", - {"onclick": "let evt = new Event('__test_restart'); " + - "let canceled = !window.dispatchEvent(evt);" + - "if (!canceled) { location.reload() }"}, - "Rerun"] + ["button", {"id":"rerun"}, "Rerun"] ]]; if (harness_status.status === harness_status.ERROR) { @@ -4205,6 +4477,13 @@ log.appendChild(render(summary_template, {num_tests:tests.length}, output_document)); + output_document.getElementById("rerun").addEventListener("click", + function() { + let evt = new Event('__test_restart'); + let canceled = !window.dispatchEvent(evt); + if (!canceled) { location.reload(); } + }); + forEach(output_document.querySelectorAll("section#summary label"), function(element) { @@ -4229,18 +4508,6 @@ }); }); - // This use of innerHTML plus manual escaping is not recommended in - // general, but is necessary here for performance. Using textContent - // on each individual adds tens of seconds of execution time for - // large test suites (tens of thousands of tests). - function escape_html(s) - { - return s.replace(/\&/g, "&") - .replace(/ { - var output_fn = "" + escape_html(assert.assert_name) + "("; - var prefix_len = output_fn.length; - var output_args = assert.args; - var output_len = output_args.reduce((prev, current) => prev+current, prefix_len); - if (output_len[output_len.length - 1] > 50) { - output_args = output_args.map((x, i) => - (i > 0 ? " ".repeat(prefix_len) : "" )+ x + (i < output_args.length - 1 ? ",\n" : "")); - } else { - output_args = output_args.map((x, i) => x + (i < output_args.length - 1 ? ", " : "")); - } - output_fn += escape_html(output_args.join("")); - output_fn += ')'; - var output_location; + + const table = asserts_output.querySelector("table"); + for (const assert of asserts) { + const status_class_name = status_class(Test.prototype.status_formats[assert.status]); + var output_fn = "(" + assert.args.join(", ") + ")"; if (assert.stack) { - output_location = assert.stack.split("\n", 1)[0].replace(/@?\w+:\/\/[^ "\/]+(?::\d+)?/g, " "); + output_fn += "\n"; + output_fn += assert.stack.split("\n", 1)[0].replace(/@?\w+:\/\/[^ "\/]+(?::\d+)?/g, " "); } - return "" + - "" + - Test.prototype.status_formats[assert.status] + "" + - "
" +
-                    output_fn +
-                    (output_location ? "\n" + escape_html(output_location) : "") +
-                    "
"; + table.appendChild(render( + ["tr", {"class":"overall-" + status_class_name}, + ["td", {"class":status_class_name}, Test.prototype.status_formats[assert.status]], + ["td", {}, ["pre", {}, ["strong", {}, assert.assert_name], output_fn]] ])); } - ).join("\n"); - rv += ""; - return rv; + return asserts_output; } - log.appendChild(document.createElementNS(xhtml_ns, "section")); var assertions = has_assertions(); - var html = "

Details

" + - "" + - (assertions ? "" : "") + - "" + - ""; - for (var i = 0; i < tests.length; i++) { - var test = tests[i]; - html += '' + - '"; - } - html += "
ResultTest NameAssertionMessage
' + - test.format_status() + - "" + - escape_html(test.name) + - "" + - (assertions ? escape_html(get_assertion(test)) + "" : "") + - escape_html(test.message ? tests[i].message : " ") + - (tests[i].stack ? "
" +
-                 escape_html(tests[i].stack) +
-                 "
": ""); + const section = render( + ["section", {}, + ["h2", {}, "Details"], + ["table", {"id":"results", "class":(assertions ? "assertions" : "")}, + ["thead", {}, + ["tr", {}, + ["th", {}, "Result"], + ["th", {}, "Test Name"], + (assertions ? ["th", {}, "Assertion"] : ""), + ["th", {}, "Message" ]]], + ["tbody", {}]]]); + + const tbody = section.querySelector("tbody"); + for (const test of tests) { + const status = test.format_status(); + const status_class_name = status_class(status); + tbody.appendChild(render( + ["tr", {"class":"overall-" + status_class_name}, + ["td", {"class":status_class_name}, status], + ["td", {}, test.name], + (assertions ? ["td", {}, get_assertion(test)] : ""), + ["td", {}, + test.message ?? "", + ["pre", {}, test.stack ?? ""]]])); if (!(test instanceof RemoteTest)) { - html += "
Asserts run" + get_asserts_output(test) + "
" + tbody.lastChild.lastChild.appendChild(get_asserts_output(test)); } - html += "
"; - try { - log.lastChild.innerHTML = html; - } catch (e) { - log.appendChild(document.createElementNS(xhtml_ns, "p")) - .textContent = "Setting innerHTML for the log threw an exception."; - log.appendChild(document.createElementNS(xhtml_ns, "pre")) - .textContent = html; } + log.appendChild(section); }; /* @@ -4410,13 +4659,20 @@ { var substitution_re = /\$\{([^ }]*)\}/g; - function do_substitution(input) { + function do_substitution(input) + { var components = input.split(substitution_re); var rv = []; - for (var i = 0; i < components.length; i += 2) { - rv.push(components[i]); - if (components[i + 1]) { - rv.push(String(substitutions[components[i + 1]])); + if (components.length === 1) { + rv = components; + } else if (substitutions) { + for (var i = 0; i < components.length; i += 2) { + if (components[i]) { + rv.push(components[i]); + } + if (substitutions[components[i + 1]]) { + rv.push(String(substitutions[components[i + 1]])); + } } } return rv; @@ -4532,7 +4788,7 @@ */ function AssertionError(message) { - if (typeof message == "string") { + if (typeof message === "string") { message = sanitize_unpaired_surrogates(message); } this.message = message; @@ -4578,7 +4834,7 @@ } return lines.slice(i).join("\n"); - } + }; function OptionalFeatureUnsupportedError(message) { @@ -4767,11 +5023,21 @@ return META_TITLE; } if ('location' in global_scope && 'pathname' in location) { - return location.pathname.substring(location.pathname.lastIndexOf('/') + 1, location.pathname.indexOf('.')); + var filename = location.pathname.substring(location.pathname.lastIndexOf('/') + 1); + return filename.substring(0, filename.indexOf('.')); } return "Untitled"; } + /** Fetches a JSON resource and parses it */ + async function fetch_json(resource) { + const response = await fetch(resource); + return await response.json(); + } + if (!global_scope.GLOBAL || !global_scope.GLOBAL.isShadowRealm()) { + expose(fetch_json, 'fetch_json'); + } + /** * Setup globals */ diff --git a/test/fixtures/wpt/resources/testharnessreport.js b/test/fixtures/wpt/resources/testharnessreport.js index e5cb40fe0ef652..405a2d8b06f00f 100644 --- a/test/fixtures/wpt/resources/testharnessreport.js +++ b/test/fixtures/wpt/resources/testharnessreport.js @@ -14,31 +14,6 @@ * parameters they are called with see testharness.js */ -function dump_test_results(tests, status) { - var results_element = document.createElement("script"); - results_element.type = "text/json"; - results_element.id = "__testharness__results__"; - var test_results = tests.map(function(x) { - return {name:x.name, status:x.status, message:x.message, stack:x.stack} - }); - var data = {test:window.location.href, - tests:test_results, - status: status.status, - message: status.message, - stack: status.stack}; - results_element.textContent = JSON.stringify(data); - - // To avoid a HierarchyRequestError with XML documents, ensure that 'results_element' - // is inserted at a location that results in a valid document. - var parent = document.body - ? document.body // is required in XHTML documents - : document.documentElement; // fallback for optional in HTML5, SVG, etc. - - parent.appendChild(results_element); -} - -add_completion_callback(dump_test_results); - /* If the parent window has a testharness_properties object, * we use this to provide the test settings. This is used by the * default in-browser runner to configure the timeout and the diff --git a/test/fixtures/wpt/resources/web-bluetooth-bidi-test.js b/test/fixtures/wpt/resources/web-bluetooth-bidi-test.js new file mode 100644 index 00000000000000..3283fef43fc7d2 --- /dev/null +++ b/test/fixtures/wpt/resources/web-bluetooth-bidi-test.js @@ -0,0 +1,408 @@ +'use strict' + +// Convert `manufacturerData` to an array of bluetooth.BluetoothManufacturerData +// defined in +// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-bidi-definitions. +function convertToBidiManufacturerData(manufacturerData) { + const bidiManufacturerData = []; + for (const key in manufacturerData) { + bidiManufacturerData.push({ + key: parseInt(key), + data: btoa(String.fromCharCode(...manufacturerData[key])) + }) + } + return bidiManufacturerData; +} + +function ArrayToMojoCharacteristicProperties(arr) { + const struct = {}; + arr.forEach(property => { + struct[property] = true; + }); + return struct; +} + +class FakeBluetooth { + constructor() { + this.fake_central_ = null; + } + + // Returns a promise that resolves with a FakeCentral that clients can use + // to simulate events that a device in the Central/Observer role would + // receive as well as monitor the operations performed by the device in the + // Central/Observer role. + // + // A "Central" object would allow its clients to receive advertising events + // and initiate connections to peripherals i.e. operations of two roles + // defined by the Bluetooth Spec: Observer and Central. + // See Bluetooth 4.2 Vol 3 Part C 2.2.2 "Roles when Operating over an + // LE Physical Transport". + async simulateCentral({state}) { + if (this.fake_central_) { + throw 'simulateCentral() should only be called once'; + } + + await test_driver.bidi.bluetooth.simulate_adapter({state: state}); + this.fake_central_ = new FakeCentral(); + return this.fake_central_; + } +} + +// FakeCentral allows clients to simulate events that a device in the +// Central/Observer role would receive as well as monitor the operations +// performed by the device in the Central/Observer role. +class FakeCentral { + constructor() { + this.peripherals_ = new Map(); + } + + // Simulates a peripheral with |address|, |name|, |manufacturerData| and + // |known_service_uuids| that has already been connected to the system. If the + // peripheral existed already it updates its name, manufacturer data, and + // known UUIDs. |known_service_uuids| should be an array of + // BluetoothServiceUUIDs + // https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-bluetoothserviceuuid + // + // Platforms offer methods to retrieve devices that have already been + // connected to the system or weren't connected through the UA e.g. a user + // connected a peripheral through the system's settings. This method is + // intended to simulate peripherals that those methods would return. + async simulatePreconnectedPeripheral( + {address, name, manufacturerData = {}, knownServiceUUIDs = []}) { + await test_driver.bidi.bluetooth.simulate_preconnected_peripheral({ + address: address, + name: name, + manufacturerData: convertToBidiManufacturerData(manufacturerData), + knownServiceUuids: + knownServiceUUIDs.map(uuid => BluetoothUUID.getService(uuid)) + }); + + return this.fetchOrCreatePeripheral_(address); + } + + // Create a fake_peripheral object from the given address. + fetchOrCreatePeripheral_(address) { + let peripheral = this.peripherals_.get(address); + if (peripheral === undefined) { + peripheral = new FakePeripheral(address); + this.peripherals_.set(address, peripheral); + } + return peripheral; + } +} + +class FakePeripheral { + constructor(address) { + this.address = address; + } + + // Adds a fake GATT Service with |uuid| to be discovered when discovering + // the peripheral's GATT Attributes. Returns a FakeRemoteGATTService + // corresponding to this service. |uuid| should be a BluetoothServiceUUIDs + // https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-bluetoothserviceuuid + async addFakeService({uuid}) { + const service_uuid = BluetoothUUID.getService(uuid); + await test_driver.bidi.bluetooth.simulate_service({ + address: this.address, + uuid: service_uuid, + type: 'add', + }); + return new FakeRemoteGATTService(service_uuid, this.address); + } + + // Sets the next GATT Connection request response to |code|. |code| could be + // an HCI Error Code from BT 4.2 Vol 2 Part D 1.3 List Of Error Codes or a + // number outside that range returned by specific platforms e.g. Android + // returns 0x101 to signal a GATT failure + // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE + async setNextGATTConnectionResponse({code}) { + const remove_handler = + test_driver.bidi.bluetooth.gatt_connection_attempted.on((event) => { + if (event.address != this.address) { + return; + } + remove_handler(); + test_driver.bidi.bluetooth.simulate_gatt_connection_response({ + address: event.address, + code, + }); + }); + } + + async setNextGATTDiscoveryResponse({code}) { + // No-op for Web Bluetooth Bidi test, it will be removed when migration + // completes. + return Promise.resolve(); + } + + // Simulates a GATT connection response with |code| from the peripheral. + async simulateGATTConnectionResponse(code) { + await test_driver.bidi.bluetooth.simulate_gatt_connection_response( + {address: this.address, code}); + } + + // Simulates a GATT disconnection in the peripheral. + async simulateGATTDisconnection() { + await test_driver.bidi.bluetooth.simulate_gatt_disconnection( + {address: this.address}); + } +} + +class FakeRemoteGATTService { + constructor(service_uuid, peripheral_address) { + this.service_uuid_ = service_uuid; + this.peripheral_address_ = peripheral_address; + } + + // Adds a fake GATT Characteristic with |uuid| and |properties| + // to this fake service. The characteristic will be found when discovering + // the peripheral's GATT Attributes. Returns a FakeRemoteGATTCharacteristic + // corresponding to the added characteristic. + async addFakeCharacteristic({uuid, properties}) { + const characteristic_uuid = BluetoothUUID.getCharacteristic(uuid); + await test_driver.bidi.bluetooth.simulate_characteristic({ + address: this.peripheral_address_, + serviceUuid: this.service_uuid_, + characteristicUuid: characteristic_uuid, + characteristicProperties: ArrayToMojoCharacteristicProperties(properties), + type: 'add' + }); + return new FakeRemoteGATTCharacteristic( + characteristic_uuid, this.service_uuid_, this.peripheral_address_); + } + + // Removes the fake GATT service from its fake peripheral. + async remove() { + await test_driver.bidi.bluetooth.simulate_service({ + address: this.peripheral_address_, + uuid: this.service_uuid_, + type: 'remove' + }); + } +} + +class FakeRemoteGATTCharacteristic { + constructor(characteristic_uuid, service_uuid, peripheral_address) { + this.characteristic_uuid_ = characteristic_uuid; + this.service_uuid_ = service_uuid; + this.peripheral_address_ = peripheral_address; + this.last_written_value_ = {lastValue: null, lastWriteType: 'none'}; + } + + // Adds a fake GATT Descriptor with |uuid| to be discovered when + // discovering the peripheral's GATT Attributes. Returns a + // FakeRemoteGATTDescriptor corresponding to this descriptor. |uuid| should + // be a BluetoothDescriptorUUID + // https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-bluetoothdescriptoruuid + async addFakeDescriptor({uuid}) { + const descriptor_uuid = BluetoothUUID.getDescriptor(uuid); + await test_driver.bidi.bluetooth.simulate_descriptor({ + address: this.peripheral_address_, + serviceUuid: this.service_uuid_, + characteristicUuid: this.characteristic_uuid_, + descriptorUuid: descriptor_uuid, + type: 'add' + }); + return new FakeRemoteGATTDescriptor( + descriptor_uuid, this.characteristic_uuid_, this.service_uuid_, + this.peripheral_address_); + } + + // Simulate a characteristic for operation |type| with response |code| and + // |data|. + async simulateResponse(type, code, data) { + await test_driver.bidi.bluetooth.simulate_characteristic_response({ + address: this.peripheral_address_, + serviceUuid: this.service_uuid_, + characteristicUuid: this.characteristic_uuid_, + type, + code, + data, + }); + } + + // Simulate a characteristic response for read operation with response |code| + // and |data|. + async simulateReadResponse(code, data) { + await this.simulateResponse('read', code, data); + } + + // Simulate a characteristic response for write operation with response + // |code|. + async simulateWriteResponse(code) { + await this.simulateResponse('write', code); + } + + // Sets the next read response for characteristic to |code| and |value|. + // |code| could be a GATT Error Response from + // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range + // returned by specific platforms e.g. Android returns 0x101 to signal a GATT + // failure. + // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE + async setNextReadResponse(gatt_code, value = null) { + if (gatt_code === 0 && value === null) { + throw '|value| can\'t be null if read should success.'; + } + if (gatt_code !== 0 && value !== null) { + throw '|value| must be null if read should fail.'; + } + + const remove_handler = + test_driver.bidi.bluetooth.characteristic_event_generated.on( + (event) => { + if (event.address != this.peripheral_address_) { + return; + } + remove_handler(); + this.simulateReadResponse(gatt_code, value); + }); + } + + // Sets the next write response for this characteristic to |code|. If + // writing to a characteristic that only supports 'write-without-response' + // the set response will be ignored. + // |code| could be a GATT Error Response from + // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range + // returned by specific platforms e.g. Android returns 0x101 to signal a GATT + // failure. + async setNextWriteResponse(gatt_code) { + const remove_handler = + test_driver.bidi.bluetooth.characteristic_event_generated.on( + (event) => { + if (event.address != this.peripheral_address_) { + return; + } + this.last_written_value_ = { + lastValue: event.data, + lastWriteType: event.type + }; + remove_handler(); + if (event.type == 'write-with-response') { + this.simulateWriteResponse(gatt_code); + } + }); + } + + // Gets the last successfully written value to the characteristic and its + // write type. Write type is one of 'none', 'default-deprecated', + // 'with-response', 'without-response'. Returns {lastValue: null, + // lastWriteType: 'none'} if no value has yet been written to the + // characteristic. + async getLastWrittenValue() { + return this.last_written_value_; + } + + // Removes the fake GATT Characteristic from its fake service. + async remove() { + await test_driver.bidi.bluetooth.simulate_characteristic({ + address: this.peripheral_address_, + serviceUuid: this.service_uuid_, + characteristicUuid: this.characteristic_uuid_, + characteristicProperties: undefined, + type: 'remove' + }); + } +} + +class FakeRemoteGATTDescriptor { + constructor( + descriptor_uuid, characteristic_uuid, service_uuid, peripheral_address) { + this.descriptor_uuid_ = descriptor_uuid; + this.characteristic_uuid_ = characteristic_uuid; + this.service_uuid_ = service_uuid; + this.peripheral_address_ = peripheral_address; + this.last_written_value_ = null; + } + + // Simulate a descriptor for operation |type| with response |code| and + // |data|. + async simulateResponse(type, code, data) { + await test_driver.bidi.bluetooth.simulate_descriptor_response({ + address: this.peripheral_address_, + serviceUuid: this.service_uuid_, + characteristicUuid: this.characteristic_uuid_, + descriptorUuid: this.descriptor_uuid_, + type, + code, + data, + }); + } + + // Simulate a descriptor response for read operation with response |code| and + // |data|. + async simulateReadResponse(code, data) { + await this.simulateResponse('read', code, data); + } + + // Simulate a descriptor response for write operation with response |code|. + async simulateWriteResponse(code) { + await this.simulateResponse('write', code); + } + + // Sets the next read response for descriptor to |code| and |value|. + // |code| could be a GATT Error Response from + // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range + // returned by specific platforms e.g. Android returns 0x101 to signal a GATT + // failure. + // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE + async setNextReadResponse(gatt_code, value = null) { + if (gatt_code === 0 && value === null) { + throw '|value| can\'t be null if read should success.'; + } + if (gatt_code !== 0 && value !== null) { + throw '|value| must be null if read should fail.'; + } + + const remove_handler = + test_driver.bidi.bluetooth.descriptor_event_generated.on((event) => { + if (event.address != this.peripheral_address_) { + return; + } + remove_handler(); + this.simulateReadResponse(gatt_code, value); + }); + } + + // Sets the next write response for this descriptor to |code|. + // |code| could be a GATT Error Response from + // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range + // returned by specific platforms e.g. Android returns 0x101 to signal a GATT + // failure. + async setNextWriteResponse(gatt_code) { + const remove_handler = + test_driver.bidi.bluetooth.descriptor_event_generated.on((event) => { + if (event.address != this.peripheral_address_) { + return; + } + this.last_written_value_ = { + lastValue: event.data, + lastWriteType: event.type + }; + remove_handler(); + if (event.type == 'write-with-response') { + this.simulateWriteResponse(gatt_code); + } + }); + } + + // Gets the last successfully written value to the descriptor. + // Returns null if no value has yet been written to the descriptor. + async getLastWrittenValue() { + return this.last_written_value_; + } + + // Removes the fake GATT Descriptor from its fake characteristic. + async remove() { + await test_driver.bidi.bluetooth.simulate_descriptor({ + address: this.peripheral_address_, + serviceUuid: this.service_uuid_, + characteristicUuid: this.characteristic_uuid_, + descriptorUuid: this.descriptor_uuid_, + type: 'remove' + }); + } +} + +function initializeBluetoothBidiResources() { + navigator.bluetooth.test = new FakeBluetooth(); +} diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index 191272bb8ff043..666b1d9deaa780 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -64,7 +64,7 @@ "path": "resource-timing" }, "resources": { - "commit": "1e140d63ec885703ce24b3798abd81912696bb85", + "commit": "1d2c5fb36a6e477c8f915bde7eca027be6abe792", "path": "resources" }, "streams": { @@ -88,7 +88,7 @@ "path": "wasm/webapi" }, "WebCryptoAPI": { - "commit": "ab08796857072c5a93e27e0a25effba2e07dad11", + "commit": "1d2c5fb36a6e477c8f915bde7eca027be6abe792", "path": "WebCryptoAPI" }, "webidl/ecmascript-binding/es-exceptions": { @@ -100,7 +100,7 @@ "path": "webmessaging/broadcastchannel" }, "webstorage": { - "commit": "1291340aaaa6e73db43b412e47401eca3830c556", + "commit": "1d2c5fb36a6e477c8f915bde7eca027be6abe792", "path": "webstorage" } } diff --git a/test/fixtures/wpt/webstorage/storage_local_setitem_quotaexceedederr.window.js b/test/fixtures/wpt/webstorage/storage_local_setitem_quotaexceedederr.window.js index fff7d6444a039e..f2f3c4d6887542 100644 --- a/test/fixtures/wpt/webstorage/storage_local_setitem_quotaexceedederr.window.js +++ b/test/fixtures/wpt/webstorage/storage_local_setitem_quotaexceedederr.window.js @@ -1,16 +1,18 @@ -test(function() { +test(t => { localStorage.clear(); var index = 0; var key = "name"; var val = "x".repeat(1024); - assert_throws_dom("QUOTA_EXCEEDED_ERR", function() { + t.add_cleanup(() => { + localStorage.clear(); + }); + + assert_throws_quotaexceedederror(() => { while (true) { index++; localStorage.setItem("" + key + index, "" + val + index); } - }); - - localStorage.clear(); + }, null, null); }, "Throws QuotaExceededError when the quota has been exceeded"); diff --git a/test/fixtures/wpt/webstorage/storage_session_setitem_quotaexceedederr.window.js b/test/fixtures/wpt/webstorage/storage_session_setitem_quotaexceedederr.window.js index 42a895470efa62..693c98d29f99fd 100644 --- a/test/fixtures/wpt/webstorage/storage_session_setitem_quotaexceedederr.window.js +++ b/test/fixtures/wpt/webstorage/storage_session_setitem_quotaexceedederr.window.js @@ -1,16 +1,18 @@ -test(function() { +test(t => { sessionStorage.clear(); var index = 0; var key = "name"; var val = "x".repeat(1024); - assert_throws_dom("QUOTA_EXCEEDED_ERR", function() { + t.add_cleanup(() => { + sessionStorage.clear(); + }); + + assert_throws_quotaexceedederror(() => { while (true) { index++; sessionStorage.setItem("" + key + index, "" + val + index); } - }); - - sessionStorage.clear(); + }, null, null); }, "Throws QuotaExceededError when the quota has been exceeded"); diff --git a/test/fixtures/wpt/webstorage/symbol-props.window.js b/test/fixtures/wpt/webstorage/symbol-props.window.js index 61dd8f83dc4f5b..8f598d7076909d 100644 --- a/test/fixtures/wpt/webstorage/symbol-props.window.js +++ b/test/fixtures/wpt/webstorage/symbol-props.window.js @@ -39,10 +39,10 @@ Object.defineProperty(storage, key, { "value": "test", "configurable": false }); assert_equals(storage[key], "test"); var desc = Object.getOwnPropertyDescriptor(storage, key); - assert_true(desc.configurable, "configurable"); + assert_false(desc.configurable, "configurable"); - assert_true(delete storage[key]); - assert_equals(storage[key], undefined); + assert_false(delete storage[key]); + assert_equals(storage[key], "test"); }, name + ": defineProperty not configurable"); test(function() { diff --git a/test/wpt/status/WebCryptoAPI.cjs b/test/wpt/status/WebCryptoAPI.cjs index 709d34b8f47c40..7e4639ca497ba0 100644 --- a/test/wpt/status/WebCryptoAPI.cjs +++ b/test/wpt/status/WebCryptoAPI.cjs @@ -26,4 +26,20 @@ module.exports = { ], }, }, + 'getRandomValues.any.js': { + 'fail': { + 'note': 'https://github.com/nodejs/node/issues/58987', + 'expected': [ + 'Large length: Int8Array', + 'Large length: Int16Array', + 'Large length: Int32Array', + 'Large length: BigInt64Array', + 'Large length: Uint8Array', + 'Large length: Uint8ClampedArray', + 'Large length: Uint16Array', + 'Large length: Uint32Array', + 'Large length: BigUint64Array', + ], + }, + }, }; diff --git a/test/wpt/status/webstorage.json b/test/wpt/status/webstorage.json index 10171601480aad..1dad4e2dd48403 100644 --- a/test/wpt/status/webstorage.json +++ b/test/wpt/status/webstorage.json @@ -22,5 +22,30 @@ }, "storage_session_window_reopen.window.js": { "skip": "window.open() is not supported in Node.js." + }, + "storage_session_setitem_quotaexceedederr.window.js": { + "fail": { + "note": "https://github.com/nodejs/node/issues/58987", + "expected": [ + "Throws QuotaExceededError when the quota has been exceeded" + ] + } + }, + "storage_local_setitem_quotaexceedederr.window.js": { + "fail": { + "note": "https://github.com/nodejs/node/issues/58987", + "expected": [ + "Throws QuotaExceededError when the quota has been exceeded" + ] + } + }, + "symbol-props.window.js": { + "fail": { + "note": "https://github.com/nodejs/node/issues/59310", + "expected": [ + "localStorage: defineProperty not configurable", + "sessionStorage: defineProperty not configurable" + ] + } } } From 46c339e4f34c5cfeec37d53fc829697a06a88ecc Mon Sep 17 00:00:00 2001 From: Aditi <62544124+Aditi-1400@users.noreply.github.com> Date: Sun, 3 Aug 2025 20:54:00 +0530 Subject: [PATCH 103/134] meta: add mailmap entry for aditi-1400 PR-URL: https://github.com/nodejs/node/pull/59316 Reviewed-By: Joyee Cheung Reviewed-By: Darshan Sen Reviewed-By: Luigi Pinca --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index c0aac7e9647a69..0422fba4472601 100644 --- a/.mailmap +++ b/.mailmap @@ -6,6 +6,7 @@ Abdirahim Musse <33973272+abmusse@users.noreply.github Abe Fettig Abhimanyu Vashisht Adam Langley +Aditi Singh Akhil Marsonya Akhil Marsonya <16393876+marsonya@users.noreply.github.com> Akito Ito From 133d410cd9cb8da55901ae717042140642ae61b1 Mon Sep 17 00:00:00 2001 From: iknoom Date: Fri, 1 Aug 2025 04:09:40 +0900 Subject: [PATCH 104/134] src: use C++20 `contains()` method Refactors several `v.find(...) == v.end()` and `v.find(...) != v.end()` to use more expressive and readable C++20 `contains()` method. PR-URL: https://github.com/nodejs/node/pull/59304 Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Franziska Hinkelmann --- src/inspector/io_agent.cc | 2 +- src/inspector_profiler.h | 4 +--- src/node_blob.cc | 4 ++-- src/node_builtins.cc | 2 +- src/node_env_var.cc | 2 +- src/node_messaging.cc | 2 +- src/signal_wrap.cc | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/inspector/io_agent.cc b/src/inspector/io_agent.cc index 749774f5c3144f..c66c091d69b747 100644 --- a/src/inspector/io_agent.cc +++ b/src/inspector/io_agent.cc @@ -27,7 +27,7 @@ DispatchResponse IoAgent::read(const String& in_handle, if (in_offset.has_value()) { offset = *in_offset; offset_was_specified = true; - } else if (offset_map_.find(url) != offset_map_.end()) { + } else if (offset_map_.contains(url)) { offset = offset_map_[url]; } int size = 1 << 20; diff --git a/src/inspector_profiler.h b/src/inspector_profiler.h index fd741c1f1ff659..d07334c818d90e 100644 --- a/src/inspector_profiler.h +++ b/src/inspector_profiler.h @@ -65,9 +65,7 @@ class V8ProfilerConnection { simdjson::ondemand::object* result); virtual void WriteProfile(simdjson::ondemand::object* result); - bool HasProfileId(uint64_t id) const { - return profile_ids_.find(id) != profile_ids_.end(); - } + bool HasProfileId(uint64_t id) const { return profile_ids_.contains(id); } void RemoveProfileId(uint64_t id) { profile_ids_.erase(id); } diff --git a/src/node_blob.cc b/src/node_blob.cc index 3df23669ceb80b..9b9956f5ee3150 100644 --- a/src/node_blob.cc +++ b/src/node_blob.cc @@ -534,11 +534,11 @@ void BlobBindingData::store_data_object( } void BlobBindingData::revoke_data_object(const std::string& uuid) { - if (data_objects_.find(uuid) == data_objects_.end()) { + if (!data_objects_.contains(uuid)) { return; } data_objects_.erase(uuid); - CHECK_EQ(data_objects_.find(uuid), data_objects_.end()); + CHECK(!data_objects_.contains(uuid)); } BlobBindingData::StoredDataObject BlobBindingData::get_data_object( diff --git a/src/node_builtins.cc b/src/node_builtins.cc index abf1583cdac9f1..b4acc40618e372 100644 --- a/src/node_builtins.cc +++ b/src/node_builtins.cc @@ -307,7 +307,7 @@ MaybeLocal BuiltinLoader::LookupAndCompileInternal( if (should_eager_compile_) { options = ScriptCompiler::kEagerCompile; } else if (!to_eager_compile_.empty()) { - if (to_eager_compile_.find(id) != to_eager_compile_.end()) { + if (to_eager_compile_.contains(id)) { options = ScriptCompiler::kEagerCompile; } } diff --git a/src/node_env_var.cc b/src/node_env_var.cc index 8568f3d1fb6b8b..492d5f455f45a5 100644 --- a/src/node_env_var.cc +++ b/src/node_env_var.cc @@ -258,7 +258,7 @@ void MapKVStore::Set(Isolate* isolate, Local key, Local value) { int32_t MapKVStore::Query(const char* key) const { Mutex::ScopedLock lock(mutex_); - return map_.find(key) == map_.end() ? -1 : 0; + return map_.contains(key) ? 0 : -1; } int32_t MapKVStore::Query(Isolate* isolate, Local key) const { diff --git a/src/node_messaging.cc b/src/node_messaging.cc index 42d0e32a9ec21b..66c8868b9d8e69 100644 --- a/src/node_messaging.cc +++ b/src/node_messaging.cc @@ -1508,7 +1508,7 @@ Maybe SiblingGroup::Dispatch( RwLock::ScopedReadLock lock(group_mutex_); // The source MessagePortData is not part of this group. - if (ports_.find(source) == ports_.end()) { + if (!ports_.contains(source)) { if (error != nullptr) *error = "Source MessagePort is not entangled with this group."; return Nothing(); diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index d4fe8a3bcdd9ff..cd4960a4ec9e28 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -170,7 +170,7 @@ void DecreaseSignalHandlerCount(int signum) { bool HasSignalJSHandler(int signum) { Mutex::ScopedLock lock(handled_signals_mutex); - return handled_signals.find(signum) != handled_signals.end(); + return handled_signals.contains(signum); } } // namespace node From 390a9dc20b9b098cc24706693f9789f8b023e978 Mon Sep 17 00:00:00 2001 From: Haram Jeong <91401364+haramj@users.noreply.github.com> Date: Mon, 4 Aug 2025 22:47:09 +0900 Subject: [PATCH 105/134] http: add server.keepAliveTimeoutBuffer option PR-URL: https://github.com/nodejs/node/pull/59243 Reviewed-By: Matteo Collina Reviewed-By: Jason Zhang --- doc/api/http.md | 29 ++++++++++++-- lib/_http_server.js | 23 +++++++++-- .../test-http-keep-alive-timeout-buffer.js | 39 +++++++++++++++++++ 3 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 test/parallel/test-http-keep-alive-timeout-buffer.js diff --git a/doc/api/http.md b/doc/api/http.md index 0ab2910f9194a9..a3f3023937be56 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -1920,18 +1920,39 @@ added: v8.0.0 The number of milliseconds of inactivity a server needs to wait for additional incoming data, after it has finished writing the last response, before a socket -will be destroyed. If the server receives new data before the keep-alive -timeout has fired, it will reset the regular inactivity timeout, i.e., -[`server.timeout`][]. +will be destroyed. + +This timeout value is combined with the +\[`server.keepAliveTimeoutBuffer`]\[] option to determine the actual socket +timeout, calculated as: +socketTimeout = keepAliveTimeout + keepAliveTimeoutBuffer +If the server receives new data before the keep-alive timeout has fired, it +will reset the regular inactivity timeout, i.e., [`server.timeout`][]. A value of `0` will disable the keep-alive timeout behavior on incoming connections. -A value of `0` makes the http server behave similarly to Node.js versions prior +A value of `0` makes the HTTP server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout. The socket timeout logic is set up on connection, so changing this value only affects new connections to the server, not any existing connections. +### `server.keepAliveTimeoutBuffer` + + + +* Type: {number} Timeout in milliseconds. **Default:** `1000` (1 second). + +An additional buffer time added to the +[`server.keepAliveTimeout`][] to extend the internal socket timeout. + +This buffer helps reduce connection reset (`ECONNRESET`) errors by increasing +the socket timeout slightly beyond the advertised keep-alive timeout. + +This option applies only to new incoming connections. + ### `server[Symbol.asyncDispose]()` + +The `Assert` class allows creating independent assertion instances with custom options. + +### `new assert.Assert([options])` + +* `options` {Object} + * `diff` {string} If set to `'full'`, shows the full diff in assertion errors. Defaults to `'simple'`. + Accepted values: `'simple'`, `'full'`. + * `strict` {boolean} If set to `true`, non-strict methods behave like their + corresponding strict methods. Defaults to `true`. + +Creates a new assertion instance. The `diff` option controls the verbosity of diffs in assertion error messages. + +```js +const { Assert } = require('node:assert'); +const assertInstance = new Assert({ diff: 'full' }); +assertInstance.deepStrictEqual({ a: 1 }, { a: 2 }); +// Shows a full diff in the error message. +``` + +**Important**: When destructuring assertion methods from an `Assert` instance, +the methods lose their connection to the instance's configuration options (such as `diff` and `strict` settings). +The destructured methods will fall back to default behavior instead. + +```js +const myAssert = new Assert({ diff: 'full' }); + +// This works as expected - uses 'full' diff +myAssert.strictEqual({ a: 1 }, { b: { c: 1 } }); + +// This loses the 'full' diff setting - falls back to default 'simple' diff +const { strictEqual } = myAssert; +strictEqual({ a: 1 }, { b: { c: 1 } }); +``` + +When destructured, methods lose access to the instance's `this` context and revert to default assertion behavior +(diff: 'simple', non-strict mode). +To maintain custom options when using destructured methods, avoid +destructuring and call methods directly on the instance. + ## Class: `assert.CallTracker` -#### `pbkdb2Params.hash` +#### `pbkdf2Params.hash` - -* Type: {string\[]} - -An array detailing the key extended usages for this certificate. - ### `x509.fingerprint` + +* Type: {string\[]} + +An array detailing the key extended usages for this certificate. + ### `x509.publicKey` + +Node.js uses the trusted CA certificates present in the system store along with +the `--use-bundled-ca` option and the `NODE_EXTRA_CA_CERTS` environment variable. + +This can also be enabled using the [`--use-system-ca`][] command-line flag. +When both are set, `--use-system-ca` takes precedence. + ### `NODE_V8_COVERAGE=dir` When set, Node.js will begin outputting [V8 JavaScript code coverage][] and @@ -3933,6 +3945,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12 [`--print`]: #-p---print-script [`--redirect-warnings`]: #--redirect-warningsfile [`--require`]: #-r---require-module +[`--use-system-ca`]: #--use-system-ca [`AsyncLocalStorage`]: async_context.md#class-asynclocalstorage [`Atomics.wait()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait [`Buffer`]: buffer.md#class-buffer diff --git a/doc/node.1 b/doc/node.1 index 7dbdf038711dec..6fbec527e9c47c 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -809,6 +809,12 @@ When set to .Ar 0 , TLS certificate validation is disabled. . +.It Ev NODE_USE_SYSTEM_CA +Similar to +.Fl -use-system-ca . +Use the trusted CA certificates present in the system store, in addition to the certificates in the +bundled Mozilla CA store and certificates from `NODE_EXTRA_CA_CERTS`. +. .It Ev NODE_V8_COVERAGE Ar dir When set, Node.js writes JavaScript code coverage information to .Ar dir . diff --git a/src/node.cc b/src/node.cc index c0d0b734edfa72..ab2c069fd42466 100644 --- a/src/node.cc +++ b/src/node.cc @@ -912,6 +912,15 @@ static ExitCode InitializeNodeWithArgsInternal( // default value. V8::SetFlagsFromString("--rehash-snapshot"); +#if HAVE_OPENSSL + // TODO(joyeecheung): make this a per-env option and move the normalization + // into HandleEnvOptions. + std::string use_system_ca; + if (credentials::SafeGetenv("NODE_USE_SYSTEM_CA", &use_system_ca) && + use_system_ca == "1") { + per_process::cli_options->use_system_ca = true; + } +#endif // HAVE_OPENSSL HandleEnvOptions(per_process::cli_options->per_isolate->per_env); std::string node_options; diff --git a/test/parallel/test-tls-get-ca-certificates-node-use-system-ca.js b/test/parallel/test-tls-get-ca-certificates-node-use-system-ca.js new file mode 100644 index 00000000000000..81a5cba4da77e2 --- /dev/null +++ b/test/parallel/test-tls-get-ca-certificates-node-use-system-ca.js @@ -0,0 +1,29 @@ +'use strict'; +// This tests that NODE_USE_SYSTEM_CA environment variable works the same +// as --use-system-ca flag by comparing certificate counts. + +const common = require('../common'); +if (!common.hasCrypto) common.skip('missing crypto'); + +const tls = require('tls'); +const { spawnSyncAndExitWithoutError } = require('../common/child_process'); + +const systemCerts = tls.getCACertificates('system'); +if (systemCerts.length === 0) { + common.skip('no system certificates available'); +} + +const { child: { stdout: expectedLength } } = spawnSyncAndExitWithoutError(process.execPath, [ + '--use-system-ca', + '-p', + `tls.getCACertificates('default').length`, +], { + env: { ...process.env, NODE_USE_SYSTEM_CA: '0' }, +}); + +spawnSyncAndExitWithoutError(process.execPath, [ + '-p', + `assert.strictEqual(tls.getCACertificates('default').length, ${expectedLength.toString()})`, +], { + env: { ...process.env, NODE_USE_SYSTEM_CA: '1' }, +}); diff --git a/test/system-ca/test-native-root-certs-env.mjs b/test/system-ca/test-native-root-certs-env.mjs new file mode 100644 index 00000000000000..bde7dfcd9610bc --- /dev/null +++ b/test/system-ca/test-native-root-certs-env.mjs @@ -0,0 +1,56 @@ +// Env: NODE_USE_SYSTEM_CA=1 +// Same as test-native-root-certs.mjs, just testing the environment variable instead of the flag. + +import * as common from '../common/index.mjs'; +import assert from 'node:assert/strict'; +import https from 'node:https'; +import fixtures from '../common/fixtures.js'; +import { it, beforeEach, afterEach, describe } from 'node:test'; +import { once } from 'events'; + +if (!common.hasCrypto) { + common.skip('requires crypto'); +} + +// To run this test, the system needs to be configured to trust +// the CA certificate first (which needs an interactive GUI approval, e.g. TouchID): +// see the README.md in this folder for instructions on how to do this. +const handleRequest = (req, res) => { + const path = req.url; + switch (path) { + case '/hello-world': + res.writeHead(200); + res.end('hello world\n'); + break; + default: + assert(false, `Unexpected path: ${path}`); + } +}; + +describe('use-system-ca', function() { + + async function setupServer(key, cert) { + const theServer = https.createServer({ + key: fixtures.readKey(key), + cert: fixtures.readKey(cert), + }, handleRequest); + theServer.listen(0); + await once(theServer, 'listening'); + + return theServer; + } + + let server; + + beforeEach(async function() { + server = await setupServer('agent8-key.pem', 'agent8-cert.pem'); + }); + + it('trusts a valid root certificate', async function() { + await fetch(`https://localhost:${server.address().port}/hello-world`); + }); + + afterEach(async function() { + server?.close(); + }); +}); From d22d2fa6d4d77ff8ea48e5bbfd5496163f509f41 Mon Sep 17 00:00:00 2001 From: Yoo <121166835+ri7116@users.noreply.github.com> Date: Mon, 11 Aug 2025 12:29:01 +0900 Subject: [PATCH 126/134] lib: optimize writable stream buffer clearing Improved the `clearBuffer` function by replacing `buffered.splice` with `ArrayPrototypeSlice`. - Eliminates O(N) shifting overhead. - Improves CPU utilization and reduces GC overhead. PR-URL: https://github.com/nodejs/node/pull/59406 Reviewed-By: Matteo Collina Reviewed-By: Ethan Arrowood Reviewed-By: Ruben Bridgewater Reviewed-By: Anna Henningsen --- lib/internal/streams/writable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/streams/writable.js b/lib/internal/streams/writable.js index a3a1a965b00a87..84ef2e2629f4f3 100644 --- a/lib/internal/streams/writable.js +++ b/lib/internal/streams/writable.js @@ -786,7 +786,7 @@ function clearBuffer(stream, state) { if (i === buffered.length) { resetBuffer(state); } else if (i > 256) { - buffered.splice(0, i); + state[kBufferedValue] = ArrayPrototypeSlice(buffered, i); state.bufferedIndex = 0; } else { state.bufferedIndex = i; From 264a838779c624da55e23a17669697729fca4156 Mon Sep 17 00:00:00 2001 From: theanarkh Date: Mon, 11 Aug 2025 17:14:44 +0800 Subject: [PATCH 127/134] lib: add trace-sigint APIs PR-URL: https://github.com/nodejs/node/pull/59040 Reviewed-By: Chengzhong Wu --- doc/api/util.md | 10 ++++++ lib/internal/process/pre_execution.js | 5 +-- lib/internal/util/trace_sigint.js | 29 ++++++++++++++++++ lib/util.js | 6 ++++ test/parallel/test-trace-sigint-in-worker.js | 20 ++++++++++++ test/pseudo-tty/test-start-trace-sigint.js | 32 ++++++++++++++++++++ test/pseudo-tty/test-start-trace-sigint.out | 11 +++++++ test/pseudo-tty/test-stop-trace-sigint.js | 32 ++++++++++++++++++++ test/pseudo-tty/test-stop-trace-sigint.out | 0 9 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 lib/internal/util/trace_sigint.js create mode 100644 test/parallel/test-trace-sigint-in-worker.js create mode 100644 test/pseudo-tty/test-start-trace-sigint.js create mode 100644 test/pseudo-tty/test-start-trace-sigint.out create mode 100644 test/pseudo-tty/test-stop-trace-sigint.js create mode 100644 test/pseudo-tty/test-stop-trace-sigint.out diff --git a/doc/api/util.md b/doc/api/util.md index 38c996434021b3..f1769973b12e9d 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -729,6 +729,16 @@ fs.access('file/that/does/not/exist', (err) => { }); ``` +## `util.setTraceSigInt(enable)` + + + +* `enable` {boolean} + +Enable or disable printing a stack trace on `SIGINT`. The API is only available on the main thread. + ## `util.inherits(constructor, superConstructor)` + +* `enabled` {boolean} Enables or disables the return of query results as arrays. + +When enabled, query results returned by the `all()`, `get()`, and `iterate()` methods will be returned as arrays instead +of objects. + ### `statement.setReadBigInts(enabled)` + +When importing WebAssembly modules, the +[WebAssembly JS String Builtins Proposal][] is automatically enabled through the +ESM Integration. This allows WebAssembly modules to directly use efficient +compile-time string builtins from the `wasm:js-string` namespace. + +For example, the following Wasm module exports a string `getLength` function using +the `wasm:js-string` `length` builtin: + +```text +(module + ;; Compile-time import of the string length builtin. + (import "wasm:js-string" "length" (func $string_length (param externref) (result i32))) + + ;; Define getLength, taking a JS value parameter assumed to be a string, + ;; calling string length on it and returning the result. + (func $getLength (param $str externref) (result i32) + local.get $str + call $string_length + ) + + ;; Export the getLength function. + (export "getLength" (func $get_length)) +) +``` + +```js +import { getLength } from './string-len.wasm'; +getLength('foo'); // Returns 3. +``` + +Wasm builtins are compile-time imports that are linked during module compilation +rather than during instantiation. They do not behave like normal module graph +imports and they cannot be inspected via `WebAssembly.Module.imports(mod)` +or virtualized unless recompiling the module using the direct +`WebAssembly.compile` API with string builtins disabled. + +Importing a module in the source phase before it has been instantiated will also +use the compile-time builtins automatically: + +```js +import source mod from './string-len.wasm'; +const { exports: { getLength } } = await WebAssembly.instantiate(mod, {}); +getLength('foo'); // Also returns 3. +``` + +### Reserved Wasm Namespaces + + + +When importing WebAssembly modules through the ESM Integration, they cannot use +import module names or import/export names that start with reserved prefixes: + +* `wasm-js:` - reserved in all module import names, module names and export + names. +* `wasm:` - reserved in module import names and export names (imported module + names are allowed in order to support future builtin polyfills). + +Importing a module using the above reserved names will throw a +`WebAssembly.LinkError`. + ## Top-level `await` @@ -1134,6 +1202,7 @@ resolution for ESM specifiers is [commonjs-extension-resolution-loader][]. [Node.js Module Resolution And Loading Algorithm]: #resolution-algorithm-specification [Terminology]: #terminology [URL]: https://url.spec.whatwg.org/ +[WebAssembly JS String Builtins Proposal]: https://github.com/WebAssembly/js-string-builtins [`"exports"`]: packages.md#exports [`"type"`]: packages.md#type [`--experimental-default-type`]: cli.md#--experimental-default-typetype diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index 3a69558d7a3dba..89b96f38db378c 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -444,7 +444,9 @@ translators.set('wasm', async function(url, source) { // TODO(joyeecheung): implement a translator that just uses // compiled = new WebAssembly.Module(source) to compile it // synchronously. - compiled = await WebAssembly.compile(source); + compiled = await WebAssembly.compile(source, { + builtins: ['js-string'], + }); } catch (err) { err.message = errPath(url) + ': ' + err.message; throw err; @@ -456,6 +458,13 @@ translators.set('wasm', async function(url, source) { if (impt.kind === 'global') { ArrayPrototypePush(wasmGlobalImports, impt); } + // Prefix reservations per https://webassembly.github.io/esm-integration/js-api/index.html#parse-a-webassembly-module. + if (impt.module.startsWith('wasm-js:')) { + throw new WebAssembly.LinkError(`Invalid Wasm import "${impt.module}" in ${url}`); + } + if (impt.name.startsWith('wasm:') || impt.name.startsWith('wasm-js:')) { + throw new WebAssembly.LinkError(`Invalid Wasm import name "${impt.module}" in ${url}`); + } importsList.add(impt.module); } @@ -465,6 +474,9 @@ translators.set('wasm', async function(url, source) { if (expt.kind === 'global') { wasmGlobalExports.add(expt.name); } + if (expt.name.startsWith('wasm:') || expt.name.startsWith('wasm-js:')) { + throw new WebAssembly.LinkError(`Invalid Wasm export name "${expt.name}" in ${url}`); + } exportsList.add(expt.name); } @@ -487,6 +499,7 @@ translators.set('wasm', async function(url, source) { reflect.imports[impt] = wrappedModule; } } + // In cycles importing unexecuted Wasm, wasmInstance will be undefined, which will fail during // instantiation, since all bindings will be in the Temporal Deadzone (TDZ). const { exports } = new WebAssembly.Instance(compiled, reflect.imports); diff --git a/src/node.cc b/src/node.cc index ab2c069fd42466..1b5e989e5456a9 100644 --- a/src/node.cc +++ b/src/node.cc @@ -826,6 +826,11 @@ static ExitCode ProcessGlobalArgsInternal(std::vector* args, env_opts->abort_on_uncaught_exception = true; } + // Support stable Phase 5 WebAssembly proposals + v8_args.emplace_back("--experimental-wasm-imported-strings"); + v8_args.emplace_back("--experimental-wasm-memory64"); + v8_args.emplace_back("--experimental-wasm-exnref"); + #ifdef __POSIX__ // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc. Avoids the // performance penalty of frequent EINTR wakeups when the profiler is running. diff --git a/test/es-module/test-esm-wasm.mjs b/test/es-module/test-esm-wasm.mjs index a6f056b823172f..5931f637662398 100644 --- a/test/es-module/test-esm-wasm.mjs +++ b/test/es-module/test-esm-wasm.mjs @@ -410,4 +410,95 @@ describe('ESM: WASM modules', { concurrency: !process.env.TEST_PARALLEL }, () => strictEqual(stdout, ''); notStrictEqual(code, 0); }); + + it('should reject wasm: import names', async () => { + const { code, stderr, stdout } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-wasm-modules', + '--input-type=module', + '--eval', + `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-import-name.wasm'))})`, + ]); + + match(stderr, /Invalid Wasm import name/); + strictEqual(stdout, ''); + notStrictEqual(code, 0); + }); + + it('should reject wasm-js: import names', async () => { + const { code, stderr, stdout } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-wasm-modules', + '--input-type=module', + '--eval', + `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-import-name-wasm-js.wasm'))})`, + ]); + + match(stderr, /Invalid Wasm import name/); + strictEqual(stdout, ''); + notStrictEqual(code, 0); + }); + + it('should reject wasm-js: import module names', async () => { + const { code, stderr, stdout } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-wasm-modules', + '--input-type=module', + '--eval', + `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-import-module.wasm'))})`, + ]); + + match(stderr, /Invalid Wasm import/); + strictEqual(stdout, ''); + notStrictEqual(code, 0); + }); + + it('should reject wasm: export names', async () => { + const { code, stderr, stdout } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-wasm-modules', + '--input-type=module', + '--eval', + `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-export-name.wasm'))})`, + ]); + + match(stderr, /Invalid Wasm export/); + strictEqual(stdout, ''); + notStrictEqual(code, 0); + }); + + it('should reject wasm-js: export names', async () => { + const { code, stderr, stdout } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-wasm-modules', + '--input-type=module', + '--eval', + `import(${JSON.stringify(fixtures.fileURL('es-modules/invalid-export-name-wasm-js.wasm'))})`, + ]); + + match(stderr, /Invalid Wasm export/); + strictEqual(stdout, ''); + notStrictEqual(code, 0); + }); + + it('should support js-string builtins', async () => { + const { code, stderr, stdout } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-wasm-modules', + '--input-type=module', + '--eval', + [ + 'import { strictEqual } from "node:assert";', + `import * as wasmExports from ${JSON.stringify(fixtures.fileURL('es-modules/js-string-builtins.wasm'))};`, + 'strictEqual(wasmExports.getLength("hello"), 5);', + 'strictEqual(wasmExports.concatStrings("hello", " world"), "hello world");', + 'strictEqual(wasmExports.compareStrings("test", "test"), 1);', + 'strictEqual(wasmExports.compareStrings("test", "different"), 0);', + ].join('\n'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, ''); + strictEqual(code, 0); + }); }); diff --git a/test/fixtures/es-modules/invalid-export-name-wasm-js.wasm b/test/fixtures/es-modules/invalid-export-name-wasm-js.wasm new file mode 100644 index 0000000000000000000000000000000000000000..a6b9a7f7c5ad57d8347003d77940f6ec99dadf26 GIT binary patch literal 64 zcmZQbEY4+QU|?WmWlUgTtY>CoWMCI&t+>OW#*M7=47TYFmSOkvM@MmaWn9- SCoWMCIy{zCFW$NFfeejF|sf?YH>60vE(J@ PrZTcKGO(1S7MB13J$4H? literal 0 HcmV?d00001 diff --git a/test/fixtures/es-modules/invalid-export-name.wat b/test/fixtures/es-modules/invalid-export-name.wat new file mode 100644 index 00000000000000..ef99fef9cfa52f --- /dev/null +++ b/test/fixtures/es-modules/invalid-export-name.wat @@ -0,0 +1,7 @@ +;; Test WASM module with invalid export name starting with 'wasm:' +(module + (func $test (result i32) + i32.const 42 + ) + (export "wasm:invalid" (func $test)) +) \ No newline at end of file diff --git a/test/fixtures/es-modules/invalid-import-module.wasm b/test/fixtures/es-modules/invalid-import-module.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ead151ac0c84ad5a2504c1f7752a08e14b989a0e GIT binary patch literal 94 zcmZQbEY4+QU|?WmWlUgTtY?y71GvMW#*M7=47U@l%y7yFfcGPF*2}oFhY2Y iTx^Ui3<3{zCFW$NFfcGPF*2}oKx7#h ix!4$47z7x&8Dv@V5_3}-#h4g)p-Me-3-XIfAPNDJ%oP;? literal 0 HcmV?d00001 diff --git a/test/fixtures/es-modules/invalid-import-name-wasm-js.wat b/test/fixtures/es-modules/invalid-import-name-wasm-js.wat new file mode 100644 index 00000000000000..cb4d3eaf162818 --- /dev/null +++ b/test/fixtures/es-modules/invalid-import-name-wasm-js.wat @@ -0,0 +1,8 @@ +;; Test WASM module with invalid import name starting with 'wasm-js:' +(module + (import "test" "wasm-js:invalid" (func $invalidImport (result i32))) + (export "test" (func $test)) + (func $test (result i32) + call $invalidImport + ) +) \ No newline at end of file diff --git a/test/fixtures/es-modules/invalid-import-name.wasm b/test/fixtures/es-modules/invalid-import-name.wasm new file mode 100644 index 0000000000000000000000000000000000000000..3c631418294584fecbe13fc122c28dbab5670525 GIT binary patch literal 91 zcmZQbEY4+QU|?WmWlUgTtY;EsWGP84F5xK$id$vol_ln6rZ6xtGchu-b3mjR7`fOO fSr`NuxEW+w@)C1X8O4|wc%e!?a|`l|N+1dWJZlsM literal 0 HcmV?d00001 diff --git a/test/fixtures/es-modules/invalid-import-name.wat b/test/fixtures/es-modules/invalid-import-name.wat new file mode 100644 index 00000000000000..1aae87aaed4840 --- /dev/null +++ b/test/fixtures/es-modules/invalid-import-name.wat @@ -0,0 +1,8 @@ +;; Test WASM module with invalid import name starting with 'wasm:' +(module + (import "test" "wasm:invalid" (func $invalidImport (result i32))) + (export "test" (func $test)) + (func $test (result i32) + call $invalidImport + ) +) \ No newline at end of file diff --git a/test/fixtures/es-modules/js-string-builtins.wasm b/test/fixtures/es-modules/js-string-builtins.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b4c08587dd08e715fa2a79fead8fc46143d949d2 GIT binary patch literal 325 zcmZ9GF%tnX6omKXe2#F;aBfPR5i{xQH%ZBuiCj+Q#U4x}B$^V12y^ m*0XTp2)>iej}7&6 Date: Tue, 5 Aug 2025 11:17:03 -0700 Subject: [PATCH 133/134] esm: unflag --experimental-wasm-modules PR-URL: https://github.com/nodejs/node/pull/57038 Backport-PR-URL: https://github.com/nodejs/node/pull/59179 Reviewed-By: Yagiz Nizipli Reviewed-By: Matteo Collina Reviewed-By: James M Snell Reviewed-By: Stephen Belanger Reviewed-By: Geoffrey Booth Reviewed-By: Chengzhong Wu --- doc/api/cli.md | 19 ++-------- doc/api/esm.md | 36 ++++++++++--------- doc/node-config-schema.json | 3 -- doc/node.1 | 3 -- lib/internal/modules/esm/formats.js | 10 ++---- lib/internal/modules/esm/translators.js | 3 +- src/node_options.cc | 5 +-- src/node_options.h | 1 - test/es-module/test-esm-wasm.mjs | 25 ++----------- .../test-module-hooks-import-wasm.mjs | 3 +- .../test-module-hooks-require-wasm.js | 3 +- ...rocess-env-allowed-flags-are-documented.js | 1 + 12 files changed, 32 insertions(+), 80 deletions(-) diff --git a/doc/api/cli.md b/doc/api/cli.md index 689a0867ac5f72..f826c558bc2a1c 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -36,8 +36,7 @@ If a file is found, its path will be passed to the point to be loaded with ECMAScript module loader, such as `--import` or [`--experimental-default-type=module`][]. * The file has an `.mjs` extension. -* The file has an `.mjs` or `.wasm` (with `--experimental-wasm-modules`) - extension. +* The file has an `.mjs` or `.wasm` extension. * The file does not have a `.cjs` extension, and the nearest parent `package.json` file contains a top-level [`"type"`][] field with a value of `"module"`. @@ -49,8 +48,7 @@ Otherwise, the file is loaded using the CommonJS module loader. See When loading, the [ES module loader][Modules loaders] loads the program entry point, the `node` command will accept as input only files with `.js`, -`.mjs`, or `.cjs` extensions; with `.wasm` extensions when -[`--experimental-wasm-modules`][] is enabled; and with no extension when +`.mjs`, `.cjs` or `.wasm` extensions; and with no extension when [`--experimental-default-type=module`][] is passed. ## Options @@ -1015,8 +1013,7 @@ Node.js currently defaults to CommonJS to instead default to ECMAScript modules, with the exception of folders and subfolders below `node_modules`, for backward compatibility. -Under `--experimental-default-type=module` and `--experimental-wasm-modules`, -files with no extension will be treated as WebAssembly if they begin with the +Files with no extension will be treated as WebAssembly if they begin with the WebAssembly magic number (`\0asm`); otherwise they will be treated as ES module JavaScript. @@ -1233,14 +1230,6 @@ changes: Enable experimental WebAssembly System Interface (WASI) support. -### `--experimental-wasm-modules` - - - -Enable experimental WebAssembly module support. - ### `--experimental-webstorage` + +Importing both WebAssembly module instances and WebAssembly source phase +imports is supported. + +This integration is in line with the +[ES Module Integration Proposal for WebAssembly][]. + +## Wasm modules + > Stability: 1 - Experimental -Importing WebAssembly modules is supported under the -`--experimental-wasm-modules` flag, allowing any `.wasm` files to be +Importing WebAssembly modules is supported allowing any `.wasm` files to be imported as normal modules while also supporting their module imports. This integration is in line with the @@ -691,7 +705,7 @@ console.log(M); executed under: ```bash -node --experimental-wasm-modules index.mjs +node index.mjs ``` would provide the exports interface for the instantiation of `module.wasm`. @@ -738,15 +752,6 @@ imports and they cannot be inspected via `WebAssembly.Module.imports(mod)` or virtualized unless recompiling the module using the direct `WebAssembly.compile` API with string builtins disabled. -Importing a module in the source phase before it has been instantiated will also -use the compile-time builtins automatically: - -```js -import source mod from './string-len.wasm'; -const { exports: { getLength } } = await WebAssembly.instantiate(mod, {}); -getLength('foo'); // Also returns 3. -``` - ### Reserved Wasm Namespaces The `Assert` class allows creating independent assertion instances with custom options. diff --git a/doc/api/cli.md b/doc/api/cli.md index f826c558bc2a1c..1a1e0ec1d89a4d 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -1050,7 +1050,7 @@ Previously gated the entire `import.meta.resolve` feature. > Stability: 1.1 - Active Development @@ -3593,7 +3593,7 @@ variable is strongly discouraged. ### `NODE_USE_SYSTEM_CA=1` Node.js uses the trusted CA certificates present in the system store along with diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 0d074ce672b639..7ee2f298e83875 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -3869,7 +3869,7 @@ Creating SHAKE-128 and SHAKE-256 digests without an explicit `options.outputLeng diff --git a/doc/api/esm.md b/doc/api/esm.md index c2d3876d54e0c8..1c7c1b00f8f17c 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -674,7 +674,7 @@ imported from the same path. @@ -713,7 +713,7 @@ would provide the exports interface for the instantiation of `module.wasm`. ### JavaScript String Builtins When importing WebAssembly modules, the @@ -755,7 +755,7 @@ or virtualized unless recompiling the module using the direct ### Reserved Wasm Namespaces When importing WebAssembly modules through the ESM Integration, they cannot use diff --git a/doc/api/http.md b/doc/api/http.md index 0b92cd151560f1..cc65635f1043a2 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -1940,7 +1940,7 @@ affects new connections to the server, not any existing connections. ### `server.keepAliveTimeoutBuffer` * Type: {number} Timeout in milliseconds. **Default:** `1000` (1 second). diff --git a/doc/api/inspector.md b/doc/api/inspector.md index b4685a72214895..22cf8d13c831b6 100644 --- a/doc/api/inspector.md +++ b/doc/api/inspector.md @@ -598,7 +598,7 @@ HTTP request has failed to load. > Stability: 1.1 - Active Development diff --git a/doc/api/net.md b/doc/api/net.md index ba49daecf13043..5385856ae8c83b 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -184,7 +184,7 @@ added: v22.13.0 > Stability: 1 - Experimental ```js @@ -206,7 +206,7 @@ blockList.fromJSON(JSON.stringify(data)); > Stability: 1 - Experimental * Returns Blocklist.rules diff --git a/doc/api/process.md b/doc/api/process.md index fb9e9099225244..eb7b9b3265d529 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -4257,7 +4257,7 @@ Thrown: ## `process.threadCpuUsage([previousValue])` * `previousValue` {Object} A previous return value from calling diff --git a/doc/api/tls.md b/doc/api/tls.md index a4368e0a0105d9..3c95d01564bf74 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -2345,7 +2345,7 @@ The server can be tested by connecting to it using the example client from ## `tls.setDefaultCACertificates(certs)` * `certs` {string\[]|ArrayBufferView\[]} An array of CA certificates in PEM format. diff --git a/doc/api/util.md b/doc/api/util.md index f1769973b12e9d..30ef8da1bb07de 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -732,7 +732,7 @@ fs.access('file/that/does/not/exist', (err) => { ## `util.setTraceSigInt(enable)` * `enable` {boolean} diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index 48b91e7672a572..e307bfe9398604 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -1600,7 +1600,7 @@ JavaScript code. * Returns: {Promise} diff --git a/doc/changelogs/CHANGELOG_V22.md b/doc/changelogs/CHANGELOG_V22.md index 2624c69ecccdc3..358b4d9318c9a4 100644 --- a/doc/changelogs/CHANGELOG_V22.md +++ b/doc/changelogs/CHANGELOG_V22.md @@ -9,6 +9,7 @@ +22.19.0
22.18.0
22.17.1
22.17.0
@@ -63,6 +64,160 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + + +## 2025-08-28, Version 22.19.0 'Jod' (LTS), @aduh95 + +### Notable Changes + +* \[[`8e2076a24f`](https://github.com/nodejs/node/commit/8e2076a24f)] - **(SEMVER-MINOR)** **cli**: add NODE\_USE\_SYSTEM\_CA=1 (Joyee Cheung) [#59276](https://github.com/nodejs/node/pull/59276) +* \[[`e592d739c2`](https://github.com/nodejs/node/commit/e592d739c2)] - **(SEMVER-MINOR)** **cli**: support `${pid}` placeholder in --cpu-prof-name (Haram Jeong) [#59072](https://github.com/nodejs/node/pull/59072) +* \[[`cda1dab6e2`](https://github.com/nodejs/node/commit/cda1dab6e2)] - **(SEMVER-MINOR)** **crypto**: add tls.setDefaultCACertificates() (Joyee Cheung) [#58822](https://github.com/nodejs/node/pull/58822) +* \[[`1f184513e9`](https://github.com/nodejs/node/commit/1f184513e9)] - **(SEMVER-MINOR)** **dns**: support max timeout (theanarkh) [#58440](https://github.com/nodejs/node/pull/58440) +* \[[`bace73a173`](https://github.com/nodejs/node/commit/bace73a173)] - **doc**: update the instruction on how to verify releases (Antoine du Hamel) [#59113](https://github.com/nodejs/node/pull/59113) +* \[[`fa9a9e9c69`](https://github.com/nodejs/node/commit/fa9a9e9c69)] - **(SEMVER-MINOR)** **esm**: unflag --experimental-wasm-modules (Guy Bedford) [#57038](https://github.com/nodejs/node/pull/57038) +* \[[`390a9dc20b`](https://github.com/nodejs/node/commit/390a9dc20b)] - **(SEMVER-MINOR)** **http**: add server.keepAliveTimeoutBuffer option (Haram Jeong) [#59243](https://github.com/nodejs/node/pull/59243) +* \[[`c12c5343ad`](https://github.com/nodejs/node/commit/c12c5343ad)] - **lib**: docs deprecate \_http\_\* (Sebastian Beltran) [#59293](https://github.com/nodejs/node/pull/59293) +* \[[`f57ee3d71f`](https://github.com/nodejs/node/commit/f57ee3d71f)] - **(SEMVER-MINOR)** **net**: update net.blocklist to allow file save and file management (alphaleadership) [#58087](https://github.com/nodejs/node/pull/58087) +* \[[`035da74c31`](https://github.com/nodejs/node/commit/035da74c31)] - **(SEMVER-MINOR)** **process**: add threadCpuUsage (Paolo Insogna) [#56467](https://github.com/nodejs/node/pull/56467) +* \[[`8e697d1884`](https://github.com/nodejs/node/commit/8e697d1884)] - **(SEMVER-MINOR)** **zlib**: add dictionary support to zstdCompress and zstdDecompress (lluisemper) [#59240](https://github.com/nodejs/node/pull/59240) + +### Commits + +* \[[`73aa0ae37f`](https://github.com/nodejs/node/commit/73aa0ae37f)] - **assert**: change utils to use index instead of for...of (방진혁) [#59278](https://github.com/nodejs/node/pull/59278) +* \[[`dfe3a11eed`](https://github.com/nodejs/node/commit/dfe3a11eed)] - **benchmark**: remove deprecated \_extend from benchmark (Rafael Gonzaga) [#59228](https://github.com/nodejs/node/pull/59228) +* \[[`9b9d30042a`](https://github.com/nodejs/node/commit/9b9d30042a)] - **benchmark**: add fs warmup to writefile-promises (Bruno Rodrigues) [#59215](https://github.com/nodejs/node/pull/59215) +* \[[`a663f7f954`](https://github.com/nodejs/node/commit/a663f7f954)] - **benchmark**: add calibrate-n script (Rafael Gonzaga) [#59186](https://github.com/nodejs/node/pull/59186) +* \[[`1b9b5bddd6`](https://github.com/nodejs/node/commit/1b9b5bddd6)] - **benchmark**: adjust configuration for string-decoder bench (Rafael Gonzaga) [#59187](https://github.com/nodejs/node/pull/59187) +* \[[`d0ac3319f9`](https://github.com/nodejs/node/commit/d0ac3319f9)] - **benchmark**: add --track to benchmark (Rafael Gonzaga) [#59174](https://github.com/nodejs/node/pull/59174) +* \[[`2044968b86`](https://github.com/nodejs/node/commit/2044968b86)] - **benchmark**: small lint fix on \_cli.js (Rafael Gonzaga) [#59172](https://github.com/nodejs/node/pull/59172) +* \[[`4e519934cb`](https://github.com/nodejs/node/commit/4e519934cb)] - **benchmark**: drop misc/punycode benchmark (Rafael Gonzaga) [#59171](https://github.com/nodejs/node/pull/59171) +* \[[`07e173d969`](https://github.com/nodejs/node/commit/07e173d969)] - **benchmark**: fix sqlite-is-transaction (Rafael Gonzaga) [#59170](https://github.com/nodejs/node/pull/59170) +* \[[`8440b6177f`](https://github.com/nodejs/node/commit/8440b6177f)] - **benchmark**: reduce N for diagnostics\_channel subscribe benchmark (Arthur Angelo) [#59116](https://github.com/nodejs/node/pull/59116) +* \[[`8615ea6db0`](https://github.com/nodejs/node/commit/8615ea6db0)] - **buffer**: cache Environment::GetCurrent to avoid repeated calls (Mert Can Altin) [#59043](https://github.com/nodejs/node/pull/59043) +* \[[`3deb5361d2`](https://github.com/nodejs/node/commit/3deb5361d2)] - **build**: fix node\_use\_sqlite for GN builds (Shelley Vohr) [#59017](https://github.com/nodejs/node/pull/59017) +* \[[`0f0ce63116`](https://github.com/nodejs/node/commit/0f0ce63116)] - **build**: remove suppressions.supp (Rafael Gonzaga) [#59079](https://github.com/nodejs/node/pull/59079) +* \[[`b30a2117dc`](https://github.com/nodejs/node/commit/b30a2117dc)] - **build,deps,tools**: prepare to update to OpenSSL 3.5 (Richard Lau) [#58100](https://github.com/nodejs/node/pull/58100) +* \[[`8e2076a24f`](https://github.com/nodejs/node/commit/8e2076a24f)] - **(SEMVER-MINOR)** **cli**: add NODE\_USE\_SYSTEM\_CA=1 (Joyee Cheung) [#59276](https://github.com/nodejs/node/pull/59276) +* \[[`e592d739c2`](https://github.com/nodejs/node/commit/e592d739c2)] - **(SEMVER-MINOR)** **cli**: support `${pid}` placeholder in --cpu-prof-name (Haram Jeong) [#59072](https://github.com/nodejs/node/pull/59072) +* \[[`b5571047ed`](https://github.com/nodejs/node/commit/b5571047ed)] - **crypto**: prepare webcrypto key import/export for modern algorithms (Filip Skokan) [#59284](https://github.com/nodejs/node/pull/59284) +* \[[`cda1dab6e2`](https://github.com/nodejs/node/commit/cda1dab6e2)] - **(SEMVER-MINOR)** **crypto**: add tls.setDefaultCACertificates() (Joyee Cheung) [#58822](https://github.com/nodejs/node/pull/58822) +* \[[`76dab34fb7`](https://github.com/nodejs/node/commit/76dab34fb7)] - **deps**: support madvise(3C) across ALL illumos revisions (Dan McDonald) [#58237](https://github.com/nodejs/node/pull/58237) +* \[[`19d3ed64b6`](https://github.com/nodejs/node/commit/19d3ed64b6)] - **deps**: update sqlite to 3.50.4 (Node.js GitHub Bot) [#59337](https://github.com/nodejs/node/pull/59337) +* \[[`38bafc59e0`](https://github.com/nodejs/node/commit/38bafc59e0)] - **deps**: V8: backport 493cb53691be (Chengzhong Wu) [#59238](https://github.com/nodejs/node/pull/59238) +* \[[`e8da171cc3`](https://github.com/nodejs/node/commit/e8da171cc3)] - **deps**: update sqlite to 3.50.3 (Node.js GitHub Bot) [#59132](https://github.com/nodejs/node/pull/59132) +* \[[`fd4ba38ab6`](https://github.com/nodejs/node/commit/fd4ba38ab6)] - **deps**: update googletest to 7e17b15 (Node.js GitHub Bot) [#59131](https://github.com/nodejs/node/pull/59131) +* \[[`f71f427b95`](https://github.com/nodejs/node/commit/f71f427b95)] - **deps**: update archs files for openssl-3.0.17 (Node.js GitHub Bot) [#59134](https://github.com/nodejs/node/pull/59134) +* \[[`79c5a8f4d2`](https://github.com/nodejs/node/commit/79c5a8f4d2)] - **deps**: upgrade openssl sources to openssl-3.0.17 (Node.js GitHub Bot) [#59134](https://github.com/nodejs/node/pull/59134) +* \[[`0dcc84cf53`](https://github.com/nodejs/node/commit/0dcc84cf53)] - **deps**: update corepack to 0.34.0 (Node.js GitHub Bot) [#59133](https://github.com/nodejs/node/pull/59133) +* \[[`1f184513e9`](https://github.com/nodejs/node/commit/1f184513e9)] - **(SEMVER-MINOR)** **dns**: support max timeout (theanarkh) [#58440](https://github.com/nodejs/node/pull/58440) +* \[[`f64f5df80e`](https://github.com/nodejs/node/commit/f64f5df80e)] - **doc**: fix `--use-system-ca` history (Joyee Cheung) [#59411](https://github.com/nodejs/node/pull/59411) +* \[[`e22aeaa38f`](https://github.com/nodejs/node/commit/e22aeaa38f)] - **doc**: add missing section for `setReturnArrays` in `sqlite.md` (Edy Silva) [#59074](https://github.com/nodejs/node/pull/59074) +* \[[`e44ef07235`](https://github.com/nodejs/node/commit/e44ef07235)] - **doc**: rename x509.extKeyUsage to x509.keyUsage (Filip Skokan) [#59332](https://github.com/nodejs/node/pull/59332) +* \[[`2c5d0aac5e`](https://github.com/nodejs/node/commit/2c5d0aac5e)] - **doc**: fix Pbkdf2Params hash attribute heading (Filip Skokan) [#59395](https://github.com/nodejs/node/pull/59395) +* \[[`fde94346e5`](https://github.com/nodejs/node/commit/fde94346e5)] - **doc**: fix missing reference links for server.keepAliveTimeoutBuffer (Lee Jiho) [#59356](https://github.com/nodejs/node/pull/59356) +* \[[`9af8bcea58`](https://github.com/nodejs/node/commit/9af8bcea58)] - **doc**: fix grammar in global dispatcher usage (Eng Zer Jun) [#59344](https://github.com/nodejs/node/pull/59344) +* \[[`0edf17198f`](https://github.com/nodejs/node/commit/0edf17198f)] - **doc**: run license-builder (github-actions\[bot]) [#59343](https://github.com/nodejs/node/pull/59343) +* \[[`7f767a2e38`](https://github.com/nodejs/node/commit/7f767a2e38)] - **doc**: correct orthography `eg.` → `e.g.` (Jacob Smith) [#59329](https://github.com/nodejs/node/pull/59329) +* \[[`a46ed50350`](https://github.com/nodejs/node/commit/a46ed50350)] - **doc**: clarify the need of compiler compatible with c++20 (Rafael Gonzaga) [#59297](https://github.com/nodejs/node/pull/59297) +* \[[`212263a305`](https://github.com/nodejs/node/commit/212263a305)] - **doc**: clarify release candidate stability index (Filip Skokan) [#59295](https://github.com/nodejs/node/pull/59295) +* \[[`ce93b8b556`](https://github.com/nodejs/node/commit/ce93b8b556)] - **doc**: add WDYT to glossary (btea) [#59280](https://github.com/nodejs/node/pull/59280) +* \[[`ebaaf2c67f`](https://github.com/nodejs/node/commit/ebaaf2c67f)] - **doc**: add manpage entry for --use-system-ca (Joyee Cheung) [#59273](https://github.com/nodejs/node/pull/59273) +* \[[`43b5a21916`](https://github.com/nodejs/node/commit/43b5a21916)] - **doc**: add path.join and path.normalize clarification (Rafael Gonzaga) [#59262](https://github.com/nodejs/node/pull/59262) +* \[[`409c66d328`](https://github.com/nodejs/node/commit/409c66d328)] - **doc**: fix typo in `test/common/README.md` (Yoo) [#59180](https://github.com/nodejs/node/pull/59180) +* \[[`cbb0a8eb13`](https://github.com/nodejs/node/commit/cbb0a8eb13)] - **doc**: add note on process memoryUsage (fengmk2) [#59026](https://github.com/nodejs/node/pull/59026) +* \[[`9892b15d81`](https://github.com/nodejs/node/commit/9892b15d81)] - **doc**: format safely for `doc-kit` (Aviv Keller) [#59229](https://github.com/nodejs/node/pull/59229) +* \[[`bace73a173`](https://github.com/nodejs/node/commit/bace73a173)] - **doc**: update the instruction on how to verify releases (Antoine du Hamel) [#59113](https://github.com/nodejs/node/pull/59113) +* \[[`b549deac02`](https://github.com/nodejs/node/commit/b549deac02)] - **doc**: copyedit SECURITY.md (Rich Trott) [#59190](https://github.com/nodejs/node/pull/59190) +* \[[`ef1bc3f344`](https://github.com/nodejs/node/commit/ef1bc3f344)] - **doc**: fix broken sentence in `URL.parse` (Superchupu) [#59164](https://github.com/nodejs/node/pull/59164) +* \[[`3c6639e8ec`](https://github.com/nodejs/node/commit/3c6639e8ec)] - **doc**: improve onboarding instructions (Joyee Cheung) [#59159](https://github.com/nodejs/node/pull/59159) +* \[[`6ffaac66bc`](https://github.com/nodejs/node/commit/6ffaac66bc)] - **doc**: add constraints for mem leak to threat model (Rafael Gonzaga) [#58917](https://github.com/nodejs/node/pull/58917) +* \[[`e419d20144`](https://github.com/nodejs/node/commit/e419d20144)] - **doc**: add Aditi-1400 to collaborators (Aditi Singh) [#59157](https://github.com/nodejs/node/pull/59157) +* \[[`ba380f7bf3`](https://github.com/nodejs/node/commit/ba380f7bf3)] - **doc**: avoid suggesting testing fast api with intense loop (Chengzhong Wu) [#59111](https://github.com/nodejs/node/pull/59111) +* \[[`fa1a532f2b`](https://github.com/nodejs/node/commit/fa1a532f2b)] - **doc**: fix typo in writing-test.md (SeokHun) [#59123](https://github.com/nodejs/node/pull/59123) +* \[[`0b93ca3d19`](https://github.com/nodejs/node/commit/0b93ca3d19)] - **doc**: add RafaelGSS as steward July 25 (Rafael Gonzaga) [#59078](https://github.com/nodejs/node/pull/59078) +* \[[`7d747aeac8`](https://github.com/nodejs/node/commit/7d747aeac8)] - **doc**: clarify ERR\_FS\_FILE\_TOO\_LARGE to reflect fs.readFile() I/O limit (Haram Jeong) [#59050](https://github.com/nodejs/node/pull/59050) +* \[[`0b5613f9fe`](https://github.com/nodejs/node/commit/0b5613f9fe)] - **doc**: run license-builder (github-actions\[bot]) [#59056](https://github.com/nodejs/node/pull/59056) +* \[[`1b6b5e72d3`](https://github.com/nodejs/node/commit/1b6b5e72d3)] - **doc**: fix typed list formatting (Aviv Keller) [#59019](https://github.com/nodejs/node/pull/59019) +* \[[`756c7dd639`](https://github.com/nodejs/node/commit/756c7dd639)] - **doc**: refine `util.parseArgs` `default` definition (Slayer95) [#58958](https://github.com/nodejs/node/pull/58958) +* \[[`0b840523a2`](https://github.com/nodejs/node/commit/0b840523a2)] - **doc**: remove unused import in `zlib.md` (coderaiser) [#59041](https://github.com/nodejs/node/pull/59041) +* \[[`3e9ed4b080`](https://github.com/nodejs/node/commit/3e9ed4b080)] - **doc**: add stability index to the `--watch-kill-signal` flag (Dario Piotrowicz) [#58997](https://github.com/nodejs/node/pull/58997) +* \[[`cb08a5d43f`](https://github.com/nodejs/node/commit/cb08a5d43f)] - **doc**: add missing `` blocks (Antoine du Hamel) [#58995](https://github.com/nodejs/node/pull/58995) +* \[[`4a42360fe5`](https://github.com/nodejs/node/commit/4a42360fe5)] - **doc**: add scroll margin to links (Roman Reiss) [#58982](https://github.com/nodejs/node/pull/58982) +* \[[`9d073f32da`](https://github.com/nodejs/node/commit/9d073f32da)] - **doc**: add sponsorship link to RafaelGSS (Rafael Gonzaga) [#58983](https://github.com/nodejs/node/pull/58983) +* \[[`3cc11fc9ac`](https://github.com/nodejs/node/commit/3cc11fc9ac)] - **domain**: remove deprecated API call (Alex Yang) [#59339](https://github.com/nodejs/node/pull/59339) +* \[[`fa9a9e9c69`](https://github.com/nodejs/node/commit/fa9a9e9c69)] - **(SEMVER-MINOR)** **esm**: unflag --experimental-wasm-modules (Guy Bedford) [#57038](https://github.com/nodejs/node/pull/57038) +* \[[`177ed3b3dd`](https://github.com/nodejs/node/commit/177ed3b3dd)] - **esm**: js-string Wasm builtins in ESM Integration (Guy Bedford) [#59020](https://github.com/nodejs/node/pull/59020) +* \[[`4619fe0e04`](https://github.com/nodejs/node/commit/4619fe0e04)] - **fs**: fix glob TypeError on restricted dirs (Sylphy-0xd3ac) [#58674](https://github.com/nodejs/node/pull/58674) +* \[[`ad2089e32d`](https://github.com/nodejs/node/commit/ad2089e32d)] - **fs**: correct error message when FileHandle is transferred (Alex Yang) [#59156](https://github.com/nodejs/node/pull/59156) +* \[[`390a9dc20b`](https://github.com/nodejs/node/commit/390a9dc20b)] - **(SEMVER-MINOR)** **http**: add server.keepAliveTimeoutBuffer option (Haram Jeong) [#59243](https://github.com/nodejs/node/pull/59243) +* \[[`659002359d`](https://github.com/nodejs/node/commit/659002359d)] - **http2**: set Http2Stream#sentHeaders for raw headers (Darshan Sen) [#59244](https://github.com/nodejs/node/pull/59244) +* \[[`d02831ef73`](https://github.com/nodejs/node/commit/d02831ef73)] - **inspector**: initial support for Network.loadNetworkResource (Shima Ryuhei) [#58077](https://github.com/nodejs/node/pull/58077) +* \[[`264a838779`](https://github.com/nodejs/node/commit/264a838779)] - **lib**: add trace-sigint APIs (theanarkh) [#59040](https://github.com/nodejs/node/pull/59040) +* \[[`d22d2fa6d4`](https://github.com/nodejs/node/commit/d22d2fa6d4)] - **lib**: optimize writable stream buffer clearing (Yoo) [#59406](https://github.com/nodejs/node/pull/59406) +* \[[`a5e9759409`](https://github.com/nodejs/node/commit/a5e9759409)] - **lib**: do not modify prototype deprecated asyncResource (RafaelGSS) [#59195](https://github.com/nodejs/node/pull/59195) +* \[[`9254257fc0`](https://github.com/nodejs/node/commit/9254257fc0)] - **lib**: restructure assert to become a class (Miguel Marcondes Filho) [#58253](https://github.com/nodejs/node/pull/58253) +* \[[`946eab8d77`](https://github.com/nodejs/node/commit/946eab8d77)] - **lib**: handle superscript variants on windows device (Rafael Gonzaga) [#59261](https://github.com/nodejs/node/pull/59261) +* \[[`cd857a97b5`](https://github.com/nodejs/node/commit/cd857a97b5)] - **lib**: use validateString (hotpineapple) [#59296](https://github.com/nodejs/node/pull/59296) +* \[[`c12c5343ad`](https://github.com/nodejs/node/commit/c12c5343ad)] - **lib**: docs deprecate \_http\_\* (Sebastian Beltran) [#59293](https://github.com/nodejs/node/pull/59293) +* \[[`a28e5f0938`](https://github.com/nodejs/node/commit/a28e5f0938)] - **lib**: add type names in source mapped stack traces (Chengzhong Wu) [#58976](https://github.com/nodejs/node/pull/58976) +* \[[`6aec5aee7c`](https://github.com/nodejs/node/commit/6aec5aee7c)] - **lib**: prefer AsyncIteratorPrototype primordial (René) [#59097](https://github.com/nodejs/node/pull/59097) +* \[[`e704349858`](https://github.com/nodejs/node/commit/e704349858)] - **lib**: fix incorrect `ArrayBufferPrototypeGetDetached` primordial type (Dario Piotrowicz) [#58978](https://github.com/nodejs/node/pull/58978) +* \[[`2fc25fd400`](https://github.com/nodejs/node/commit/2fc25fd400)] - **lib**: flag to conditionally modify proto on deprecate (Rafael Gonzaga) [#58928](https://github.com/nodejs/node/pull/58928) +* \[[`446ee98e00`](https://github.com/nodejs/node/commit/446ee98e00)] - **meta**: clarify pr objection process further (James M Snell) [#59096](https://github.com/nodejs/node/pull/59096) +* \[[`46c339e4f3`](https://github.com/nodejs/node/commit/46c339e4f3)] - **meta**: add mailmap entry for aditi-1400 (Aditi) [#59316](https://github.com/nodejs/node/pull/59316) +* \[[`70a586261f`](https://github.com/nodejs/node/commit/70a586261f)] - **meta**: add tsc and build team as codeowners building.md (Rafael Gonzaga) [#59298](https://github.com/nodejs/node/pull/59298) +* \[[`e666e06781`](https://github.com/nodejs/node/commit/e666e06781)] - **meta**: add nodejs/path to path files (Rafael Gonzaga) [#59289](https://github.com/nodejs/node/pull/59289) +* \[[`251b65dd6c`](https://github.com/nodejs/node/commit/251b65dd6c)] - **meta**: move one or more collaborators to emeritus (Node.js GitHub Bot) [#59140](https://github.com/nodejs/node/pull/59140) +* \[[`c8a7964da8`](https://github.com/nodejs/node/commit/c8a7964da8)] - **meta**: add marco-ippolito to security release stewards (Marco Ippolito) [#58944](https://github.com/nodejs/node/pull/58944) +* \[[`0eec5cc492`](https://github.com/nodejs/node/commit/0eec5cc492)] - **module**: fix conditions override in synchronous resolve hooks (Joyee Cheung) [#59011](https://github.com/nodejs/node/pull/59011) +* \[[`4acf7cd6d3`](https://github.com/nodejs/node/commit/4acf7cd6d3)] - **module**: throw error when re-runing errored module jobs (Joyee Cheung) [#58957](https://github.com/nodejs/node/pull/58957) +* \[[`f57ee3d71f`](https://github.com/nodejs/node/commit/f57ee3d71f)] - **(SEMVER-MINOR)** **net**: update net.blocklist to allow file save and file management (alphaleadership) [#58087](https://github.com/nodejs/node/pull/58087) +* \[[`4aefcfc318`](https://github.com/nodejs/node/commit/4aefcfc318)] - **node-api**: reword "implementation in an alternative VM" as implementable (Chengzhong Wu) [#59036](https://github.com/nodejs/node/pull/59036) +* \[[`ff6be2ed5d`](https://github.com/nodejs/node/commit/ff6be2ed5d)] - **node-api,doc**: update links to ecma262 with section names (Chengzhong Wu) [#59087](https://github.com/nodejs/node/pull/59087) +* \[[`8d60602677`](https://github.com/nodejs/node/commit/8d60602677)] - **perf\_hooks**: do not expose SafeMap via Histogram wrapper (René) [#59094](https://github.com/nodejs/node/pull/59094) +* \[[`035da74c31`](https://github.com/nodejs/node/commit/035da74c31)] - **(SEMVER-MINOR)** **process**: add threadCpuUsage (Paolo Insogna) [#56467](https://github.com/nodejs/node/pull/56467) +* \[[`74e1aa4d06`](https://github.com/nodejs/node/commit/74e1aa4d06)] - **process**: make execve's args argument optional (Allon Murienik) [#58412](https://github.com/nodejs/node/pull/58412) +* \[[`3366e60bd9`](https://github.com/nodejs/node/commit/3366e60bd9)] - **src**: use simdjson to parse SEA configuration (Joyee Cheung) [#59323](https://github.com/nodejs/node/pull/59323) +* \[[`63cc06977a`](https://github.com/nodejs/node/commit/63cc06977a)] - **src**: mark realm leaf classes final (Anna Henningsen) [#59355](https://github.com/nodejs/node/pull/59355) +* \[[`133d410cd9`](https://github.com/nodejs/node/commit/133d410cd9)] - **src**: use C++20 `contains()` method (iknoom) [#59304](https://github.com/nodejs/node/pull/59304) +* \[[`57fe96fe49`](https://github.com/nodejs/node/commit/57fe96fe49)] - **src**: added CHECK\_NOT\_NULL check for multiple eq\_wrap\_async (F3lixTheCat) [#59267](https://github.com/nodejs/node/pull/59267) +* \[[`a8f381a6c5`](https://github.com/nodejs/node/commit/a8f381a6c5)] - **src**: add nullptr checks in `StreamPipe::New` (Burkov Egor) [#57613](https://github.com/nodejs/node/pull/57613) +* \[[`0769e5a0dc`](https://github.com/nodejs/node/commit/0769e5a0dc)] - **src**: call unmask after install signal handler (theanarkh) [#59059](https://github.com/nodejs/node/pull/59059) +* \[[`1e7639e9e1`](https://github.com/nodejs/node/commit/1e7639e9e1)] - **src**: use `FastStringKey` for `TrackV8FastApiCall` (Anna Henningsen) [#59148](https://github.com/nodejs/node/pull/59148) +* \[[`9075a1a4bf`](https://github.com/nodejs/node/commit/9075a1a4bf)] - **src**: use C++20 `consteval` for `FastStringKey` (Anna Henningsen) [#59148](https://github.com/nodejs/node/pull/59148) +* \[[`5a0fd5689b`](https://github.com/nodejs/node/commit/5a0fd5689b)] - **src**: remove declarations of removed BaseObject static fns (Anna Henningsen) [#59093](https://github.com/nodejs/node/pull/59093) +* \[[`c637a2c41d`](https://github.com/nodejs/node/commit/c637a2c41d)] - **src**: add cache to nearest parent package json (Ilyas Shabi) [#59086](https://github.com/nodejs/node/pull/59086) +* \[[`3375a6cfee`](https://github.com/nodejs/node/commit/3375a6cfee)] - **test**: deflake sequential/test-tls-session-timeout (Joyee Cheung) [#59423](https://github.com/nodejs/node/pull/59423) +* \[[`438cb11a15`](https://github.com/nodejs/node/commit/438cb11a15)] - **test**: update WPT resources,WebCryptoAPI,webstorage (Filip Skokan) [#59311](https://github.com/nodejs/node/pull/59311) +* \[[`68bec19f76`](https://github.com/nodejs/node/commit/68bec19f76)] - **test**: add known issue test for fs.cpSync dereference bug (James M Snell) [#58941](https://github.com/nodejs/node/pull/58941) +* \[[`a100cce379`](https://github.com/nodejs/node/commit/a100cce379)] - **test**: deflake stream-readable-to-web test (Ethan Arrowood) [#58948](https://github.com/nodejs/node/pull/58948) +* \[[`b7577d853b`](https://github.com/nodejs/node/commit/b7577d853b)] - **test**: make test-inspector-network-resource sequential (Shima Ryuhei) [#59104](https://github.com/nodejs/node/pull/59104) +* \[[`667ee82443`](https://github.com/nodejs/node/commit/667ee82443)] - **test**: don't use expose internals in test-http-outgoing-buffer.js (Meghan Denny) [#59219](https://github.com/nodejs/node/pull/59219) +* \[[`feec26d3bb`](https://github.com/nodejs/node/commit/feec26d3bb)] - **test**: use mustSucceed in test-fs-read (Sungwon) [#59204](https://github.com/nodejs/node/pull/59204) +* \[[`d7e23769ab`](https://github.com/nodejs/node/commit/d7e23769ab)] - **test**: prepare test-crypto-rsa-dsa for newer OpenSSL (Richard Lau) [#58100](https://github.com/nodejs/node/pull/58100) +* \[[`3a9aca91c6`](https://github.com/nodejs/node/commit/3a9aca91c6)] - **test**: fix flaky test-worker-message-port-transfer-filehandle test (Alex Yang) [#59158](https://github.com/nodejs/node/pull/59158) +* \[[`3aee7625b9`](https://github.com/nodejs/node/commit/3aee7625b9)] - **test**: expand linting rules around `assert` w literal messages (Anna Henningsen) [#59147](https://github.com/nodejs/node/pull/59147) +* \[[`667c2ced38`](https://github.com/nodejs/node/commit/667c2ced38)] - **test**: update WPT for WebCryptoAPI to ab08796857 (Node.js GitHub Bot) [#59129](https://github.com/nodejs/node/pull/59129) +* \[[`89ac344393`](https://github.com/nodejs/node/commit/89ac344393)] - **test**: update WPT for WebCryptoAPI to 19d82c57ab (Node.js GitHub Bot) [#59129](https://github.com/nodejs/node/pull/59129) +* \[[`d332957ac6`](https://github.com/nodejs/node/commit/d332957ac6)] - **test**: skip tests that cause timeouts on IBM i (Abdirahim Musse) [#59014](https://github.com/nodejs/node/pull/59014) +* \[[`a23562ff72`](https://github.com/nodejs/node/commit/a23562ff72)] - **test**: update `startCLI` to set `--port=0` by default (Dario Piotrowicz) [#59042](https://github.com/nodejs/node/pull/59042) +* \[[`4a12f5d83b`](https://github.com/nodejs/node/commit/4a12f5d83b)] - **test**: mark test-inspector-network-fetch as flaky on Windows (Joyee Cheung) [#59091](https://github.com/nodejs/node/pull/59091) +* \[[`ac4f7aa69c`](https://github.com/nodejs/node/commit/ac4f7aa69c)] - **test**: add missing port=0 arg in test-debugger-extract-function-name (Dario Piotrowicz) [#58977](https://github.com/nodejs/node/pull/58977) +* \[[`8dd09267e3`](https://github.com/nodejs/node/commit/8dd09267e3)] - **test,crypto**: skip unsupported ciphers (Shelley Vohr) [#59388](https://github.com/nodejs/node/pull/59388) +* \[[`45200b43ea`](https://github.com/nodejs/node/commit/45200b43ea)] - **tools**: update coverage GitHub Actions to fixed version (Rich Trott) [#59512](https://github.com/nodejs/node/pull/59512) +* \[[`8f2b8b3dc4`](https://github.com/nodejs/node/commit/8f2b8b3dc4)] - **tools**: allow selecting test subsystems with numbers in their names (Darshan Sen) [#59242](https://github.com/nodejs/node/pull/59242) +* \[[`f9bc2573dd`](https://github.com/nodejs/node/commit/f9bc2573dd)] - **tools**: clarify README linter error message (Joyee Cheung) [#59160](https://github.com/nodejs/node/pull/59160) +* \[[`cba0de128d`](https://github.com/nodejs/node/commit/cba0de128d)] - **tools**: add support for URLs to PR commits in `merge.sh` (Antoine du Hamel) [#59162](https://github.com/nodejs/node/pull/59162) +* \[[`039949ef5b`](https://github.com/nodejs/node/commit/039949ef5b)] - **tools**: bump @eslint/plugin-kit from 0.3.1 to 0.3.3 in /tools/eslint (dependabot\[bot]) [#59119](https://github.com/nodejs/node/pull/59119) +* \[[`6a8a73aa35`](https://github.com/nodejs/node/commit/6a8a73aa35)] - **tools**: ignore CVE mention when linting release proposals (Antoine du Hamel) [#59037](https://github.com/nodejs/node/pull/59037) +* \[[`d0f40f3a3a`](https://github.com/nodejs/node/commit/d0f40f3a3a)] - **tools,test**: enforce best practices to detect never settling promises (Antoine du Hamel) [#58992](https://github.com/nodejs/node/pull/58992) +* \[[`9d801a3f00`](https://github.com/nodejs/node/commit/9d801a3f00)] - **typings**: improve internal binding types (Nam Yooseong) [#59351](https://github.com/nodejs/node/pull/59351) +* \[[`6dbda6cb25`](https://github.com/nodejs/node/commit/6dbda6cb25)] - **typings**: improve internal binding types (Michaël Zasso) [#59176](https://github.com/nodejs/node/pull/59176) +* \[[`e22dddf859`](https://github.com/nodejs/node/commit/e22dddf859)] - **util**: respect nested formats in styleText (Alex Yang) [#59098](https://github.com/nodejs/node/pull/59098) +* \[[`491f390515`](https://github.com/nodejs/node/commit/491f390515)] - **worker**: add cpuUsage for worker (theanarkh) [#59177](https://github.com/nodejs/node/pull/59177) +* \[[`8e697d1884`](https://github.com/nodejs/node/commit/8e697d1884)] - **(SEMVER-MINOR)** **zlib**: add dictionary support to zstdCompress and zstdDecompress (lluisemper) [#59240](https://github.com/nodejs/node/pull/59240) + ## 2025-07-31, Version 22.18.0 'Jod' (LTS), @aduh95 diff --git a/src/node_version.h b/src/node_version.h index f721c0071607d0..e0b2f884c576dd 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -23,13 +23,13 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 22 -#define NODE_MINOR_VERSION 18 -#define NODE_PATCH_VERSION 1 +#define NODE_MINOR_VERSION 19 +#define NODE_PATCH_VERSION 0 #define NODE_VERSION_IS_LTS 1 #define NODE_VERSION_LTS_CODENAME "Jod" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)