diff options
Diffstat (limited to 'deps/v8/test/inspector/isolate-data.cc')
-rw-r--r-- | deps/v8/test/inspector/isolate-data.cc | 298 |
1 files changed, 286 insertions, 12 deletions
diff --git a/deps/v8/test/inspector/isolate-data.cc b/deps/v8/test/inspector/isolate-data.cc index b1e85ede80..74c367a5e9 100644 --- a/deps/v8/test/inspector/isolate-data.cc +++ b/deps/v8/test/inspector/isolate-data.cc @@ -4,7 +4,7 @@ #include "test/inspector/isolate-data.h" -#include "test/inspector/inspector-impl.h" +#include "src/inspector/test-interface.h" #include "test/inspector/task-runner.h" namespace { @@ -19,12 +19,44 @@ v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { 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); +} + +class Inspectable : public v8_inspector::V8InspectorSession::Inspectable { + public: + Inspectable(v8::Isolate* isolate, v8::Local<v8::Value> object) + : object_(isolate, object) {} + ~Inspectable() override {} + v8::Local<v8::Value> get(v8::Local<v8::Context> context) override { + return object_.Get(context->GetIsolate()); + } + + private: + v8::Global<v8::Value> object_; +}; + } // namespace IsolateData::IsolateData(TaskRunner* task_runner, IsolateData::SetupGlobalTasks setup_global_tasks, - v8::StartupData* startup_data, - InspectorClientImpl::FrontendChannel* channel) + v8::StartupData* startup_data, bool with_inspector) : task_runner_(task_runner), setup_global_tasks_(std::move(setup_global_tasks)) { v8::Isolate::CreateParams params; @@ -33,8 +65,11 @@ IsolateData::IsolateData(TaskRunner* task_runner, params.snapshot_blob = startup_data; isolate_ = v8::Isolate::New(params); isolate_->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped); - if (channel) - inspector_.reset(new InspectorClientImpl(isolate_, task_runner, channel)); + if (with_inspector) { + isolate_->AddMessageListener(&IsolateData::MessageHandler); + isolate_->SetPromiseRejectCallback(&IsolateData::PromiseRejectHandler); + inspector_ = v8_inspector::V8Inspector::create(isolate_, this); + } } IsolateData* IsolateData::FromContext(v8::Local<v8::Context> context) { @@ -58,7 +93,7 @@ int IsolateData::CreateContextGroup() { context->SetAlignedPointerInEmbedderData( kContextGroupIdIndex, reinterpret_cast<void*>(context_group_id * 2)); contexts_[context_group_id].Reset(isolate_, context); - if (inspector_) inspector_->ContextCreated(context, context_group_id); + if (inspector_) FireContextCreated(context, context_group_id); return context_group_id; } @@ -79,13 +114,16 @@ void IsolateData::RegisterModule(v8::Local<v8::Context> context, v8::Local<v8::Module> module; if (!v8::ScriptCompiler::CompileModule(isolate(), source).ToLocal(&module)) return; - if (!module->Instantiate(context, &IsolateData::ModuleResolveCallback)) + 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) { @@ -94,9 +132,245 @@ v8::MaybeLocal<v8::Module> IsolateData::ModuleResolveCallback( return data->modules_[ToVector(specifier)].Get(data->isolate_); } -void IsolateData::FreeContext(v8::Local<v8::Context> context) { - int context_group_id = GetContextGroupId(context); - auto it = contexts_.find(context_group_id); - if (it == contexts_.end()) return; - contexts_.erase(it); +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::AddInspectedObject(int session_id, + v8::Local<v8::Value> object) { + auto it = sessions_.find(session_id); + if (it == sessions_.end()) return; + std::unique_ptr<Inspectable> inspectable(new Inspectable(isolate_, object)); + it->second->addInspectedObject(std::move(inspectable)); +} + +void IsolateData::SetMaxAsyncTaskStacksForTest(int limit) { + v8_inspector::SetMaxAsyncTaskStacksForTest(inspector_.get(), limit); +} + +void IsolateData::DumpAsyncTaskStacksStateForTest() { + v8_inspector::DumpAsyncTaskStacksStateForTest(inspector_.get()); +} + +// static +int IsolateData::HandleMessage(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 0; + 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()); + + return inspector->exceptionThrown( + context, message_text, exception, detailed_message, url, line_number, + column_number, inspector->createStackTrace(stack), script_id); +} + +// static +void IsolateData::MessageHandler(v8::Local<v8::Message> message, + v8::Local<v8::Value> exception) { + HandleMessage(message, exception); +} + +// static +void IsolateData::PromiseRejectHandler(v8::PromiseRejectMessage data) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Context> context = isolate->GetEnteredContext(); + if (context.IsEmpty()) return; + v8::Local<v8::Promise> promise = data.GetPromise(); + v8::Local<v8::Private> id_private = v8::Private::ForApi( + isolate, + v8::String::NewFromUtf8(isolate, "id", v8::NewStringType::kNormal) + .ToLocalChecked()); + + if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { + v8::Local<v8::Value> id; + if (!promise->GetPrivate(context, id_private).ToLocal(&id)) return; + if (!id->IsInt32()) return; + v8_inspector::V8Inspector* inspector = + IsolateData::FromContext(context)->inspector_.get(); + const char* reason_str = "Handler added to rejected promise"; + inspector->exceptionRevoked( + context, id.As<v8::Int32>()->Value(), + v8_inspector::StringView(reinterpret_cast<const uint8_t*>(reason_str), + strlen(reason_str))); + return; + } + + v8::Local<v8::Value> exception = data.GetValue(); + int exception_id = HandleMessage( + v8::Exception::CreateMessage(isolate, exception), exception); + if (exception_id) { + promise + ->SetPrivate(isolate->GetCurrentContext(), id_private, + v8::Int32::New(isolate, exception_id)) + .ToChecked(); + } +} + +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"); } |