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: use final API #9028

Merged
merged 0 commits into from
Oct 26, 2016
Merged

inspector: use final API #9028

merged 0 commits into from
Oct 26, 2016

Conversation

eugeneo
Copy link
Contributor

@eugeneo eugeneo commented Oct 11, 2016

Checklist
  • make -j8 test (UNIX), or vcbuild test nosign (Windows) passes
  • commit message follows commit guidelines
Affected core subsystem(s)

deps: new version of the v8_inspector dependency
inspector: updated the code to use the new API

Description of change

This implementation switches to V8 inspector from the V8 repository. The
new inspector integration is now using final APIs and exposes a stable
wire protocol, removing the need for pointing the users to specific
devtools version.

CC: @ofrobots

@nodejs-github-bot nodejs-github-bot added the inspector Issues and PRs related to the V8 inspector protocol label Oct 11, 2016
@eugeneo
Copy link
Contributor Author

eugeneo commented Oct 11, 2016

I'll be looking into CI failures - CI UI seems to be down, so this might take some time.

@eugeneo eugeneo added the c++ Issues and PRs that require attention from people who are familiar with C++. label Oct 11, 2016
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.

Rubber stamp LGTM once CI is good.

view.length());

// Reserve 1 character for terminator.
std::string result(view.length() * sizeof(UChar) + 1, '\0');
Copy link
Member

Choose a reason for hiding this comment

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

sizeof(UChar) doesn't look self-evidently correct. I assume it's shorthand for sizeof(*view.characters16()) (which is sizeof(uint16_t)) but code points >= 0x800 encode to more than two bytes.

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. I changed the sizeof & allowed the code to resize the buffer if need be.

public:
explicit ChannelImpl(AgentImpl* agent): agent_(agent) {}
virtual ~ChannelImpl() {}
private:
void sendProtocolResponse(int callId, const String16& message) override {
void sendProtocolResponse(int callId,
const v8_inspector::StringView& message) override {
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: can you line break at the ( or line up the second argument?

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's no longer need for a line break here.

const char CONTEXT_NAME[] = "NodeJS Main Context";
inspector_->contextCreated(v8_inspector::V8ContextInfo(env->context(), 1,
StringView(reinterpret_cast<const uint8_t*>(CONTEXT_NAME),
sizeof(CONTEXT_NAME) - 1)));
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: can you line up arguments more 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.

I rearranged the code.

size_t len = string_value->Length();
std::basic_string<uint16_t> buffer(len, '\0');
string_value->Write(&buffer[0], 0, len);
return StringBuffer::create(StringView(buffer.c_str(), len));
Copy link
Member

Choose a reason for hiding this comment

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

For my own curiosity, is .c_str() rather than .data() necessary here if you also pass len?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Coding mistake.

if (wait_) {
std::string message(buf->base, read);
if (message.find("\"Runtime.runIfWaitingForDebugger\"")
!= std::string::npos) {
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 put the operator on the line before?

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

if (AppendMessage(&incoming_message_queue_, frontend_session_id_, message)) {
void AgentImpl::PostIncomingMessage(const char* message, size_t len) {
if (AppendMessage(&incoming_message_queue_, frontend_session_id_,
Utf8ToStringView(message, len))) {
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: can you line up the arguments?

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

AppendMessage(&outgoing_message_queue_, session_id, message);
void AgentImpl::Write(int session_id, const StringView& inspector_message) {
AppendMessage(&outgoing_message_queue_, session_id,
StringBuffer::create(inspector_message));
Copy link
Member

Choose a reason for hiding this comment

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

Ditto.

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

std::string tag;
if (message.length() <= sizeof(TAG_CONNECT) ||
message.length() <= sizeof(TAG_DISCONNECT))
tag = StringViewToUtf8(message);
Copy link
Member

Choose a reason for hiding this comment

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

It's not exactly wrong but I'd wrap the body in braces for legibility.

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

@eugeneo
Copy link
Contributor Author

eugeneo commented Oct 13, 2016

@bnoordhuis I addressed your comments, please take another look.

CI: https://ci.nodejs.org/job/node-test-pull-request/4506/

Linux ARM failure: exception in Hudson on one bot.
Free BSD: some tests fail on one bot and run on another. The tests do not start inspector.
SmartOS: CI success, not reported to this PR.

@rvagg rvagg force-pushed the master branch 2 times, most recently from c133999 to 83c7a88 Compare October 18, 2016 17:02
@eugeneo
Copy link
Contributor Author

eugeneo commented Oct 18, 2016

@bnoordhuis Please take another look.

#include "libplatform/libplatform.h"

#include <unicode/unistr.h>
Copy link
Member

Choose a reason for hiding this comment

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

If you're taking a dependency on ICU, then configure should have a --with-intl=none -> --without-inspector implication.

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 modified configure - now disabling either ICU or OpenSSL will also disable inspector.

std::string StringViewToUtf8(const StringView& view) {
if (view.is8Bit())
return std::string(reinterpret_cast<const char*>(view.characters8()),
view.length());
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 line up the arguments and maybe put braces around the block?

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 uint16_t* source = view.characters16();
std::string result(view.length() * sizeof(*source), '\0');
UnicodeString utf16(reinterpret_cast<const UChar*>(source), view.length());
Copy link
Member

Choose a reason for hiding this comment

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

Is this reinterpret_cast necessary? If for some reason UChar != uint16_t, then this line should arguably fail to compile instead of silently doing the wrong thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Windows uses some different type for UChar (not clear from compiler messages - but probably wchar).

CheckedArrayByteSink sink(&result[0], result.length());
utf16.toUTF8(sink);
result.resize(sink.NumberOfBytesAppended());
done = !sink.Overflowed();
Copy link
Member

Choose a reason for hiding this comment

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

Does that mean this function may return partial strings? How bad is that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure what you mean here. This code makes sure string has enough capacity.

Copy link
Member

Choose a reason for hiding this comment

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

Correct me if I'm wrong but CheckedArrayByteSink is instantiated every time with the same arguments in this loop so logically sink.Overflowed() is either always true or always false. That means this loop either isn't (i.e., it's not a loop because it exits after the first iteration) or it's an infinite loop.

std::unique_ptr<StringBuffer> Utf8ToStringView(const char* source,
size_t length) {
UnicodeString utf16 = UnicodeString::fromUTF8(StringPiece(source, length));
StringView view(reinterpret_cast<const uint16_t*>(utf16.getBuffer()),
Copy link
Member

Choose a reason for hiding this comment

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

Same question as on line 212: is the reinterpret_cast necessary?

@@ -350,8 +373,10 @@ class V8NodeInspector : public v8_inspector::V8InspectorClient {
terminated_(false),
running_nested_loop_(false),
inspector_(V8Inspector::create(env->isolate(), this)) {
inspector_->contextCreated(
v8_inspector::V8ContextInfo(env->context(), 1, "NodeJS Main Context"));
const uint8_t CONTEXT_NAME[] = "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.

While you're here: s/NodeJS/Node.js/

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! Done.

String16::fromInteger(script_id) == stack_trace->topScriptId()) {
v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();

if (!stack_trace.IsEmpty() && stack_trace->GetFrameCount() &&
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 put each clause on its own 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

StringView message = pair.second->string();
std::string tag;
if (message.length() <= sizeof(TAG_CONNECT) ||
message.length() <= sizeof(TAG_DISCONNECT)) {
Copy link
Member

Choose a reason for hiding this comment

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

Just ==?

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

@eugeneo
Copy link
Contributor Author

eugeneo commented Oct 21, 2016

@bnoordhuis Thank you for the review. I've updated the code, please take another look.

@eugeneo
Copy link
Contributor Author

eugeneo commented Oct 25, 2016

@bnoordhuis Please, take another look.

def configure_inspector(o):
o['variables']['v8_inspector'] = b(not options.without_inspector
and o['variables']['v8_enable_i18n_support']
and o['variables']['node_use_openssl'] == 'true')
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 options here? That way it won't depend on the order in which the configure_intl an/configure_openssl/configure_inspector functions are executed.

Also, please keep lines <= 80 columns.

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.

CheckedArrayByteSink sink(&result[0], result.length());
utf16.toUTF8(sink);
result.resize(sink.NumberOfBytesAppended());
done = !sink.Overflowed();
Copy link
Member

Choose a reason for hiding this comment

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

Correct me if I'm wrong but CheckedArrayByteSink is instantiated every time with the same arguments in this loop so logically sink.Overflowed() is either always true or always false. That means this loop either isn't (i.e., it's not a loop because it exits after the first iteration) or it's an infinite loop.

v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();

if (!stack_trace.IsEmpty() &&
stack_trace->GetFrameCount() &&
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 stack_trace->GetFrameCount() > 0?

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

@eugeneo
Copy link
Contributor Author

eugeneo commented Oct 25, 2016

@bnoordhuis thank you for the review, I uploaded a new version - please take a look.

GitHub Ui is not allowing me to answer this comment (does not show the reply entry field for some reason):

Correct me if I'm wrong but CheckedArrayByteSink is instantiated every time with the same arguments in this loop so logically sink.Overflowed() is either always true or always false. That means this loop either isn't (i.e., it's not a loop because it exits after the first iteration) or it's an infinite loop.

The code was relying on string length, that was updated in the loop. I changed the code to make it more obvious.

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 with some final comments. I think I understand how sinking works now.

def configure_inspector(o):
disable_inspector = (options.without_inspector
or options.with_intl in (None, 'none')
or options.without_ssl)
Copy link
Member

Choose a reason for hiding this comment

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

I realize this is nitpicking but since we put operators at the end of the line everywhere else can you do it here too?

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

@@ -1250,6 +1255,8 @@ configure_v8(output)
configure_openssl(output)
configure_intl(output)
configure_static(output)
# should come after configure_openssl and configure_intl
Copy link
Member

Choose a reason for hiding this comment

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

This comment is no longer necessary.

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 uint16_t* source = view.characters16();
size_t result_length = view.length() * sizeof(*source);
std::string result(result_length, '\0');
UnicodeString utf16(reinterpret_cast<const UChar*>(source), view.length());
Copy link
Member

Choose a reason for hiding this comment

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

If the reinterpret_cast is non-optional here, can you at least add a static_assert that checks the pointed-to types are of the same size? See #9280 for an example of what I mean.

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.

@eugeneo
Copy link
Contributor Author

eugeneo commented Oct 25, 2016

Thank you for the review, I addressed the comments and submitted to CI: https://ci.nodejs.org/job/node-test-pull-request/4674/

@eugeneo eugeneo closed this Oct 26, 2016
@eugeneo eugeneo merged commit 8f00455 into nodejs:master Oct 26, 2016
@eugeneo
Copy link
Contributor Author

eugeneo commented Oct 26, 2016

Landed as 8f00455

evanlucas pushed a commit that referenced this pull request Nov 3, 2016
This implementation switches to V8 inspector from the V8 repository. The
new inspector integration is now using final APIs and exposes a stable
wire protocol, removing the need for pointing the users to specific
devtools version.

PR-URL: #9028
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@MylesBorins
Copy link
Contributor

hey @eugeneo this seemed to break configure on v6.x

Would you be willing to manually backport

@eugeneo
Copy link
Contributor Author

eugeneo commented Nov 18, 2016

Let me take a look.

On Fri, Nov 18, 2016 at 1:50 PM Myles Borins notifications@github.com
wrote:

hey @eugeneo https://github.com/eugeneo this seemed to break configure
on v6.x

Would you be willing to manually backport


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#9028 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AARkrQ5CyRRfH7_y8ajVFRyc6bx-Fwtaks5q_h2kgaJpZM4KT2Fh
.

@eugeneo
Copy link
Contributor Author

eugeneo commented Nov 18, 2016

@thealphanerd backporting this inspector to V8 5.1 is a significant effort. Can we opt out of it? I am not familiar with the process.

@MylesBorins
Copy link
Contributor

@eugeneo we absolutely can opt out. Considering that v6.x has over 2 years of support left I'd like to get something as up to date as possible though. At what point will we no longer be able to update the inspector that we ship in v6?

@eugeneo
Copy link
Contributor Author

eugeneo commented Nov 19, 2016

I guess this is the point inspector stops getting updated... The new
inspector that is in Node7 is the one imported from the V8 repository (as
opposed to the Blink repository) so it relies on new V8 build setup and
probably some APIs. In the past we had to do some extra work to support
older V8 that the Node uses - but that was lost with the code moving to the
V8 repository.

On Fri, Nov 18, 2016 at 4:08 PM Myles Borins notifications@github.com
wrote:

@eugeneo https://github.com/eugeneo we absolutely can opt out.
Considering that v6.x has over 2 years of support left I'd like to get
something as up to date as possible though. At what point will we no longer
be able to update the inspector that we ship in v6?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#9028 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AARkrbf_GPJxY3-YJmNzvjVy_ixxidKpks5q_j3IgaJpZM4KT2Fh
.

@eugeneo eugeneo deleted the inspector_icu branch December 27, 2016 18:49
thefourtheye added a commit to thefourtheye/io.js that referenced this pull request Feb 11, 2017
nodejs#9028 made Node.js use the V8
inspector bundled with the deps/v8 and removed the third party
dependency. We can safely omit the non-existent license file.
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants