[inspector] Cleanup inspector test

- reduce boilerplate;
- encapsulate V8Inspector inside IsolateData;
- remove extra interfaces and classes.

BUG=none

Review-Url: https://codereview.chromium.org/2901523003
Cr-Commit-Position: refs/heads/master@{#45470}
This commit is contained in:
dgozman 2017-05-22 13:46:42 -07:00 committed by Commit bot
parent 66d242dea5
commit 93c12e5d3f
5 changed files with 294 additions and 444 deletions

View File

@ -13,7 +13,6 @@
#include "src/base/platform/platform.h"
#include "src/flags.h"
#include "src/inspector/test-interface.h"
#include "src/utils.h"
#include "src/vector.h"
@ -51,6 +50,20 @@ v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str) {
.ToLocalChecked();
}
v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str,
int length) {
return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal,
length)
.ToLocalChecked();
}
v8::Local<v8::String> ToV8String(v8::Isolate* isolate,
const v8::internal::Vector<uint16_t>& buffer) {
return v8::String::NewFromTwoByte(isolate, buffer.start(),
v8::NewStringType::kNormal, buffer.length())
.ToLocalChecked();
}
v8::internal::Vector<uint16_t> ToVector(
const v8_inspector::StringView& string) {
v8::internal::Vector<uint16_t> buffer =
@ -64,180 +77,193 @@ v8::internal::Vector<uint16_t> ToVector(
return buffer;
}
class CreateContextGroupTask : public TaskRunner::Task {
class FrontendChannelImpl : public v8_inspector::V8Inspector::Channel {
public:
CreateContextGroupTask(v8::base::Semaphore* ready_semaphore,
int* context_group_id)
: ready_semaphore_(ready_semaphore),
context_group_id_(context_group_id) {}
virtual ~CreateContextGroupTask() = default;
bool is_inspector_task() final { return true; }
private:
void Run() override {
*context_group_id_ = data()->CreateContextGroup();
if (ready_semaphore_) ready_semaphore_->Signal();
}
v8::base::Semaphore* ready_semaphore_;
int* context_group_id_;
};
class ConnectSessionTask : public TaskRunner::Task {
public:
ConnectSessionTask(v8::base::Semaphore* ready_semaphore, int context_group_id,
const v8::internal::Vector<uint16_t>& state,
int* session_id)
: ready_semaphore_(ready_semaphore),
FrontendChannelImpl(TaskRunner* task_runner, int context_group_id,
v8::Isolate* isolate, v8::Local<v8::Function> function)
: task_runner_(task_runner),
context_group_id_(context_group_id),
state_(state),
session_id_(session_id) {}
virtual ~ConnectSessionTask() = default;
bool is_inspector_task() final { return true; }
function_(isolate, function) {}
virtual ~FrontendChannelImpl() = default;
void set_session_id(int session_id) { session_id_ = session_id; }
private:
void Run() override {
v8_inspector::StringView state(state_.start(), state_.length());
*session_id_ = data()->ConnectSession(context_group_id_, state);
if (ready_semaphore_) ready_semaphore_->Signal();
void sendResponse(
int callId,
std::unique_ptr<v8_inspector::StringBuffer> message) override {
task_runner_->Append(
new SendMessageTask(this, ToVector(message->string())));
}
void sendNotification(
std::unique_ptr<v8_inspector::StringBuffer> message) override {
task_runner_->Append(
new SendMessageTask(this, ToVector(message->string())));
}
void flushProtocolNotifications() override {}
v8::base::Semaphore* ready_semaphore_;
class SendMessageTask : public TaskRunner::Task {
public:
SendMessageTask(FrontendChannelImpl* channel,
const v8::internal::Vector<uint16_t>& message)
: channel_(channel), message_(message) {}
virtual ~SendMessageTask() {}
bool is_priority_task() final { return false; }
private:
void Run(IsolateData* data) override {
v8::MicrotasksScope microtasks_scope(data->isolate(),
v8::MicrotasksScope::kRunMicrotasks);
v8::HandleScope handle_scope(data->isolate());
v8::Local<v8::Context> context =
data->GetContext(channel_->context_group_id_);
v8::Context::Scope context_scope(context);
v8::Local<v8::Value> message = ToV8String(data->isolate(), message_);
v8::MaybeLocal<v8::Value> result;
result = channel_->function_.Get(data->isolate())
->Call(context, context->Global(), 1, &message);
}
FrontendChannelImpl* channel_;
v8::internal::Vector<uint16_t> message_;
};
TaskRunner* task_runner_;
int context_group_id_;
const v8::internal::Vector<uint16_t>& state_;
int* session_id_;
};
class DisconnectSessionTask : public TaskRunner::Task {
public:
DisconnectSessionTask(v8::base::Semaphore* ready_semaphore, int session_id,
v8::internal::Vector<uint16_t>* state)
: ready_semaphore_(ready_semaphore),
session_id_(session_id),
state_(state) {}
virtual ~DisconnectSessionTask() = default;
bool is_inspector_task() final { return true; }
private:
void Run() override {
std::unique_ptr<v8_inspector::StringBuffer> state =
data()->DisconnectSession(session_id_);
*state_ = ToVector(state->string());
if (ready_semaphore_) ready_semaphore_->Signal();
}
v8::base::Semaphore* ready_semaphore_;
v8::Global<v8::Function> function_;
int session_id_;
v8::internal::Vector<uint16_t>* state_;
DISALLOW_COPY_AND_ASSIGN(FrontendChannelImpl);
};
template <typename T>
void RunSyncTask(TaskRunner* task_runner, T callback) {
class SyncTask : public TaskRunner::Task {
public:
SyncTask(v8::base::Semaphore* ready_semaphore, T callback)
: ready_semaphore_(ready_semaphore), callback_(callback) {}
virtual ~SyncTask() = default;
bool is_priority_task() final { return true; }
private:
void Run(IsolateData* data) override {
callback_(data);
if (ready_semaphore_) ready_semaphore_->Signal();
}
v8::base::Semaphore* ready_semaphore_;
T callback_;
};
v8::base::Semaphore ready_semaphore(0);
task_runner->Append(new SyncTask(&ready_semaphore, callback));
ready_semaphore.Wait();
}
class SendMessageToBackendTask : public TaskRunner::Task {
public:
explicit SendMessageToBackendTask(
int session_id, const v8::internal::Vector<uint16_t>& message)
SendMessageToBackendTask(int session_id,
const v8::internal::Vector<uint16_t>& message)
: session_id_(session_id), message_(message) {}
bool is_inspector_task() final { return true; }
bool is_priority_task() final { return true; }
private:
void Run() override {
void Run(IsolateData* data) override {
v8_inspector::StringView message_view(message_.start(), message_.length());
data()->SendMessage(session_id_, message_view);
data->SendMessage(session_id_, message_view);
}
int session_id_;
v8::internal::Vector<uint16_t> message_;
};
class SchedulePauseOnNextStatementTask : public TaskRunner::Task {
void RunAsyncTask(TaskRunner* task_runner, const char* task_name,
TaskRunner::Task* task) {
class AsyncTask : public TaskRunner::Task {
public:
explicit AsyncTask(TaskRunner::Task* inner) : inner_(inner) {}
virtual ~AsyncTask() = default;
bool is_priority_task() override { return inner_->is_priority_task(); }
void Run(IsolateData* data) override {
data->AsyncTaskStarted(inner_.get());
inner_->Run(data);
data->AsyncTaskFinished(inner_.get());
}
private:
std::unique_ptr<TaskRunner::Task> inner_;
DISALLOW_COPY_AND_ASSIGN(AsyncTask);
};
task_runner->data()->AsyncTaskScheduled(
v8_inspector::StringView(reinterpret_cast<const uint8_t*>(task_name),
strlen(task_name)),
task, false);
task_runner->Append(new AsyncTask(task));
}
class ExecuteStringTask : public TaskRunner::Task {
public:
SchedulePauseOnNextStatementTask(
v8::base::Semaphore* ready_semaphore, int context_group_id,
const v8::internal::Vector<uint16_t>& reason,
const v8::internal::Vector<uint16_t>& details)
: ready_semaphore_(ready_semaphore),
context_group_id_(context_group_id),
reason_(reason),
details_(details) {}
virtual ~SchedulePauseOnNextStatementTask() = default;
bool is_inspector_task() final { return true; }
private:
void Run() override {
v8_inspector::StringView reason(reason_.start(), reason_.length());
v8_inspector::StringView details(details_.start(), details_.length());
data()->SchedulePauseOnNextStatement(context_group_id_, reason, details);
if (ready_semaphore_) ready_semaphore_->Signal();
}
v8::base::Semaphore* ready_semaphore_;
int context_group_id_;
const v8::internal::Vector<uint16_t>& reason_;
const v8::internal::Vector<uint16_t>& details_;
};
class CancelPauseOnNextStatementTask : public TaskRunner::Task {
public:
CancelPauseOnNextStatementTask(v8::base::Semaphore* ready_semaphore,
int context_group_id)
: ready_semaphore_(ready_semaphore),
ExecuteStringTask(int context_group_id,
const v8::internal::Vector<uint16_t>& expression,
v8::Local<v8::String> name,
v8::Local<v8::Integer> line_offset,
v8::Local<v8::Integer> column_offset,
v8::Local<v8::Boolean> is_module)
: expression_(expression),
name_(ToVector(name)),
line_offset_(line_offset.As<v8::Int32>()->Value()),
column_offset_(column_offset.As<v8::Int32>()->Value()),
is_module_(is_module->Value()),
context_group_id_(context_group_id) {}
virtual ~CancelPauseOnNextStatementTask() = default;
bool is_inspector_task() final { return true; }
private:
void Run() override {
data()->CancelPauseOnNextStatement(context_group_id_);
if (ready_semaphore_) ready_semaphore_->Signal();
}
v8::base::Semaphore* ready_semaphore_;
int context_group_id_;
};
class SendMessageToFrontendTask : public TaskRunner::Task {
public:
SendMessageToFrontendTask(int context_group_id, int session_id,
const v8::internal::Vector<uint16_t>& message)
: context_group_id_(context_group_id),
session_id_(session_id),
message_(message) {}
virtual ~SendMessageToFrontendTask() {}
bool is_inspector_task() final { return false; }
static void Register(int session_id, v8::Isolate* isolate,
v8::Local<v8::Function> dispatcher) {
dispatchers_[session_id].Reset(isolate, dispatcher);
}
static void Unregister(int session_id) { dispatchers_.erase(session_id); }
private:
void Run() override {
v8::MicrotasksScope microtasks_scope(isolate(),
ExecuteStringTask(const v8::internal::Vector<const char>& expression,
int context_group_id)
: expression_utf8_(expression), context_group_id_(context_group_id) {}
bool is_priority_task() override { return false; }
void Run(IsolateData* data) override {
v8::MicrotasksScope microtasks_scope(data->isolate(),
v8::MicrotasksScope::kRunMicrotasks);
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = data()->GetContext(context_group_id_);
v8::HandleScope handle_scope(data->isolate());
v8::Local<v8::Context> context = data->GetContext(context_group_id_);
v8::Context::Scope context_scope(context);
v8::ScriptOrigin origin(
ToV8String(data->isolate(), name_),
v8::Integer::New(data->isolate(), line_offset_),
v8::Integer::New(data->isolate(), column_offset_),
/* resource_is_shared_cross_origin */ v8::Local<v8::Boolean>(),
/* script_id */ v8::Local<v8::Integer>(),
/* source_map_url */ v8::Local<v8::Value>(),
/* resource_is_opaque */ v8::Local<v8::Boolean>(),
/* is_wasm */ v8::Local<v8::Boolean>(),
v8::Boolean::New(data->isolate(), is_module_));
v8::Local<v8::String> source;
if (expression_.length())
source = ToV8String(data->isolate(), expression_);
else
source = ToV8String(data->isolate(), expression_utf8_.start(),
expression_utf8_.length());
if (dispatchers_.find(session_id_) == dispatchers_.end()) return;
v8::Local<v8::Function> function = dispatchers_[session_id_].Get(isolate());
v8::Local<v8::Value> message =
v8::String::NewFromTwoByte(isolate(), message_.start(),
v8::NewStringType::kNormal,
static_cast<int>(message_.size()))
.ToLocalChecked();
v8::MaybeLocal<v8::Value> result;
result = function->Call(context, context->Global(), 1, &message);
v8::ScriptCompiler::Source scriptSource(source, origin);
if (!is_module_) {
v8::Local<v8::Script> script;
if (!v8::ScriptCompiler::Compile(context, &scriptSource).ToLocal(&script))
return;
v8::MaybeLocal<v8::Value> result;
result = script->Run(context);
} else {
data->RegisterModule(context, name_, &scriptSource);
}
}
static std::map<int, v8::Global<v8::Function>> dispatchers_;
private:
v8::internal::Vector<uint16_t> expression_;
v8::internal::Vector<const char> expression_utf8_;
v8::internal::Vector<uint16_t> name_;
int32_t line_offset_ = 0;
int32_t column_offset_ = 0;
bool is_module_ = false;
int context_group_id_;
int session_id_;
v8::internal::Vector<uint16_t> message_;
};
std::map<int, v8::Global<v8::Function>> SendMessageToFrontendTask::dispatchers_;
DISALLOW_COPY_AND_ASSIGN(ExecuteStringTask);
};
class UtilsExtension : public IsolateData::SetupGlobalTask {
public:
@ -346,10 +372,7 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
std::string filename(*str, str.length());
*chars = v8::internal::ReadFile(filename.c_str(), &exists);
if (!exists) {
isolate->ThrowException(
v8::String::NewFromUtf8(isolate, "Error reading file",
v8::NewStringType::kNormal)
.ToLocalChecked());
isolate->ThrowException(ToV8String(isolate, "Error reading file"));
return false;
}
return true;
@ -362,12 +385,8 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
}
v8::internal::Vector<const char> chars;
v8::Isolate* isolate = args.GetIsolate();
if (ReadFile(isolate, args[0], &chars)) {
args.GetReturnValue().Set(
v8::String::NewFromUtf8(isolate, chars.start(),
v8::NewStringType::kNormal, chars.length())
.ToLocalChecked());
}
if (ReadFile(isolate, args[0], &chars))
args.GetReturnValue().Set(ToV8String(isolate, chars.start()));
}
static void Load(const v8::FunctionCallbackInfo<v8::Value>& args) {
@ -381,7 +400,7 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
IsolateData* data = IsolateData::FromContext(context);
int context_group_id = data->GetContextGroupId(context);
if (ReadFile(isolate, args[0], &chars)) {
ExecuteStringTask(chars, context_group_id).RunOnIsolate(data);
ExecuteStringTask(chars, context_group_id).Run(data);
}
}
@ -398,10 +417,9 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
}
backend_runner_->Append(new ExecuteStringTask(
nullptr, args[0].As<v8::Int32>()->Value(), nullptr,
ToVector(args[1].As<v8::String>()), args[2].As<v8::String>(),
args[3].As<v8::Int32>(), args[4].As<v8::Int32>(),
args[5].As<v8::Boolean>()));
args[0].As<v8::Int32>()->Value(), ToVector(args[1].As<v8::String>()),
args[2].As<v8::String>(), args[3].As<v8::Int32>(),
args[4].As<v8::Int32>(), args[5].As<v8::Boolean>()));
}
static void SetCurrentTimeMSForTest(
@ -434,10 +452,14 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
}
v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>());
v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>());
v8::base::Semaphore ready_semaphore(0);
backend_runner_->Append(new SchedulePauseOnNextStatementTask(
&ready_semaphore, args[0].As<v8::Int32>()->Value(), reason, details));
ready_semaphore.Wait();
int context_group_id = args[0].As<v8::Int32>()->Value();
RunSyncTask(backend_runner_, [&context_group_id, &reason,
&details](IsolateData* data) {
data->SchedulePauseOnNextStatement(
context_group_id,
v8_inspector::StringView(reason.start(), reason.length()),
v8_inspector::StringView(details.start(), details.length()));
});
}
static void CancelPauseOnNextStatement(
@ -447,10 +469,10 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
"Internal error: cancelPauseOnNextStatement(context_group_id).");
Exit();
}
v8::base::Semaphore ready_semaphore(0);
backend_runner_->Append(new CancelPauseOnNextStatementTask(
&ready_semaphore, args[0].As<v8::Int32>()->Value()));
ready_semaphore.Wait();
int context_group_id = args[0].As<v8::Int32>()->Value();
RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) {
data->CancelPauseOnNextStatement(context_group_id);
});
}
static void SetLogConsoleApiMessageCalls(
@ -469,11 +491,10 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
fprintf(stderr, "Internal error: createContextGroup().");
Exit();
}
v8::base::Semaphore ready_semaphore(0);
int context_group_id = 0;
backend_runner_->Append(
new CreateContextGroupTask(&ready_semaphore, &context_group_id));
ready_semaphore.Wait();
RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) {
context_group_id = data->CreateContextGroup();
});
args.GetReturnValue().Set(
v8::Int32::New(args.GetIsolate(), context_group_id));
}
@ -486,15 +507,24 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
"dispatch).");
Exit();
}
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
FrontendChannelImpl* channel = new FrontendChannelImpl(
IsolateData::FromContext(context)->task_runner(),
IsolateData::FromContext(context)->GetContextGroupId(context),
args.GetIsolate(), args[2].As<v8::Function>());
v8::internal::Vector<uint16_t> state = ToVector(args[1].As<v8::String>());
v8::base::Semaphore ready_semaphore(0);
int context_group_id = args[0].As<v8::Int32>()->Value();
int session_id = 0;
backend_runner_->Append(new ConnectSessionTask(
&ready_semaphore, args[0].As<v8::Int32>()->Value(), state,
&session_id));
ready_semaphore.Wait();
SendMessageToFrontendTask::Register(session_id, args.GetIsolate(),
args[2].As<v8::Function>());
RunSyncTask(backend_runner_, [&context_group_id, &session_id, &channel,
&state](IsolateData* data) {
session_id = data->ConnectSession(
context_group_id,
v8_inspector::StringView(state.start(), state.length()), channel);
channel->set_session_id(session_id);
});
channels_[session_id].reset(channel);
args.GetReturnValue().Set(v8::Int32::New(args.GetIsolate(), session_id));
}
@ -505,17 +535,12 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
Exit();
}
int session_id = args[0].As<v8::Int32>()->Value();
SendMessageToFrontendTask::Unregister(session_id);
v8::base::Semaphore ready_semaphore(0);
v8::internal::Vector<uint16_t> state;
backend_runner_->Append(
new DisconnectSessionTask(&ready_semaphore, session_id, &state));
ready_semaphore.Wait();
args.GetReturnValue().Set(
v8::String::NewFromTwoByte(args.GetIsolate(), state.start(),
v8::NewStringType::kNormal,
static_cast<int>(state.size()))
.ToLocalChecked());
RunSyncTask(backend_runner_, [&session_id, &state](IsolateData* data) {
state = ToVector(data->DisconnectSession(session_id)->string());
});
channels_.erase(session_id);
args.GetReturnValue().Set(ToV8String(args.GetIsolate(), state));
}
static void SendMessageToBackend(
@ -528,30 +553,30 @@ class UtilsExtension : public IsolateData::SetupGlobalTask {
backend_runner_->Append(new SendMessageToBackendTask(
args[0].As<v8::Int32>()->Value(), ToVector(args[1].As<v8::String>())));
}
static std::map<int, std::unique_ptr<FrontendChannelImpl>> channels_;
};
TaskRunner* UtilsExtension::backend_runner_ = nullptr;
std::map<int, std::unique_ptr<FrontendChannelImpl>> UtilsExtension::channels_;
class SetTimeoutTask : public AsyncTask {
class SetTimeoutTask : public TaskRunner::Task {
public:
SetTimeoutTask(IsolateData* data, int context_group_id, const char* task_name,
SetTimeoutTask(int context_group_id, v8::Isolate* isolate,
v8::Local<v8::Function> function)
: AsyncTask(data, task_name),
function_(data->isolate(), function),
context_group_id_(context_group_id) {}
: function_(isolate, function), context_group_id_(context_group_id) {}
virtual ~SetTimeoutTask() {}
bool is_inspector_task() final { return false; }
bool is_priority_task() final { return false; }
private:
void AsyncRun() override {
v8::MicrotasksScope microtasks_scope(isolate(),
void Run(IsolateData* data) override {
v8::MicrotasksScope microtasks_scope(data->isolate(),
v8::MicrotasksScope::kRunMicrotasks);
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = data()->GetContext(context_group_id_);
v8::HandleScope handle_scope(data->isolate());
v8::Local<v8::Context> context = data->GetContext(context_group_id_);
v8::Context::Scope context_scope(context);
v8::Local<v8::Function> function = function_.Get(isolate());
v8::Local<v8::Function> function = function_.Get(data->isolate());
v8::MaybeLocal<v8::Value> result;
result = function->Call(context, context->Global(), 0, nullptr);
}
@ -583,18 +608,18 @@ class SetTimeoutExtension : public IsolateData::SetupGlobalTask {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
IsolateData* data = IsolateData::FromContext(context);
int context_group_id = data->GetContextGroupId(context);
std::unique_ptr<TaskRunner::Task> task;
if (args[0]->IsFunction()) {
task.reset(new SetTimeoutTask(data, context_group_id, "setTimeout",
v8::Local<v8::Function>::Cast(args[0])));
RunAsyncTask(data->task_runner(), "setTimeout",
new SetTimeoutTask(context_group_id, isolate,
v8::Local<v8::Function>::Cast(args[0])));
} else {
task.reset(new ExecuteStringTask(
data, context_group_id, "setTimeout",
ToVector(args[0].As<v8::String>()), v8::String::Empty(isolate),
v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0),
v8::Boolean::New(isolate, false)));
RunAsyncTask(
data->task_runner(), "setTimeout",
new ExecuteStringTask(
context_group_id, ToVector(args[0].As<v8::String>()),
v8::String::Empty(isolate), v8::Integer::New(isolate, 0),
v8::Integer::New(isolate, 0), v8::Boolean::New(isolate, false)));
}
data->task_runner()->Append(task.release());
}
};
@ -661,10 +686,8 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
fprintf(stderr, "Internal error: setMaxAsyncTaskStacks(max).");
Exit();
}
v8_inspector::SetMaxAsyncTaskStacksForTest(
IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
->inspector(),
args[0].As<v8::Int32>()->Value());
IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
->SetMaxAsyncTaskStacksForTest(args[0].As<v8::Int32>()->Value());
}
static void DumpAsyncTaskStacksStateForTest(
@ -673,9 +696,8 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
fprintf(stderr, "Internal error: dumpAsyncTaskStacksStateForTest().");
Exit();
}
v8_inspector::DumpAsyncTaskStacksStateForTest(
IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
->inspector());
IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
->DumpAsyncTaskStacksStateForTest();
}
static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) {
@ -739,9 +761,7 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
v8::Local<v8::Object> object = args[0].As<v8::Object>();
v8::Isolate* isolate = args.GetIsolate();
v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi(
isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting",
v8::NewStringType::kNormal)
.ToLocalChecked());
isolate, ToV8String(isolate, "allowAccessorFormatting"));
object
->SetPrivate(isolate->GetCurrentContext(), shouldFormatAccessorsPrivate,
v8::Null(isolate))
@ -749,24 +769,6 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
}
};
class FrontendChannelImpl : public IsolateData::FrontendChannel {
public:
FrontendChannelImpl(TaskRunner* frontend_task_runner, int context_group_id)
: frontend_task_runner_(frontend_task_runner),
context_group_id_(context_group_id) {}
virtual ~FrontendChannelImpl() {}
void SendMessageToFrontend(int session_id,
const v8_inspector::StringView& message) final {
frontend_task_runner_->Append(new SendMessageToFrontendTask(
context_group_id_, session_id, ToVector(message)));
}
private:
TaskRunner* frontend_task_runner_;
int context_group_id_;
};
} // namespace
int main(int argc, char* argv[]) {
@ -792,22 +794,21 @@ int main(int argc, char* argv[]) {
IsolateData::SetupGlobalTasks frontend_extensions;
frontend_extensions.emplace_back(new UtilsExtension());
TaskRunner frontend_runner(std::move(frontend_extensions), true,
&ready_semaphore, nullptr, nullptr);
&ready_semaphore, nullptr, false);
ready_semaphore.Wait();
int frontend_context_group_id = 0;
frontend_runner.Append(
new CreateContextGroupTask(&ready_semaphore, &frontend_context_group_id));
ready_semaphore.Wait();
RunSyncTask(&frontend_runner,
[&frontend_context_group_id](IsolateData* data) {
frontend_context_group_id = data->CreateContextGroup();
});
IsolateData::SetupGlobalTasks backend_extensions;
backend_extensions.emplace_back(new SetTimeoutExtension());
backend_extensions.emplace_back(new InspectorExtension());
FrontendChannelImpl frontend_channel(&frontend_runner,
frontend_context_group_id);
TaskRunner backend_runner(
std::move(backend_extensions), false, &ready_semaphore,
startup_data.data ? &startup_data : nullptr, &frontend_channel);
TaskRunner backend_runner(std::move(backend_extensions), false,
&ready_semaphore,
startup_data.data ? &startup_data : nullptr, true);
ready_semaphore.Wait();
UtilsExtension::set_backend_task_runner(&backend_runner);

View File

@ -4,6 +4,7 @@
#include "test/inspector/isolate-data.h"
#include "src/inspector/test-interface.h"
#include "test/inspector/task-runner.h"
namespace {
@ -38,45 +39,20 @@ void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) {
fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout);
}
class ChannelImpl final : public v8_inspector::V8Inspector::Channel {
public:
ChannelImpl(IsolateData::FrontendChannel* frontend_channel, int session_id)
: frontend_channel_(frontend_channel), session_id_(session_id) {}
virtual ~ChannelImpl() = default;
private:
void sendResponse(
int callId,
std::unique_ptr<v8_inspector::StringBuffer> message) override {
frontend_channel_->SendMessageToFrontend(session_id_, message->string());
}
void sendNotification(
std::unique_ptr<v8_inspector::StringBuffer> message) override {
frontend_channel_->SendMessageToFrontend(session_id_, message->string());
}
void flushProtocolNotifications() override {}
IsolateData::FrontendChannel* frontend_channel_;
int session_id_;
DISALLOW_COPY_AND_ASSIGN(ChannelImpl);
};
} // namespace
IsolateData::IsolateData(TaskRunner* task_runner,
IsolateData::SetupGlobalTasks setup_global_tasks,
v8::StartupData* startup_data,
FrontendChannel* channel)
v8::StartupData* startup_data, bool with_inspector)
: task_runner_(task_runner),
setup_global_tasks_(std::move(setup_global_tasks)),
frontend_channel_(channel) {
setup_global_tasks_(std::move(setup_global_tasks)) {
v8::Isolate::CreateParams params;
params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
params.snapshot_blob = startup_data;
isolate_ = v8::Isolate::New(params);
isolate_->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
if (frontend_channel_) {
if (with_inspector) {
isolate_->AddMessageListener(&IsolateData::MessageHandler);
inspector_ = v8_inspector::V8Inspector::create(isolate_, this);
}
@ -141,11 +117,10 @@ v8::MaybeLocal<v8::Module> IsolateData::ModuleResolveCallback(
}
int IsolateData::ConnectSession(int context_group_id,
const v8_inspector::StringView& state) {
const v8_inspector::StringView& state,
v8_inspector::V8Inspector::Channel* channel) {
int session_id = ++last_session_id_;
channels_[session_id].reset(new ChannelImpl(frontend_channel_, session_id));
sessions_[session_id] =
inspector_->connect(context_group_id, channels_[session_id].get(), state);
sessions_[session_id] = inspector_->connect(context_group_id, channel, state);
context_group_by_session_[sessions_[session_id].get()] = context_group_id;
return session_id;
}
@ -157,7 +132,6 @@ std::unique_ptr<v8_inspector::StringBuffer> IsolateData::DisconnectSession(
context_group_by_session_.erase(it->second.get());
std::unique_ptr<v8_inspector::StringBuffer> result = it->second->stateJSON();
sessions_.erase(it);
channels_.erase(session_id);
return result;
}
@ -193,6 +167,27 @@ void IsolateData::CancelPauseOnNextStatement(int context_group_id) {
}
}
void IsolateData::AsyncTaskScheduled(const v8_inspector::StringView& name,
void* task, bool recurring) {
inspector_->asyncTaskScheduled(name, task, recurring);
}
void IsolateData::AsyncTaskStarted(void* task) {
inspector_->asyncTaskStarted(task);
}
void IsolateData::AsyncTaskFinished(void* task) {
inspector_->asyncTaskFinished(task);
}
void IsolateData::SetMaxAsyncTaskStacksForTest(int limit) {
v8_inspector::SetMaxAsyncTaskStacksForTest(inspector_.get(), limit);
}
void IsolateData::DumpAsyncTaskStacksStateForTest() {
v8_inspector::DumpAsyncTaskStacksStateForTest(inspector_.get());
}
// static
void IsolateData::MessageHandler(v8::Local<v8::Message> message,
v8::Local<v8::Value> exception) {

View File

@ -26,19 +26,11 @@ class IsolateData : public v8_inspector::V8InspectorClient {
};
using SetupGlobalTasks = std::vector<std::unique_ptr<SetupGlobalTask>>;
class FrontendChannel {
public:
virtual ~FrontendChannel() = default;
virtual void SendMessageToFrontend(
int session_id, const v8_inspector::StringView& message) = 0;
};
IsolateData(TaskRunner* task_runner, SetupGlobalTasks setup_global_tasks,
v8::StartupData* startup_data, FrontendChannel* channel);
v8::StartupData* startup_data, bool with_inspector);
static IsolateData* FromContext(v8::Local<v8::Context> context);
v8::Isolate* isolate() const { return isolate_; }
v8_inspector::V8Inspector* inspector() const { return inspector_.get(); }
TaskRunner* task_runner() const { return task_runner_; }
// Setting things up.
@ -51,7 +43,8 @@ class IsolateData : public v8_inspector::V8InspectorClient {
// Working with V8Inspector api.
int ConnectSession(int context_group_id,
const v8_inspector::StringView& state);
const v8_inspector::StringView& state,
v8_inspector::V8Inspector::Channel* channel);
std::unique_ptr<v8_inspector::StringBuffer> DisconnectSession(int session_id);
void SendMessage(int session_id, const v8_inspector::StringView& message);
void BreakProgram(int context_group_id,
@ -61,11 +54,17 @@ class IsolateData : public v8_inspector::V8InspectorClient {
const v8_inspector::StringView& reason,
const v8_inspector::StringView& details);
void CancelPauseOnNextStatement(int context_group_id);
void AsyncTaskScheduled(const v8_inspector::StringView& name, void* task,
bool recurring);
void AsyncTaskStarted(void* task);
void AsyncTaskFinished(void* task);
// Test utilities.
void SetCurrentTimeMS(double time);
void SetMemoryInfo(v8::Local<v8::Value> memory_info);
void SetLogConsoleApiMessageCalls(bool log);
void SetMaxAsyncTaskStacksForTest(int limit);
void DumpAsyncTaskStacksStateForTest();
void FireContextCreated(v8::Local<v8::Context> context, int context_group_id);
void FireContextDestroyed(v8::Local<v8::Context> context);
@ -114,9 +113,7 @@ class IsolateData : public v8_inspector::V8InspectorClient {
int last_session_id_ = 0;
std::map<int, std::unique_ptr<v8_inspector::V8InspectorSession>> sessions_;
std::map<v8_inspector::V8InspectorSession*, int> context_group_by_session_;
std::map<int, std::unique_ptr<v8_inspector::V8Inspector::Channel>> channels_;
v8::Global<v8::Value> memory_info_;
FrontendChannel* frontend_channel_;
bool current_time_set_ = false;
double current_time_ = 0.0;
bool log_console_api_message_calls_ = false;

View File

@ -26,24 +26,16 @@ void ReportUncaughtException(v8::Isolate* isolate,
source_line.data(), line);
}
v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) {
v8::internal::Vector<uint16_t> buffer =
v8::internal::Vector<uint16_t>::New(str->Length());
str->Write(buffer.start(), 0, str->Length());
return buffer;
}
} // namespace
TaskRunner::TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks,
bool catch_exceptions,
v8::base::Semaphore* ready_semaphore,
v8::StartupData* startup_data,
IsolateData::FrontendChannel* channel)
v8::StartupData* startup_data, bool with_inspector)
: Thread(Options("Task Runner")),
setup_global_tasks_(std::move(setup_global_tasks)),
startup_data_(startup_data),
channel_(channel),
with_inspector_(with_inspector),
catch_exceptions_(catch_exceptions),
ready_semaphore_(ready_semaphore),
data_(nullptr),
@ -56,7 +48,7 @@ TaskRunner::~TaskRunner() { Join(); }
void TaskRunner::Run() {
data_.reset(new IsolateData(this, std::move(setup_global_tasks_),
startup_data_, channel_));
startup_data_, with_inspector_));
if (ready_semaphore_) ready_semaphore_->Signal();
RunMessageLoop(false);
}
@ -69,7 +61,7 @@ void TaskRunner::RunMessageLoop(bool only_protocol) {
v8::Isolate::Scope isolate_scope(isolate());
if (catch_exceptions_) {
v8::TryCatch try_catch(isolate());
task->RunOnIsolate(data_.get());
task->Run(data_.get());
delete task;
if (try_catch.HasCaught()) {
ReportUncaughtException(isolate(), try_catch);
@ -78,7 +70,7 @@ void TaskRunner::RunMessageLoop(bool only_protocol) {
_exit(0);
}
} else {
task->RunOnIsolate(data_.get());
task->Run(data_.get());
delete task;
}
}
@ -105,7 +97,7 @@ TaskRunner::Task* TaskRunner::GetNext(bool only_protocol) {
if (only_protocol) {
Task* task = nullptr;
if (queue_.Dequeue(&task)) {
if (task->is_inspector_task()) return task;
if (task->is_priority_task()) return task;
deffered_queue_.Enqueue(task);
}
} else {
@ -117,86 +109,3 @@ TaskRunner::Task* TaskRunner::GetNext(bool only_protocol) {
}
return nullptr;
}
AsyncTask::AsyncTask(IsolateData* data, const char* task_name)
: instrumenting_(data && task_name) {
if (!instrumenting_) return;
data->inspector()->asyncTaskScheduled(
v8_inspector::StringView(reinterpret_cast<const uint8_t*>(task_name),
strlen(task_name)),
this, false);
}
void AsyncTask::Run() {
if (instrumenting_) data()->inspector()->asyncTaskStarted(this);
AsyncRun();
if (instrumenting_) data()->inspector()->asyncTaskFinished(this);
}
ExecuteStringTask::ExecuteStringTask(
IsolateData* data, int context_group_id, const char* task_name,
const v8::internal::Vector<uint16_t>& expression,
v8::Local<v8::String> name, v8::Local<v8::Integer> line_offset,
v8::Local<v8::Integer> column_offset, v8::Local<v8::Boolean> is_module)
: AsyncTask(data, task_name),
expression_(expression),
name_(ToVector(name)),
line_offset_(line_offset.As<v8::Int32>()->Value()),
column_offset_(column_offset.As<v8::Int32>()->Value()),
is_module_(is_module->Value()),
context_group_id_(context_group_id) {}
ExecuteStringTask::ExecuteStringTask(
const v8::internal::Vector<const char>& expression, int context_group_id)
: AsyncTask(nullptr, nullptr),
expression_utf8_(expression),
context_group_id_(context_group_id) {}
void ExecuteStringTask::AsyncRun() {
v8::MicrotasksScope microtasks_scope(isolate(),
v8::MicrotasksScope::kRunMicrotasks);
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Context> context = data()->GetContext(context_group_id_);
v8::Context::Scope context_scope(context);
v8::Local<v8::String> name =
v8::String::NewFromTwoByte(isolate(), name_.start(),
v8::NewStringType::kNormal, name_.length())
.ToLocalChecked();
v8::Local<v8::Integer> line_offset =
v8::Integer::New(isolate(), line_offset_);
v8::Local<v8::Integer> column_offset =
v8::Integer::New(isolate(), column_offset_);
v8::ScriptOrigin origin(
name, line_offset, column_offset,
/* resource_is_shared_cross_origin */ v8::Local<v8::Boolean>(),
/* script_id */ v8::Local<v8::Integer>(),
/* source_map_url */ v8::Local<v8::Value>(),
/* resource_is_opaque */ v8::Local<v8::Boolean>(),
/* is_wasm */ v8::Local<v8::Boolean>(),
v8::Boolean::New(isolate(), is_module_));
v8::Local<v8::String> source;
if (expression_.length()) {
source = v8::String::NewFromTwoByte(isolate(), expression_.start(),
v8::NewStringType::kNormal,
expression_.length())
.ToLocalChecked();
} else {
source = v8::String::NewFromUtf8(isolate(), expression_utf8_.start(),
v8::NewStringType::kNormal,
expression_utf8_.length())
.ToLocalChecked();
}
v8::ScriptCompiler::Source scriptSource(source, origin);
if (!is_module_) {
v8::Local<v8::Script> script;
if (!v8::ScriptCompiler::Compile(context, &scriptSource).ToLocal(&script))
return;
v8::MaybeLocal<v8::Value> result;
result = script->Run(context);
} else {
data()->RegisterModule(context, name_, &scriptSource);
}
}

View File

@ -22,26 +22,13 @@ class TaskRunner : public v8::base::Thread {
class Task {
public:
virtual ~Task() {}
virtual bool is_inspector_task() = 0;
void RunOnIsolate(IsolateData* data) {
data_ = data;
Run();
data_ = nullptr;
}
protected:
virtual void Run() = 0;
v8::Isolate* isolate() const { return data_->isolate(); }
IsolateData* data() const { return data_; }
private:
IsolateData* data_ = nullptr;
virtual bool is_priority_task() = 0;
virtual void Run(IsolateData* data) = 0;
};
TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks,
bool catch_exceptions, v8::base::Semaphore* ready_semaphore,
v8::StartupData* startup_data,
IsolateData::FrontendChannel* channel);
v8::StartupData* startup_data, bool with_inspector);
virtual ~TaskRunner();
IsolateData* data() const { return data_.get(); }
@ -63,7 +50,7 @@ class TaskRunner : public v8::base::Thread {
IsolateData::SetupGlobalTasks setup_global_tasks_;
v8::StartupData* startup_data_;
IsolateData::FrontendChannel* channel_;
bool with_inspector_;
bool catch_exceptions_;
v8::base::Semaphore* ready_semaphore_;
std::unique_ptr<IsolateData> data_;
@ -82,43 +69,4 @@ class TaskRunner : public v8::base::Thread {
DISALLOW_COPY_AND_ASSIGN(TaskRunner);
};
class AsyncTask : public TaskRunner::Task {
public:
AsyncTask(IsolateData* data, const char* task_name);
virtual ~AsyncTask() = default;
protected:
virtual void AsyncRun() = 0;
void Run() override;
bool instrumenting_;
};
class ExecuteStringTask : public AsyncTask {
public:
ExecuteStringTask(IsolateData* data, int context_group_id,
const char* task_name,
const v8::internal::Vector<uint16_t>& expression,
v8::Local<v8::String> name,
v8::Local<v8::Integer> line_offset,
v8::Local<v8::Integer> column_offset,
v8::Local<v8::Boolean> is_module);
ExecuteStringTask(const v8::internal::Vector<const char>& expression,
int context_group_id);
bool is_inspector_task() override { return false; }
private:
void AsyncRun() override;
v8::internal::Vector<uint16_t> expression_;
v8::internal::Vector<const char> expression_utf8_;
v8::internal::Vector<uint16_t> name_;
int32_t line_offset_ = 0;
int32_t column_offset_ = 0;
bool is_module_ = false;
int context_group_id_;
DISALLOW_COPY_AND_ASSIGN(ExecuteStringTask);
};
#endif // V8_TEST_INSPECTOR_PROTOCOL_TASK_RUNNER_H_