summaryrefslogtreecommitdiff
path: root/deps/v8/test/inspector/inspector-test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/inspector/inspector-test.cc')
-rw-r--r--deps/v8/test/inspector/inspector-test.cc814
1 files changed, 467 insertions, 347 deletions
diff --git a/deps/v8/test/inspector/inspector-test.cc b/deps/v8/test/inspector/inspector-test.cc
index b2dd6474bf..2e105c54d9 100644
--- a/deps/v8/test/inspector/inspector-test.cc
+++ b/deps/v8/test/inspector/inspector-test.cc
@@ -46,125 +46,256 @@ v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) {
return buffer;
}
-class UtilsExtension : public v8::Extension {
+v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str) {
+ return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal)
+ .ToLocalChecked();
+}
+
+v8::internal::Vector<uint16_t> ToVector(
+ const v8_inspector::StringView& string) {
+ v8::internal::Vector<uint16_t> buffer =
+ v8::internal::Vector<uint16_t>::New(static_cast<int>(string.length()));
+ for (size_t i = 0; i < string.length(); i++) {
+ if (string.is8Bit())
+ buffer[i] = string.characters8()[i];
+ else
+ buffer[i] = string.characters16()[i];
+ }
+ return buffer;
+}
+
+class CreateContextGroupTask : public TaskRunner::Task {
public:
- UtilsExtension()
- : v8::Extension("v8_inspector/utils",
- "native function print();"
- "native function quit();"
- "native function setlocale();"
- "native function read();"
- "native function load();"
- "native function compileAndRunWithOrigin();"
- "native function setCurrentTimeMSForTest();"
- "native function setMemoryInfoForTest();"
- "native function schedulePauseOnNextStatement();"
- "native function cancelPauseOnNextStatement();"
- "native function reconnect();"
- "native function disconnect();"
- "native function createContextGroup();") {}
- virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
- v8::Isolate* isolate, v8::Local<v8::String> name) {
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "print", v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, UtilsExtension::Print);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "quit",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, UtilsExtension::Quit);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "setlocale",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, UtilsExtension::SetLocale);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "read",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, UtilsExtension::Read);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "load",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, UtilsExtension::Load);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "compileAndRunWithOrigin",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate,
- UtilsExtension::CompileAndRunWithOrigin);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "setCurrentTimeMSForTest",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate,
- UtilsExtension::SetCurrentTimeMSForTest);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "setMemoryInfoForTest",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate,
- UtilsExtension::SetMemoryInfoForTest);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(
- isolate, "schedulePauseOnNextStatement",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(
- isolate, UtilsExtension::SchedulePauseOnNextStatement);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "cancelPauseOnNextStatement",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(
- isolate, UtilsExtension::CancelPauseOnNextStatement);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "reconnect",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, UtilsExtension::Reconnect);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "disconnect",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, UtilsExtension::Disconnect);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "createContextGroup",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate,
- UtilsExtension::CreateContextGroup);
- }
- return v8::Local<v8::FunctionTemplate>();
+ 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();
}
- static void set_backend_task_runner(TaskRunner* runner) {
- backend_runner_ = runner;
+ 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),
+ context_group_id_(context_group_id),
+ state_(state),
+ session_id_(session_id) {}
+ virtual ~ConnectSessionTask() = default;
+ bool is_inspector_task() final { return true; }
+
+ private:
+ void Run() override {
+ v8_inspector::StringView state(state_.start(), state_.length());
+ *session_id_ =
+ data()->inspector()->ConnectSession(context_group_id_, state);
+ if (ready_semaphore_) ready_semaphore_->Signal();
+ }
+
+ v8::base::Semaphore* ready_semaphore_;
+ 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()->inspector()->DisconnectSession(session_id_);
+ *state_ = ToVector(state->string());
+ if (ready_semaphore_) ready_semaphore_->Signal();
+ }
+
+ v8::base::Semaphore* ready_semaphore_;
+ int session_id_;
+ v8::internal::Vector<uint16_t>* state_;
+};
+
+class SendMessageToBackendTask : public TaskRunner::Task {
+ public:
+ explicit SendMessageToBackendTask(
+ int session_id, const v8::internal::Vector<uint16_t>& message)
+ : session_id_(session_id), message_(message) {}
+ bool is_inspector_task() final { return true; }
+
+ private:
+ void Run() override {
+ v8_inspector::StringView message_view(message_.start(), message_.length());
+ data()->inspector()->SendMessage(session_id_, message_view);
+ }
+
+ int session_id_;
+ v8::internal::Vector<uint16_t> message_;
+};
+
+class SchedulePauseOnNextStatementTask : 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()->inspector()->SchedulePauseOnNextStatement(context_group_id_, reason,
+ details);
+ if (ready_semaphore_) ready_semaphore_->Signal();
}
- static void set_inspector_client(InspectorClientImpl* client) {
- inspector_client_ = client;
+ 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),
+ context_group_id_(context_group_id) {}
+ virtual ~CancelPauseOnNextStatementTask() = default;
+ bool is_inspector_task() final { return true; }
+
+ private:
+ void Run() override {
+ data()->inspector()->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(),
+ v8::MicrotasksScope::kRunMicrotasks);
+ v8::HandleScope handle_scope(isolate());
+ v8::Local<v8::Context> context = data()->GetContext(context_group_id_);
+ v8::Context::Scope context_scope(context);
+
+ 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);
+ }
+
+ static std::map<int, v8::Global<v8::Function>> dispatchers_;
+ int context_group_id_;
+ int session_id_;
+ v8::internal::Vector<uint16_t> message_;
+};
+
+std::map<int, v8::Global<v8::Function>> SendMessageToFrontendTask::dispatchers_;
+
+class UtilsExtension : public IsolateData::SetupGlobalTask {
+ public:
+ ~UtilsExtension() override = default;
+ void Run(v8::Isolate* isolate,
+ v8::Local<v8::ObjectTemplate> global) override {
+ v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate);
+ utils->Set(ToV8String(isolate, "print"),
+ v8::FunctionTemplate::New(isolate, &UtilsExtension::Print));
+ utils->Set(ToV8String(isolate, "quit"),
+ v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit));
+ utils->Set(ToV8String(isolate, "setlocale"),
+ v8::FunctionTemplate::New(isolate, &UtilsExtension::Setlocale));
+ utils->Set(ToV8String(isolate, "read"),
+ v8::FunctionTemplate::New(isolate, &UtilsExtension::Read));
+ utils->Set(ToV8String(isolate, "load"),
+ v8::FunctionTemplate::New(isolate, &UtilsExtension::Load));
+ utils->Set(ToV8String(isolate, "compileAndRunWithOrigin"),
+ v8::FunctionTemplate::New(
+ isolate, &UtilsExtension::CompileAndRunWithOrigin));
+ utils->Set(ToV8String(isolate, "setCurrentTimeMSForTest"),
+ v8::FunctionTemplate::New(
+ isolate, &UtilsExtension::SetCurrentTimeMSForTest));
+ utils->Set(ToV8String(isolate, "setMemoryInfoForTest"),
+ v8::FunctionTemplate::New(
+ isolate, &UtilsExtension::SetMemoryInfoForTest));
+ utils->Set(ToV8String(isolate, "schedulePauseOnNextStatement"),
+ v8::FunctionTemplate::New(
+ isolate, &UtilsExtension::SchedulePauseOnNextStatement));
+ utils->Set(ToV8String(isolate, "cancelPauseOnNextStatement"),
+ v8::FunctionTemplate::New(
+ isolate, &UtilsExtension::CancelPauseOnNextStatement));
+ utils->Set(ToV8String(isolate, "setLogConsoleApiMessageCalls"),
+ v8::FunctionTemplate::New(
+ isolate, &UtilsExtension::SetLogConsoleApiMessageCalls));
+ utils->Set(ToV8String(isolate, "createContextGroup"),
+ v8::FunctionTemplate::New(isolate,
+ &UtilsExtension::CreateContextGroup));
+ utils->Set(
+ ToV8String(isolate, "connectSession"),
+ v8::FunctionTemplate::New(isolate, &UtilsExtension::ConnectSession));
+ utils->Set(
+ ToV8String(isolate, "disconnectSession"),
+ v8::FunctionTemplate::New(isolate, &UtilsExtension::DisconnectSession));
+ utils->Set(ToV8String(isolate, "sendMessageToBackend"),
+ v8::FunctionTemplate::New(
+ isolate, &UtilsExtension::SendMessageToBackend));
+ global->Set(ToV8String(isolate, "utils"), utils);
+ }
+
+ static void set_backend_task_runner(TaskRunner* runner) {
+ backend_runner_ = runner;
}
private:
static TaskRunner* backend_runner_;
- static InspectorClientImpl* inspector_client_;
static void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
for (int i = 0; i < args.Length(); i++) {
@@ -201,7 +332,7 @@ class UtilsExtension : public v8::Extension {
static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args) { Exit(); }
- static void SetLocale(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ static void Setlocale(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1 || !args[0]->IsString()) {
fprintf(stderr, "Internal error: setlocale get one string argument.");
Exit();
@@ -248,27 +379,31 @@ class UtilsExtension : public v8::Extension {
}
v8::internal::Vector<const char> chars;
v8::Isolate* isolate = args.GetIsolate();
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ IsolateData* data = IsolateData::FromContext(context);
+ int context_group_id = data->GetContextGroupId(context);
if (ReadFile(isolate, args[0], &chars)) {
- ExecuteStringTask task(chars);
- v8::Global<v8::Context> context(isolate, isolate->GetCurrentContext());
- task.Run(isolate, context);
+ ExecuteStringTask(chars, context_group_id).RunOnIsolate(data);
}
}
static void CompileAndRunWithOrigin(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- if (args.Length() != 5 || !args[0]->IsString() || !args[1]->IsString() ||
- !args[2]->IsInt32() || !args[3]->IsInt32() || !args[4]->IsBoolean()) {
+ if (args.Length() != 6 || !args[0]->IsInt32() || !args[1]->IsString() ||
+ !args[2]->IsString() || !args[3]->IsInt32() || !args[4]->IsInt32() ||
+ !args[5]->IsBoolean()) {
fprintf(stderr,
- "Internal error: compileAndRunWithOrigin(source, name, line, "
+ "Internal error: compileAndRunWithOrigin(context_group_id, "
+ "source, name, line, "
"column, is_module).");
Exit();
}
backend_runner_->Append(new ExecuteStringTask(
- ToVector(args[0].As<v8::String>()), args[1].As<v8::String>(),
- args[2].As<v8::Int32>(), args[3].As<v8::Int32>(),
- args[4].As<v8::Boolean>(), nullptr, nullptr));
+ 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>()));
}
static void SetCurrentTimeMSForTest(
@@ -277,7 +412,7 @@ class UtilsExtension : public v8::Extension {
fprintf(stderr, "Internal error: setCurrentTimeMSForTest(time).");
Exit();
}
- inspector_client_->setCurrentTimeMSForTest(
+ backend_runner_->data()->inspector()->SetCurrentTimeMSForTest(
args[0].As<v8::Number>()->Value());
}
@@ -287,112 +422,153 @@ class UtilsExtension : public v8::Extension {
fprintf(stderr, "Internal error: setMemoryInfoForTest(value).");
Exit();
}
- inspector_client_->setMemoryInfoForTest(args[0]);
+ backend_runner_->data()->inspector()->SetMemoryInfoForTest(args[0]);
}
static void SchedulePauseOnNextStatement(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
- fprintf(
- stderr,
- "Internal error: schedulePauseOnNextStatement('reason', 'details').");
+ if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
+ !args[2]->IsString()) {
+ fprintf(stderr,
+ "Internal error: schedulePauseOnNextStatement(context_group_id, "
+ "'reason', 'details').");
Exit();
}
- v8::internal::Vector<uint16_t> reason = ToVector(args[0].As<v8::String>());
- v8_inspector::StringView reason_view(reason.start(), reason.length());
- v8::internal::Vector<uint16_t> details = ToVector(args[1].As<v8::String>());
- v8_inspector::StringView details_view(details.start(), details.length());
- inspector_client_->session()->schedulePauseOnNextStatement(reason_view,
- details_view);
+ 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();
}
static void CancelPauseOnNextStatement(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- if (args.Length() != 0) {
- fprintf(stderr, "Internal error: cancelPauseOnNextStatement().");
+ if (args.Length() != 1 || !args[0]->IsInt32()) {
+ fprintf(stderr,
+ "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();
+ }
+
+ static void SetLogConsoleApiMessageCalls(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 1 || !args[0]->IsBoolean()) {
+ fprintf(stderr, "Internal error: setLogConsoleApiMessageCalls(bool).");
Exit();
}
- inspector_client_->session()->cancelPauseOnNextStatement();
+ backend_runner_->data()->inspector()->SetLogConsoleApiMessageCalls(
+ args[0].As<v8::Boolean>()->Value());
}
- static void Reconnect(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ static void CreateContextGroup(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 0) {
- fprintf(stderr, "Internal error: reconnect().");
+ fprintf(stderr, "Internal error: createContextGroup().");
Exit();
}
v8::base::Semaphore ready_semaphore(0);
- inspector_client_->scheduleReconnect(&ready_semaphore);
+ int context_group_id = 0;
+ backend_runner_->Append(
+ new CreateContextGroupTask(&ready_semaphore, &context_group_id));
ready_semaphore.Wait();
+ args.GetReturnValue().Set(
+ v8::Int32::New(args.GetIsolate(), context_group_id));
}
- static void Disconnect(const v8::FunctionCallbackInfo<v8::Value>& args) {
- if (args.Length() != 0) {
- fprintf(stderr, "Internal error: disconnect().");
+ static void ConnectSession(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
+ !args[2]->IsFunction()) {
+ fprintf(stderr,
+ "Internal error: connectionSession(context_group_id, state, "
+ "dispatch).");
Exit();
}
+ v8::internal::Vector<uint16_t> state = ToVector(args[1].As<v8::String>());
v8::base::Semaphore ready_semaphore(0);
- inspector_client_->scheduleDisconnect(&ready_semaphore);
+ 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>());
+ args.GetReturnValue().Set(v8::Int32::New(args.GetIsolate(), session_id));
}
- static void CreateContextGroup(
+ static void DisconnectSession(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- if (args.Length() != 0) {
- fprintf(stderr, "Internal error: createContextGroup().");
+ if (args.Length() != 1 || !args[0]->IsInt32()) {
+ fprintf(stderr, "Internal error: disconnectionSession(session_id).");
Exit();
}
- const char* backend_extensions[] = {"v8_inspector/setTimeout",
- "v8_inspector/inspector"};
- v8::ExtensionConfiguration backend_configuration(
- arraysize(backend_extensions), backend_extensions);
+ int session_id = args[0].As<v8::Int32>()->Value();
+ SendMessageToFrontendTask::Unregister(session_id);
v8::base::Semaphore ready_semaphore(0);
- int context_group_id = 0;
- inspector_client_->scheduleCreateContextGroup(
- &backend_configuration, &ready_semaphore, &context_group_id);
+ v8::internal::Vector<uint16_t> state;
+ backend_runner_->Append(
+ new DisconnectSessionTask(&ready_semaphore, session_id, &state));
ready_semaphore.Wait();
args.GetReturnValue().Set(
- v8::Int32::New(args.GetIsolate(), context_group_id));
+ v8::String::NewFromTwoByte(args.GetIsolate(), state.start(),
+ v8::NewStringType::kNormal,
+ static_cast<int>(state.size()))
+ .ToLocalChecked());
+ }
+
+ static void SendMessageToBackend(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {
+ fprintf(stderr,
+ "Internal error: sendMessageToBackend(session_id, message).");
+ Exit();
+ }
+ backend_runner_->Append(new SendMessageToBackendTask(
+ args[0].As<v8::Int32>()->Value(), ToVector(args[1].As<v8::String>())));
}
};
TaskRunner* UtilsExtension::backend_runner_ = nullptr;
-InspectorClientImpl* UtilsExtension::inspector_client_ = nullptr;
class SetTimeoutTask : public AsyncTask {
public:
- SetTimeoutTask(v8::Isolate* isolate, v8::Local<v8::Function> function,
- const char* task_name, v8_inspector::V8Inspector* inspector)
- : AsyncTask(task_name, inspector), function_(isolate, function) {}
+ SetTimeoutTask(IsolateData* data, int context_group_id, const char* task_name,
+ v8::Local<v8::Function> function)
+ : AsyncTask(data, task_name),
+ function_(data->isolate(), function),
+ context_group_id_(context_group_id) {}
virtual ~SetTimeoutTask() {}
bool is_inspector_task() final { return false; }
- void AsyncRun(v8::Isolate* isolate,
- const v8::Global<v8::Context>& global_context) override {
- v8::MicrotasksScope microtasks_scope(isolate,
+ private:
+ void AsyncRun() override {
+ v8::MicrotasksScope microtasks_scope(isolate(),
v8::MicrotasksScope::kRunMicrotasks);
- v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Context> context = global_context.Get(isolate);
+ v8::HandleScope handle_scope(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(isolate());
v8::MaybeLocal<v8::Value> result;
result = function->Call(context, context->Global(), 0, nullptr);
}
- private:
v8::Global<v8::Function> function_;
+ int context_group_id_;
};
-class SetTimeoutExtension : public v8::Extension {
+class SetTimeoutExtension : public IsolateData::SetupGlobalTask {
public:
- SetTimeoutExtension()
- : v8::Extension("v8_inspector/setTimeout",
- "native function setTimeout();") {}
-
- virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
- v8::Isolate* isolate, v8::Local<v8::String> name) {
- return v8::FunctionTemplate::New(isolate, SetTimeoutExtension::SetTimeout);
+ void Run(v8::Isolate* isolate,
+ v8::Local<v8::ObjectTemplate> global) override {
+ global->Set(
+ ToV8String(isolate, "setTimeout"),
+ v8::FunctionTemplate::New(isolate, &SetTimeoutExtension::SetTimeout));
}
private:
@@ -400,26 +576,27 @@ class SetTimeoutExtension : public v8::Extension {
if (args.Length() != 2 || !args[1]->IsNumber() ||
(!args[0]->IsFunction() && !args[0]->IsString()) ||
args[1].As<v8::Number>()->Value() != 0.0) {
- fprintf(stderr,
- "Internal error: only setTimeout(function, 0) is supported.");
+ fprintf(
+ stderr,
+ "Internal error: only setTimeout(function|code, 0) is supported.");
Exit();
}
v8::Isolate* isolate = args.GetIsolate();
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;
- v8_inspector::V8Inspector* inspector =
- InspectorClientImpl::InspectorFromContext(context);
if (args[0]->IsFunction()) {
- task.reset(new SetTimeoutTask(isolate,
- v8::Local<v8::Function>::Cast(args[0]),
- "setTimeout", inspector));
+ task.reset(new SetTimeoutTask(data, context_group_id, "setTimeout",
+ 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), "setTimeout", inspector));
+ v8::Boolean::New(isolate, false)));
}
- TaskRunner::FromContext(context)->Append(task.release());
+ data->task_runner()->Append(task.release());
}
};
@@ -430,96 +607,55 @@ bool StrictAccessCheck(v8::Local<v8::Context> accessing_context,
return accessing_context.IsEmpty();
}
-class InspectorExtension : public v8::Extension {
+class InspectorExtension : public IsolateData::SetupGlobalTask {
public:
- InspectorExtension()
- : v8::Extension("v8_inspector/inspector",
- "native function attachInspector();"
- "native function detachInspector();"
- "native function setMaxAsyncTaskStacks();"
- "native function breakProgram();"
- "native function createObjectWithStrictCheck();"
- "native function callWithScheduledBreak();"
- "native function allowAccessorFormatting();") {}
-
- virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
- v8::Isolate* isolate, v8::Local<v8::String> name) {
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "attachInspector",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, InspectorExtension::Attach);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "detachInspector",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate, InspectorExtension::Detach);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "setMaxAsyncTaskStacks",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(
- isolate, InspectorExtension::SetMaxAsyncTaskStacks);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "breakProgram",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate,
- InspectorExtension::BreakProgram);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "createObjectWithStrictCheck",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(
- isolate, InspectorExtension::CreateObjectWithStrictCheck);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "callWithScheduledBreak",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(
- isolate, InspectorExtension::CallWithScheduledBreak);
- } else if (name->Equals(context, v8::String::NewFromUtf8(
- isolate, "allowAccessorFormatting",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(
- isolate, InspectorExtension::AllowAccessorFormatting);
- }
- return v8::Local<v8::FunctionTemplate>();
+ ~InspectorExtension() override = default;
+ void Run(v8::Isolate* isolate,
+ v8::Local<v8::ObjectTemplate> global) override {
+ v8::Local<v8::ObjectTemplate> inspector = v8::ObjectTemplate::New(isolate);
+ inspector->Set(ToV8String(isolate, "fireContextCreated"),
+ v8::FunctionTemplate::New(
+ isolate, &InspectorExtension::FireContextCreated));
+ inspector->Set(ToV8String(isolate, "fireContextDestroyed"),
+ v8::FunctionTemplate::New(
+ isolate, &InspectorExtension::FireContextDestroyed));
+ inspector->Set(ToV8String(isolate, "setMaxAsyncTaskStacks"),
+ v8::FunctionTemplate::New(
+ isolate, &InspectorExtension::SetMaxAsyncTaskStacks));
+ inspector->Set(
+ ToV8String(isolate, "dumpAsyncTaskStacksStateForTest"),
+ v8::FunctionTemplate::New(
+ isolate, &InspectorExtension::DumpAsyncTaskStacksStateForTest));
+ inspector->Set(
+ ToV8String(isolate, "breakProgram"),
+ v8::FunctionTemplate::New(isolate, &InspectorExtension::BreakProgram));
+ inspector->Set(
+ ToV8String(isolate, "createObjectWithStrictCheck"),
+ v8::FunctionTemplate::New(
+ isolate, &InspectorExtension::CreateObjectWithStrictCheck));
+ inspector->Set(ToV8String(isolate, "callWithScheduledBreak"),
+ v8::FunctionTemplate::New(
+ isolate, &InspectorExtension::CallWithScheduledBreak));
+ inspector->Set(ToV8String(isolate, "allowAccessorFormatting"),
+ v8::FunctionTemplate::New(
+ isolate, &InspectorExtension::AllowAccessorFormatting));
+ global->Set(ToV8String(isolate, "inspector"), inspector);
}
private:
- static void Attach(const v8::FunctionCallbackInfo<v8::Value>& args) {
- v8::Isolate* isolate = args.GetIsolate();
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- v8_inspector::V8Inspector* inspector =
- InspectorClientImpl::InspectorFromContext(context);
- if (!inspector) {
- fprintf(stderr, "Inspector client not found - cannot attach!");
- Exit();
- }
- inspector->contextCreated(
- v8_inspector::V8ContextInfo(context, 1, v8_inspector::StringView()));
+ static void FireContextCreated(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
+ IsolateData* data = IsolateData::FromContext(context);
+ data->inspector()->ContextCreated(context,
+ data->GetContextGroupId(context));
}
- static void Detach(const v8::FunctionCallbackInfo<v8::Value>& args) {
- v8::Isolate* isolate = args.GetIsolate();
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
- v8_inspector::V8Inspector* inspector =
- InspectorClientImpl::InspectorFromContext(context);
- if (!inspector) {
- fprintf(stderr, "Inspector client not found - cannot detach!");
- Exit();
- }
- inspector->contextDestroyed(context);
+ static void FireContextDestroyed(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
+ IsolateData* data = IsolateData::FromContext(context);
+ data->inspector()->ContextDestroyed(context);
}
static void SetMaxAsyncTaskStacks(
@@ -528,12 +664,23 @@ class InspectorExtension : public v8::Extension {
fprintf(stderr, "Internal error: setMaxAsyncTaskStacks(max).");
Exit();
}
- v8_inspector::V8Inspector* inspector =
- InspectorClientImpl::InspectorFromContext(
- args.GetIsolate()->GetCurrentContext());
- CHECK(inspector);
v8_inspector::SetMaxAsyncTaskStacksForTest(
- inspector, args[0].As<v8::Int32>()->Value());
+ IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
+ ->inspector()
+ ->inspector(),
+ args[0].As<v8::Int32>()->Value());
+ }
+
+ static void DumpAsyncTaskStacksStateForTest(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 0) {
+ fprintf(stderr, "Internal error: dumpAsyncTaskStacksStateForTest().");
+ Exit();
+ }
+ v8_inspector::DumpAsyncTaskStacksStateForTest(
+ IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
+ ->inspector()
+ ->inspector());
}
static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) {
@@ -541,16 +688,14 @@ class InspectorExtension : public v8::Extension {
fprintf(stderr, "Internal error: breakProgram('reason', 'details').");
Exit();
}
- v8_inspector::V8InspectorSession* session =
- InspectorClientImpl::SessionFromContext(
- args.GetIsolate()->GetCurrentContext());
- CHECK(session);
-
+ v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
+ IsolateData* data = IsolateData::FromContext(context);
v8::internal::Vector<uint16_t> reason = ToVector(args[0].As<v8::String>());
v8_inspector::StringView reason_view(reason.start(), reason.length());
v8::internal::Vector<uint16_t> details = ToVector(args[1].As<v8::String>());
v8_inspector::StringView details_view(details.start(), details.length());
- session->breakProgram(reason_view, details_view);
+ data->inspector()->BreakProgram(data->GetContextGroupId(context),
+ reason_view, details_view);
}
static void CreateObjectWithStrictCheck(
@@ -571,24 +716,23 @@ class InspectorExtension : public v8::Extension {
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() ||
!args[2]->IsString()) {
- fprintf(stderr, "Internal error: breakProgram('reason', 'details').");
+ fprintf(stderr,
+ "Internal error: callWithScheduledBreak('reason', 'details').");
Exit();
}
- v8_inspector::V8InspectorSession* session =
- InspectorClientImpl::SessionFromContext(
- args.GetIsolate()->GetCurrentContext());
- CHECK(session);
-
v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>());
v8_inspector::StringView reason_view(reason.start(), reason.length());
v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>());
v8_inspector::StringView details_view(details.start(), details.length());
- session->schedulePauseOnNextStatement(reason_view, details_view);
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
+ IsolateData* data = IsolateData::FromContext(context);
+ int context_group_id = data->GetContextGroupId(context);
+ data->inspector()->SchedulePauseOnNextStatement(context_group_id,
+ reason_view, details_view);
v8::MaybeLocal<v8::Value> result;
result = args[0].As<v8::Function>()->Call(context, context->Global(), 0,
nullptr);
- session->cancelPauseOnNextStatement();
+ data->inspector()->CancelPauseOnNextStatement(context_group_id);
}
static void AllowAccessorFormatting(
@@ -610,50 +754,22 @@ class InspectorExtension : public v8::Extension {
}
};
-v8::Local<v8::String> ToString(v8::Isolate* isolate,
- const v8_inspector::StringView& string) {
- if (string.is8Bit())
- return v8::String::NewFromOneByte(isolate, string.characters8(),
- v8::NewStringType::kNormal,
- static_cast<int>(string.length()))
- .ToLocalChecked();
- else
- return v8::String::NewFromTwoByte(isolate, string.characters16(),
- v8::NewStringType::kNormal,
- static_cast<int>(string.length()))
- .ToLocalChecked();
-}
-
class FrontendChannelImpl : public InspectorClientImpl::FrontendChannel {
public:
- explicit FrontendChannelImpl(TaskRunner* frontend_task_runner)
- : frontend_task_runner_(frontend_task_runner) {}
+ 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(const v8_inspector::StringView& message) final {
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
- v8::HandleScope scope(v8::Isolate::GetCurrent());
-
- v8::Local<v8::String> prefix =
- v8::String::NewFromUtf8(isolate, "InspectorTest._dispatchMessage(",
- v8::NewStringType::kInternalized)
- .ToLocalChecked();
- v8::Local<v8::String> message_string = ToString(isolate, message);
- v8::Local<v8::String> suffix =
- v8::String::NewFromUtf8(isolate, ")", v8::NewStringType::kInternalized)
- .ToLocalChecked();
-
- v8::Local<v8::String> result = v8::String::Concat(prefix, message_string);
- result = v8::String::Concat(result, suffix);
-
- frontend_task_runner_->Append(new ExecuteStringTask(
- ToVector(result), v8::String::Empty(isolate),
- v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0),
- v8::Boolean::New(isolate, false), nullptr, nullptr));
+ 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
@@ -666,45 +782,46 @@ int main(int argc, char* argv[]) {
v8::V8::InitializeExternalStartupData(argv[0]);
v8::V8::Initialize();
- SetTimeoutExtension set_timeout_extension;
- v8::RegisterExtension(&set_timeout_extension);
- InspectorExtension inspector_extension;
- v8::RegisterExtension(&inspector_extension);
- UtilsExtension utils_extension;
- v8::RegisterExtension(&utils_extension);
- SendMessageToBackendExtension send_message_to_backend_extension;
- v8::RegisterExtension(&send_message_to_backend_extension);
-
v8::base::Semaphore ready_semaphore(0);
- const char* backend_extensions[] = {"v8_inspector/setTimeout",
- "v8_inspector/inspector"};
- v8::ExtensionConfiguration backend_configuration(
- arraysize(backend_extensions), backend_extensions);
- TaskRunner backend_runner(&backend_configuration, false, &ready_semaphore);
+ v8::StartupData startup_data = {nullptr, 0};
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "--embed") == 0) {
+ argv[i++] = nullptr;
+ printf("Embedding script '%s'\n", argv[i]);
+ startup_data = v8::V8::CreateSnapshotDataBlob(argv[i]);
+ argv[i] = nullptr;
+ }
+ }
+
+ IsolateData::SetupGlobalTasks frontend_extensions;
+ frontend_extensions.emplace_back(new UtilsExtension());
+ TaskRunner frontend_runner(std::move(frontend_extensions), true,
+ &ready_semaphore, nullptr, nullptr);
ready_semaphore.Wait();
- SendMessageToBackendExtension::set_backend_task_runner(&backend_runner);
- UtilsExtension::set_backend_task_runner(&backend_runner);
- const char* frontend_extensions[] = {"v8_inspector/utils",
- "v8_inspector/frontend"};
- v8::ExtensionConfiguration frontend_configuration(
- arraysize(frontend_extensions), frontend_extensions);
- TaskRunner frontend_runner(&frontend_configuration, true, &ready_semaphore);
+ int frontend_context_group_id = 0;
+ frontend_runner.Append(
+ new CreateContextGroupTask(&ready_semaphore, &frontend_context_group_id));
ready_semaphore.Wait();
- FrontendChannelImpl frontend_channel(&frontend_runner);
- InspectorClientImpl inspector_client(&backend_runner, &frontend_channel,
- &ready_semaphore);
+ 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);
ready_semaphore.Wait();
- UtilsExtension::set_inspector_client(&inspector_client);
+ UtilsExtension::set_backend_task_runner(&backend_runner);
task_runners.push_back(&frontend_runner);
task_runners.push_back(&backend_runner);
for (int i = 1; i < argc; ++i) {
// Ignore unknown flags.
- if (argv[i][0] == '-') continue;
+ if (argv[i] == nullptr || argv[i][0] == '-') continue;
bool exists = false;
v8::internal::Vector<const char> chars =
@@ -714,10 +831,13 @@ int main(int argc, char* argv[]) {
argv[i]);
Exit();
}
- frontend_runner.Append(new ExecuteStringTask(chars));
+ frontend_runner.Append(
+ new ExecuteStringTask(chars, frontend_context_group_id));
}
frontend_runner.Join();
backend_runner.Join();
+
+ delete startup_data.data;
return 0;
}