| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1031,6 +1031,17 @@ passing a second `parentURL` argument for contextual resolution. | |||
| 1031 | 1031 | ||
| 1032 | 1032 | Previously gated the entire `import.meta.resolve` feature. | |
| 1033 | 1033 | ||
| 1034 | + ### `--experimental-inspector-network-resource` | ||
| 1035 | + | ||
| 1036 | + <!-- YAML | ||
| 1037 | + added: | ||
| 1038 | + - REPLACEME | ||
| 1039 | + --> | ||
| 1040 | + | ||
| 1041 | + > Stability: 1.1 - Active Development | ||
| 1042 | + | ||
| 1043 | + Enable experimental support for inspector network resources. | ||
| 1044 | + | ||
| 1034 | 1045 | ### `--experimental-loader=module` | |
| 1035 | 1046 | ||
| 1036 | 1047 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -598,6 +598,43 @@ This feature is only available with the `--experimental-network-inspection` flag | |||
| 598 | 598 | Broadcasts the `Network.loadingFailed` event to connected frontends. This event indicates that | |
| 599 | 599 | HTTP request has failed to load. | |
| 600 | 600 | ||
| 601 | + ### `inspector.NetworkResources.put` | ||
| 602 | + | ||
| 603 | + <!-- YAML | ||
| 604 | + added: | ||
| 605 | + - REPLACEME | ||
| 606 | + --> | ||
| 607 | + | ||
| 608 | + > Stability: 1.1 - Active Development | ||
| 609 | + | ||
| 610 | + This feature is only available with the `--experimental-inspector-network-resource` flag enabled. | ||
| 611 | + | ||
| 612 | + The inspector.NetworkResources.put method is used to provide a response for a loadNetworkResource | ||
| 613 | + request issued via the Chrome DevTools Protocol (CDP). | ||
| 614 | + This is typically triggered when a source map is specified by URL, and a DevTools frontend—such as | ||
| 615 | + Chrome—requests the resource to retrieve the source map. | ||
| 616 | + | ||
| 617 | + This method allows developers to predefine the resource content to be served in response to such CDP requests. | ||
| 618 | + | ||
| 619 | + ```js | ||
| 620 | + const inspector = require('node:inspector'); | ||
| 621 | + // By preemptively calling put to register the resource, a source map can be resolved when | ||
| 622 | + // a loadNetworkResource request is made from the frontend. | ||
| 623 | + async function setNetworkResources() { | ||
| 624 | + const mapUrl = 'http://localhost:3000/dist/app.js.map'; | ||
| 625 | + const tsUrl = 'http://localhost:3000/src/app.ts'; | ||
| 626 | + const distAppJsMap = await fetch(mapUrl).then((res) => res.text()); | ||
| 627 | + const srcAppTs = await fetch(tsUrl).then((res) => res.text()); | ||
| 628 | + inspector.NetworkResources.put(mapUrl, distAppJsMap); | ||
| 629 | + inspector.NetworkResources.put(tsUrl, srcAppTs); | ||
| 630 | + }; | ||
| 631 | + setNetworkResources().then(() => { | ||
| 632 | + require('./dist/app'); | ||
| 633 | + }); | ||
| 634 | + ``` | ||
| 635 | + | ||
| 636 | + For more details, see the official CDP documentation: [Network.loadNetworkResource](https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-loadNetworkResource) | ||
| 637 | + | ||
| 601 | 638 | ## Support of breakpoints | |
| 602 | 639 | ||
| 603 | 640 | The Chrome DevTools Protocol [`Debugger` domain][] allows an | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -226,6 +226,9 @@ Enable experimental WebAssembly module support. | |||
| 226 | 226 | .It Fl -experimental-quic | |
| 227 | 227 | Enable the experimental QUIC support. | |
| 228 | 228 | . | |
| 229 | + .It Fl -experimental-inspector-network-resource | ||
| 230 | + Enable experimental support for inspector network resources. | ||
| 231 | + . | ||
| 229 | 232 | .It Fl -force-context-aware | |
| 230 | 233 | Disable loading native addons that are not context-aware. | |
| 231 | 234 | . | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,6 +36,9 @@ const { | |||
| 36 | 36 | } = require('internal/validators'); | |
| 37 | 37 | const { isMainThread } = require('worker_threads'); | |
| 38 | 38 | const { _debugEnd } = internalBinding('process_methods'); | |
| 39 | + const { | ||
| 40 | + put, | ||
| 41 | + } = require('internal/inspector/network_resources'); | ||
| 39 | 42 | ||
| 40 | 43 | const { | |
| 41 | 44 | Connection, | |
@@ -218,6 +221,10 @@ const Network = { | |||
| 218 | 221 | dataReceived: (params) => broadcastToFrontend('Network.dataReceived', params), | |
| 219 | 222 | }; | |
| 220 | 223 | ||
| 224 | + const NetworkResources = { | ||
| 225 | + put, | ||
| 226 | + }; | ||
| 227 | + | ||
| 221 | 228 | module.exports = { | |
| 222 | 229 | open: inspectorOpen, | |
| 223 | 230 | close: _debugEnd, | |
@@ -226,4 +233,5 @@ module.exports = { | |||
| 226 | 233 | console, | |
| 227 | 234 | Session, | |
| 228 | 235 | Network, | |
| 236 | + NetworkResources, | ||
| 229 | 237 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,27 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const { getOptionValue } = require('internal/options'); | ||
| 4 | + const { validateString } = require('internal/validators'); | ||
| 5 | + const { putNetworkResource } = internalBinding('inspector'); | ||
| 6 | + | ||
| 7 | + /** | ||
| 8 | + * Registers a resource for the inspector using the internal 'putNetworkResource' binding. | ||
| 9 | + * @param {string} url - The URL of the resource. | ||
| 10 | + * @param {string} data - The content of the resource to provide. | ||
| 11 | + */ | ||
| 12 | + function put(url, data) { | ||
| 13 | + if (!getOptionValue('--experimental-inspector-network-resource')) { | ||
| 14 | + process.emitWarning( | ||
| 15 | + 'The --experimental-inspector-network-resource option is not enabled. ' + | ||
| 16 | + 'Please enable it to use the putNetworkResource function'); | ||
| 17 | + return; | ||
| 18 | + } | ||
| 19 | + validateString(url, 'url'); | ||
| 20 | + validateString(data, 'data'); | ||
| 21 | + | ||
| 22 | + putNetworkResource(url, data); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + module.exports = { | ||
| 26 | + put, | ||
| 27 | + }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,57 @@ | |||
| 1 | + #include "io_agent.h" | ||
| 2 | + #include <algorithm> | ||
| 3 | + #include <iostream> | ||
| 4 | + #include <string> | ||
| 5 | + #include <string_view> | ||
| 6 | + #include "crdtp/dispatch.h" | ||
| 7 | + #include "inspector/network_resource_manager.h" | ||
| 8 | + | ||
| 9 | + namespace node::inspector::protocol { | ||
| 10 | + | ||
| 11 | + void IoAgent::Wire(UberDispatcher* dispatcher) { | ||
| 12 | + frontend_ = std::make_shared<IO::Frontend>(dispatcher->channel()); | ||
| 13 | + IO::Dispatcher::wire(dispatcher, this); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + DispatchResponse IoAgent::read(const String& in_handle, | ||
| 17 | + std::optional<int> in_offset, | ||
| 18 | + std::optional<int> in_size, | ||
| 19 | + String* out_data, | ||
| 20 | + bool* out_eof) { | ||
| 21 | + std::string url = in_handle; | ||
| 22 | + std::string txt = network_resource_manager_->Get(url); | ||
| 23 | + std::string_view txt_view(txt); | ||
| 24 | + | ||
| 25 | + int offset = 0; | ||
| 26 | + bool offset_was_specified = false; | ||
| 27 | + if (in_offset.has_value()) { | ||
| 28 | + offset = *in_offset; | ||
| 29 | + offset_was_specified = true; | ||
| 30 | + } else if (offset_map_.find(url) != offset_map_.end()) { | ||
| 31 | + offset = offset_map_[url]; | ||
| 32 | + } | ||
| 33 | + int size = 1 << 20; | ||
| 34 | + if (in_size.has_value()) { | ||
| 35 | + size = *in_size; | ||
| 36 | + } | ||
| 37 | + if (static_cast<std::size_t>(offset) < txt_view.length()) { | ||
| 38 | + std::string_view out_view = txt_view.substr(offset, size); | ||
| 39 | + out_data->assign(out_view.data(), out_view.size()); | ||
| 40 | + *out_eof = false; | ||
| 41 | + if (!offset_was_specified) { | ||
| 42 | + offset_map_[url] = offset + size; | ||
| 43 | + } | ||
| 44 | + } else { | ||
| 45 | + *out_data = ""; | ||
| 46 | + *out_eof = true; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + return DispatchResponse::Success(); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + DispatchResponse IoAgent::close(const String& in_handle) { | ||
| 53 | + std::string url = in_handle; | ||
| 54 | + network_resource_manager_->Erase(url); | ||
| 55 | + return DispatchResponse::Success(); | ||
| 56 | + } | ||
| 57 | + } // namespace node::inspector::protocol | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,30 @@ | |||
| 1 | + #ifndef SRC_INSPECTOR_IO_AGENT_H_ | ||
| 2 | + #define SRC_INSPECTOR_IO_AGENT_H_ | ||
| 3 | + | ||
| 4 | + #include <memory> | ||
| 5 | + #include "inspector/network_resource_manager.h" | ||
| 6 | + #include "node/inspector/protocol/IO.h" | ||
| 7 | + | ||
| 8 | + namespace node::inspector::protocol { | ||
| 9 | + | ||
| 10 | + class IoAgent : public IO::Backend { | ||
| 11 | + public: | ||
| 12 | + explicit IoAgent( | ||
| 13 | + std::shared_ptr<NetworkResourceManager> network_resource_manager) | ||
| 14 | + : network_resource_manager_(std::move(network_resource_manager)) {} | ||
| 15 | + void Wire(UberDispatcher* dispatcher); | ||
| 16 | + DispatchResponse read(const String& in_handle, | ||
| 17 | + std::optional<int> in_offset, | ||
| 18 | + std::optional<int> in_size, | ||
| 19 | + String* out_data, | ||
| 20 | + bool* out_eof) override; | ||
| 21 | + DispatchResponse close(const String& in_handle) override; | ||
| 22 | + | ||
| 23 | + private: | ||
| 24 | + std::shared_ptr<IO::Frontend> frontend_; | ||
| 25 | + std::unordered_map<std::string, int> offset_map_ = | ||
| 26 | + {}; // Maps stream_id to offset | ||
| 27 | + std::shared_ptr<NetworkResourceManager> network_resource_manager_; | ||
| 28 | + }; | ||
| 29 | + } // namespace node::inspector::protocol | ||
| 30 | + #endif // SRC_INSPECTOR_IO_AGENT_H_ | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,8 +1,14 @@ | |||
| 1 | 1 | #include "network_agent.h" | |
| 2 | + #include <string> | ||
| 2 | 3 | #include "debug_utils-inl.h" | |
| 4 | + #include "env-inl.h" | ||
| 5 | + #include "inspector/network_resource_manager.h" | ||
| 3 | 6 | #include "inspector/protocol_helper.h" | |
| 4 | 7 | #include "network_inspector.h" | |
| 8 | + #include "node_metadata.h" | ||
| 5 | 9 | #include "util-inl.h" | |
| 10 | + #include "uv.h" | ||
| 11 | + #include "v8-context.h" | ||
| 6 | 12 | #include "v8.h" | |
| 7 | 13 | ||
| 8 | 14 | namespace node { | |
@@ -202,9 +208,15 @@ std::unique_ptr<protocol::Network::Response> createResponseFromObject( | |||
| 202 | 208 | .build(); | |
| 203 | 209 | } | |
| 204 | 210 | ||
| 205 | - NetworkAgent::NetworkAgent(NetworkInspector* inspector, | ||
| 206 | - v8_inspector::V8Inspector* v8_inspector) | ||
| 207 | - : inspector_(inspector), v8_inspector_(v8_inspector) { | ||
| 211 | + NetworkAgent::NetworkAgent( | ||
| 212 | + NetworkInspector* inspector, | ||
| 213 | + v8_inspector::V8Inspector* v8_inspector, | ||
| 214 | + Environment* env, | ||
| 215 | + std::shared_ptr<NetworkResourceManager> network_resource_manager) | ||
| 216 | + : inspector_(inspector), | ||
| 217 | + v8_inspector_(v8_inspector), | ||
| 218 | + env_(env), | ||
| 219 | + network_resource_manager_(std::move(network_resource_manager)) { | ||
| 208 | 220 | event_notifier_map_["requestWillBeSent"] = &NetworkAgent::requestWillBeSent; | |
| 209 | 221 | event_notifier_map_["responseReceived"] = &NetworkAgent::responseReceived; | |
| 210 | 222 | event_notifier_map_["loadingFailed"] = &NetworkAgent::loadingFailed; | |
@@ -329,10 +341,38 @@ protocol::DispatchResponse NetworkAgent::streamResourceContent( | |||
| 329 | 341 | // If the request is finished, remove the entry. | |
| 330 | 342 | requests_.erase(in_requestId); | |
| 331 | 343 | } | |
| 332 | - | ||
| 333 | 344 | return protocol::DispatchResponse::Success(); | |
| 334 | 345 | } | |
| 335 | 346 | ||
| 347 | + protocol::DispatchResponse NetworkAgent::loadNetworkResource( | ||
| 348 | + const protocol::String& in_url, | ||
| 349 | + std::unique_ptr<protocol::Network::LoadNetworkResourcePageResult>* | ||
| 350 | + out_resource) { | ||
| 351 | + if (!env_->options()->experimental_inspector_network_resource) { | ||
| 352 | + return protocol::DispatchResponse::ServerError( | ||
| 353 | + "Network resource loading is not enabled. This feature is " | ||
| 354 | + "experimental and requires --experimental-inspector-network-resource " | ||
| 355 | + "flag to be set."); | ||
| 356 | + } | ||
| 357 | + CHECK_NOT_NULL(network_resource_manager_); | ||
| 358 | + std::string data = network_resource_manager_->Get(in_url); | ||
| 359 | + bool found = !data.empty(); | ||
| 360 | + if (found) { | ||
| 361 | + auto result = protocol::Network::LoadNetworkResourcePageResult::create() | ||
| 362 | + .setSuccess(true) | ||
| 363 | + .setStream(in_url) | ||
| 364 | + .build(); | ||
| 365 | + *out_resource = std::move(result); | ||
| 366 | + return protocol::DispatchResponse::Success(); | ||
| 367 | + } else { | ||
| 368 | + auto result = protocol::Network::LoadNetworkResourcePageResult::create() | ||
| 369 | + .setSuccess(false) | ||
| 370 | + .build(); | ||
| 371 | + *out_resource = std::move(result); | ||
| 372 | + return protocol::DispatchResponse::Success(); | ||
| 373 | + } | ||
| 374 | + } | ||
| 375 | + | ||
| 336 | 376 | void NetworkAgent::requestWillBeSent(v8::Local<v8::Context> context, | |
| 337 | 377 | v8::Local<v8::Object> params) { | |
| 338 | 378 | protocol::String request_id; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,9 +1,13 @@ | |||
| 1 | 1 | #ifndef SRC_INSPECTOR_NETWORK_AGENT_H_ | |
| 2 | 2 | #define SRC_INSPECTOR_NETWORK_AGENT_H_ | |
| 3 | 3 | ||
| 4 | + #include "env.h" | ||
| 5 | + #include "io_agent.h" | ||
| 6 | + #include "network_resource_manager.h" | ||
| 4 | 7 | #include "node/inspector/protocol/Network.h" | |
| 5 | 8 | ||
| 6 | 9 | #include <map> | |
| 10 | + #include <memory> | ||
| 7 | 11 | #include <unordered_map> | |
| 8 | 12 | ||
| 9 | 13 | namespace node { | |
@@ -38,8 +42,11 @@ struct RequestEntry { | |||
| 38 | 42 | ||
| 39 | 43 | class NetworkAgent : public protocol::Network::Backend { | |
| 40 | 44 | public: | |
| 41 | - explicit NetworkAgent(NetworkInspector* inspector, | ||
| 42 | - v8_inspector::V8Inspector* v8_inspector); | ||
| 45 | + explicit NetworkAgent( | ||
| 46 | + NetworkInspector* inspector, | ||
| 47 | + v8_inspector::V8Inspector* v8_inspector, | ||
| 48 | + Environment* env, | ||
| 49 | + std::shared_ptr<NetworkResourceManager> network_resource_manager); | ||
| 43 | 50 | ||
| 44 | 51 | void Wire(protocol::UberDispatcher* dispatcher); | |
| 45 | 52 | ||
@@ -60,6 +67,11 @@ class NetworkAgent : public protocol::Network::Backend { | |||
| 60 | 67 | const protocol::String& in_requestId, | |
| 61 | 68 | protocol::Binary* out_bufferedData) override; | |
| 62 | 69 | ||
| 70 | + protocol::DispatchResponse loadNetworkResource( | ||
| 71 | + const protocol::String& in_url, | ||
| 72 | + std::unique_ptr<protocol::Network::LoadNetworkResourcePageResult>* | ||
| 73 | + out_resource) override; | ||
| 74 | + | ||
| 63 | 75 | void emitNotification(v8::Local<v8::Context> context, | |
| 64 | 76 | const protocol::String& event, | |
| 65 | 77 | v8::Local<v8::Object> params); | |
@@ -89,6 +101,8 @@ class NetworkAgent : public protocol::Network::Backend { | |||
| 89 | 101 | v8::Local<v8::Object>); | |
| 90 | 102 | std::unordered_map<protocol::String, EventNotifier> event_notifier_map_; | |
| 91 | 103 | std::map<protocol::String, RequestEntry> requests_; | |
| 104 | + Environment* env_; | ||
| 105 | + std::shared_ptr<NetworkResourceManager> network_resource_manager_; | ||
| 92 | 106 | }; | |
| 93 | 107 | ||
| 94 | 108 | } // namespace inspector | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,10 +3,15 @@ | |||
| 3 | 3 | namespace node { | |
| 4 | 4 | namespace inspector { | |
| 5 | 5 | ||
| 6 | - NetworkInspector::NetworkInspector(Environment* env, | ||
| 7 | - v8_inspector::V8Inspector* v8_inspector) | ||
| 8 | - : enabled_(false), env_(env) { | ||
| 9 | - network_agent_ = std::make_unique<NetworkAgent>(this, v8_inspector); | ||
| 6 | + NetworkInspector::NetworkInspector( | ||
| 7 | + Environment* env, | ||
| 8 | + v8_inspector::V8Inspector* v8_inspector, | ||
| 9 | + std::shared_ptr<NetworkResourceManager> network_resource_manager) | ||
| 10 | + : enabled_(false), | ||
| 11 | + env_(env), | ||
| 12 | + network_resource_manager_(std::move(network_resource_manager)) { | ||
| 13 | + network_agent_ = std::make_unique<NetworkAgent>( | ||
| 14 | + this, v8_inspector, env, network_resource_manager_); | ||
| 10 | 15 | } | |
| 11 | 16 | NetworkInspector::~NetworkInspector() { | |
| 12 | 17 | network_agent_.reset(); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments