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

inspector: JavaScript bindings for the inspector #12263

Closed
wants to merge 1 commit into from
Closed

inspector: JavaScript bindings for the inspector #12263

wants to merge 1 commit into from

Conversation

eugeneo
Copy link
Contributor

@eugeneo eugeneo commented Apr 6, 2017

Adds bindings for accessing Inspector backend from the JavaScript code
on the main context. Following methods were added to process.inspector:

  • connect(callback) - begins a new inspector session. Callback argument
    will be notified when the message is received.
  • disconnect() - destroys the session, disables agents and frees the memory
  • dispatch(message) - sends a message to inspector dispatcher.
Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is included
  • commit message follows commit guidelines
Affected core subsystem(s)

inspector

CC: @ofrobots

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. dont-land-on-v4.x test Issues and PRs related to the tests. labels Apr 6, 2017
@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 6, 2017

The intent of this API is not to create a comprehensive "debugger" API or "profiler" API - instead, the goal is to provide a generic way to talk to inspector so such APIs could be designed for solving specific issues.

@eugeneo eugeneo added inspector Issues and PRs related to the V8 inspector protocol dont-land-on-v6.x labels Apr 6, 2017
@eugeneo eugeneo added the diag-agenda Issues and PRs to discuss during the meetings of the diagnostics working group. label Apr 6, 2017
@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 6, 2017

PPC failure needs to be investigated, I am looking into it.

@mscdex mscdex removed the test Issues and PRs related to the tests. label Apr 6, 2017
@bnoordhuis
Copy link
Member

I don't really get what this is trying to accomplish. I mean, I see what it does but not why. What is the longer-term goal here? A public debugger API?

@ofrobots
Copy link
Contributor

ofrobots commented Apr 6, 2017

The debug context is being removed in V8 by EOY. The objective is to provide an alternative mechanism to do in-process debug tooling.

  1. Node core is dependent on the debug context for some internal functionality (example). It would be good to plumb them over the inspector now.
  2. The ecosystem depends on the debug context for in-process debug tooling (example userspace code dependent on this, another example).

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 6, 2017

@TimothyGu
Copy link
Member

  1. Node core is dependent on the debug context for some internal functionality. It would be good to plumb them over the inspector now.

An even better solution is to add C++ bindings for the cases that need them. What has already happened for proxies and promises should also be done to MapIterator and SetIterator, and GeneratorObject too as a bonus.

I don't oppose the second goal of this PR, but it's simply impractical to go through the overhead of the inspector, when all I want to know is the iterated [[Map]] of an iterator object.

@bnoordhuis
Copy link
Member

Node core is dependent on the debug context for some internal functionality (example). It would be good to plumb them over the inspector now.

I agree with @TimothyGu that using the inspector is complete overkill for that.

The ecosystem depends on the debug context for in-process debug tooling (example userspace code dependent on this, another example).

strong-agent's use is not important; I wrote that code, I can rewrite it. I imagine the same is true for GCP.

@ofrobots
Copy link
Contributor

ofrobots commented Apr 7, 2017

I'm more concerned about the ecosystem usage. The linked GCP module is an in-process debugger for in-production use (outbound connections only). It needs to set breakpoints, gather stacks, evaluate expressions on specific frames. Today, it is pure JavaScript, building on top of the vm.runInDebugContext api. Once that API goes away, we'll need an alternative and having to go to a C++ native module would be reduce the number of people who can use this module.

I haven't done a very deep analysis of the ecosystem, but there are quite a few other modules that also depend on vm.runInDebugContext and they will be forced to C++ native modules unless core offers another way to offer similar functionality in JS.

I think offering JS bindings to the inspector opens up the possibility for the ecosystem to write really cool debug and profiling tooling. Just throwing out ideas: profilers / heapdumps that don't have dependencies on native code or requiring core to add apis for heapdumps; debug functionality integrated into test-frameworks like mocha etc.

Copy link
Member

@TimothyGu TimothyGu left a comment

Choose a reason for hiding this comment

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

A review of the code itself, assuming this PR is to go forward.

if (len > buffer.size() - 1) {
len = buffer.size() - 1;
}
buffer[len] = '\0';
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Did that, made code simpler.


Local<v8::Private> DelegatePrivateKey(Isolate* isolate) {
return v8::Private::ForApi(
isolate, node::OneByteString(isolate, "Inspector#Delegate"));
Copy link
Member

Choose a reason for hiding this comment

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

Can you use the existing private symbol infrastructure?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Not sure if it should be surrounded with #if to only be enabled when building with the inspector...


void Dispatch(const FunctionCallbackInfo<Value>& info) {
Environment* env = Environment::GetCurrent(info);
if (info.Length() != 1 || !info[0]->IsString()) {
Copy link
Member

Choose a reason for hiding this comment

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

The Length check isn't necessary, since if one calls the function without arguments info[0] will be Undefined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

return;
}
Agent* inspector = GetInspectorChecked(env);
if (!inspector->delegate()
Copy link
Member

@TimothyGu TimothyGu Apr 7, 2017

Choose a reason for hiding this comment

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

inspector can be nullptr here. I'd even return a Maybe<Agent*> from GetInspectorChecked() and maybe GetDelegate() to ensure nullptr is always checked for.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, though I am not entirely sold on using Maybe for pointers...


void CreateJSBindingsSession(const FunctionCallbackInfo<Value>& info) {
Environment* env = Environment::GetCurrent(info);
if (info.Length() != 1 || !info[0]->IsFunction()) {
Copy link
Member

Choose a reason for hiding this comment

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

Ditto about Length() check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor

@sam-github sam-github left a comment

Choose a reason for hiding this comment

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

Generally I'm in favour of introspectability of the runtime. This PR introduces new js APIs with no documentation, so it is WIP, but in the absence of docs, its hard to comment on it as a feature unless you already are familiar with the v8 c++ inspector session API.

Copy link
Member

@TimothyGu TimothyGu left a comment

Choose a reason for hiding this comment

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

Echoing @sam-github's concerns here as well. I'm fine with committing the code right now (other than two nits below) as a first draft, but it has to stay behind a flag or disabled by default in some other way, since we would want to be a bit more careful when making new APIs.

Other than the fact that docs are missing, I wonder if these added APIs are as polished as we could make it. To this end, it might be necessary to make an EP for this feature. A few questionable things that came to my mind:

  1. that we are putting everything into process.inspector; maybe we should at one point have a separate require('inspector') (or some other module name) for these user-facing interfaces
  2. that we are creating a new session object from scratch every time connect() is called; making an inspector session a class seems appropriate for this case (const session = new inspector.Session((notification) => { ... }); session.disconnect();)
  3. that only one inspector can be attached at one time; it doesn't take much imagination to think of an instance where the user wishes to debug an application that uses the JS-land inspector API; or am I missing something?

scopeCallback = () => (breakpointHit = true);
debuggedFunction();
assert(!breakpointHit);
testExecution();
Copy link
Member

Choose a reason for hiding this comment

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

The test looks fairly convoluted, but I don't have any better idea to refactor it.

return;
}
inspector->Dispatch(ToProtocolString(env->isolate(),
info[0])->string());
Copy link
Member

Choose a reason for hiding this comment

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

Indentation is off

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

|| delegate != GetDelegate(env, info.This()).FromMaybe(nullptr)) {
env->ThrowError("Inspector is not connected");
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

The handling here basically means that if dispatch.call(null) is executed, two errors will be attempted to be thrown (one in GetDelegate()'s Get(), one here), which of course won't work. The approach taken by GetInspectorChecked() (i.e. throwing an error in GetDelegate() if the delegate is nullptr) should be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I redid the code. Original version was written before the signal handler was merged in. Now V8 inspector is always present and there's no need to check if it exists.

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 7, 2017

Thank you for the feedback.

I will work on docs next week, will update this PR then. I will also look into user-land JS module.

  1. At this point, there can be only one concurrent V8 inspector session. Same is true for Chrome - you cannot connect two frontends to the same page.

@bnoordhuis
Copy link
Member

I think offering JS bindings to the inspector opens up the possibility for the ecosystem to write really cool debug and profiling tooling.

I'm sympathetic but this PR feels a little ad hoc. @TimothyGu already pointed out a few issues and it's not hard to poke more holes. This should be an EP first.

@ofrobots
Copy link
Contributor

An EP sounds good. We can get that put together.

Can we add this as an experimental API in the interim? This allows all existing users of vm.runInDebugContext (given #12243) to at least have an alternative to prototype with.

@bnoordhuis
Copy link
Member

Can we add this as an experimental API in the interim?

I think that would be alright, the question is where? The v8 module?

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 11, 2017 via email

assert.deepStrictEqual(failures, []);
assert.strictEqual(cur, 5);
scopeCallback = null;
session.disconnect();
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd also add test for:

  • connect twice;
  • disconnect twice;
  • disconnect without connect;
  • send 1000 messages in a row;
  • pass non-function as callback;
  • dispatch without connect.

}
Local<Object> session = Object::New(env->isolate());
env->SetMethod(session, "dispatch", Dispatch);
env->SetMethod(session, "disconnect", Disconnect);
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the API overall.

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 17, 2017

I have updated the branch with a new JS API. I also added initial revision of the docs for the module.

Copy link
Member

@jasnell jasnell left a comment

Choose a reason for hiding this comment

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

Still working through the whole PR but some initial requests...

lib/inspector.js Outdated

assert(connect, 'Inspector is not available');

exports.Session = class extends EventEmitter {
Copy link
Member

Choose a reason for hiding this comment

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

would prefer ...

class Session extends EventEmitter { /** ... **/ }

module.exports = {
  Session
};

for consistency with changes made recently in other modules.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

lib/inspector.js Outdated
const connect = process.binding('inspector').connect;
const EventEmitter = require('events');

assert(connect, 'Inspector is not available');
Copy link
Member

Choose a reason for hiding this comment

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

Not convinced this should be an assert as opposed to a throw.

Copy link
Member

Choose a reason for hiding this comment

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

Indeed; the assert is generally used for testing rather than internally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switched to exception, added a test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(Sorry, it was about a different assert below).

lib/inspector.js Outdated
exports.Session = class extends EventEmitter {
constructor() {
super();
this._connection = connect((message) => this._onMessage(message));
Copy link
Member

Choose a reason for hiding this comment

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

Would prefer using internal Symbols for these instead of _-prefixed properties.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you take a look if I did it properly?

@eugeneo
Copy link
Contributor Author

eugeneo commented May 16, 2017

@joshgav I really like the suggestion to use namespace, e.g. nodejs/inspector. It allows to efficiently indicate that the module is coming from the core Node, removes the clash with NPM modules, etc.

To me it looks like this should be a policy for all modules shipped with the Node.js...

@ofrobots
Copy link
Contributor

ofrobots commented May 17, 2017

Coming up with a new naming scheme for core modules might be out of scope for this PR. How about: require('vm').inspector()?

@eugeneo
Copy link
Contributor Author

eugeneo commented May 17, 2017

Coming up with a new naming scheme for core modules might be out of scope for this PR. How about: require('vm').inspector()?

Looks good. I also think this could be made into vm.InspectorSession.

Moving inspector session into VM would mean merging the docs, marking the new API "Stable". I don't think this would be a problem.

@sam-github
Copy link
Contributor

Didn't Andreas already say he'd give us inspector? We don't have to wait, node's builtins are loaded in preference to any on disk, I think we should stick with inspector.

If we have to move, vm seems weird to me, v8.inspector.Session makes more sense.

Btw, merging docs doesn't have to make the API stable (see url.md as an example, some is stable, some is not).

@joshgav
Copy link
Contributor

joshgav commented May 17, 2017

@sam-github

We don't have to wait, node's builtins are loaded in preference to any on disk, I think we should stick with inspector.

Users of that module may not appreciate that :)

@addaleax
Copy link
Member

@joshgav I think at 112 downloads/month we’re good ;)

@ofrobots
Copy link
Contributor

I think at 112 downloads/month we’re good ;)

If that is a low enough number for others, that works for me too!

@ofrobots
Copy link
Contributor

@sam-github, @jasnell you have existing changes-requested reviews here. Can you take another look to see if they can be disposed now?

@jasnell jasnell dismissed their stale review May 18, 2017 01:04

Issues fixed


Emitted when a notification from the V8 Inspector is received.

### Event: INSPECTOR_PROTOCOL_METHOD
Copy link
Member

Choose a reason for hiding this comment

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

Is there any reason why this is uppercase?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure what the proper syntax here. I was trying to make it look different as it is not an actual value but a variable...

Copy link
Member

Choose a reason for hiding this comment

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

How long is the list of possible events? Would something like this be doable?

### Event: Foo1
### Event: Foo2
### Event: Foo3

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The list is already quite long. And the protocol is expandable - there are plans to provide Node API to define new "domains" and hopefully to bring Chrome "Network" and subtarget domains.

Copy link
Contributor

@sam-github sam-github May 18, 2017

Choose a reason for hiding this comment

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

This is an interesting doc case, because there are no other examples of it currently in Node that I'm aware of. It is common in node packages to have events with values that aren't known before hand (websockets, etc). I think its not clear enough that its a variable, maybe <inspector-protocol-method> would be better, because its clearly not a string? Also, I think this would be more clear if the 'inspectorNotification' event had an example and some more text. IIRC, each inspectorNotification has a method: <inspector-protocol-method> field, and the notification is emitted twice, once with the event name set to the protocol-method. This allows subscribing to all notifications using 'inspectorNotificaion', but it also allows users of the API to subscribe to only the notifications they know they are interested in. <--- something like this last sentence is what is missing. With some more info in the 'inspectorNotification' event, its possible this "pseudo event" would not even need to show up as its own ## Event: ... (something)... section, or at least could be documented with a simple "See the 'inspectorNotification' event for more information.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I uploaded a new doc, PTAL.

* {Object} The notification message object

Emitted when an inspector notification is recieved that has method field set
to INSPECTOR_PROTOCOL_METHOD value.
Copy link
Member

Choose a reason for hiding this comment

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

I think there’s a missing the before INSPECTOR_PROTOCOL_METHOD, and I’d put the latter in backticks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed to notation.

Up-to-date version of the V8 inspector protocol is published on the
[Chrome DevTools Protocol Viewer][].

Node inspector supports all V8 domains.
Copy link
Member

Choose a reason for hiding this comment

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

Just curious, what does “V8 domain” refer to here?

Copy link
Contributor

Choose a reason for hiding this comment

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

@addaleax all Inspector methods are namespaced to a domain, e.g. Debugger.enable and Profiler.start.

A list of the currently supported domains is on the left of the protocol explorer at https://chromedevtools.github.io/debugger-protocol-viewer/v8/

"supports all V8 domains from the "Inspector Protocol" or "Chrome DevTools Protocol"" might make that clearer.

Copy link
Member

Choose a reason for hiding this comment

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

@joshgav Thanks, that makes sense :)

lib/inspector.js Outdated

[onMessageSymbol](message) {
const parsed = JSON.parse(message);
if (parsed['id']) {
Copy link
Member

Choose a reason for hiding this comment

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

I would just use parsed.id, parsed.result etc. here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

lib/inspector.js Outdated
post(method, params, callback) {
if (typeof method !== 'string')
throw new TypeError(
'"method" must be a string, got ' + typeof method + ' instead');
Copy link
Member

Choose a reason for hiding this comment

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

Can you use template strings for these?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

callback->Call(receiver, 1, &argument);
if (try_catch.HasCaught()) {
try_catch.ReThrow();
}
Copy link
Member

Choose a reason for hiding this comment

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

What’s the point of this try_catch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mostly to debug programmatic errors in handlers.

Copy link
Member

Choose a reason for hiding this comment

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

I’m not quite sure I understand – is the idea that people can set a debugger breakpoint for the ReThrow() line?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it's to surface simple exceptions, like null pointer dereferences, etc. It is not possible to use debugger frontend when working on a code that uses inspector.Session so printf debugging is pretty much the only option.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

@eugeneo I think we may not be talking about the same thing here.

My question is not whether it makes sense to pass along errors, but rather what this TryCatch actually changes; if you remove it, the errors won’t be caught here, but that doesn’t make a difference if the alternative is just re-throwing immediately, does it? The test you linked to does pass without it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I uploaded a new version. I assumed that you always had to use TryCatch and rethrow the exception when calling JS from native. Thanks for pointing it out that it is not needed!

TryCatch try_catch(isolate);
Local<Function> callback = callback_.Get(isolate);
Local<Object> receiver = receiver_.Get(isolate);
callback->Call(receiver, 1, &argument);
Copy link
Member

Choose a reason for hiding this comment

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

Can you use the MaybeLocal overload here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -155,6 +161,146 @@ static int RegisterDebugSignalHandler() {
}
#endif // _WIN32

class JsBindingsSessionDelegate : public InspectorSessionDelegate {
Copy link
Member

Choose a reason for hiding this comment

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

I think you can wrap (almost?) everything in here in an anonymous namespace

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved the ChannelImpl into anonymous namepace.

assert.throws(() => session.post('Debugger.enable'), (e) => !!e);
}

function testNoCrashWithExceptionInCallback() {
Copy link
Member

Choose a reason for hiding this comment

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

Is there any reason to wrap this in a function? It seems like block scope would be enough for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did it to document what it does.

@sam-github
Copy link
Contributor

Still LGTM, though every console.log() in the example would be more helpful if it had a comment after showing the output.

@eugeneo
Copy link
Contributor Author

eugeneo commented May 18, 2017

@sam-github I documented the expected outputs.

@eugeneo
Copy link
Contributor Author

eugeneo commented May 18, 2017

@addaleax addaleax added the semver-minor PRs that contain new features and should be released in the next minor version. label May 21, 2017
@addaleax
Copy link
Member

Is anything left to do for this to land?

Copy link
Member

@bnoordhuis bnoordhuis left a comment

Choose a reason for hiding this comment

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

LGTM modulo comments. Did we settle on the module name?

added: v8.0.0
-->

The `inspector.Session` class is a primary means of dispatching the messages to
Copy link
Member

Choose a reason for hiding this comment

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

'the primary means'?

Tangential: 'primary' suggests there is also a secondary means.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

session using this API will throw an exception.

Up-to-date version of the V8 inspector protocol is published on the
[protocol viewer][protocol-viewer]
Copy link
Member

Choose a reason for hiding this comment

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

Missing punctuation.

added: REPLACEME
-->

Create a new instance of the `inspector.Session` class. The resulted inspector
Copy link
Member

Choose a reason for hiding this comment

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

Typo: s/resulted/resulting/ (or just drop the word altogether, it's somewhat superfluous.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


* {Object} The notification message object

Emitted when an inspector notification is received that has method field set
Copy link
Member

Choose a reason for hiding this comment

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

s/method/its method/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

* params {Object}
* callback {Function}

Posts a message to the inspector back-end. Optional `callback` will be notified
Copy link
Member

Choose a reason for hiding this comment

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

I'd drop the word "Optional." The function prototype makes it clear it's optional and "Optional callback" reads awkward (ad "The optional callback" isn't really an improvement, IMO.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

lib/inspector.js Outdated
const remainingCallbacks = this[messageCallbacksSymbol].values();
var error = new Error('Session was closed');
for (const callback of remainingCallbacks) {
callback(error);
Copy link
Member

Choose a reason for hiding this comment

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

Consider doing for (const callback of remainingCallbacks) process.nextTick(callback, new Error(...)) for two reasons:

  1. It ensures subsequent callbacks still run if a callback throws, and
  2. new Error(...) gives each callback its own copy.

JsBindingsSessionDelegate* delegate = info.GetParameter();
delegate->Disconnect();
delete delegate;
}
Copy link
Member

Choose a reason for hiding this comment

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

Blank line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

const FunctionCallbackInfo<Value>& info) {
Environment* env = Environment::GetCurrent(info);
Local<Value> delegate;
MaybeLocal<Value> delegateField =
Copy link
Member

Choose a reason for hiding this comment

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

Style nit: delegate_field (also, maybe_delegate is perhaps a better name for it.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

env->ThrowError("Inspector message must be a string");
return;
}
Maybe<JsBindingsSessionDelegate*> maybeDelegate = GetDelegate(info);
Copy link
Member

Choose a reason for hiding this comment

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

Style nit: maybe_delegate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

delete delegate.ToChecked();
}

void CreateJSBindingsSession(const FunctionCallbackInfo<Value>& info) {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe call this Connect() since it's exposed as .connect?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There already is Agent::Connect so I renamed to "ConnectJSBindingsSession"

@eugeneo
Copy link
Contributor Author

eugeneo commented May 22, 2017

@bnoordhuis

Did we settle on the module name?

'inspector' seems to be the final name.

@eugeneo
Copy link
Contributor Author

eugeneo commented May 22, 2017

Did some edits to a doc. Please review, I hope to land it tomorrow.

Copy link
Member

@addaleax addaleax left a comment

Choose a reason for hiding this comment

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

Still LGTM, go for it.

Fresh CI: https://ci.nodejs.org/job/node-test-commit/10075/

-->

Connects a session to the inspector back-end. An exception will be thrown
if there is already a connected session esteblished either through API or by
Copy link
Member

Choose a reason for hiding this comment

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

Typo: established. Also, "the API".

[Chrome DevTools Protocol Viewer][].

Node inspector supports all the Chrome DevTools Protocol domains declared
by the V8. Chrome DevTools Protocol domain provides an interface for interacting
Copy link
Member

Choose a reason for hiding this comment

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

Just "V8". :-)

@addaleax
Copy link
Member

Landed in 60390cd, fixed Ben’s nits during landing.

@addaleax addaleax closed this May 23, 2017
addaleax pushed a commit that referenced this pull request May 23, 2017
PR-URL: #12263
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Josh Gavant <josh.gavant@outlook.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
jasnell pushed a commit that referenced this pull request May 23, 2017
PR-URL: #12263
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Josh Gavant <josh.gavant@outlook.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
jasnell pushed a commit that referenced this pull request May 28, 2017
PR-URL: #12263
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Josh Gavant <josh.gavant@outlook.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@jasnell jasnell mentioned this pull request May 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. diag-agenda Issues and PRs to discuss during the meetings of the diagnostics working group. inspector Issues and PRs related to the V8 inspector protocol semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.