v8/test/inspector/isolate-data.cc
Jochen Eisinger 68aa1ab388 Update module APIs to return Maybe<bool>
All APIs that can throw exceptions should return Maybe<> values

BUG=none
R=neis@chromium.org,gsathya@chromium.org

Change-Id: I6a6e5888cd71257bb02bdcfcc587c909d0c1d8f4
Reviewed-on: https://chromium-review.googlesource.com/517785
Commit-Queue: Jochen Eisinger <jochen@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45557}
2017-05-29 12:29:43 +00:00

313 lines
12 KiB
C++

// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test/inspector/isolate-data.h"
#include "src/inspector/test-interface.h"
#include "test/inspector/task-runner.h"
namespace {
const int kIsolateDataIndex = 2;
const int kContextGroupIdIndex = 3;
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;
}
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();
}
void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) {
v8::Local<v8::String> v8_string = ToString(isolate, string);
v8::String::Utf8Value utf8_string(v8_string);
fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout);
}
} // namespace
IsolateData::IsolateData(TaskRunner* task_runner,
IsolateData::SetupGlobalTasks setup_global_tasks,
v8::StartupData* startup_data, bool with_inspector)
: task_runner_(task_runner),
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 (with_inspector) {
isolate_->AddMessageListener(&IsolateData::MessageHandler);
inspector_ = v8_inspector::V8Inspector::create(isolate_, this);
}
}
IsolateData* IsolateData::FromContext(v8::Local<v8::Context> context) {
return static_cast<IsolateData*>(
context->GetAlignedPointerFromEmbedderData(kIsolateDataIndex));
}
int IsolateData::CreateContextGroup() {
v8::HandleScope handle_scope(isolate_);
v8::Local<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate_);
for (auto it = setup_global_tasks_.begin(); it != setup_global_tasks_.end();
++it) {
(*it)->Run(isolate_, global_template);
}
v8::Local<v8::Context> context =
v8::Context::New(isolate_, nullptr, global_template);
context->SetAlignedPointerInEmbedderData(kIsolateDataIndex, this);
int context_group_id = ++last_context_group_id_;
// Should be 2-byte aligned.
context->SetAlignedPointerInEmbedderData(
kContextGroupIdIndex, reinterpret_cast<void*>(context_group_id * 2));
contexts_[context_group_id].Reset(isolate_, context);
if (inspector_) FireContextCreated(context, context_group_id);
return context_group_id;
}
v8::Local<v8::Context> IsolateData::GetContext(int context_group_id) {
return contexts_[context_group_id].Get(isolate_);
}
int IsolateData::GetContextGroupId(v8::Local<v8::Context> context) {
return static_cast<int>(
reinterpret_cast<intptr_t>(
context->GetAlignedPointerFromEmbedderData(kContextGroupIdIndex)) /
2);
}
void IsolateData::RegisterModule(v8::Local<v8::Context> context,
v8::internal::Vector<uint16_t> name,
v8::ScriptCompiler::Source* source) {
v8::Local<v8::Module> module;
if (!v8::ScriptCompiler::CompileModule(isolate(), source).ToLocal(&module))
return;
if (!module->InstantiateModule(context, &IsolateData::ModuleResolveCallback)
.FromMaybe(false)) {
return;
}
v8::Local<v8::Value> result;
if (!module->Evaluate(context).ToLocal(&result)) return;
modules_[name] = v8::Global<v8::Module>(isolate_, module);
}
// static
v8::MaybeLocal<v8::Module> IsolateData::ModuleResolveCallback(
v8::Local<v8::Context> context, v8::Local<v8::String> specifier,
v8::Local<v8::Module> referrer) {
std::string str = *v8::String::Utf8Value(specifier);
IsolateData* data = IsolateData::FromContext(context);
return data->modules_[ToVector(specifier)].Get(data->isolate_);
}
int IsolateData::ConnectSession(int context_group_id,
const v8_inspector::StringView& state,
v8_inspector::V8Inspector::Channel* channel) {
int session_id = ++last_session_id_;
sessions_[session_id] = inspector_->connect(context_group_id, channel, state);
context_group_by_session_[sessions_[session_id].get()] = context_group_id;
return session_id;
}
std::unique_ptr<v8_inspector::StringBuffer> IsolateData::DisconnectSession(
int session_id) {
auto it = sessions_.find(session_id);
CHECK(it != sessions_.end());
context_group_by_session_.erase(it->second.get());
std::unique_ptr<v8_inspector::StringBuffer> result = it->second->stateJSON();
sessions_.erase(it);
return result;
}
void IsolateData::SendMessage(int session_id,
const v8_inspector::StringView& message) {
auto it = sessions_.find(session_id);
if (it != sessions_.end()) it->second->dispatchProtocolMessage(message);
}
void IsolateData::BreakProgram(int context_group_id,
const v8_inspector::StringView& reason,
const v8_inspector::StringView& details) {
for (int session_id : GetSessionIds(context_group_id)) {
auto it = sessions_.find(session_id);
if (it != sessions_.end()) it->second->breakProgram(reason, details);
}
}
void IsolateData::SchedulePauseOnNextStatement(
int context_group_id, const v8_inspector::StringView& reason,
const v8_inspector::StringView& details) {
for (int session_id : GetSessionIds(context_group_id)) {
auto it = sessions_.find(session_id);
if (it != sessions_.end())
it->second->schedulePauseOnNextStatement(reason, details);
}
}
void IsolateData::CancelPauseOnNextStatement(int context_group_id) {
for (int session_id : GetSessionIds(context_group_id)) {
auto it = sessions_.find(session_id);
if (it != sessions_.end()) it->second->cancelPauseOnNextStatement();
}
}
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) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Local<v8::Context> context = isolate->GetEnteredContext();
if (context.IsEmpty()) return;
v8_inspector::V8Inspector* inspector =
IsolateData::FromContext(context)->inspector_.get();
v8::Local<v8::StackTrace> stack = message->GetStackTrace();
int script_id =
static_cast<int>(message->GetScriptOrigin().ScriptID()->Value());
if (!stack.IsEmpty() && stack->GetFrameCount() > 0) {
int top_script_id = stack->GetFrame(0)->GetScriptId();
if (top_script_id == script_id) script_id = 0;
}
int line_number = message->GetLineNumber(context).FromMaybe(0);
int column_number = 0;
if (message->GetStartColumn(context).IsJust())
column_number = message->GetStartColumn(context).FromJust() + 1;
v8_inspector::StringView detailed_message;
v8::internal::Vector<uint16_t> message_text_string = ToVector(message->Get());
v8_inspector::StringView message_text(message_text_string.start(),
message_text_string.length());
v8::internal::Vector<uint16_t> url_string;
if (message->GetScriptOrigin().ResourceName()->IsString()) {
url_string =
ToVector(message->GetScriptOrigin().ResourceName().As<v8::String>());
}
v8_inspector::StringView url(url_string.start(), url_string.length());
inspector->exceptionThrown(context, message_text, exception, detailed_message,
url, line_number, column_number,
inspector->createStackTrace(stack), script_id);
}
void IsolateData::FireContextCreated(v8::Local<v8::Context> context,
int context_group_id) {
v8_inspector::V8ContextInfo info(context, context_group_id,
v8_inspector::StringView());
info.hasMemoryOnConsole = true;
inspector_->contextCreated(info);
}
void IsolateData::FireContextDestroyed(v8::Local<v8::Context> context) {
inspector_->contextDestroyed(context);
}
std::vector<int> IsolateData::GetSessionIds(int context_group_id) {
std::vector<int> result;
for (auto& it : sessions_) {
if (context_group_by_session_[it.second.get()] == context_group_id)
result.push_back(it.first);
}
return result;
}
bool IsolateData::formatAccessorsAsProperties(v8::Local<v8::Value> object) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi(
isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting",
v8::NewStringType::kNormal)
.ToLocalChecked());
CHECK(object->IsObject());
return object.As<v8::Object>()
->HasPrivate(context, shouldFormatAccessorsPrivate)
.FromMaybe(false);
}
v8::Local<v8::Context> IsolateData::ensureDefaultContextInGroup(
int context_group_id) {
return GetContext(context_group_id);
}
void IsolateData::SetCurrentTimeMS(double time) {
current_time_ = time;
current_time_set_ = true;
}
double IsolateData::currentTimeMS() {
if (current_time_set_) return current_time_;
return v8::base::OS::TimeCurrentMillis();
}
void IsolateData::SetMemoryInfo(v8::Local<v8::Value> memory_info) {
memory_info_.Reset(isolate_, memory_info);
}
void IsolateData::SetLogConsoleApiMessageCalls(bool log) {
log_console_api_message_calls_ = log;
}
v8::MaybeLocal<v8::Value> IsolateData::memoryInfo(v8::Isolate* isolate,
v8::Local<v8::Context>) {
if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>();
return memory_info_.Get(isolate);
}
void IsolateData::runMessageLoopOnPause(int) {
task_runner_->RunMessageLoop(true);
}
void IsolateData::quitMessageLoopOnPause() { task_runner_->QuitMessageLoop(); }
void IsolateData::consoleAPIMessage(int contextGroupId,
v8::Isolate::MessageErrorLevel level,
const v8_inspector::StringView& message,
const v8_inspector::StringView& url,
unsigned lineNumber, unsigned columnNumber,
v8_inspector::V8StackTrace* stack) {
if (!log_console_api_message_calls_) return;
Print(isolate_, message);
fprintf(stdout, " (");
Print(isolate_, url);
fprintf(stdout, ":%d:%d)", lineNumber, columnNumber);
Print(isolate_, stack->toString()->string());
fprintf(stdout, "\n");
}