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: add contexts when using vm module #9272

Closed
wants to merge 4 commits into from

Conversation

bmeck
Copy link
Member

@bmeck bmeck commented Oct 25, 2016

Checklist
  • make -j8 test (UNIX), or vcbuild test nosign (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

inspector

Description of change

Tracks all vm module contexts for usage in v8_inspector. These are tracked even when the inspector is not running so that they are visible when the inspector is started up.

Fixes: #7593

Adds all Contexts created by the vm module to the inspector. This does
permanent tracking of Contexts and syncing the Contexts whenever a new
inspector is created.

Fixes: nodejs#7593
@nodejs-github-bot nodejs-github-bot added the c++ Issues and PRs that require attention from people who are familiar with C++. label Oct 25, 2016
@jasnell
Copy link
Member

jasnell commented Oct 25, 2016

/cc @bnoordhuis

Copy link
Contributor

@eugeneo eugeneo left a comment

Choose a reason for hiding this comment

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

Thanks for looking into it. Some comments - mostly about keeping as much gory inspector details within inspector itself.

src/env-inl.h Outdated
@@ -356,6 +356,25 @@ inline IsolateData* Environment::isolate_data() const {
return isolate_data_;
}

inline void Environment::context_created(v8_inspector::V8ContextInfo info) {
contexts()->push_back(info);
if (inspector_agent()->IsStarted()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be enclosed in #if HAVE_INSPECTOR check?

Copy link
Member Author

Choose a reason for hiding this comment

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

good find

src/env-inl.h Outdated
inline void Environment::context_created(v8_inspector::V8ContextInfo info) {
contexts()->push_back(info);
if (inspector_agent()->IsStarted()) {
inspector_agent()->ContextCreated(info);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest to always call ContextCreated/ContextDestroyed - and then let inspector_agent check the IsStarted. This way in this header it will be a single line call (also, contexts vector will live in inspector then).

Copy link
Member Author

Choose a reason for hiding this comment

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

@eugeneo the way the inspector_agent is setup, it is unsafe to call prior to it being started since platform_ does not exist.

@@ -7,6 +7,7 @@
#include "debug-agent.h"
#if HAVE_INSPECTOR
#include "inspector_agent.h"
#include <vector>
Copy link
Contributor

Choose a reason for hiding this comment

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

Including STL header on the high level header used to cause some problems with the memory allocation on AIX (it was using a "wrong" alloc). I do not know if they were fixed...

Copy link
Member Author

Choose a reason for hiding this comment

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

these includes are also present in existing inspector files

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I had to make sure they do not leak outside of inspector_agent translation unit. This issue might've been fixed since.

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -33,6 +35,9 @@ class Agent {
// Stop the inspector agent
void Stop();

void ContextCreated(const v8_inspector::V8ContextInfo& info);
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe it would be better if this call accepted v8::Context (and, optionally, a string) rather then V8ContextInfo. This would allow us no to leak inspector API to the bigger Node.

Copy link
Member Author

Choose a reason for hiding this comment

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

possible, but there is some complexity here since the v8 inspector is already tightly bound in inspector_agent.cc, if we had a generic API I would agree, but I don't see that currently.

Copy link
Contributor

Choose a reason for hiding this comment

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

There's still some churn in inspector API (e.g. #9028 is quite major) so I feel like it would be safer to only rely on v8 namespace.

Copy link
Member Author

Choose a reason for hiding this comment

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

i saw the Threads bit in the new devtools, is that the purpose of the contextGroupId? Should we be including that as well?

@mscdex mscdex added the inspector Issues and PRs related to the V8 inspector protocol label Oct 25, 2016
src/env.h Outdated
@@ -564,6 +571,7 @@ class Environment {
debugger::Agent debugger_agent_;
#if HAVE_INSPECTOR
inspector::Agent inspector_agent_;
std::vector<v8_inspector::V8ContextInfo> contexts_;
Copy link
Member

Choose a reason for hiding this comment

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

I don't think V8ContextInfo is safe to use here because it doesn't look like it's supposed to outlive a HandleScope. The context is stored as a v8::Local<v8::Context> and Locals are clobbered when the HandleScope is destroyed.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can do it and match the other request to limit usage of v8_inspector namespace usage

src/env.h Outdated
@@ -528,6 +529,12 @@ class Environment {
inline inspector::Agent* inspector_agent() {
return &inspector_agent_;
}

inline void context_created(v8_inspector::V8ContextInfo context);
inline void context_destroyed(v8::Local<v8::Context> context);
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 call these ContextCreated() and ContextDestroyed()?

Copy link
Member Author

Choose a reason for hiding this comment

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

sounds good

@fhinkel fhinkel added the vm Issues and PRs related to the vm subsystem. label Oct 25, 2016
change context_created to ContextCreated on Environment
create node specific class instead of exposing v8_inspector for Context tracking
@bmeck
Copy link
Member Author

bmeck commented Oct 26, 2016

@bnoordhuis @eugeneo fixed, please review when you find the time :)

Copy link
Contributor

@eugeneo eugeneo left a comment

Choose a reason for hiding this comment

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

Thanks for doing this. I still strongly feel like majority of this code should remain private to the inspector. I wonder if there is a way (or should be one) to be notified of context creation/destruction so the inspector could somehow subscribe to it.

Please notice that I've updates the V8 inspector version, now the API is the same as in inspector that is in the V8 repository.

@@ -528,6 +529,12 @@ class Environment {
inline inspector::Agent* inspector_agent() {
return &inspector_agent_;
}

inline void ContextCreated(node::inspector::ContextInfo* info);
Copy link
Contributor

Choose a reason for hiding this comment

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

I still have an issue with the parameter asymmetry - especially, considering that ContextInfo is instantiated in call side in both cases (and will likely be for all future uses).

Copy link
Member Author

Choose a reason for hiding this comment

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

unclear on what you suggest as an alternative?

Copy link
Contributor

Choose a reason for hiding this comment

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

I am suggesting not to expose ContextInfo outside of inspector-agent.cc

src/env.cc Outdated
new node::inspector::ContextInfo(context(), 1, "NodeJS Main Context"));
#endif

isolate()->SetAutorunMicrotasks(false);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this related to this change?

Copy link
Member Author

Choose a reason for hiding this comment

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

unclear how this got in here, should be removed.

@@ -564,6 +571,7 @@ class Environment {
debugger::Agent debugger_agent_;
#if HAVE_INSPECTOR
inspector::Agent inspector_agent_;
std::vector<node::inspector::ContextInfo*> contexts_;
Copy link
Contributor

Choose a reason for hiding this comment

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

IMHO, this vector should be a member of inspector::AgentImpl.

Copy link
Member Author

Choose a reason for hiding this comment

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

disagree since inspector isn't really usable until it starts

Copy link
Contributor

Choose a reason for hiding this comment

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

But you're calling IsStarted - so it is usable, just not started.

I'm wondering if there's some way to introduce some sort of context registry that is not inspector specific. There might already be one in v8...

Copy link
Member Author

Choose a reason for hiding this comment

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

IsStarted just checks if things are usable, platform_ being uninitialized resulted in segfaults when I tried to call contextCreated early on

@Trott
Copy link
Member

Trott commented Oct 26, 2016

@bmeck The "tests and/or benchmarks are included" box is checked, but I'm not seeing any tests or benchmarks. Did they just get omitted accidentally? Or should that box not be checked?

@bmeck
Copy link
Member Author

bmeck commented Oct 26, 2016

@Trott accident

return;
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

You could simplify this with std::find or std::find_if.

Copy link
Member Author

Choose a reason for hiding this comment

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

the erase needs an index not value.

Copy link
Member

Choose a reason for hiding this comment

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

find() and find_if() return iterators, not values.

src/env-inl.h Outdated
}
}
}
#endif
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 write this as #endif // HAVE_INSPECTOR? Note the two spaces after #endif.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixing, but copy paste only shows

#endif [<= one space?]// HAVE_INSPECTOR

src/env.cc Outdated
@@ -30,6 +34,11 @@ void Environment::Start(int argc,
HandleScope handle_scope(isolate());
Context::Scope context_scope(context());

#if HAVE_INSPECTOR
ContextCreated(
new node::inspector::ContextInfo(context(), 1, "NodeJS Main Context"));
Copy link
Member

Choose a reason for hiding this comment

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

Line continuations should have four spaces of indent. (Ditto in other files, I won't point them out separately.)

inspector_->contextCreated(
v8_inspector::V8ContextInfo(env->context(), 1, "NodeJS Main Context"));
v8::HandleScope handles(env_->isolate());
for (auto it : *(env->contexts())) {
Copy link
Member

Choose a reason for hiding this comment

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

You don't need parens around env->contexts().

context_.Reset(context->GetIsolate(), context);
}
~ContextInfo() {
context_.Reset();
Copy link
Member

Choose a reason for hiding this comment

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

Not necessary, ~Persistent() resets by default.

const char* name() const { return name_; }
private:
v8::Persistent<v8::Context> context_;
int groupId_;
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 snake_case it to group_id_? If it never changes, consider making it const (same for name_.)

@cpojer
Copy link

cpojer commented Nov 16, 2016

So glad this is being worked on! @bmeck do you have any ETA when this will make it into a version of node? :)

@bmeck
Copy link
Member Author

bmeck commented Nov 17, 2016

@cpojer it sounds like the inspector might need changes according to @eugeneo so we don't expose some things like manual create of context information. I'm mostly in waiting position on this PR until then.

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.

Left some comments, nothing substantial. I think @eugeneo should do the final sign-off because he understands the inspector code better than I do.

return;
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

find() and find_if() return iterators, not values.

inspector_->contextCreated(
v8_inspector::V8ContextInfo(env->context(), 1, "NodeJS Main Context"));
v8::HandleScope handles(env_->isolate());
for (auto it : *env->contexts()) {
Copy link
Member

Choose a reason for hiding this comment

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

Somewhat inconsistent use of env vs. env_.

void AgentImpl::ContextCreated(const node::inspector::ContextInfo* info) {
inspector_->contextCreated(info);
}
void AgentImpl::ContextDestroyed(v8::Local<v8::Context> context) {
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 insert a blank line here and on line 894?

}
void Agent::ContextDestroyed(v8::Local<v8::Context> context) {
impl->ContextDestroyed(context);
}
Copy link
Member

Choose a reason for hiding this comment

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

Out of curiosity, is the two or three levels of forwarding strictly necessary?

Copy link
Member Author

Choose a reason for hiding this comment

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

in order to pass things to the right place and get through all the levels of abstraction, yes.

@@ -23,6 +25,25 @@ namespace inspector {

class AgentImpl;

class ContextInfo {
public:
explicit ContextInfo(v8::Local<v8::Context> context, const int groupId,
Copy link
Member

Choose a reason for hiding this comment

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

s/groupId/group_id/

inline v8::Local<v8::Context> context(v8::Isolate* isolate) const {
return context_.Get(isolate);
}
int groupId() const { return group_id_; }
Copy link
Member

Choose a reason for hiding this comment

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

Ditto, idiomatic core code would spell this as group_id().

Copy link
Member Author

Choose a reason for hiding this comment

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

is there a style guide on this or reason why linting doesn't pick these things up?

@jasnell
Copy link
Member

jasnell commented Mar 24, 2017

Ping @bmeck ... does this still make sense? Is it needed? /cc @eugeneo

@jasnell jasnell added the stalled Issues and PRs that are stalled. label Mar 24, 2017
@bmeck
Copy link
Member Author

bmeck commented Mar 24, 2017 via email

@bmeck
Copy link
Member Author

bmeck commented Apr 25, 2017

@eugeneo

Can I get updates on :

#9272 (comment)

If the platform_ comment makes sense still.

#9272 (comment)

If the asymmetry is still a blocker.

#9272 (review)

Guessing such an API is not in the works.

@eugeneo
Copy link
Contributor

eugeneo commented Apr 25, 2017

@bmeck please take a look at https://github.com/eugeneo/node/tree/contexts_crashing - this is my suggested implementation, it is very similar to yours. I had to cut a corner or two - but the real problem is that it is crashing in test/parallel/test-vm-run-in-new-context.js

@eugeneo
Copy link
Contributor

eugeneo commented Apr 25, 2017

@bmeck one thing I have been looking into (and I hope to go back to) is for the inspector to have its own WeakCallback on a context so there's no need to report to Inspector contexts going away.

@gaearon
Copy link

gaearon commented May 25, 2017

Is there any way React community could help with pushing this through? It’s affecting Jest pretty badly and I’m sure somebody could pick it up if you are busy with other things.

@bmeck
Copy link
Member Author

bmeck commented May 25, 2017

@gaearon if someone wants to merge both my and @eugeneo 's work that would probably be enough.

I don't have time right now sadly T_T

@fhinkel
Copy link
Member

fhinkel commented May 26, 2017

I'm removing the stalled label. Anybody we can ping to merge these changes together? @eugeneo ?

@fhinkel fhinkel removed the stalled Issues and PRs that are stalled. label May 26, 2017
@cdaringe
Copy link

cdaringe commented Jun 1, 2017

Im super excited about this. I haven't written c/c++ since college, but I'd be willing to at least pair as a sounding board for anyone who can keep this going!

jgoz pushed a commit to jgoz/node that referenced this pull request Jun 20, 2017
This enables inspector support for contexts created using the vm
module.

Fixes: nodejs#7593
Fixes: nodejs#12096
Refs: nodejs#9272
TimothyGu added a commit to TimothyGu/node that referenced this pull request Jul 14, 2017
Based on work by Bradley Farias <bradley.meck@gmail.com> and Eugene
Ostroukhov <eostroukhov@chromium.org>.

TODO: V8's console is injected unconditionally, which may be not desirable.

Fixes: nodejs#7593
Refs: nodejs#9272
@jgoz
Copy link

jgoz commented Aug 11, 2017

@bmeck, @eugeneo This can be closed now that #14465 is merged, right?

@bnoordhuis
Copy link
Member

Yes, #14465 should have obviated this one. I'll close it out, thanks.

@bnoordhuis bnoordhuis closed this Aug 17, 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++. inspector Issues and PRs related to the V8 inspector protocol vm Issues and PRs related to the vm subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

v8_inspector: Support the V8 debugger from within VM contexts