diff --git a/lib/inspector.js b/lib/inspector.js index b623d96b68c3f7..599a99db33855b 100644 --- a/lib/inspector.js +++ b/lib/inspector.js @@ -24,6 +24,7 @@ if (!hasInspector) const EventEmitter = require('events'); const { queueMicrotask } = require('internal/process/task_queues'); +const { kEmptyObject } = require('internal/util'); const { isUint32, validateFunction, @@ -189,12 +190,10 @@ function inspectorWaitForDebugger() { throw new ERR_INSPECTOR_NOT_ACTIVE(); } -function broadcastToFrontend(eventName, params) { +function broadcastToFrontend(eventName, params = kEmptyObject) { validateString(eventName, 'eventName'); - if (params) { - validateObject(params, 'params'); - } - emitProtocolEvent(eventName, JSONStringify(params ?? {})); + validateObject(params, 'params'); + emitProtocolEvent(eventName, params); } const Network = { diff --git a/src/inspector/network_agent.cc b/src/inspector/network_agent.cc index 157d0c52cf98e2..497260ecc93c5f 100644 --- a/src/inspector/network_agent.cc +++ b/src/inspector/network_agent.cc @@ -1,27 +1,174 @@ #include "network_agent.h" +#include "inspector/protocol_helper.h" #include "network_inspector.h" +#include "util-inl.h" +#include "v8.h" namespace node { namespace inspector { -namespace protocol { -std::unique_ptr createRequest( - const String& url, - const String& method, - std::unique_ptr headers) { - return Network::Request::create() +using v8::EscapableHandleScope; +using v8::HandleScope; +using v8::Just; +using v8::Local; +using v8::Maybe; +using v8::MaybeLocal; +using v8::Nothing; +using v8::Object; +using v8::Value; + +// Get a protocol string property from the object. +Maybe ObjectGetProtocolString(v8::Local context, + Local object, + Local property) { + HandleScope handle_scope(context->GetIsolate()); + Local value; + if (!object->Get(context, property).ToLocal(&value) || !value->IsString()) { + return Nothing(); + } + Local str = value.As(); + return Just(ToProtocolString(context->GetIsolate(), str)); +} + +// Get a protocol string property from the object. +Maybe ObjectGetProtocolString(v8::Local context, + Local object, + const char* property) { + HandleScope handle_scope(context->GetIsolate()); + return ObjectGetProtocolString( + context, object, OneByteString(context->GetIsolate(), property)); +} + +// Get a protocol double property from the object. +Maybe ObjectGetDouble(v8::Local context, + Local object, + const char* property) { + HandleScope handle_scope(context->GetIsolate()); + Local value; + if (!object->Get(context, OneByteString(context->GetIsolate(), property)) + .ToLocal(&value) || + !value->IsNumber()) { + return Nothing(); + } + return Just(value.As()->Value()); +} + +// Get a protocol int property from the object. +Maybe ObjectGetInt(v8::Local context, + Local object, + const char* property) { + HandleScope handle_scope(context->GetIsolate()); + Local value; + if (!object->Get(context, OneByteString(context->GetIsolate(), property)) + .ToLocal(&value) || + !value->IsInt32()) { + return Nothing(); + } + return Just(value.As()->Value()); +} + +// Get an object property from the object. +MaybeLocal ObjectGetObject(v8::Local context, + Local object, + const char* property) { + EscapableHandleScope handle_scope(context->GetIsolate()); + Local value; + if (!object->Get(context, OneByteString(context->GetIsolate(), property)) + .ToLocal(&value) || + !value->IsObject()) { + return {}; + } + return handle_scope.Escape(value.As()); +} + +// Create a protocol::Network::Headers from the v8 object. +std::unique_ptr createHeadersFromObject( + v8::Local context, Local headers_obj) { + HandleScope handle_scope(context->GetIsolate()); + + std::unique_ptr dict = + protocol::DictionaryValue::create(); + Local property_names; + if (!headers_obj->GetOwnPropertyNames(context).ToLocal(&property_names)) { + return {}; + } + + for (size_t idx = 0; idx < property_names->Length(); idx++) { + Local property_name_val; + if (!property_names->Get(context, idx).ToLocal(&property_name_val) || + !property_name_val->IsString()) { + return {}; + } + Local property_name = property_name_val.As(); + protocol::String property_value; + if (!ObjectGetProtocolString(context, headers_obj, property_name) + .To(&property_value)) { + return {}; + } + dict->setString(ToProtocolString(context->GetIsolate(), property_name), + property_value); + } + + return std::make_unique(std::move(dict)); +} + +// Create a protocol::Network::Request from the v8 object. +std::unique_ptr createRequestFromObject( + v8::Local context, Local request) { + HandleScope handle_scope(context->GetIsolate()); + protocol::String url; + if (!ObjectGetProtocolString(context, request, "url").To(&url)) { + return {}; + } + protocol::String method; + if (!ObjectGetProtocolString(context, request, "method").To(&method)) { + return {}; + } + Local headers_obj; + if (!ObjectGetObject(context, request, "headers").ToLocal(&headers_obj)) { + return {}; + } + std::unique_ptr headers = + createHeadersFromObject(context, headers_obj); + if (!headers) { + return {}; + } + + return protocol::Network::Request::create() .setUrl(url) .setMethod(method) .setHeaders(std::move(headers)) .build(); } -std::unique_ptr createResponse( - const String& url, - int status, - const String& statusText, - std::unique_ptr headers) { - return Network::Response::create() +// Create a protocol::Network::Response from the v8 object. +std::unique_ptr createResponseFromObject( + v8::Local context, Local response) { + HandleScope handle_scope(context->GetIsolate()); + protocol::String url; + if (!ObjectGetProtocolString(context, response, "url").To(&url)) { + return {}; + } + int status; + if (!ObjectGetInt(context, response, "status").To(&status)) { + return {}; + } + protocol::String statusText; + if (!ObjectGetProtocolString(context, response, "statusText") + .To(&statusText)) { + return {}; + } + Local headers_obj; + if (!ObjectGetObject(context, response, "headers").ToLocal(&headers_obj)) { + return {}; + } + std::unique_ptr headers = + createHeadersFromObject(context, headers_obj); + if (!headers) { + return {}; + } + + return protocol::Network::Response::create() .setUrl(url) .setStatus(status) .setStatusText(statusText) @@ -38,123 +185,131 @@ NetworkAgent::NetworkAgent(NetworkInspector* inspector, event_notifier_map_["loadingFinished"] = &NetworkAgent::loadingFinished; } -void NetworkAgent::emitNotification( - const String& event, std::unique_ptr params) { +void NetworkAgent::emitNotification(v8::Local context, + const protocol::String& event, + v8::Local params) { if (!inspector_->IsEnabled()) return; auto it = event_notifier_map_.find(event); if (it != event_notifier_map_.end()) { - (this->*(it->second))(std::move(params)); + (this->*(it->second))(context, params); } } -void NetworkAgent::Wire(UberDispatcher* dispatcher) { - frontend_ = std::make_unique(dispatcher->channel()); - Network::Dispatcher::wire(dispatcher, this); +void NetworkAgent::Wire(protocol::UberDispatcher* dispatcher) { + frontend_ = + std::make_unique(dispatcher->channel()); + protocol::Network::Dispatcher::wire(dispatcher, this); } -DispatchResponse NetworkAgent::enable() { +protocol::DispatchResponse NetworkAgent::enable() { inspector_->Enable(); - return DispatchResponse::Success(); + return protocol::DispatchResponse::Success(); } -DispatchResponse NetworkAgent::disable() { +protocol::DispatchResponse NetworkAgent::disable() { inspector_->Disable(); - return DispatchResponse::Success(); + return protocol::DispatchResponse::Success(); } -void NetworkAgent::requestWillBeSent( - std::unique_ptr params) { - String request_id; - params->getString("requestId", &request_id); +void NetworkAgent::requestWillBeSent(v8::Local context, + v8::Local params) { + protocol::String request_id; + if (!ObjectGetProtocolString(context, params, "requestId").To(&request_id)) { + return; + } double timestamp; - params->getDouble("timestamp", ×tamp); + if (!ObjectGetDouble(context, params, "timestamp").To(×tamp)) { + return; + } double wall_time; - params->getDouble("wallTime", &wall_time); - auto request = params->getObject("request"); - String url; - request->getString("url", &url); - String method; - request->getString("method", &method); - - std::unique_ptr initiator = - Network::Initiator::create() - .setType(Network::Initiator::TypeEnum::Script) + if (!ObjectGetDouble(context, params, "wallTime").To(&wall_time)) { + return; + } + Local request_obj; + if (!ObjectGetObject(context, params, "request").ToLocal(&request_obj)) { + return; + } + std::unique_ptr request = + createRequestFromObject(context, request_obj); + if (!request) { + return; + } + + std::unique_ptr initiator = + protocol::Network::Initiator::create() + .setType(protocol::Network::Initiator::TypeEnum::Script) .setStack( v8_inspector_->captureStackTrace(true)->buildInspectorObject(0)) .build(); - ErrorSupport errors; - errors.Push(); - errors.SetName("headers"); - auto headers = - Network::Headers::fromValue(request->getObject("headers"), &errors); - if (!errors.Errors().empty()) { - headers = std::make_unique(DictionaryValue::create()); - } - frontend_->requestWillBeSent(request_id, - createRequest(url, method, std::move(headers)), + std::move(request), std::move(initiator), timestamp, wall_time); } -void NetworkAgent::responseReceived( - std::unique_ptr params) { - String request_id; - params->getString("requestId", &request_id); +void NetworkAgent::responseReceived(v8::Local context, + v8::Local params) { + protocol::String request_id; + if (!ObjectGetProtocolString(context, params, "requestId").To(&request_id)) { + return; + } double timestamp; - params->getDouble("timestamp", ×tamp); - String type; - params->getString("type", &type); - auto response = params->getObject("response"); - String url; - response->getString("url", &url); - int status; - response->getInteger("status", &status); - String statusText; - response->getString("statusText", &statusText); - - ErrorSupport errors; - errors.Push(); - errors.SetName("headers"); - auto headers = - Network::Headers::fromValue(response->getObject("headers"), &errors); - if (!errors.Errors().empty()) { - headers = std::make_unique(DictionaryValue::create()); - } - - frontend_->responseReceived( - request_id, - timestamp, - type, - createResponse(url, status, statusText, std::move(headers))); -} - -void NetworkAgent::loadingFailed( - std::unique_ptr params) { - String request_id; - params->getString("requestId", &request_id); + if (!ObjectGetDouble(context, params, "timestamp").To(×tamp)) { + return; + } + protocol::String type; + if (!ObjectGetProtocolString(context, params, "type").To(&type)) { + return; + } + Local response_obj; + if (!ObjectGetObject(context, params, "response").ToLocal(&response_obj)) { + return; + } + auto response = createResponseFromObject(context, response_obj); + if (!response) { + return; + } + + frontend_->responseReceived(request_id, timestamp, type, std::move(response)); +} + +void NetworkAgent::loadingFailed(v8::Local context, + v8::Local params) { + protocol::String request_id; + if (!ObjectGetProtocolString(context, params, "requestId").To(&request_id)) { + return; + } double timestamp; - params->getDouble("timestamp", ×tamp); - String type; - params->getString("type", &type); - String error_text; - params->getString("errorText", &error_text); + if (!ObjectGetDouble(context, params, "timestamp").To(×tamp)) { + return; + } + protocol::String type; + if (!ObjectGetProtocolString(context, params, "type").To(&type)) { + return; + } + protocol::String error_text; + if (!ObjectGetProtocolString(context, params, "errorText").To(&error_text)) { + return; + } frontend_->loadingFailed(request_id, timestamp, type, error_text); } -void NetworkAgent::loadingFinished( - std::unique_ptr params) { - String request_id; - params->getString("requestId", &request_id); +void NetworkAgent::loadingFinished(v8::Local context, + Local params) { + protocol::String request_id; + if (!ObjectGetProtocolString(context, params, "requestId").To(&request_id)) { + return; + } double timestamp; - params->getDouble("timestamp", ×tamp); + if (!ObjectGetDouble(context, params, "timestamp").To(×tamp)) { + return; + } frontend_->loadingFinished(request_id, timestamp); } -} // namespace protocol } // namespace inspector } // namespace node diff --git a/src/inspector/network_agent.h b/src/inspector/network_agent.h index 67994e19475d65..459195ad6d31c2 100644 --- a/src/inspector/network_agent.h +++ b/src/inspector/network_agent.h @@ -6,44 +6,46 @@ #include namespace node { - namespace inspector { -class NetworkInspector; -namespace protocol { +class NetworkInspector; -class NetworkAgent : public Network::Backend { +class NetworkAgent : public protocol::Network::Backend { public: explicit NetworkAgent(NetworkInspector* inspector, v8_inspector::V8Inspector* v8_inspector); - void Wire(UberDispatcher* dispatcher); + void Wire(protocol::UberDispatcher* dispatcher); - DispatchResponse enable() override; + protocol::DispatchResponse enable() override; - DispatchResponse disable() override; + protocol::DispatchResponse disable() override; - void emitNotification(const String& event, - std::unique_ptr params); + void emitNotification(v8::Local context, + const protocol::String& event, + v8::Local params); - void requestWillBeSent(std::unique_ptr params); + void requestWillBeSent(v8::Local context, + v8::Local params); - void responseReceived(std::unique_ptr params); + void responseReceived(v8::Local context, + v8::Local params); - void loadingFailed(std::unique_ptr params); + void loadingFailed(v8::Local context, + v8::Local params); - void loadingFinished(std::unique_ptr params); + void loadingFinished(v8::Local context, + v8::Local params); private: NetworkInspector* inspector_; v8_inspector::V8Inspector* v8_inspector_; - std::shared_ptr frontend_; - using EventNotifier = - void (NetworkAgent::*)(std::unique_ptr); - std::unordered_map event_notifier_map_; + std::shared_ptr frontend_; + using EventNotifier = void (NetworkAgent::*)(v8::Local context, + v8::Local); + std::unordered_map event_notifier_map_; }; -} // namespace protocol } // namespace inspector } // namespace node diff --git a/src/inspector/network_inspector.cc b/src/inspector/network_inspector.cc index 2a3488b8ffd854..e93db7bbe922f6 100644 --- a/src/inspector/network_inspector.cc +++ b/src/inspector/network_inspector.cc @@ -6,7 +6,7 @@ namespace inspector { NetworkInspector::NetworkInspector(Environment* env, v8_inspector::V8Inspector* v8_inspector) : enabled_(false), env_(env) { - network_agent_ = std::make_unique(this, v8_inspector); + network_agent_ = std::make_unique(this, v8_inspector); } NetworkInspector::~NetworkInspector() { network_agent_.reset(); @@ -20,12 +20,12 @@ bool NetworkInspector::canEmit(const std::string& domain) { return domain == "Network"; } -void NetworkInspector::emitNotification( - const std::string& domain, - const std::string& method, - std::unique_ptr params) { +void NetworkInspector::emitNotification(v8::Local context, + const std::string& domain, + const std::string& method, + v8::Local params) { if (domain == "Network") { - network_agent_->emitNotification(method, std::move(params)); + network_agent_->emitNotification(context, method, params); } else { UNREACHABLE("Unknown domain"); } diff --git a/src/inspector/network_inspector.h b/src/inspector/network_inspector.h index a77260e3815a5c..4095a05394cd8a 100644 --- a/src/inspector/network_inspector.h +++ b/src/inspector/network_inspector.h @@ -19,9 +19,10 @@ class NetworkInspector { bool canEmit(const std::string& domain); - void emitNotification(const std::string& domain, + void emitNotification(v8::Local context, + const std::string& domain, const std::string& method, - std::unique_ptr params); + v8::Local params); void Enable(); void Disable(); @@ -30,7 +31,7 @@ class NetworkInspector { private: bool enabled_; Environment* env_; - std::unique_ptr network_agent_; + std::unique_ptr network_agent_; }; } // namespace inspector diff --git a/src/inspector/node_inspector.gypi b/src/inspector/node_inspector.gypi index db0709dfcf17ed..b789018e24f545 100644 --- a/src/inspector/node_inspector.gypi +++ b/src/inspector/node_inspector.gypi @@ -21,6 +21,7 @@ 'src/inspector/node_json.h', 'src/inspector/node_string.cc', 'src/inspector/node_string.h', + 'src/inspector/protocol_helper.h', 'src/inspector/runtime_agent.cc', 'src/inspector/runtime_agent.h', 'src/inspector/tracing_agent.cc', diff --git a/src/inspector/protocol_helper.h b/src/inspector/protocol_helper.h new file mode 100644 index 00000000000000..a0f88aa93532a4 --- /dev/null +++ b/src/inspector/protocol_helper.h @@ -0,0 +1,27 @@ +#ifndef SRC_INSPECTOR_PROTOCOL_HELPER_H_ +#define SRC_INSPECTOR_PROTOCOL_HELPER_H_ + +#include "node/inspector/protocol/Protocol.h" +#include "util.h" +#include "v8-inspector.h" + +namespace node::inspector { + +// Convert a V8 string to v8_inspector StringBuffer, encoded in UTF16. +inline std::unique_ptr ToInspectorString( + v8::Isolate* isolate, v8::Local value) { + TwoByteValue buffer(isolate, value); + return v8_inspector::StringBuffer::create( + v8_inspector::StringView(*buffer, buffer.length())); +} + +// Convert a V8 string to node::inspector::protocol::String, encoded in UTF8. +inline protocol::String ToProtocolString(v8::Isolate* isolate, + v8::Local value) { + Utf8Value buffer(isolate, value); + return *buffer; +} + +} // namespace node::inspector + +#endif // SRC_INSPECTOR_PROTOCOL_HELPER_H_ diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index f730ca2028316c..a68b19fd8a3930 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -6,6 +6,7 @@ #include "inspector/network_inspector.h" #include "inspector/node_json.h" #include "inspector/node_string.h" +#include "inspector/protocol_helper.h" #include "inspector/runtime_agent.h" #include "inspector/tracing_agent.h" #include "inspector/worker_agent.h" @@ -69,12 +70,6 @@ static std::atomic_bool start_io_thread_async_initialized { false }; // Protects the Agent* stored in start_io_thread_async.data. static Mutex start_io_thread_async_mutex; -std::unique_ptr ToProtocolString(Isolate* isolate, - Local value) { - TwoByteValue buffer(isolate, value); - return StringBuffer::create(StringView(*buffer, buffer.length())); -} - // Called on the main thread. void StartIoThreadAsyncCallback(uv_async_t* handle) { static_cast(handle->data)->StartIoThread(); @@ -259,16 +254,15 @@ class ChannelImpl final : public v8_inspector::V8Inspector::Channel, network_inspector_.reset(); // Dispose before the dispatchers } - void emitNotificationFromBackend(const StringView& event, - const StringView& params) { - std::unique_ptr value = - protocol::DictionaryValue::cast(JsonUtil::parseJSON(params)); + void emitNotificationFromBackend(v8::Local context, + const StringView& event, + Local params) { std::string raw_event = protocol::StringUtil::StringViewToUtf8(event); std::string domain_name = raw_event.substr(0, raw_event.find('.')); std::string event_name = raw_event.substr(raw_event.find('.') + 1); if (network_inspector_->canEmit(domain_name)) { network_inspector_->emitNotification( - domain_name, event_name, std::move(value)); + context, domain_name, event_name, params); } else { UNREACHABLE("Unknown domain for emitNotificationFromBackend"); } @@ -619,8 +613,8 @@ class NodeInspectorClient : public V8InspectorClient { context, StringView(DETAILS, sizeof(DETAILS) - 1), error, - ToProtocolString(isolate, message->Get())->string(), - ToProtocolString(isolate, message->GetScriptResourceName())->string(), + ToInspectorString(isolate, message->Get())->string(), + ToInspectorString(isolate, message->GetScriptResourceName())->string(), message->GetLineNumber(context).FromMaybe(0), message->GetStartColumn(context).FromMaybe(0), client_->createStackTrace(stack_trace), @@ -688,9 +682,11 @@ class NodeInspectorClient : public V8InspectorClient { return retaining_context; } - void emitNotification(const StringView& event, const StringView& params) { + void emitNotification(v8::Local context, + const StringView& event, + Local params) { for (const auto& id_channel : channels_) { - id_channel.second->emitNotificationFromBackend(event, params); + id_channel.second->emitNotificationFromBackend(context, event, params); } } @@ -907,10 +903,11 @@ std::unique_ptr Agent::ConnectToMainThread( prevent_shutdown); } -void Agent::EmitProtocolEvent(const StringView& event, - const StringView& params) { +void Agent::EmitProtocolEvent(v8::Local context, + const StringView& event, + Local params) { if (!env()->options()->experimental_network_inspection) return; - client_->emitNotification(event, params); + client_->emitNotification(context, event, params); } void Agent::SetupNetworkTracking(Local enable_function, diff --git a/src/inspector_agent.h b/src/inspector_agent.h index 2ddffdb63ffee3..ad7a8e6c069968 100644 --- a/src/inspector_agent.h +++ b/src/inspector_agent.h @@ -69,8 +69,9 @@ class Agent { void ReportUncaughtException(v8::Local error, v8::Local message); - void EmitProtocolEvent(const v8_inspector::StringView& event, - const v8_inspector::StringView& params); + void EmitProtocolEvent(v8::Local context, + const v8_inspector::StringView& event, + v8::Local params); void SetupNetworkTracking(v8::Local enable_function, v8::Local disable_function); diff --git a/src/inspector_js_api.cc b/src/inspector_js_api.cc index 8f8a72b05ab3b9..94dcb194914e11 100644 --- a/src/inspector_js_api.cc +++ b/src/inspector_js_api.cc @@ -1,4 +1,5 @@ #include "base_object-inl.h" +#include "inspector/protocol_helper.h" #include "inspector_agent.h" #include "inspector_io.h" #include "memory_tracker-inl.h" @@ -27,16 +28,8 @@ using v8::Object; using v8::String; using v8::Uint32; using v8::Value; - -using v8_inspector::StringBuffer; using v8_inspector::StringView; -std::unique_ptr ToProtocolString(Isolate* isolate, - Local value) { - TwoByteValue buffer(isolate, value); - return StringBuffer::create(StringView(*buffer, buffer.length())); -} - struct LocalConnection { static std::unique_ptr Connect( Agent* inspector, std::unique_ptr delegate) { @@ -143,7 +136,7 @@ class JSBindingsConnection : public BaseObject { if (session->session_) { session->session_->Dispatch( - ToProtocolString(env->isolate(), info[0])->string()); + ToInspectorString(env->isolate(), info[0])->string()); } } @@ -275,12 +268,13 @@ void EmitProtocolEvent(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); CHECK(args[0]->IsString()); Local eventName = args[0].As(); - CHECK(args[1]->IsString()); - Local params = args[1].As(); + CHECK(args[1]->IsObject()); + Local params = args[1].As(); env->inspector_agent()->EmitProtocolEvent( - ToProtocolString(env->isolate(), eventName)->string(), - ToProtocolString(env->isolate(), params)->string()); + args.GetIsolate()->GetCurrentContext(), + ToInspectorString(env->isolate(), eventName)->string(), + params); } void SetupNetworkTracking(const FunctionCallbackInfo& args) { diff --git a/test/parallel/test-inspector-emit-protocol-event.js b/test/parallel/test-inspector-emit-protocol-event.js index eda95d34e57620..e17e994ee520a3 100644 --- a/test/parallel/test-inspector-emit-protocol-event.js +++ b/test/parallel/test-inspector-emit-protocol-event.js @@ -16,6 +16,7 @@ const EXPECTED_EVENTS = { request: { url: 'https://nodejs.org/en', method: 'GET', + headers: {}, }, timestamp: 1000, wallTime: 1000, @@ -25,7 +26,7 @@ const EXPECTED_EVENTS = { request: { url: 'https://nodejs.org/en', method: 'GET', - headers: {} // Headers should be an empty object if not provided. + headers: {}, }, timestamp: 1000, wallTime: 1000, @@ -40,6 +41,7 @@ const EXPECTED_EVENTS = { response: { url: 'https://nodejs.org/en', status: 200, + statusText: '', headers: { host: 'nodejs.org' } } }, @@ -50,7 +52,7 @@ const EXPECTED_EVENTS = { response: { url: 'https://nodejs.org/en', status: 200, - statusText: '', // Status text should be an empty string if not provided. + statusText: '', headers: { host: 'nodejs.org' } } } @@ -104,6 +106,11 @@ const runAsyncTest = async () => { for (const [domain, events] of Object.entries(EXPECTED_EVENTS)) { for (const event of events) { session.on(`${domain}.${event.name}`, common.mustCall(({ params }) => { + if (event.name === 'requestWillBeSent') { + // Initiator is automatically captured and contains caller info. + // No need to validate it. + delete params.initiator; + } assert.deepStrictEqual(params, event.expected ?? event.params); })); inspector[domain][event.name](event.params);