Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Node support for the inspector "Target" domain #16629

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,12 @@ The `inspector` module is not available for use.
While using the `inspector` module, an attempt was made to use the inspector
before it was connected.

<a id="ERR_INSPECTOR_NO_DOMAIN_OVERRIDE"></a>
### ERR_INSPECTOR_NO_DOMAIN_OVERRIDE

The `ERR_INSPECTOR_NO_DOMAIN_OVERRIDE` error code indicates an attemp to
override one of the V8 built in inspector protocol domains.

<a id="ERR_INVALID_ARG_TYPE"></a>
### ERR_INVALID_ARG_TYPE

Expand Down
77 changes: 77 additions & 0 deletions doc/guides/extending-inspector-protocol.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Extending Node.js Inspector Protocol

Node.js Inspector Protocol (based on the [Chrome DevTools](https://chromedevtools.github.io/devtools-protocol/v8/))
is designed to be easily extensible by the implementers. This document provides
details on such extension.

## Terminology

* *Inspector session* - message exchange between protocol client and Node.js
* *Protocol handler* - object with a lifetime of the inspector session that
interacts with the protocol client.
* *Protocol domain* - 'API unit' of the inspector protocol. Defines message
formats for specific and related functionality. Node.js exposes protocol
domains provided by the V8. These include `Runtime`, `Debugger`, `Profiler` and
`HeapProfiler`.
* *Message* - a JSON string passed between Node.js backend and an inspector
protocol client. Message types are: request, response and notification. Protocol
client only sends out requests. Messages are asynchronous and client should not
assume response will be sent immediately after serving the request.
* *Method field* - a mandatory field in request and notification messages.
This field value includes *domain* and *method* strings separated by a dot
(e.g. `Debugger.pause`).

## API

`internal/inspector_node_domains` module provides API for extending inspector
protocol exposed by the Node.js

### inspector_node_domains.registerDomainHandlerClass(domain, constructor)

* domain {string} - a JavaScript identifier string that serves as a unique
identifier for the messages that target this domain. Domains should be unique.
It is not permitted to override built-in Node.js domains.
* constructor {ES6 class|constructor function} - creates a protocol handler that
Copy link
Contributor

@vsemozhetbyt vsemozhetbyt Oct 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a reminder that both ES6 class and constructor function need to be added in type-parser.js

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw this isn’t part of the external API documentation

will receive messages for the specified domain. This function should accept a
single callback argument. This callback can be used by the handler to send
notifications to protocol clients. Callback accepts two arguments - *method* and
optional *parameters* object. This callback can be called multiple times.

### Handler method

Protocol dispatcher will call handler method with the name that was specified in
the *method field*. Handler method will receive message *params* object as an
argument. Handler method can return one of the following:
* Nothing. Empty response will be sent to the client.
* Object. This object will be sent to the client as *params* field of
the response.
* Throw exception. Error response will be sent to the client. Exception message
will be included in the response. In the case thrown object does not have the
message field, entire object will be included in the response.
* Function that accepts a callback argument. This function will be invoked
immediately by the dispatcher and enables asynchronous processing of
the inspector message.

### [SessionTerminatedSymbol] handler method

This method is invoked when inspector session is terminated and should perform
all necessary cleanup.

## Things to keep in mind

Regular event loop is interrupted to process the protocol message. This is to
ensure that tooling is available even while the application is running a
continuous body of code (e.g. infinite loop) or is waiting for IO events.

This means that the handler implementation should be careful when relying on
async APIs (e.g. promise resolution) as those events may never happen if
the user code is stuck in the infinite loop or if the JavaScript VM is paused on
a breakpoint.

## Being a good citizen

* Any state should not outlive the session state. E.g. event collection should
be disabled, buffers should be freed.
* Handlers should never be initiating the exchange. E.g. handlers should not
send any notifications before the client explicitly requests them. Convention
is to only send notification after the client invokes '*Domain*.enable' method.
1 change: 1 addition & 0 deletions lib/internal/bootstrap_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@

NativeModule.require('internal/trace_events_async_hooks').setup();
NativeModule.require('internal/inspector_async_hook').setup();
NativeModule.require('internal/inspector_node_domains').setup();

// Do not initialize channel in debugger agent, it deletes env variable
// and the main thread won't see it.
Expand Down
1 change: 1 addition & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ E('ERR_INSPECTOR_ALREADY_CONNECTED', 'The inspector is already connected');
E('ERR_INSPECTOR_CLOSED', 'Session was closed');
E('ERR_INSPECTOR_NOT_AVAILABLE', 'Inspector is not available');
E('ERR_INSPECTOR_NOT_CONNECTED', 'Session is not connected');
E('ERR_INSPECTOR_NO_DOMAIN_OVERRIDE', 'Cannot override V8 protocol domain');
E('ERR_INVALID_ARG_TYPE', invalidArgType);
E('ERR_INVALID_ARG_VALUE', (name, value) =>
`The value "${String(value)}" is invalid for argument "${name}"`);
Expand Down
Loading