| Index: src/d8.cc
|
| diff --git a/src/d8.cc b/src/d8.cc
|
| index 28ebfc05b9839327fb596ac491514e1b341fe1a9..bce9103f6499fbbafb869c2085d5a40e69e523df 100644
|
| --- a/src/d8.cc
|
| +++ b/src/d8.cc
|
| @@ -34,6 +34,10 @@
|
| #include "src/utils.h"
|
| #include "src/v8.h"
|
|
|
| +#ifdef V8_INSPECTOR_ENABLED
|
| +#include "include/v8-inspector.h"
|
| +#endif // V8_INSPECTOR_ENABLED
|
| +
|
| #if !defined(_WIN32) && !defined(_WIN64)
|
| #include <unistd.h> // NOLINT
|
| #else
|
| @@ -596,7 +600,8 @@ class ModuleEmbedderData {
|
| enum {
|
| // The debugger reserves the first slot in the Context embedder data.
|
| kDebugIdIndex = Context::kDebugIdIndex,
|
| - kModuleEmbedderDataIndex
|
| + kModuleEmbedderDataIndex,
|
| + kInspectorClientIndex
|
| };
|
|
|
| void InitializeModuleEmbedderData(Local<Context> context) {
|
| @@ -1759,6 +1764,130 @@ void Shell::RunShell(Isolate* isolate) {
|
| printf("\n");
|
| }
|
|
|
| +#ifdef V8_INSPECTOR_ENABLED
|
| +class InspectorFrontend final : public v8_inspector::V8Inspector::Channel {
|
| + public:
|
| + explicit InspectorFrontend(Local<Context> context) {
|
| + isolate_ = context->GetIsolate();
|
| + context_.Reset(isolate_, context);
|
| + }
|
| + virtual ~InspectorFrontend() = default;
|
| +
|
| + private:
|
| + void sendProtocolResponse(int callId,
|
| + const v8_inspector::StringView& message) override {
|
| + Send(message);
|
| + }
|
| + void sendProtocolNotification(
|
| + const v8_inspector::StringView& message) override {
|
| + Send(message);
|
| + }
|
| + void flushProtocolNotifications() override {}
|
| +
|
| + void Send(const v8_inspector::StringView& string) {
|
| + int length = static_cast<int>(string.length());
|
| + DCHECK(length < v8::String::kMaxLength);
|
| + Local<String> message =
|
| + (string.is8Bit()
|
| + ? v8::String::NewFromOneByte(
|
| + isolate_,
|
| + reinterpret_cast<const uint8_t*>(string.characters8()),
|
| + v8::NewStringType::kNormal, length)
|
| + : v8::String::NewFromTwoByte(
|
| + isolate_,
|
| + reinterpret_cast<const uint16_t*>(string.characters16()),
|
| + v8::NewStringType::kNormal, length))
|
| + .ToLocalChecked();
|
| + Local<String> callback_name =
|
| + v8::String::NewFromUtf8(isolate_, "receive", v8::NewStringType::kNormal)
|
| + .ToLocalChecked();
|
| + Local<Context> context = context_.Get(isolate_);
|
| + Local<Value> callback =
|
| + context->Global()->Get(context, callback_name).ToLocalChecked();
|
| + if (callback->IsFunction()) {
|
| + v8::TryCatch try_catch(isolate_);
|
| + Local<Value> args[] = {message};
|
| + if (Local<Function>::Cast(callback)
|
| + ->Call(context, Undefined(isolate_), 1, args)
|
| + .IsEmpty()) {
|
| + try_catch.ReThrow();
|
| + }
|
| + }
|
| + }
|
| +
|
| + Isolate* isolate_;
|
| + Global<Context> context_;
|
| +};
|
| +
|
| +class InspectorClient : public v8_inspector::V8InspectorClient {
|
| + public:
|
| + InspectorClient(Local<Context> context, bool connect) {
|
| + if (!connect) return;
|
| + isolate_ = context->GetIsolate();
|
| + channel_.reset(new InspectorFrontend(context));
|
| + inspector_ = v8_inspector::V8Inspector::create(isolate_, this);
|
| + session_ =
|
| + inspector_->connect(1, channel_.get(), v8_inspector::StringView());
|
| + context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this);
|
| + inspector_->contextCreated(v8_inspector::V8ContextInfo(
|
| + context, kContextGroupId, v8_inspector::StringView()));
|
| +
|
| + Local<Value> function =
|
| + FunctionTemplate::New(isolate_, SendInspectorMessage)
|
| + ->GetFunction(context)
|
| + .ToLocalChecked();
|
| + Local<String> function_name =
|
| + String::NewFromUtf8(isolate_, "send", NewStringType::kNormal)
|
| + .ToLocalChecked();
|
| + CHECK(context->Global()->Set(context, function_name, function).FromJust());
|
| +
|
| + context_.Reset(isolate_, context);
|
| + }
|
| +
|
| + private:
|
| + static v8_inspector::V8InspectorSession* GetSession(Local<Context> context) {
|
| + InspectorClient* inspector_client = static_cast<InspectorClient*>(
|
| + context->GetAlignedPointerFromEmbedderData(kInspectorClientIndex));
|
| + return inspector_client->session_.get();
|
| + }
|
| +
|
| + Local<Context> ensureDefaultContextInGroup(int group_id) override {
|
| + DCHECK(isolate_);
|
| + DCHECK_EQ(kContextGroupId, group_id);
|
| + return context_.Get(isolate_);
|
| + }
|
| +
|
| + static void SendInspectorMessage(
|
| + const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| + Isolate* isolate = args.GetIsolate();
|
| + v8::HandleScope handle_scope(isolate);
|
| + Local<Context> context = isolate->GetCurrentContext();
|
| + args.GetReturnValue().Set(Undefined(isolate));
|
| + Local<String> message = args[0]->ToString(context).ToLocalChecked();
|
| + v8_inspector::V8InspectorSession* session =
|
| + InspectorClient::GetSession(context);
|
| + int length = message->Length();
|
| + std::unique_ptr<uint16_t> buffer(new uint16_t[length]);
|
| + message->Write(buffer.get(), 0, length);
|
| + v8_inspector::StringView message_view(buffer.get(), length);
|
| + session->dispatchProtocolMessage(message_view);
|
| + args.GetReturnValue().Set(True(isolate));
|
| + }
|
| +
|
| + static const int kContextGroupId = 1;
|
| +
|
| + std::unique_ptr<v8_inspector::V8Inspector> inspector_;
|
| + std::unique_ptr<v8_inspector::V8InspectorSession> session_;
|
| + std::unique_ptr<v8_inspector::V8Inspector::Channel> channel_;
|
| + Global<Context> context_;
|
| + Isolate* isolate_;
|
| +};
|
| +#else // V8_INSPECTOR_ENABLED
|
| +class InspectorClient {
|
| + public:
|
| + InspectorClient(Local<Context> context, bool connect) { CHECK(!connect); }
|
| +};
|
| +#endif // V8_INSPECTOR_ENABLED
|
|
|
| SourceGroup::~SourceGroup() {
|
| delete thread_;
|
| @@ -1842,7 +1971,6 @@ base::Thread::Options SourceGroup::GetThreadOptions() {
|
| return base::Thread::Options("IsolateThread", 2 * MB);
|
| }
|
|
|
| -
|
| void SourceGroup::ExecuteInThread() {
|
| Isolate::CreateParams create_params;
|
| create_params.array_buffer_allocator = Shell::array_buffer_allocator;
|
| @@ -1857,6 +1985,8 @@ void SourceGroup::ExecuteInThread() {
|
| Local<Context> context = Shell::CreateEvaluationContext(isolate);
|
| {
|
| Context::Scope cscope(context);
|
| + InspectorClient inspector_client(context,
|
| + Shell::options.enable_inspector);
|
| PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
|
| Execute(isolate);
|
| }
|
| @@ -2252,6 +2382,9 @@ bool Shell::SetOptions(int argc, char* argv[]) {
|
| } else if (strncmp(argv[i], "--trace-config=", 15) == 0) {
|
| options.trace_config = argv[i] + 15;
|
| argv[i] = NULL;
|
| + } else if (strcmp(argv[i], "--enable-inspector") == 0) {
|
| + options.enable_inspector = true;
|
| + argv[i] = NULL;
|
| }
|
| }
|
|
|
| @@ -2301,6 +2434,7 @@ int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) {
|
| }
|
| {
|
| Context::Scope cscope(context);
|
| + InspectorClient inspector_client(context, options.enable_inspector);
|
| PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
|
| options.isolate_sources[0].Execute(isolate);
|
| }
|
|
|