mirror of https://github.com/nodejs/node.git
inspector: convert event params to protocol without json
Event params object can be converted to inspector protocol directly. This also enables binary data, like `Network.dataReceived`, to be sent in the inspector protocol from JavaScript since JSON representation does not support plain binary data. PR-URL: https://github.com/nodejs/node/pull/57027 Reviewed-By: Kohei Ueno <kohei.ueno119@gmail.com>
This commit is contained in:
parent
044d69a0af
commit
b7beb3334e
|
@ -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 = {
|
||||
|
|
|
@ -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<Network::Request> createRequest(
|
||||
const String& url,
|
||||
const String& method,
|
||||
std::unique_ptr<Network::Headers> 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<protocol::String> ObjectGetProtocolString(v8::Local<v8::Context> context,
|
||||
Local<Object> object,
|
||||
Local<v8::String> property) {
|
||||
HandleScope handle_scope(context->GetIsolate());
|
||||
Local<Value> value;
|
||||
if (!object->Get(context, property).ToLocal(&value) || !value->IsString()) {
|
||||
return Nothing<protocol::String>();
|
||||
}
|
||||
Local<v8::String> str = value.As<v8::String>();
|
||||
return Just(ToProtocolString(context->GetIsolate(), str));
|
||||
}
|
||||
|
||||
// Get a protocol string property from the object.
|
||||
Maybe<protocol::String> ObjectGetProtocolString(v8::Local<v8::Context> context,
|
||||
Local<Object> 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<double> ObjectGetDouble(v8::Local<v8::Context> context,
|
||||
Local<Object> object,
|
||||
const char* property) {
|
||||
HandleScope handle_scope(context->GetIsolate());
|
||||
Local<Value> value;
|
||||
if (!object->Get(context, OneByteString(context->GetIsolate(), property))
|
||||
.ToLocal(&value) ||
|
||||
!value->IsNumber()) {
|
||||
return Nothing<double>();
|
||||
}
|
||||
return Just(value.As<v8::Number>()->Value());
|
||||
}
|
||||
|
||||
// Get a protocol int property from the object.
|
||||
Maybe<int> ObjectGetInt(v8::Local<v8::Context> context,
|
||||
Local<Object> object,
|
||||
const char* property) {
|
||||
HandleScope handle_scope(context->GetIsolate());
|
||||
Local<Value> value;
|
||||
if (!object->Get(context, OneByteString(context->GetIsolate(), property))
|
||||
.ToLocal(&value) ||
|
||||
!value->IsInt32()) {
|
||||
return Nothing<int>();
|
||||
}
|
||||
return Just(value.As<v8::Int32>()->Value());
|
||||
}
|
||||
|
||||
// Get an object property from the object.
|
||||
MaybeLocal<v8::Object> ObjectGetObject(v8::Local<v8::Context> context,
|
||||
Local<Object> object,
|
||||
const char* property) {
|
||||
EscapableHandleScope handle_scope(context->GetIsolate());
|
||||
Local<Value> value;
|
||||
if (!object->Get(context, OneByteString(context->GetIsolate(), property))
|
||||
.ToLocal(&value) ||
|
||||
!value->IsObject()) {
|
||||
return {};
|
||||
}
|
||||
return handle_scope.Escape(value.As<v8::Object>());
|
||||
}
|
||||
|
||||
// Create a protocol::Network::Headers from the v8 object.
|
||||
std::unique_ptr<protocol::Network::Headers> createHeadersFromObject(
|
||||
v8::Local<v8::Context> context, Local<Object> headers_obj) {
|
||||
HandleScope handle_scope(context->GetIsolate());
|
||||
|
||||
std::unique_ptr<protocol::DictionaryValue> dict =
|
||||
protocol::DictionaryValue::create();
|
||||
Local<v8::Array> property_names;
|
||||
if (!headers_obj->GetOwnPropertyNames(context).ToLocal(&property_names)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < property_names->Length(); idx++) {
|
||||
Local<v8::Value> property_name_val;
|
||||
if (!property_names->Get(context, idx).ToLocal(&property_name_val) ||
|
||||
!property_name_val->IsString()) {
|
||||
return {};
|
||||
}
|
||||
Local<v8::String> property_name = property_name_val.As<v8::String>();
|
||||
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<protocol::Network::Headers>(std::move(dict));
|
||||
}
|
||||
|
||||
// Create a protocol::Network::Request from the v8 object.
|
||||
std::unique_ptr<protocol::Network::Request> createRequestFromObject(
|
||||
v8::Local<v8::Context> context, Local<Object> 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<Object> headers_obj;
|
||||
if (!ObjectGetObject(context, request, "headers").ToLocal(&headers_obj)) {
|
||||
return {};
|
||||
}
|
||||
std::unique_ptr<protocol::Network::Headers> 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<Network::Response> createResponse(
|
||||
const String& url,
|
||||
int status,
|
||||
const String& statusText,
|
||||
std::unique_ptr<Network::Headers> headers) {
|
||||
return Network::Response::create()
|
||||
// Create a protocol::Network::Response from the v8 object.
|
||||
std::unique_ptr<protocol::Network::Response> createResponseFromObject(
|
||||
v8::Local<v8::Context> context, Local<Object> 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<Object> headers_obj;
|
||||
if (!ObjectGetObject(context, response, "headers").ToLocal(&headers_obj)) {
|
||||
return {};
|
||||
}
|
||||
std::unique_ptr<protocol::Network::Headers> 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<protocol::DictionaryValue> params) {
|
||||
void NetworkAgent::emitNotification(v8::Local<v8::Context> context,
|
||||
const protocol::String& event,
|
||||
v8::Local<v8::Object> 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<Network::Frontend>(dispatcher->channel());
|
||||
Network::Dispatcher::wire(dispatcher, this);
|
||||
void NetworkAgent::Wire(protocol::UberDispatcher* dispatcher) {
|
||||
frontend_ =
|
||||
std::make_unique<protocol::Network::Frontend>(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<protocol::DictionaryValue> params) {
|
||||
String request_id;
|
||||
params->getString("requestId", &request_id);
|
||||
void NetworkAgent::requestWillBeSent(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> 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);
|
||||
if (!ObjectGetDouble(context, params, "wallTime").To(&wall_time)) {
|
||||
return;
|
||||
}
|
||||
Local<v8::Object> request_obj;
|
||||
if (!ObjectGetObject(context, params, "request").ToLocal(&request_obj)) {
|
||||
return;
|
||||
}
|
||||
std::unique_ptr<protocol::Network::Request> request =
|
||||
createRequestFromObject(context, request_obj);
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<Network::Initiator> initiator =
|
||||
Network::Initiator::create()
|
||||
.setType(Network::Initiator::TypeEnum::Script)
|
||||
std::unique_ptr<protocol::Network::Initiator> 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<Network::Headers>(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<protocol::DictionaryValue> params) {
|
||||
String request_id;
|
||||
params->getString("requestId", &request_id);
|
||||
void NetworkAgent::responseReceived(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> 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<Network::Headers>(DictionaryValue::create());
|
||||
if (!ObjectGetDouble(context, params, "timestamp").To(×tamp)) {
|
||||
return;
|
||||
}
|
||||
protocol::String type;
|
||||
if (!ObjectGetProtocolString(context, params, "type").To(&type)) {
|
||||
return;
|
||||
}
|
||||
Local<Object> 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,
|
||||
createResponse(url, status, statusText, std::move(headers)));
|
||||
frontend_->responseReceived(request_id, timestamp, type, std::move(response));
|
||||
}
|
||||
|
||||
void NetworkAgent::loadingFailed(
|
||||
std::unique_ptr<protocol::DictionaryValue> params) {
|
||||
String request_id;
|
||||
params->getString("requestId", &request_id);
|
||||
void NetworkAgent::loadingFailed(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> 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<protocol::DictionaryValue> params) {
|
||||
String request_id;
|
||||
params->getString("requestId", &request_id);
|
||||
void NetworkAgent::loadingFinished(v8::Local<v8::Context> context,
|
||||
Local<v8::Object> 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
|
||||
|
|
|
@ -6,44 +6,46 @@
|
|||
#include <unordered_map>
|
||||
|
||||
namespace node {
|
||||
|
||||
namespace inspector {
|
||||
|
||||
class NetworkInspector;
|
||||
|
||||
namespace protocol {
|
||||
|
||||
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<protocol::DictionaryValue> params);
|
||||
void emitNotification(v8::Local<v8::Context> context,
|
||||
const protocol::String& event,
|
||||
v8::Local<v8::Object> params);
|
||||
|
||||
void requestWillBeSent(std::unique_ptr<protocol::DictionaryValue> params);
|
||||
void requestWillBeSent(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> params);
|
||||
|
||||
void responseReceived(std::unique_ptr<protocol::DictionaryValue> params);
|
||||
void responseReceived(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> params);
|
||||
|
||||
void loadingFailed(std::unique_ptr<protocol::DictionaryValue> params);
|
||||
void loadingFailed(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> params);
|
||||
|
||||
void loadingFinished(std::unique_ptr<protocol::DictionaryValue> params);
|
||||
void loadingFinished(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> params);
|
||||
|
||||
private:
|
||||
NetworkInspector* inspector_;
|
||||
v8_inspector::V8Inspector* v8_inspector_;
|
||||
std::shared_ptr<Network::Frontend> frontend_;
|
||||
using EventNotifier =
|
||||
void (NetworkAgent::*)(std::unique_ptr<protocol::DictionaryValue>);
|
||||
std::unordered_map<String, EventNotifier> event_notifier_map_;
|
||||
std::shared_ptr<protocol::Network::Frontend> frontend_;
|
||||
using EventNotifier = void (NetworkAgent::*)(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object>);
|
||||
std::unordered_map<protocol::String, EventNotifier> event_notifier_map_;
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace inspector
|
||||
} // namespace node
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace inspector {
|
|||
NetworkInspector::NetworkInspector(Environment* env,
|
||||
v8_inspector::V8Inspector* v8_inspector)
|
||||
: enabled_(false), env_(env) {
|
||||
network_agent_ = std::make_unique<protocol::NetworkAgent>(this, v8_inspector);
|
||||
network_agent_ = std::make_unique<NetworkAgent>(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<protocol::DictionaryValue> params) {
|
||||
void NetworkInspector::emitNotification(v8::Local<v8::Context> context,
|
||||
const std::string& domain,
|
||||
const std::string& method,
|
||||
v8::Local<v8::Object> params) {
|
||||
if (domain == "Network") {
|
||||
network_agent_->emitNotification(method, std::move(params));
|
||||
network_agent_->emitNotification(context, method, params);
|
||||
} else {
|
||||
UNREACHABLE("Unknown domain");
|
||||
}
|
||||
|
|
|
@ -19,9 +19,10 @@ class NetworkInspector {
|
|||
|
||||
bool canEmit(const std::string& domain);
|
||||
|
||||
void emitNotification(const std::string& domain,
|
||||
void emitNotification(v8::Local<v8::Context> context,
|
||||
const std::string& domain,
|
||||
const std::string& method,
|
||||
std::unique_ptr<protocol::DictionaryValue> params);
|
||||
v8::Local<v8::Object> params);
|
||||
|
||||
void Enable();
|
||||
void Disable();
|
||||
|
@ -30,7 +31,7 @@ class NetworkInspector {
|
|||
private:
|
||||
bool enabled_;
|
||||
Environment* env_;
|
||||
std::unique_ptr<protocol::NetworkAgent> network_agent_;
|
||||
std::unique_ptr<NetworkAgent> network_agent_;
|
||||
};
|
||||
|
||||
} // namespace inspector
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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<v8_inspector::StringBuffer> ToInspectorString(
|
||||
v8::Isolate* isolate, v8::Local<v8::Value> 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<v8::Value> value) {
|
||||
Utf8Value buffer(isolate, value);
|
||||
return *buffer;
|
||||
}
|
||||
|
||||
} // namespace node::inspector
|
||||
|
||||
#endif // SRC_INSPECTOR_PROTOCOL_HELPER_H_
|
|
@ -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<StringBuffer> ToProtocolString(Isolate* isolate,
|
||||
Local<Value> 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<Agent*>(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<protocol::DictionaryValue> value =
|
||||
protocol::DictionaryValue::cast(JsonUtil::parseJSON(params));
|
||||
void emitNotificationFromBackend(v8::Local<v8::Context> context,
|
||||
const StringView& event,
|
||||
Local<Object> 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<v8::Context> context,
|
||||
const StringView& event,
|
||||
Local<Object> 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<InspectorSession> Agent::ConnectToMainThread(
|
|||
prevent_shutdown);
|
||||
}
|
||||
|
||||
void Agent::EmitProtocolEvent(const StringView& event,
|
||||
const StringView& params) {
|
||||
void Agent::EmitProtocolEvent(v8::Local<v8::Context> context,
|
||||
const StringView& event,
|
||||
Local<Object> params) {
|
||||
if (!env()->options()->experimental_network_inspection) return;
|
||||
client_->emitNotification(event, params);
|
||||
client_->emitNotification(context, event, params);
|
||||
}
|
||||
|
||||
void Agent::SetupNetworkTracking(Local<Function> enable_function,
|
||||
|
|
|
@ -69,8 +69,9 @@ class Agent {
|
|||
void ReportUncaughtException(v8::Local<v8::Value> error,
|
||||
v8::Local<v8::Message> message);
|
||||
|
||||
void EmitProtocolEvent(const v8_inspector::StringView& event,
|
||||
const v8_inspector::StringView& params);
|
||||
void EmitProtocolEvent(v8::Local<v8::Context> context,
|
||||
const v8_inspector::StringView& event,
|
||||
v8::Local<v8::Object> params);
|
||||
|
||||
void SetupNetworkTracking(v8::Local<v8::Function> enable_function,
|
||||
v8::Local<v8::Function> disable_function);
|
||||
|
|
|
@ -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<StringBuffer> ToProtocolString(Isolate* isolate,
|
||||
Local<Value> value) {
|
||||
TwoByteValue buffer(isolate, value);
|
||||
return StringBuffer::create(StringView(*buffer, buffer.length()));
|
||||
}
|
||||
|
||||
struct LocalConnection {
|
||||
static std::unique_ptr<InspectorSession> Connect(
|
||||
Agent* inspector, std::unique_ptr<InspectorSessionDelegate> 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<Value>& args) {
|
|||
Environment* env = Environment::GetCurrent(args);
|
||||
CHECK(args[0]->IsString());
|
||||
Local<String> eventName = args[0].As<String>();
|
||||
CHECK(args[1]->IsString());
|
||||
Local<String> params = args[1].As<String>();
|
||||
CHECK(args[1]->IsObject());
|
||||
Local<Object> params = args[1].As<Object>();
|
||||
|
||||
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<Value>& args) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue