11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 31cb0ef41Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 41cb0ef41Sopenharmony_ci * you may not use this file except in compliance with the License. 51cb0ef41Sopenharmony_ci * You may obtain a copy of the License at 61cb0ef41Sopenharmony_ci * 71cb0ef41Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 81cb0ef41Sopenharmony_ci * 91cb0ef41Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 101cb0ef41Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 111cb0ef41Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 121cb0ef41Sopenharmony_ci * See the License for the specific language governing permissions and 131cb0ef41Sopenharmony_ci * limitations under the License. 141cb0ef41Sopenharmony_ci */ 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci#include "js_native_api_v8_inspector.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci#include "js_native_api_v8.h" 191cb0ef41Sopenharmony_ci#include "inspector_socket_server.h" 201cb0ef41Sopenharmony_ci#include "inspector/main_thread_interface.h" 211cb0ef41Sopenharmony_ci#include "inspector/node_string.h" 221cb0ef41Sopenharmony_ci#include "inspector/runtime_agent.h" 231cb0ef41Sopenharmony_ci#include "inspector/tracing_agent.h" 241cb0ef41Sopenharmony_ci#include "inspector/worker_agent.h" 251cb0ef41Sopenharmony_ci#include "inspector/worker_inspector.h" 261cb0ef41Sopenharmony_ci#include "crypto/crypto_util.h" 271cb0ef41Sopenharmony_ci#include "node/inspector/protocol/Protocol.h" 281cb0ef41Sopenharmony_ci#include "node_errors.h" 291cb0ef41Sopenharmony_ci#include "node_internals.h" 301cb0ef41Sopenharmony_ci#include "node_mutex.h" 311cb0ef41Sopenharmony_ci#include "node_options-inl.h" 321cb0ef41Sopenharmony_ci#include "node_process-inl.h" 331cb0ef41Sopenharmony_ci#include "node_url.h" 341cb0ef41Sopenharmony_ci#include "permission/permission.h" 351cb0ef41Sopenharmony_ci#include "util-inl.h" 361cb0ef41Sopenharmony_ci#include "v8-inspector.h" 371cb0ef41Sopenharmony_ci#include "v8-platform.h" 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci#include "libplatform/libplatform.h" 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci#ifdef __POSIX__ 421cb0ef41Sopenharmony_ci#include <pthread.h> 431cb0ef41Sopenharmony_ci#include <climits> // PTHREAD_STACK_MIN 441cb0ef41Sopenharmony_ci#endif // __POSIX__ 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci#include <algorithm> 471cb0ef41Sopenharmony_ci#include <cstring> 481cb0ef41Sopenharmony_ci#include <sstream> 491cb0ef41Sopenharmony_ci#include <unordered_map> 501cb0ef41Sopenharmony_ci#include <vector> 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_cinamespace v8impl { 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cinamespace { 551cb0ef41Sopenharmony_ciusing node::ConditionVariable; 561cb0ef41Sopenharmony_ciusing node::Mutex; 571cb0ef41Sopenharmony_ciusing node::inspector::Utf8ToStringView; 581cb0ef41Sopenharmony_ciusing v8_inspector::StringBuffer; 591cb0ef41Sopenharmony_ciusing v8_inspector::StringView; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ciclass MainThreadInterface; 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ciclass Request { 641cb0ef41Sopenharmony_ci public: 651cb0ef41Sopenharmony_ci virtual void Call(MainThreadInterface*) = 0; 661cb0ef41Sopenharmony_ci virtual ~Request() = default; 671cb0ef41Sopenharmony_ci}; 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ciclass Deletable { 701cb0ef41Sopenharmony_ci public: 711cb0ef41Sopenharmony_ci virtual ~Deletable() = default; 721cb0ef41Sopenharmony_ci}; 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ciusing MessageQueue = std::deque<std::unique_ptr<Request>>; 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ciclass MainThreadHandle : public std::enable_shared_from_this<MainThreadHandle> { 771cb0ef41Sopenharmony_ci public: 781cb0ef41Sopenharmony_ci explicit MainThreadHandle(MainThreadInterface* main_thread) 791cb0ef41Sopenharmony_ci : main_thread_(main_thread) { 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci ~MainThreadHandle() { 821cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(block_lock_); 831cb0ef41Sopenharmony_ci CHECK_NULL(main_thread_); // main_thread_ should have called Reset 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSession> Connect( 861cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate, 871cb0ef41Sopenharmony_ci bool prevent_shutdown); 881cb0ef41Sopenharmony_ci int newObjectId() { 891cb0ef41Sopenharmony_ci return ++next_object_id_; 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci bool Post(std::unique_ptr<Request> request); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci private: 941cb0ef41Sopenharmony_ci void Reset(); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci MainThreadInterface* main_thread_; 971cb0ef41Sopenharmony_ci Mutex block_lock_; 981cb0ef41Sopenharmony_ci int next_session_id_ = 0; 991cb0ef41Sopenharmony_ci std::atomic_int next_object_id_ = {1}; 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci friend class MainThreadInterface; 1021cb0ef41Sopenharmony_ci}; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ciclass MainThreadInterface : 1051cb0ef41Sopenharmony_ci public std::enable_shared_from_this<MainThreadInterface> { 1061cb0ef41Sopenharmony_ci public: 1071cb0ef41Sopenharmony_ci explicit MainThreadInterface(Agent* agent); 1081cb0ef41Sopenharmony_ci ~MainThreadInterface(); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci void DispatchMessages(); 1111cb0ef41Sopenharmony_ci void Post(std::unique_ptr<Request> request); 1121cb0ef41Sopenharmony_ci bool WaitForFrontendEvent(); 1131cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> GetHandle(); 1141cb0ef41Sopenharmony_ci Agent* inspector_agent() { 1151cb0ef41Sopenharmony_ci return agent_; 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci void AddObject(int handle, std::unique_ptr<Deletable> object); 1181cb0ef41Sopenharmony_ci Deletable* GetObject(int id); 1191cb0ef41Sopenharmony_ci Deletable* GetObjectIfExists(int id); 1201cb0ef41Sopenharmony_ci void RemoveObject(int handle); 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci private: 1231cb0ef41Sopenharmony_ci MessageQueue requests_; 1241cb0ef41Sopenharmony_ci Mutex requests_lock_; // requests_ live across threads 1251cb0ef41Sopenharmony_ci // This queue is to maintain the order of the messages for the cases 1261cb0ef41Sopenharmony_ci // when we reenter the DispatchMessages function. 1271cb0ef41Sopenharmony_ci MessageQueue dispatching_message_queue_; 1281cb0ef41Sopenharmony_ci bool dispatching_messages_ = false; 1291cb0ef41Sopenharmony_ci ConditionVariable incoming_message_cond_; 1301cb0ef41Sopenharmony_ci // Used from any thread 1311cb0ef41Sopenharmony_ci Agent* const agent_; 1321cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> handle_; 1331cb0ef41Sopenharmony_ci std::unordered_map<int, std::unique_ptr<Deletable>> managed_objects_; 1341cb0ef41Sopenharmony_ci}; 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_citemplate <typename T> 1371cb0ef41Sopenharmony_ciclass DeletableWrapper : public Deletable { 1381cb0ef41Sopenharmony_ci public: 1391cb0ef41Sopenharmony_ci explicit DeletableWrapper(std::unique_ptr<T> object) 1401cb0ef41Sopenharmony_ci : object_(std::move(object)) {} 1411cb0ef41Sopenharmony_ci ~DeletableWrapper() override = default; 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci static T* get(MainThreadInterface* thread, int id) { 1441cb0ef41Sopenharmony_ci return 1451cb0ef41Sopenharmony_ci static_cast<DeletableWrapper<T>*>(thread->GetObject(id))->object_.get(); 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci private: 1491cb0ef41Sopenharmony_ci std::unique_ptr<T> object_; 1501cb0ef41Sopenharmony_ci}; 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_citemplate <typename T> 1531cb0ef41Sopenharmony_cistd::unique_ptr<Deletable> WrapInDeletable(std::unique_ptr<T> object) { 1541cb0ef41Sopenharmony_ci return std::unique_ptr<DeletableWrapper<T>>( 1551cb0ef41Sopenharmony_ci new DeletableWrapper<T>(std::move(object))); 1561cb0ef41Sopenharmony_ci} 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_citemplate <typename Factory> 1591cb0ef41Sopenharmony_ciclass CreateObjectRequest : public Request { 1601cb0ef41Sopenharmony_ci public: 1611cb0ef41Sopenharmony_ci CreateObjectRequest(int object_id, Factory factory) 1621cb0ef41Sopenharmony_ci : object_id_(object_id), factory_(std::move(factory)) {} 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci void Call(MainThreadInterface* thread) override { 1651cb0ef41Sopenharmony_ci thread->AddObject(object_id_, WrapInDeletable(factory_(thread))); 1661cb0ef41Sopenharmony_ci } 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci private: 1691cb0ef41Sopenharmony_ci int object_id_; 1701cb0ef41Sopenharmony_ci Factory factory_; 1711cb0ef41Sopenharmony_ci}; 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_citemplate <typename Factory> 1741cb0ef41Sopenharmony_cistd::unique_ptr<Request> NewCreateRequest(int object_id, Factory factory) { 1751cb0ef41Sopenharmony_ci return std::unique_ptr<Request>( 1761cb0ef41Sopenharmony_ci new CreateObjectRequest<Factory>(object_id, std::move(factory))); 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ciclass DeleteRequest : public Request { 1801cb0ef41Sopenharmony_ci public: 1811cb0ef41Sopenharmony_ci explicit DeleteRequest(int object_id) : object_id_(object_id) {} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci void Call(MainThreadInterface* thread) override { 1841cb0ef41Sopenharmony_ci thread->RemoveObject(object_id_); 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci private: 1881cb0ef41Sopenharmony_ci int object_id_; 1891cb0ef41Sopenharmony_ci}; 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_citemplate <typename Target, typename Fn> 1921cb0ef41Sopenharmony_ciclass CallRequest : public Request { 1931cb0ef41Sopenharmony_ci public: 1941cb0ef41Sopenharmony_ci CallRequest(int id, Fn fn) : id_(id), fn_(std::move(fn)) {} 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci void Call(MainThreadInterface* thread) override { 1971cb0ef41Sopenharmony_ci fn_(DeletableWrapper<Target>::get(thread, id_)); 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci private: 2011cb0ef41Sopenharmony_ci int id_; 2021cb0ef41Sopenharmony_ci Fn fn_; 2031cb0ef41Sopenharmony_ci}; 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_citemplate <typename T> 2061cb0ef41Sopenharmony_ciclass AnotherThreadObjectReference { 2071cb0ef41Sopenharmony_ci public: 2081cb0ef41Sopenharmony_ci AnotherThreadObjectReference( 2091cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> thread, int object_id) 2101cb0ef41Sopenharmony_ci : thread_(thread), object_id_(object_id) {} 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci template <typename Factory> 2131cb0ef41Sopenharmony_ci AnotherThreadObjectReference( 2141cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> thread, Factory factory) 2151cb0ef41Sopenharmony_ci : AnotherThreadObjectReference(thread, thread->newObjectId()) { 2161cb0ef41Sopenharmony_ci thread_->Post(NewCreateRequest(object_id_, std::move(factory))); 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci AnotherThreadObjectReference(AnotherThreadObjectReference&) = delete; 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci ~AnotherThreadObjectReference() { 2211cb0ef41Sopenharmony_ci // Disappearing thread may cause a memory leak 2221cb0ef41Sopenharmony_ci thread_->Post(std::make_unique<DeleteRequest>(object_id_)); 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci template <typename Fn> 2261cb0ef41Sopenharmony_ci void Call(Fn fn) const { 2271cb0ef41Sopenharmony_ci using Request = CallRequest<T, Fn>; 2281cb0ef41Sopenharmony_ci thread_->Post(std::unique_ptr<Request>( 2291cb0ef41Sopenharmony_ci new Request(object_id_, std::move(fn)))); 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci template <typename Arg> 2331cb0ef41Sopenharmony_ci void Call(void (T::*fn)(Arg), Arg argument) const { 2341cb0ef41Sopenharmony_ci Call(std::bind(Apply<Arg>, std::placeholders::_1, fn, std::move(argument))); 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci private: 2381cb0ef41Sopenharmony_ci // This has to use non-const reference to support std::bind with non-copyable 2391cb0ef41Sopenharmony_ci // types 2401cb0ef41Sopenharmony_ci template <typename Argument> 2411cb0ef41Sopenharmony_ci static void Apply(T* target, void (T::*fn)(Argument), 2421cb0ef41Sopenharmony_ci /* NOLINT (runtime/references) */ Argument& argument) { 2431cb0ef41Sopenharmony_ci (target->*fn)(std::move(argument)); 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> thread_; 2471cb0ef41Sopenharmony_ci const int object_id_; 2481cb0ef41Sopenharmony_ci}; 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ciclass MainThreadSessionState { 2511cb0ef41Sopenharmony_ci public: 2521cb0ef41Sopenharmony_ci MainThreadSessionState(MainThreadInterface* thread, bool prevent_shutdown) 2531cb0ef41Sopenharmony_ci : thread_(thread), 2541cb0ef41Sopenharmony_ci prevent_shutdown_(prevent_shutdown) {} 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci static std::unique_ptr<MainThreadSessionState> Create( 2571cb0ef41Sopenharmony_ci MainThreadInterface* thread, bool prevent_shutdown) { 2581cb0ef41Sopenharmony_ci return std::make_unique<MainThreadSessionState>(thread, prevent_shutdown); 2591cb0ef41Sopenharmony_ci } 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci void Connect(std::unique_ptr<InspectorSessionDelegate> delegate) { 2621cb0ef41Sopenharmony_ci Agent* agent = thread_->inspector_agent(); 2631cb0ef41Sopenharmony_ci if (agent != nullptr) 2641cb0ef41Sopenharmony_ci session_ = agent->Connect(std::move(delegate), prevent_shutdown_); 2651cb0ef41Sopenharmony_ci } 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci void Dispatch(std::unique_ptr<StringBuffer> message) { 2681cb0ef41Sopenharmony_ci session_->Dispatch(message->string()); 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci private: 2721cb0ef41Sopenharmony_ci MainThreadInterface* thread_; 2731cb0ef41Sopenharmony_ci bool prevent_shutdown_; 2741cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSession> session_; 2751cb0ef41Sopenharmony_ci}; 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ciclass CrossThreadInspectorSession : public InspectorSession { 2781cb0ef41Sopenharmony_ci public: 2791cb0ef41Sopenharmony_ci CrossThreadInspectorSession( 2801cb0ef41Sopenharmony_ci int id, 2811cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> thread, 2821cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate, 2831cb0ef41Sopenharmony_ci bool prevent_shutdown) 2841cb0ef41Sopenharmony_ci : state_(thread, std::bind(MainThreadSessionState::Create, 2851cb0ef41Sopenharmony_ci std::placeholders::_1, 2861cb0ef41Sopenharmony_ci prevent_shutdown)) { 2871cb0ef41Sopenharmony_ci state_.Call(&MainThreadSessionState::Connect, std::move(delegate)); 2881cb0ef41Sopenharmony_ci } 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci void Dispatch(const StringView& message) override { 2911cb0ef41Sopenharmony_ci state_.Call(&MainThreadSessionState::Dispatch, 2921cb0ef41Sopenharmony_ci StringBuffer::create(message)); 2931cb0ef41Sopenharmony_ci } 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci private: 2961cb0ef41Sopenharmony_ci AnotherThreadObjectReference<MainThreadSessionState> state_; 2971cb0ef41Sopenharmony_ci}; 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ciclass ThreadSafeDelegate : public InspectorSessionDelegate { 3001cb0ef41Sopenharmony_ci public: 3011cb0ef41Sopenharmony_ci ThreadSafeDelegate(std::shared_ptr<MainThreadHandle> thread, int object_id) 3021cb0ef41Sopenharmony_ci : thread_(thread), delegate_(thread, object_id) {} 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci void SendMessageToFrontend(const v8_inspector::StringView& message) override { 3051cb0ef41Sopenharmony_ci delegate_.Call( 3061cb0ef41Sopenharmony_ci [m = StringBuffer::create(message)] 3071cb0ef41Sopenharmony_ci (InspectorSessionDelegate* delegate) { 3081cb0ef41Sopenharmony_ci delegate->SendMessageToFrontend(m->string()); 3091cb0ef41Sopenharmony_ci }); 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci private: 3131cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> thread_; 3141cb0ef41Sopenharmony_ci AnotherThreadObjectReference<InspectorSessionDelegate> delegate_; 3151cb0ef41Sopenharmony_ci}; 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ciMainThreadInterface::MainThreadInterface(Agent* agent) : agent_(agent) {} 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ciMainThreadInterface::~MainThreadInterface() { 3201cb0ef41Sopenharmony_ci if (handle_) 3211cb0ef41Sopenharmony_ci handle_->Reset(); 3221cb0ef41Sopenharmony_ci} 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_civoid MainThreadInterface::Post(std::unique_ptr<Request> request) { 3251cb0ef41Sopenharmony_ci CHECK_NOT_NULL(agent_); 3261cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(requests_lock_); 3271cb0ef41Sopenharmony_ci bool needs_notify = requests_.empty(); 3281cb0ef41Sopenharmony_ci requests_.push_back(std::move(request)); 3291cb0ef41Sopenharmony_ci if (needs_notify) { 3301cb0ef41Sopenharmony_ci std::weak_ptr<MainThreadInterface> weak_self {shared_from_this()}; 3311cb0ef41Sopenharmony_ci agent_->env()->RequestInterrupt([weak_self](Environment*) { 3321cb0ef41Sopenharmony_ci if (auto iface = weak_self.lock()) iface->DispatchMessages(); 3331cb0ef41Sopenharmony_ci }); 3341cb0ef41Sopenharmony_ci } 3351cb0ef41Sopenharmony_ci incoming_message_cond_.Broadcast(scoped_lock); 3361cb0ef41Sopenharmony_ci} 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_cibool MainThreadInterface::WaitForFrontendEvent() { 3391cb0ef41Sopenharmony_ci // We allow DispatchMessages reentry as we enter the pause. This is important 3401cb0ef41Sopenharmony_ci // to support debugging the code invoked by an inspector call, such 3411cb0ef41Sopenharmony_ci // as Runtime.evaluate 3421cb0ef41Sopenharmony_ci dispatching_messages_ = false; 3431cb0ef41Sopenharmony_ci if (dispatching_message_queue_.empty()) { 3441cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(requests_lock_); 3451cb0ef41Sopenharmony_ci while (requests_.empty()) incoming_message_cond_.Wait(scoped_lock); 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci return true; 3481cb0ef41Sopenharmony_ci} 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_civoid MainThreadInterface::DispatchMessages() { 3511cb0ef41Sopenharmony_ci if (dispatching_messages_) 3521cb0ef41Sopenharmony_ci return; 3531cb0ef41Sopenharmony_ci dispatching_messages_ = true; 3541cb0ef41Sopenharmony_ci bool had_messages = false; 3551cb0ef41Sopenharmony_ci do { 3561cb0ef41Sopenharmony_ci if (dispatching_message_queue_.empty()) { 3571cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(requests_lock_); 3581cb0ef41Sopenharmony_ci requests_.swap(dispatching_message_queue_); 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci had_messages = !dispatching_message_queue_.empty(); 3611cb0ef41Sopenharmony_ci while (!dispatching_message_queue_.empty()) { 3621cb0ef41Sopenharmony_ci MessageQueue::value_type task; 3631cb0ef41Sopenharmony_ci std::swap(dispatching_message_queue_.front(), task); 3641cb0ef41Sopenharmony_ci dispatching_message_queue_.pop_front(); 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci v8::SealHandleScope seal_handle_scope(agent_->env()->isolate); 3671cb0ef41Sopenharmony_ci task->Call(this); 3681cb0ef41Sopenharmony_ci } 3691cb0ef41Sopenharmony_ci } while (had_messages); 3701cb0ef41Sopenharmony_ci dispatching_messages_ = false; 3711cb0ef41Sopenharmony_ci} 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_cistd::shared_ptr<MainThreadHandle> MainThreadInterface::GetHandle() { 3741cb0ef41Sopenharmony_ci if (handle_ == nullptr) 3751cb0ef41Sopenharmony_ci handle_ = std::make_shared<MainThreadHandle>(this); 3761cb0ef41Sopenharmony_ci return handle_; 3771cb0ef41Sopenharmony_ci} 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_civoid MainThreadInterface::AddObject(int id, 3801cb0ef41Sopenharmony_ci std::unique_ptr<Deletable> object) { 3811cb0ef41Sopenharmony_ci CHECK_NOT_NULL(object); 3821cb0ef41Sopenharmony_ci managed_objects_[id] = std::move(object); 3831cb0ef41Sopenharmony_ci} 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_civoid MainThreadInterface::RemoveObject(int id) { 3861cb0ef41Sopenharmony_ci CHECK_EQ(1, managed_objects_.erase(id)); 3871cb0ef41Sopenharmony_ci} 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ciDeletable* MainThreadInterface::GetObject(int id) { 3901cb0ef41Sopenharmony_ci Deletable* pointer = GetObjectIfExists(id); 3911cb0ef41Sopenharmony_ci // This would mean the object is requested after it was disposed, which is 3921cb0ef41Sopenharmony_ci // a coding error. 3931cb0ef41Sopenharmony_ci CHECK_NOT_NULL(pointer); 3941cb0ef41Sopenharmony_ci return pointer; 3951cb0ef41Sopenharmony_ci} 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ciDeletable* MainThreadInterface::GetObjectIfExists(int id) { 3981cb0ef41Sopenharmony_ci auto iterator = managed_objects_.find(id); 3991cb0ef41Sopenharmony_ci if (iterator == managed_objects_.end()) { 4001cb0ef41Sopenharmony_ci return nullptr; 4011cb0ef41Sopenharmony_ci } 4021cb0ef41Sopenharmony_ci return iterator->second.get(); 4031cb0ef41Sopenharmony_ci} 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_cistd::unique_ptr<InspectorSession> MainThreadHandle::Connect( 4061cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate, 4071cb0ef41Sopenharmony_ci bool prevent_shutdown) { 4081cb0ef41Sopenharmony_ci return std::unique_ptr<InspectorSession>( 4091cb0ef41Sopenharmony_ci new CrossThreadInspectorSession(++next_session_id_, 4101cb0ef41Sopenharmony_ci shared_from_this(), 4111cb0ef41Sopenharmony_ci std::move(delegate), 4121cb0ef41Sopenharmony_ci prevent_shutdown)); 4131cb0ef41Sopenharmony_ci} 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_cibool MainThreadHandle::Post(std::unique_ptr<Request> request) { 4161cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(block_lock_); 4171cb0ef41Sopenharmony_ci if (!main_thread_) 4181cb0ef41Sopenharmony_ci return false; 4191cb0ef41Sopenharmony_ci main_thread_->Post(std::move(request)); 4201cb0ef41Sopenharmony_ci return true; 4211cb0ef41Sopenharmony_ci} 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_civoid MainThreadHandle::Reset() { 4241cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(block_lock_); 4251cb0ef41Sopenharmony_ci main_thread_ = nullptr; 4261cb0ef41Sopenharmony_ci} 4271cb0ef41Sopenharmony_ci} // namespace 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_cinamespace { 4301cb0ef41Sopenharmony_ciusing node::CheckedUvLoopClose; 4311cb0ef41Sopenharmony_ciusing node::GetHumanReadableProcessName; 4321cb0ef41Sopenharmony_ciusing node::InspectPublishUid; 4331cb0ef41Sopenharmony_ciusing node::RegisterSignalHandler; 4341cb0ef41Sopenharmony_ciusing node::inspector::FormatWsAddress; 4351cb0ef41Sopenharmony_ciusing node::inspector::InspectorSocketServer; 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_cinamespace crypto = node::crypto; 4381cb0ef41Sopenharmony_cinamespace protocol = node::inspector::protocol; 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci// kKill closes connections and stops the server, kStop only stops the server 4411cb0ef41Sopenharmony_cienum class TransportAction { kKill, kSendMessage, kStop }; 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_cistd::string ScriptPath(uv_loop_t* loop, const std::string& script_name) { 4441cb0ef41Sopenharmony_ci std::string script_path; 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci if (!script_name.empty()) { 4471cb0ef41Sopenharmony_ci uv_fs_t req; 4481cb0ef41Sopenharmony_ci req.ptr = nullptr; 4491cb0ef41Sopenharmony_ci if (0 == uv_fs_realpath(loop, &req, script_name.c_str(), nullptr)) { 4501cb0ef41Sopenharmony_ci CHECK_NOT_NULL(req.ptr); 4511cb0ef41Sopenharmony_ci script_path = std::string(static_cast<char*>(req.ptr)); 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci uv_fs_req_cleanup(&req); 4541cb0ef41Sopenharmony_ci } 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci return script_path; 4571cb0ef41Sopenharmony_ci} 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci// UUID RFC: https://www.ietf.org/rfc/rfc4122.txt 4601cb0ef41Sopenharmony_ci// Used ver 4 - with numbers 4611cb0ef41Sopenharmony_cistd::string GenerateID() { 4621cb0ef41Sopenharmony_ci uint16_t buffer[8]; 4631cb0ef41Sopenharmony_ci CHECK(crypto::CSPRNG(buffer, sizeof(buffer)).is_ok()); 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci char uuid[256]; 4661cb0ef41Sopenharmony_ci snprintf(uuid, sizeof(uuid), "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", 4671cb0ef41Sopenharmony_ci buffer[0], // time_low 4681cb0ef41Sopenharmony_ci buffer[1], // time_mid 4691cb0ef41Sopenharmony_ci buffer[2], // time_low 4701cb0ef41Sopenharmony_ci (buffer[3] & 0x0fff) | 0x4000, // time_hi_and_version 4711cb0ef41Sopenharmony_ci (buffer[4] & 0x3fff) | 0x8000, // clk_seq_hi clk_seq_low 4721cb0ef41Sopenharmony_ci buffer[5], // node 4731cb0ef41Sopenharmony_ci buffer[6], 4741cb0ef41Sopenharmony_ci buffer[7]); 4751cb0ef41Sopenharmony_ci return uuid; 4761cb0ef41Sopenharmony_ci} 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ciclass RequestToServer { 4791cb0ef41Sopenharmony_ci public: 4801cb0ef41Sopenharmony_ci RequestToServer(TransportAction action, 4811cb0ef41Sopenharmony_ci int session_id, 4821cb0ef41Sopenharmony_ci std::unique_ptr<v8_inspector::StringBuffer> message) 4831cb0ef41Sopenharmony_ci : action_(action), 4841cb0ef41Sopenharmony_ci session_id_(session_id), 4851cb0ef41Sopenharmony_ci message_(std::move(message)) {} 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci void Dispatch(InspectorSocketServer* server) const { 4881cb0ef41Sopenharmony_ci switch (action_) { 4891cb0ef41Sopenharmony_ci case TransportAction::kKill: 4901cb0ef41Sopenharmony_ci server->TerminateConnections(); 4911cb0ef41Sopenharmony_ci [[fallthrough]]; 4921cb0ef41Sopenharmony_ci case TransportAction::kStop: 4931cb0ef41Sopenharmony_ci server->Stop(); 4941cb0ef41Sopenharmony_ci break; 4951cb0ef41Sopenharmony_ci case TransportAction::kSendMessage: 4961cb0ef41Sopenharmony_ci server->Send( 4971cb0ef41Sopenharmony_ci session_id_, 4981cb0ef41Sopenharmony_ci protocol::StringUtil::StringViewToUtf8(message_->string())); 4991cb0ef41Sopenharmony_ci break; 5001cb0ef41Sopenharmony_ci } 5011cb0ef41Sopenharmony_ci } 5021cb0ef41Sopenharmony_ci 5031cb0ef41Sopenharmony_ci private: 5041cb0ef41Sopenharmony_ci TransportAction action_; 5051cb0ef41Sopenharmony_ci int session_id_; 5061cb0ef41Sopenharmony_ci std::unique_ptr<v8_inspector::StringBuffer> message_; 5071cb0ef41Sopenharmony_ci}; 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ciclass RequestQueue; 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_ciclass RequestQueueData { 5121cb0ef41Sopenharmony_ci public: 5131cb0ef41Sopenharmony_ci using MessageQueue = std::deque<RequestToServer>; 5141cb0ef41Sopenharmony_ci 5151cb0ef41Sopenharmony_ci explicit RequestQueueData(uv_loop_t* loop) 5161cb0ef41Sopenharmony_ci : handle_(std::make_shared<RequestQueue>(this)) { 5171cb0ef41Sopenharmony_ci int err = uv_async_init(loop, &async_, [](uv_async_t* async) { 5181cb0ef41Sopenharmony_ci RequestQueueData* wrapper = 5191cb0ef41Sopenharmony_ci node::ContainerOf(&RequestQueueData::async_, async); 5201cb0ef41Sopenharmony_ci wrapper->DoDispatch(); 5211cb0ef41Sopenharmony_ci }); 5221cb0ef41Sopenharmony_ci CHECK_EQ(0, err); 5231cb0ef41Sopenharmony_ci } 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_ci static void CloseAndFree(RequestQueueData* queue); 5261cb0ef41Sopenharmony_ci 5271cb0ef41Sopenharmony_ci void Post(int session_id, 5281cb0ef41Sopenharmony_ci TransportAction action, 5291cb0ef41Sopenharmony_ci std::unique_ptr<StringBuffer> message) { 5301cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(state_lock_); 5311cb0ef41Sopenharmony_ci bool notify = messages_.empty(); 5321cb0ef41Sopenharmony_ci messages_.emplace_back(action, session_id, std::move(message)); 5331cb0ef41Sopenharmony_ci if (notify) { 5341cb0ef41Sopenharmony_ci CHECK_EQ(0, uv_async_send(&async_)); 5351cb0ef41Sopenharmony_ci incoming_message_cond_.Broadcast(scoped_lock); 5361cb0ef41Sopenharmony_ci } 5371cb0ef41Sopenharmony_ci } 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci void Wait() { 5401cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(state_lock_); 5411cb0ef41Sopenharmony_ci if (messages_.empty()) { 5421cb0ef41Sopenharmony_ci incoming_message_cond_.Wait(scoped_lock); 5431cb0ef41Sopenharmony_ci } 5441cb0ef41Sopenharmony_ci } 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci void SetServer(InspectorSocketServer* server) { 5471cb0ef41Sopenharmony_ci server_ = server; 5481cb0ef41Sopenharmony_ci } 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci std::shared_ptr<RequestQueue> handle() { 5511cb0ef41Sopenharmony_ci return handle_; 5521cb0ef41Sopenharmony_ci } 5531cb0ef41Sopenharmony_ci 5541cb0ef41Sopenharmony_ci private: 5551cb0ef41Sopenharmony_ci ~RequestQueueData() = default; 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci MessageQueue GetMessages() { 5581cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(state_lock_); 5591cb0ef41Sopenharmony_ci MessageQueue messages; 5601cb0ef41Sopenharmony_ci messages_.swap(messages); 5611cb0ef41Sopenharmony_ci return messages; 5621cb0ef41Sopenharmony_ci } 5631cb0ef41Sopenharmony_ci 5641cb0ef41Sopenharmony_ci void DoDispatch() { 5651cb0ef41Sopenharmony_ci if (server_ == nullptr) 5661cb0ef41Sopenharmony_ci return; 5671cb0ef41Sopenharmony_ci for (const auto& request : GetMessages()) { 5681cb0ef41Sopenharmony_ci request.Dispatch(server_); 5691cb0ef41Sopenharmony_ci } 5701cb0ef41Sopenharmony_ci } 5711cb0ef41Sopenharmony_ci 5721cb0ef41Sopenharmony_ci std::shared_ptr<RequestQueue> handle_; 5731cb0ef41Sopenharmony_ci uv_async_t async_; 5741cb0ef41Sopenharmony_ci InspectorSocketServer* server_ = nullptr; 5751cb0ef41Sopenharmony_ci MessageQueue messages_; 5761cb0ef41Sopenharmony_ci Mutex state_lock_; // Locked before mutating the queue. 5771cb0ef41Sopenharmony_ci ConditionVariable incoming_message_cond_; 5781cb0ef41Sopenharmony_ci}; 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_ciclass RequestQueue { 5811cb0ef41Sopenharmony_ci public: 5821cb0ef41Sopenharmony_ci explicit RequestQueue(RequestQueueData* data) : data_(data) {} 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_ci void Reset() { 5851cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(lock_); 5861cb0ef41Sopenharmony_ci data_ = nullptr; 5871cb0ef41Sopenharmony_ci } 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci void Post(int session_id, 5901cb0ef41Sopenharmony_ci TransportAction action, 5911cb0ef41Sopenharmony_ci std::unique_ptr<StringBuffer> message) { 5921cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(lock_); 5931cb0ef41Sopenharmony_ci if (data_ != nullptr) 5941cb0ef41Sopenharmony_ci data_->Post(session_id, action, std::move(message)); 5951cb0ef41Sopenharmony_ci } 5961cb0ef41Sopenharmony_ci 5971cb0ef41Sopenharmony_ci bool Expired() { 5981cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(lock_); 5991cb0ef41Sopenharmony_ci return data_ == nullptr; 6001cb0ef41Sopenharmony_ci } 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci private: 6031cb0ef41Sopenharmony_ci RequestQueueData* data_; 6041cb0ef41Sopenharmony_ci Mutex lock_; 6051cb0ef41Sopenharmony_ci}; 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ciclass IoSessionDelegate : public InspectorSessionDelegate { 6081cb0ef41Sopenharmony_ci public: 6091cb0ef41Sopenharmony_ci explicit IoSessionDelegate(std::shared_ptr<RequestQueue> queue, int id) 6101cb0ef41Sopenharmony_ci : request_queue_(queue), id_(id) { } 6111cb0ef41Sopenharmony_ci void SendMessageToFrontend(const v8_inspector::StringView& message) override { 6121cb0ef41Sopenharmony_ci request_queue_->Post(id_, TransportAction::kSendMessage, 6131cb0ef41Sopenharmony_ci StringBuffer::create(message)); 6141cb0ef41Sopenharmony_ci } 6151cb0ef41Sopenharmony_ci 6161cb0ef41Sopenharmony_ci private: 6171cb0ef41Sopenharmony_ci std::shared_ptr<RequestQueue> request_queue_; 6181cb0ef41Sopenharmony_ci int id_; 6191cb0ef41Sopenharmony_ci}; 6201cb0ef41Sopenharmony_ci 6211cb0ef41Sopenharmony_ci// Passed to InspectorSocketServer to handle WS inspector protocol events, 6221cb0ef41Sopenharmony_ci// mostly session start, message received, and session end. 6231cb0ef41Sopenharmony_ciclass InspectorIoDelegate: public node::inspector::SocketServerDelegate { 6241cb0ef41Sopenharmony_ci public: 6251cb0ef41Sopenharmony_ci InspectorIoDelegate(std::shared_ptr<RequestQueueData> queue, 6261cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> main_thread, 6271cb0ef41Sopenharmony_ci const std::string& target_id, 6281cb0ef41Sopenharmony_ci const std::string& script_path, 6291cb0ef41Sopenharmony_ci const std::string& script_name); 6301cb0ef41Sopenharmony_ci ~InspectorIoDelegate() override = default; 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_ci void StartSession(int session_id, const std::string& target_id) override; 6331cb0ef41Sopenharmony_ci void MessageReceived(int session_id, const std::string& message) override; 6341cb0ef41Sopenharmony_ci void EndSession(int session_id) override; 6351cb0ef41Sopenharmony_ci 6361cb0ef41Sopenharmony_ci std::vector<std::string> GetTargetIds() override; 6371cb0ef41Sopenharmony_ci std::string GetTargetTitle(const std::string& id) override; 6381cb0ef41Sopenharmony_ci std::string GetTargetUrl(const std::string& id) override; 6391cb0ef41Sopenharmony_ci void AssignServer(InspectorSocketServer* server) override { 6401cb0ef41Sopenharmony_ci request_queue_->SetServer(server); 6411cb0ef41Sopenharmony_ci } 6421cb0ef41Sopenharmony_ci 6431cb0ef41Sopenharmony_ci private: 6441cb0ef41Sopenharmony_ci std::shared_ptr<RequestQueueData> request_queue_; 6451cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> main_thread_; 6461cb0ef41Sopenharmony_ci std::unordered_map<int, std::unique_ptr<InspectorSession>> sessions_; 6471cb0ef41Sopenharmony_ci const std::string script_name_; 6481cb0ef41Sopenharmony_ci const std::string script_path_; 6491cb0ef41Sopenharmony_ci const std::string target_id_; 6501cb0ef41Sopenharmony_ci}; 6511cb0ef41Sopenharmony_ci 6521cb0ef41Sopenharmony_ciInspectorIoDelegate::InspectorIoDelegate( 6531cb0ef41Sopenharmony_ci std::shared_ptr<RequestQueueData> queue, 6541cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> main_thread, 6551cb0ef41Sopenharmony_ci const std::string& target_id, 6561cb0ef41Sopenharmony_ci const std::string& script_path, 6571cb0ef41Sopenharmony_ci const std::string& script_name) 6581cb0ef41Sopenharmony_ci : request_queue_(queue), main_thread_(main_thread), 6591cb0ef41Sopenharmony_ci script_name_(script_name), script_path_(script_path), 6601cb0ef41Sopenharmony_ci target_id_(target_id) {} 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_civoid InspectorIoDelegate::StartSession(int session_id, 6631cb0ef41Sopenharmony_ci const std::string& target_id) { 6641cb0ef41Sopenharmony_ci auto session = main_thread_->Connect( 6651cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate>( 6661cb0ef41Sopenharmony_ci new IoSessionDelegate(request_queue_->handle(), session_id)), true); 6671cb0ef41Sopenharmony_ci if (session) { 6681cb0ef41Sopenharmony_ci sessions_[session_id] = std::move(session); 6691cb0ef41Sopenharmony_ci fprintf(stderr, "Debugger attached.\n"); 6701cb0ef41Sopenharmony_ci } 6711cb0ef41Sopenharmony_ci} 6721cb0ef41Sopenharmony_ci 6731cb0ef41Sopenharmony_civoid InspectorIoDelegate::MessageReceived(int session_id, 6741cb0ef41Sopenharmony_ci const std::string& message) { 6751cb0ef41Sopenharmony_ci auto session = sessions_.find(session_id); 6761cb0ef41Sopenharmony_ci if (session != sessions_.end()) 6771cb0ef41Sopenharmony_ci session->second->Dispatch(Utf8ToStringView(message)->string()); 6781cb0ef41Sopenharmony_ci} 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_civoid InspectorIoDelegate::EndSession(int session_id) { 6811cb0ef41Sopenharmony_ci sessions_.erase(session_id); 6821cb0ef41Sopenharmony_ci} 6831cb0ef41Sopenharmony_ci 6841cb0ef41Sopenharmony_cistd::vector<std::string> InspectorIoDelegate::GetTargetIds() { 6851cb0ef41Sopenharmony_ci return { target_id_ }; 6861cb0ef41Sopenharmony_ci} 6871cb0ef41Sopenharmony_ci 6881cb0ef41Sopenharmony_cistd::string InspectorIoDelegate::GetTargetTitle(const std::string& id) { 6891cb0ef41Sopenharmony_ci return script_name_.empty() ? GetHumanReadableProcessName() : script_name_; 6901cb0ef41Sopenharmony_ci} 6911cb0ef41Sopenharmony_ci 6921cb0ef41Sopenharmony_cistd::string InspectorIoDelegate::GetTargetUrl(const std::string& id) { 6931cb0ef41Sopenharmony_ci return "file://" + script_path_; 6941cb0ef41Sopenharmony_ci} 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_ci// static 6971cb0ef41Sopenharmony_civoid RequestQueueData::CloseAndFree(RequestQueueData* queue) { 6981cb0ef41Sopenharmony_ci queue->handle_->Reset(); 6991cb0ef41Sopenharmony_ci queue->handle_.reset(); 7001cb0ef41Sopenharmony_ci uv_close(reinterpret_cast<uv_handle_t*>(&queue->async_), 7011cb0ef41Sopenharmony_ci [](uv_handle_t* handle) { 7021cb0ef41Sopenharmony_ci uv_async_t* async = reinterpret_cast<uv_async_t*>(handle); 7031cb0ef41Sopenharmony_ci RequestQueueData* wrapper = 7041cb0ef41Sopenharmony_ci node::ContainerOf(&RequestQueueData::async_, async); 7051cb0ef41Sopenharmony_ci delete wrapper; 7061cb0ef41Sopenharmony_ci }); 7071cb0ef41Sopenharmony_ci} 7081cb0ef41Sopenharmony_ci} // namespace 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ciclass InspectorIo { 7111cb0ef41Sopenharmony_ci public: 7121cb0ef41Sopenharmony_ci // Start the inspector agent thread, waiting for it to initialize 7131cb0ef41Sopenharmony_ci // bool Start(); 7141cb0ef41Sopenharmony_ci // Returns empty pointer if thread was not started 7151cb0ef41Sopenharmony_ci static std::unique_ptr<InspectorIo> Start( 7161cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> main_thread, 7171cb0ef41Sopenharmony_ci const std::string& path, 7181cb0ef41Sopenharmony_ci std::shared_ptr<ExclusiveAccess<HostPort>> host_port, 7191cb0ef41Sopenharmony_ci const node::InspectPublishUid& inspect_publish_uid); 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci // Will block till the transport thread shuts down 7221cb0ef41Sopenharmony_ci ~InspectorIo(); 7231cb0ef41Sopenharmony_ci 7241cb0ef41Sopenharmony_ci void StopAcceptingNewConnections(); 7251cb0ef41Sopenharmony_ci std::string GetWsUrl() const; 7261cb0ef41Sopenharmony_ci 7271cb0ef41Sopenharmony_ci private: 7281cb0ef41Sopenharmony_ci InspectorIo(std::shared_ptr<MainThreadHandle> handle, 7291cb0ef41Sopenharmony_ci const std::string& path, 7301cb0ef41Sopenharmony_ci std::shared_ptr<ExclusiveAccess<HostPort>> host_port, 7311cb0ef41Sopenharmony_ci const node::InspectPublishUid& inspect_publish_uid); 7321cb0ef41Sopenharmony_ci 7331cb0ef41Sopenharmony_ci // Wrapper for agent->ThreadMain() 7341cb0ef41Sopenharmony_ci static void ThreadMain(void* agent); 7351cb0ef41Sopenharmony_ci 7361cb0ef41Sopenharmony_ci // Runs a uv_loop_t 7371cb0ef41Sopenharmony_ci void ThreadMain(); 7381cb0ef41Sopenharmony_ci 7391cb0ef41Sopenharmony_ci // This is a thread-safe object that will post async tasks. It lives as long 7401cb0ef41Sopenharmony_ci // as an Inspector object lives (almost as long as an Isolate). 7411cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> main_thread_; 7421cb0ef41Sopenharmony_ci // Used to post on a frontend interface thread, lives while the server is 7431cb0ef41Sopenharmony_ci // running 7441cb0ef41Sopenharmony_ci std::shared_ptr<RequestQueue> request_queue_; 7451cb0ef41Sopenharmony_ci std::shared_ptr<ExclusiveAccess<HostPort>> host_port_; 7461cb0ef41Sopenharmony_ci node::InspectPublishUid inspect_publish_uid_; 7471cb0ef41Sopenharmony_ci 7481cb0ef41Sopenharmony_ci // The IO thread runs its own uv_loop to implement the TCP server off 7491cb0ef41Sopenharmony_ci // the main thread. 7501cb0ef41Sopenharmony_ci uv_thread_t thread_; 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_ci // For setting up interthread communications 7531cb0ef41Sopenharmony_ci Mutex thread_start_lock_; 7541cb0ef41Sopenharmony_ci node::ConditionVariable thread_start_condition_; 7551cb0ef41Sopenharmony_ci std::string script_name_; 7561cb0ef41Sopenharmony_ci // May be accessed from any thread 7571cb0ef41Sopenharmony_ci const std::string id_; 7581cb0ef41Sopenharmony_ci}; 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ci// static 7611cb0ef41Sopenharmony_cistd::unique_ptr<InspectorIo> InspectorIo::Start( 7621cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> main_thread, 7631cb0ef41Sopenharmony_ci const std::string& path, 7641cb0ef41Sopenharmony_ci std::shared_ptr<ExclusiveAccess<HostPort>> host_port, 7651cb0ef41Sopenharmony_ci const InspectPublishUid& inspect_publish_uid) { 7661cb0ef41Sopenharmony_ci auto io = std::unique_ptr<InspectorIo>( 7671cb0ef41Sopenharmony_ci new InspectorIo(main_thread, 7681cb0ef41Sopenharmony_ci path, 7691cb0ef41Sopenharmony_ci host_port, 7701cb0ef41Sopenharmony_ci inspect_publish_uid)); 7711cb0ef41Sopenharmony_ci if (io->request_queue_->Expired()) { // Thread is not running 7721cb0ef41Sopenharmony_ci return nullptr; 7731cb0ef41Sopenharmony_ci } 7741cb0ef41Sopenharmony_ci return io; 7751cb0ef41Sopenharmony_ci} 7761cb0ef41Sopenharmony_ci 7771cb0ef41Sopenharmony_ciInspectorIo::InspectorIo(std::shared_ptr<MainThreadHandle> main_thread, 7781cb0ef41Sopenharmony_ci const std::string& path, 7791cb0ef41Sopenharmony_ci std::shared_ptr<ExclusiveAccess<HostPort>> host_port, 7801cb0ef41Sopenharmony_ci const InspectPublishUid& inspect_publish_uid) 7811cb0ef41Sopenharmony_ci : main_thread_(main_thread), 7821cb0ef41Sopenharmony_ci host_port_(host_port), 7831cb0ef41Sopenharmony_ci inspect_publish_uid_(inspect_publish_uid), 7841cb0ef41Sopenharmony_ci thread_(), 7851cb0ef41Sopenharmony_ci script_name_(path), 7861cb0ef41Sopenharmony_ci id_(GenerateID()) { 7871cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(thread_start_lock_); 7881cb0ef41Sopenharmony_ci CHECK_EQ(uv_thread_create(&thread_, InspectorIo::ThreadMain, this), 0); 7891cb0ef41Sopenharmony_ci thread_start_condition_.Wait(scoped_lock); 7901cb0ef41Sopenharmony_ci} 7911cb0ef41Sopenharmony_ci 7921cb0ef41Sopenharmony_ciInspectorIo::~InspectorIo() { 7931cb0ef41Sopenharmony_ci request_queue_->Post(0, TransportAction::kKill, nullptr); 7941cb0ef41Sopenharmony_ci int err = uv_thread_join(&thread_); 7951cb0ef41Sopenharmony_ci CHECK_EQ(err, 0); 7961cb0ef41Sopenharmony_ci} 7971cb0ef41Sopenharmony_ci 7981cb0ef41Sopenharmony_civoid InspectorIo::StopAcceptingNewConnections() { 7991cb0ef41Sopenharmony_ci request_queue_->Post(0, TransportAction::kStop, nullptr); 8001cb0ef41Sopenharmony_ci} 8011cb0ef41Sopenharmony_ci 8021cb0ef41Sopenharmony_ci// static 8031cb0ef41Sopenharmony_civoid InspectorIo::ThreadMain(void* io) { 8041cb0ef41Sopenharmony_ci static_cast<InspectorIo*>(io)->ThreadMain(); 8051cb0ef41Sopenharmony_ci} 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_civoid InspectorIo::ThreadMain() { 8081cb0ef41Sopenharmony_ci uv_loop_t loop; 8091cb0ef41Sopenharmony_ci loop.data = nullptr; 8101cb0ef41Sopenharmony_ci int err = uv_loop_init(&loop); 8111cb0ef41Sopenharmony_ci CHECK_EQ(err, 0); 8121cb0ef41Sopenharmony_ci std::shared_ptr<RequestQueueData> queue(new RequestQueueData(&loop), 8131cb0ef41Sopenharmony_ci RequestQueueData::CloseAndFree); 8141cb0ef41Sopenharmony_ci std::string script_path = ScriptPath(&loop, script_name_); 8151cb0ef41Sopenharmony_ci std::unique_ptr<InspectorIoDelegate> delegate( 8161cb0ef41Sopenharmony_ci new InspectorIoDelegate(queue, main_thread_, id_, 8171cb0ef41Sopenharmony_ci script_path, script_name_)); 8181cb0ef41Sopenharmony_ci std::string host; 8191cb0ef41Sopenharmony_ci int port; 8201cb0ef41Sopenharmony_ci int pid; 8211cb0ef41Sopenharmony_ci { 8221cb0ef41Sopenharmony_ci ExclusiveAccess<HostPort>::Scoped host_port(host_port_); 8231cb0ef41Sopenharmony_ci host = host_port->host(); 8241cb0ef41Sopenharmony_ci port = host_port->port(); 8251cb0ef41Sopenharmony_ci pid = host_port->pid(); 8261cb0ef41Sopenharmony_ci } 8271cb0ef41Sopenharmony_ci InspectorSocketServer server(std::move(delegate), 8281cb0ef41Sopenharmony_ci &loop, 8291cb0ef41Sopenharmony_ci std::move(host), 8301cb0ef41Sopenharmony_ci port, 8311cb0ef41Sopenharmony_ci inspect_publish_uid_, 8321cb0ef41Sopenharmony_ci stderr, 8331cb0ef41Sopenharmony_ci pid); 8341cb0ef41Sopenharmony_ci request_queue_ = queue->handle(); 8351cb0ef41Sopenharmony_ci // Its lifetime is now that of the server delegate 8361cb0ef41Sopenharmony_ci queue.reset(); 8371cb0ef41Sopenharmony_ci { 8381cb0ef41Sopenharmony_ci Mutex::ScopedLock scoped_lock(thread_start_lock_); 8391cb0ef41Sopenharmony_ci if (server.Start()) { 8401cb0ef41Sopenharmony_ci ExclusiveAccess<HostPort>::Scoped host_port(host_port_); 8411cb0ef41Sopenharmony_ci host_port->set_port(server.Port()); 8421cb0ef41Sopenharmony_ci } 8431cb0ef41Sopenharmony_ci thread_start_condition_.Broadcast(scoped_lock); 8441cb0ef41Sopenharmony_ci } 8451cb0ef41Sopenharmony_ci uv_run(&loop, UV_RUN_DEFAULT); 8461cb0ef41Sopenharmony_ci CheckedUvLoopClose(&loop); 8471cb0ef41Sopenharmony_ci} 8481cb0ef41Sopenharmony_ci 8491cb0ef41Sopenharmony_cistd::string InspectorIo::GetWsUrl() const { 8501cb0ef41Sopenharmony_ci ExclusiveAccess<HostPort>::Scoped host_port(host_port_); 8511cb0ef41Sopenharmony_ci return FormatWsAddress(host_port->host(), host_port->port(), id_, true); 8521cb0ef41Sopenharmony_ci} 8531cb0ef41Sopenharmony_ci 8541cb0ef41Sopenharmony_cinamespace { 8551cb0ef41Sopenharmony_ci 8561cb0ef41Sopenharmony_ciusing node::DebugCategory; 8571cb0ef41Sopenharmony_ciusing node::TwoByteValue; 8581cb0ef41Sopenharmony_ci 8591cb0ef41Sopenharmony_ciusing v8::Context; 8601cb0ef41Sopenharmony_ciusing v8::Function; 8611cb0ef41Sopenharmony_ciusing v8::HandleScope; 8621cb0ef41Sopenharmony_ciusing v8::Isolate; 8631cb0ef41Sopenharmony_ciusing v8::Local; 8641cb0ef41Sopenharmony_ciusing v8::Message; 8651cb0ef41Sopenharmony_ciusing v8::Object; 8661cb0ef41Sopenharmony_ciusing v8::Value; 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_ciusing v8_inspector::StringBuffer; 8691cb0ef41Sopenharmony_ciusing v8_inspector::StringView; 8701cb0ef41Sopenharmony_ciusing v8_inspector::V8Inspector; 8711cb0ef41Sopenharmony_ciusing v8_inspector::V8InspectorClient; 8721cb0ef41Sopenharmony_ci 8731cb0ef41Sopenharmony_cinamespace per_process = node::per_process; 8741cb0ef41Sopenharmony_ci 8751cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> ToProtocolString(Isolate* isolate, 8761cb0ef41Sopenharmony_ci Local<Value> value) { 8771cb0ef41Sopenharmony_ci TwoByteValue buffer(isolate, value); 8781cb0ef41Sopenharmony_ci return StringBuffer::create(StringView(*buffer, buffer.length())); 8791cb0ef41Sopenharmony_ci} 8801cb0ef41Sopenharmony_ci 8811cb0ef41Sopenharmony_ci 8821cb0ef41Sopenharmony_ciconst int CONTEXT_GROUP_ID = 1; 8831cb0ef41Sopenharmony_ci 8841cb0ef41Sopenharmony_cistd::string GetWorkerLabel(Environment* env) { 8851cb0ef41Sopenharmony_ci std::ostringstream result; 8861cb0ef41Sopenharmony_ci // TODO: use thread ID as part of worker label. 8871cb0ef41Sopenharmony_ci result << "Worker[" << "env->thread_id()" << "]"; 8881cb0ef41Sopenharmony_ci return result.str(); 8891cb0ef41Sopenharmony_ci} 8901cb0ef41Sopenharmony_ci 8911cb0ef41Sopenharmony_ciclass ChannelImpl final : public v8_inspector::V8Inspector::Channel, 8921cb0ef41Sopenharmony_ci public protocol::FrontendChannel { 8931cb0ef41Sopenharmony_ci public: 8941cb0ef41Sopenharmony_ci explicit ChannelImpl(const std::unique_ptr<V8Inspector>& inspector, 8951cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate, 8961cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> main_thread_, 8971cb0ef41Sopenharmony_ci bool prevent_shutdown) 8981cb0ef41Sopenharmony_ci : delegate_(std::move(delegate)), prevent_shutdown_(prevent_shutdown), 8991cb0ef41Sopenharmony_ci retaining_context_(false) { 9001cb0ef41Sopenharmony_ci session_ = inspector->connect(CONTEXT_GROUP_ID, 9011cb0ef41Sopenharmony_ci this, 9021cb0ef41Sopenharmony_ci StringView(), 9031cb0ef41Sopenharmony_ci V8Inspector::ClientTrustLevel::kFullyTrusted); 9041cb0ef41Sopenharmony_ci node_dispatcher_ = std::make_unique<protocol::UberDispatcher>(this); 9051cb0ef41Sopenharmony_ci runtime_agent_ = std::make_unique<protocol::RuntimeAgent>(); 9061cb0ef41Sopenharmony_ci runtime_agent_->Wire(node_dispatcher_.get()); 9071cb0ef41Sopenharmony_ci } 9081cb0ef41Sopenharmony_ci 9091cb0ef41Sopenharmony_ci ~ChannelImpl() override { 9101cb0ef41Sopenharmony_ci if (worker_agent_) { 9111cb0ef41Sopenharmony_ci worker_agent_->disable(); 9121cb0ef41Sopenharmony_ci worker_agent_.reset(); // Dispose before the dispatchers 9131cb0ef41Sopenharmony_ci } 9141cb0ef41Sopenharmony_ci runtime_agent_->disable(); 9151cb0ef41Sopenharmony_ci runtime_agent_.reset(); // Dispose before the dispatchers 9161cb0ef41Sopenharmony_ci } 9171cb0ef41Sopenharmony_ci 9181cb0ef41Sopenharmony_ci void dispatchProtocolMessage(const StringView& message) { 9191cb0ef41Sopenharmony_ci std::string raw_message = protocol::StringUtil::StringViewToUtf8(message); 9201cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::INSPECTOR_SERVER, 9211cb0ef41Sopenharmony_ci "[inspector received] %s\n", 9221cb0ef41Sopenharmony_ci raw_message); 9231cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> value = 9241cb0ef41Sopenharmony_ci protocol::DictionaryValue::cast( 9251cb0ef41Sopenharmony_ci protocol::StringUtil::parseJSON(message)); 9261cb0ef41Sopenharmony_ci int call_id; 9271cb0ef41Sopenharmony_ci std::string method; 9281cb0ef41Sopenharmony_ci node_dispatcher_->parseCommand(value.get(), &call_id, &method); 9291cb0ef41Sopenharmony_ci if (v8_inspector::V8InspectorSession::canDispatchMethod( 9301cb0ef41Sopenharmony_ci Utf8ToStringView(method)->string())) { 9311cb0ef41Sopenharmony_ci session_->dispatchProtocolMessage(message); 9321cb0ef41Sopenharmony_ci } else { 9331cb0ef41Sopenharmony_ci node_dispatcher_->dispatch(call_id, method, std::move(value), 9341cb0ef41Sopenharmony_ci raw_message); 9351cb0ef41Sopenharmony_ci } 9361cb0ef41Sopenharmony_ci } 9371cb0ef41Sopenharmony_ci 9381cb0ef41Sopenharmony_ci void schedulePauseOnNextStatement(const std::string& reason) { 9391cb0ef41Sopenharmony_ci std::unique_ptr<StringBuffer> buffer = Utf8ToStringView(reason); 9401cb0ef41Sopenharmony_ci session_->schedulePauseOnNextStatement(buffer->string(), buffer->string()); 9411cb0ef41Sopenharmony_ci } 9421cb0ef41Sopenharmony_ci 9431cb0ef41Sopenharmony_ci bool preventShutdown() { 9441cb0ef41Sopenharmony_ci return prevent_shutdown_; 9451cb0ef41Sopenharmony_ci } 9461cb0ef41Sopenharmony_ci 9471cb0ef41Sopenharmony_ci bool notifyWaitingForDisconnect() { 9481cb0ef41Sopenharmony_ci retaining_context_ = runtime_agent_->notifyWaitingForDisconnect(); 9491cb0ef41Sopenharmony_ci return retaining_context_; 9501cb0ef41Sopenharmony_ci } 9511cb0ef41Sopenharmony_ci 9521cb0ef41Sopenharmony_ci bool retainingContext() { 9531cb0ef41Sopenharmony_ci return retaining_context_; 9541cb0ef41Sopenharmony_ci } 9551cb0ef41Sopenharmony_ci 9561cb0ef41Sopenharmony_ci private: 9571cb0ef41Sopenharmony_ci void sendResponse( 9581cb0ef41Sopenharmony_ci int callId, 9591cb0ef41Sopenharmony_ci std::unique_ptr<v8_inspector::StringBuffer> message) override { 9601cb0ef41Sopenharmony_ci sendMessageToFrontend(message->string()); 9611cb0ef41Sopenharmony_ci } 9621cb0ef41Sopenharmony_ci 9631cb0ef41Sopenharmony_ci void sendNotification( 9641cb0ef41Sopenharmony_ci std::unique_ptr<v8_inspector::StringBuffer> message) override { 9651cb0ef41Sopenharmony_ci sendMessageToFrontend(message->string()); 9661cb0ef41Sopenharmony_ci } 9671cb0ef41Sopenharmony_ci 9681cb0ef41Sopenharmony_ci void flushProtocolNotifications() override { } 9691cb0ef41Sopenharmony_ci 9701cb0ef41Sopenharmony_ci void sendMessageToFrontend(const StringView& message) { 9711cb0ef41Sopenharmony_ci if (per_process::enabled_debug_list.enabled( 9721cb0ef41Sopenharmony_ci DebugCategory::INSPECTOR_SERVER)) { 9731cb0ef41Sopenharmony_ci std::string raw_message = protocol::StringUtil::StringViewToUtf8(message); 9741cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::INSPECTOR_SERVER, 9751cb0ef41Sopenharmony_ci "[inspector send] %s\n", 9761cb0ef41Sopenharmony_ci raw_message); 9771cb0ef41Sopenharmony_ci } 9781cb0ef41Sopenharmony_ci delegate_->SendMessageToFrontend(message); 9791cb0ef41Sopenharmony_ci } 9801cb0ef41Sopenharmony_ci 9811cb0ef41Sopenharmony_ci void sendMessageToFrontend(const std::string& message) { 9821cb0ef41Sopenharmony_ci sendMessageToFrontend(Utf8ToStringView(message)->string()); 9831cb0ef41Sopenharmony_ci } 9841cb0ef41Sopenharmony_ci 9851cb0ef41Sopenharmony_ci using Serializable = protocol::Serializable; 9861cb0ef41Sopenharmony_ci 9871cb0ef41Sopenharmony_ci void sendProtocolResponse(int callId, 9881cb0ef41Sopenharmony_ci std::unique_ptr<Serializable> message) override { 9891cb0ef41Sopenharmony_ci sendMessageToFrontend(message->serializeToJSON()); 9901cb0ef41Sopenharmony_ci } 9911cb0ef41Sopenharmony_ci void sendProtocolNotification( 9921cb0ef41Sopenharmony_ci std::unique_ptr<Serializable> message) override { 9931cb0ef41Sopenharmony_ci sendMessageToFrontend(message->serializeToJSON()); 9941cb0ef41Sopenharmony_ci } 9951cb0ef41Sopenharmony_ci 9961cb0ef41Sopenharmony_ci void fallThrough(int callId, 9971cb0ef41Sopenharmony_ci const std::string& method, 9981cb0ef41Sopenharmony_ci const std::string& message) override { 9991cb0ef41Sopenharmony_ci DCHECK(false); 10001cb0ef41Sopenharmony_ci } 10011cb0ef41Sopenharmony_ci 10021cb0ef41Sopenharmony_ci std::unique_ptr<protocol::RuntimeAgent> runtime_agent_; 10031cb0ef41Sopenharmony_ci std::unique_ptr<protocol::WorkerAgent> worker_agent_; 10041cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate_; 10051cb0ef41Sopenharmony_ci std::unique_ptr<v8_inspector::V8InspectorSession> session_; 10061cb0ef41Sopenharmony_ci std::unique_ptr<protocol::UberDispatcher> node_dispatcher_; 10071cb0ef41Sopenharmony_ci bool prevent_shutdown_; 10081cb0ef41Sopenharmony_ci bool retaining_context_; 10091cb0ef41Sopenharmony_ci}; 10101cb0ef41Sopenharmony_ci 10111cb0ef41Sopenharmony_ciclass SameThreadInspectorSession : public InspectorSession { 10121cb0ef41Sopenharmony_ci public: 10131cb0ef41Sopenharmony_ci SameThreadInspectorSession( 10141cb0ef41Sopenharmony_ci int session_id, std::shared_ptr<InspectorClient> client) 10151cb0ef41Sopenharmony_ci : session_id_(session_id), client_(client) {} 10161cb0ef41Sopenharmony_ci ~SameThreadInspectorSession() override; 10171cb0ef41Sopenharmony_ci void Dispatch(const v8_inspector::StringView& message) override; 10181cb0ef41Sopenharmony_ci 10191cb0ef41Sopenharmony_ci private: 10201cb0ef41Sopenharmony_ci int session_id_; 10211cb0ef41Sopenharmony_ci std::weak_ptr<InspectorClient> client_; 10221cb0ef41Sopenharmony_ci}; 10231cb0ef41Sopenharmony_ci 10241cb0ef41Sopenharmony_cibool IsFilePath(const std::string& path) { 10251cb0ef41Sopenharmony_ci return !path.empty() && path[0] == '/'; 10261cb0ef41Sopenharmony_ci} 10271cb0ef41Sopenharmony_ci 10281cb0ef41Sopenharmony_civoid ThrowUninitializedInspectorError(Environment* env) { 10291cb0ef41Sopenharmony_ci HandleScope scope(env->isolate); 10301cb0ef41Sopenharmony_ci 10311cb0ef41Sopenharmony_ci const char* msg = "This Environment was initialized without a V8::Inspector"; 10321cb0ef41Sopenharmony_ci Local<Value> exception = 10331cb0ef41Sopenharmony_ci v8::String::NewFromUtf8(env->isolate, msg).ToLocalChecked(); 10341cb0ef41Sopenharmony_ci 10351cb0ef41Sopenharmony_ci env->isolate->ThrowException(exception); 10361cb0ef41Sopenharmony_ci} 10371cb0ef41Sopenharmony_ci 10381cb0ef41Sopenharmony_ci} // namespace 10391cb0ef41Sopenharmony_ci 10401cb0ef41Sopenharmony_ciclass InspectorClient : public V8InspectorClient { 10411cb0ef41Sopenharmony_ci public: 10421cb0ef41Sopenharmony_ci explicit InspectorClient(Environment* env, bool is_main) 10431cb0ef41Sopenharmony_ci : env_(env), is_main_(is_main) { 10441cb0ef41Sopenharmony_ci client_ = V8Inspector::create(env->isolate, this); 10451cb0ef41Sopenharmony_ci // TODO(bnoordhuis) Make name configurable from src/node.cc. 10461cb0ef41Sopenharmony_ci std::string name = 10471cb0ef41Sopenharmony_ci is_main_ ? GetHumanReadableProcessName() : GetWorkerLabel(env); 10481cb0ef41Sopenharmony_ci ContextInfo info(name); 10491cb0ef41Sopenharmony_ci info.is_default = true; 10501cb0ef41Sopenharmony_ci contextCreated(env->context(), info); 10511cb0ef41Sopenharmony_ci } 10521cb0ef41Sopenharmony_ci 10531cb0ef41Sopenharmony_ci void runMessageLoopOnPause(int context_group_id) override { 10541cb0ef41Sopenharmony_ci waiting_for_resume_ = true; 10551cb0ef41Sopenharmony_ci runMessageLoop(); 10561cb0ef41Sopenharmony_ci } 10571cb0ef41Sopenharmony_ci 10581cb0ef41Sopenharmony_ci void waitForSessionsDisconnect() { 10591cb0ef41Sopenharmony_ci waiting_for_sessions_disconnect_ = true; 10601cb0ef41Sopenharmony_ci runMessageLoop(); 10611cb0ef41Sopenharmony_ci } 10621cb0ef41Sopenharmony_ci 10631cb0ef41Sopenharmony_ci void waitForFrontend() { 10641cb0ef41Sopenharmony_ci waiting_for_frontend_ = true; 10651cb0ef41Sopenharmony_ci runMessageLoop(); 10661cb0ef41Sopenharmony_ci } 10671cb0ef41Sopenharmony_ci 10681cb0ef41Sopenharmony_ci void maxAsyncCallStackDepthChanged(int depth) override { 10691cb0ef41Sopenharmony_ci if (waiting_for_sessions_disconnect_) { 10701cb0ef41Sopenharmony_ci // V8 isolate is mostly done and is only letting Inspector protocol 10711cb0ef41Sopenharmony_ci // clients gather data. 10721cb0ef41Sopenharmony_ci return; 10731cb0ef41Sopenharmony_ci } 10741cb0ef41Sopenharmony_ci } 10751cb0ef41Sopenharmony_ci 10761cb0ef41Sopenharmony_ci void contextCreated(Local<Context> context, const ContextInfo& info) { 10771cb0ef41Sopenharmony_ci auto name_buffer = Utf8ToStringView(info.name); 10781cb0ef41Sopenharmony_ci auto origin_buffer = Utf8ToStringView(info.origin); 10791cb0ef41Sopenharmony_ci std::unique_ptr<StringBuffer> aux_data_buffer; 10801cb0ef41Sopenharmony_ci 10811cb0ef41Sopenharmony_ci v8_inspector::V8ContextInfo v8info( 10821cb0ef41Sopenharmony_ci context, CONTEXT_GROUP_ID, name_buffer->string()); 10831cb0ef41Sopenharmony_ci v8info.origin = origin_buffer->string(); 10841cb0ef41Sopenharmony_ci 10851cb0ef41Sopenharmony_ci if (info.is_default) { 10861cb0ef41Sopenharmony_ci aux_data_buffer = Utf8ToStringView("{\"isDefault\":true}"); 10871cb0ef41Sopenharmony_ci } else { 10881cb0ef41Sopenharmony_ci aux_data_buffer = Utf8ToStringView("{\"isDefault\":false}"); 10891cb0ef41Sopenharmony_ci } 10901cb0ef41Sopenharmony_ci v8info.auxData = aux_data_buffer->string(); 10911cb0ef41Sopenharmony_ci 10921cb0ef41Sopenharmony_ci client_->contextCreated(v8info); 10931cb0ef41Sopenharmony_ci } 10941cb0ef41Sopenharmony_ci 10951cb0ef41Sopenharmony_ci void contextDestroyed(Local<Context> context) { 10961cb0ef41Sopenharmony_ci client_->contextDestroyed(context); 10971cb0ef41Sopenharmony_ci } 10981cb0ef41Sopenharmony_ci 10991cb0ef41Sopenharmony_ci void quitMessageLoopOnPause() override { 11001cb0ef41Sopenharmony_ci waiting_for_resume_ = false; 11011cb0ef41Sopenharmony_ci } 11021cb0ef41Sopenharmony_ci 11031cb0ef41Sopenharmony_ci void runIfWaitingForDebugger(int context_group_id) override { 11041cb0ef41Sopenharmony_ci waiting_for_frontend_ = false; 11051cb0ef41Sopenharmony_ci } 11061cb0ef41Sopenharmony_ci 11071cb0ef41Sopenharmony_ci int connectFrontend(std::unique_ptr<InspectorSessionDelegate> delegate, 11081cb0ef41Sopenharmony_ci bool prevent_shutdown) { 11091cb0ef41Sopenharmony_ci int session_id = next_session_id_++; 11101cb0ef41Sopenharmony_ci channels_[session_id] = std::make_unique<ChannelImpl>(client_, 11111cb0ef41Sopenharmony_ci std::move(delegate), 11121cb0ef41Sopenharmony_ci getThreadHandle(), 11131cb0ef41Sopenharmony_ci prevent_shutdown); 11141cb0ef41Sopenharmony_ci return session_id; 11151cb0ef41Sopenharmony_ci } 11161cb0ef41Sopenharmony_ci 11171cb0ef41Sopenharmony_ci void disconnectFrontend(int session_id) { 11181cb0ef41Sopenharmony_ci auto it = channels_.find(session_id); 11191cb0ef41Sopenharmony_ci if (it == channels_.end()) 11201cb0ef41Sopenharmony_ci return; 11211cb0ef41Sopenharmony_ci bool retaining_context = it->second->retainingContext(); 11221cb0ef41Sopenharmony_ci channels_.erase(it); 11231cb0ef41Sopenharmony_ci if (retaining_context) { 11241cb0ef41Sopenharmony_ci for (const auto& id_channel : channels_) { 11251cb0ef41Sopenharmony_ci if (id_channel.second->retainingContext()) 11261cb0ef41Sopenharmony_ci return; 11271cb0ef41Sopenharmony_ci } 11281cb0ef41Sopenharmony_ci contextDestroyed(env_->context()); 11291cb0ef41Sopenharmony_ci } 11301cb0ef41Sopenharmony_ci if (waiting_for_sessions_disconnect_ && !is_main_) 11311cb0ef41Sopenharmony_ci waiting_for_sessions_disconnect_ = false; 11321cb0ef41Sopenharmony_ci } 11331cb0ef41Sopenharmony_ci 11341cb0ef41Sopenharmony_ci void dispatchMessageFromFrontend(int session_id, const StringView& message) { 11351cb0ef41Sopenharmony_ci channels_[session_id]->dispatchProtocolMessage(message); 11361cb0ef41Sopenharmony_ci } 11371cb0ef41Sopenharmony_ci 11381cb0ef41Sopenharmony_ci Local<Context> ensureDefaultContextInGroup(int contextGroupId) override { 11391cb0ef41Sopenharmony_ci return env_->context(); 11401cb0ef41Sopenharmony_ci } 11411cb0ef41Sopenharmony_ci 11421cb0ef41Sopenharmony_ci void ReportUncaughtException(Local<Value> error, Local<Message> message) { 11431cb0ef41Sopenharmony_ci Isolate* isolate = env_->isolate; 11441cb0ef41Sopenharmony_ci Local<Context> context = env_->context(); 11451cb0ef41Sopenharmony_ci 11461cb0ef41Sopenharmony_ci int script_id = message->GetScriptOrigin().ScriptId(); 11471cb0ef41Sopenharmony_ci 11481cb0ef41Sopenharmony_ci Local<v8::StackTrace> stack_trace = message->GetStackTrace(); 11491cb0ef41Sopenharmony_ci 11501cb0ef41Sopenharmony_ci if (!stack_trace.IsEmpty() && stack_trace->GetFrameCount() > 0 && 11511cb0ef41Sopenharmony_ci script_id == stack_trace->GetFrame(isolate, 0)->GetScriptId()) { 11521cb0ef41Sopenharmony_ci script_id = 0; 11531cb0ef41Sopenharmony_ci } 11541cb0ef41Sopenharmony_ci 11551cb0ef41Sopenharmony_ci const uint8_t DETAILS[] = "Uncaught"; 11561cb0ef41Sopenharmony_ci 11571cb0ef41Sopenharmony_ci client_->exceptionThrown( 11581cb0ef41Sopenharmony_ci context, 11591cb0ef41Sopenharmony_ci StringView(DETAILS, sizeof(DETAILS) - 1), 11601cb0ef41Sopenharmony_ci error, 11611cb0ef41Sopenharmony_ci ToProtocolString(isolate, message->Get())->string(), 11621cb0ef41Sopenharmony_ci ToProtocolString(isolate, message->GetScriptResourceName())->string(), 11631cb0ef41Sopenharmony_ci message->GetLineNumber(context).FromMaybe(0), 11641cb0ef41Sopenharmony_ci message->GetStartColumn(context).FromMaybe(0), 11651cb0ef41Sopenharmony_ci client_->createStackTrace(stack_trace), 11661cb0ef41Sopenharmony_ci script_id); 11671cb0ef41Sopenharmony_ci } 11681cb0ef41Sopenharmony_ci 11691cb0ef41Sopenharmony_ci void startRepeatingTimer(double interval_s, 11701cb0ef41Sopenharmony_ci TimerCallback callback, 11711cb0ef41Sopenharmony_ci void* data) override { 11721cb0ef41Sopenharmony_ci // TODO: implement this for supporting heap profiler. 11731cb0ef41Sopenharmony_ci } 11741cb0ef41Sopenharmony_ci 11751cb0ef41Sopenharmony_ci void cancelTimer(void* data) override { 11761cb0ef41Sopenharmony_ci // TODO: implement this for supporting heap profiler. 11771cb0ef41Sopenharmony_ci } 11781cb0ef41Sopenharmony_ci 11791cb0ef41Sopenharmony_ci // Async stack traces instrumentation. 11801cb0ef41Sopenharmony_ci void AsyncTaskScheduled(const StringView& task_name, void* task, 11811cb0ef41Sopenharmony_ci bool recurring) { 11821cb0ef41Sopenharmony_ci client_->asyncTaskScheduled(task_name, task, recurring); 11831cb0ef41Sopenharmony_ci } 11841cb0ef41Sopenharmony_ci 11851cb0ef41Sopenharmony_ci void AsyncTaskCanceled(void* task) { 11861cb0ef41Sopenharmony_ci client_->asyncTaskCanceled(task); 11871cb0ef41Sopenharmony_ci } 11881cb0ef41Sopenharmony_ci 11891cb0ef41Sopenharmony_ci void AsyncTaskStarted(void* task) { 11901cb0ef41Sopenharmony_ci client_->asyncTaskStarted(task); 11911cb0ef41Sopenharmony_ci } 11921cb0ef41Sopenharmony_ci 11931cb0ef41Sopenharmony_ci void AsyncTaskFinished(void* task) { 11941cb0ef41Sopenharmony_ci client_->asyncTaskFinished(task); 11951cb0ef41Sopenharmony_ci } 11961cb0ef41Sopenharmony_ci 11971cb0ef41Sopenharmony_ci void AllAsyncTasksCanceled() { 11981cb0ef41Sopenharmony_ci client_->allAsyncTasksCanceled(); 11991cb0ef41Sopenharmony_ci } 12001cb0ef41Sopenharmony_ci 12011cb0ef41Sopenharmony_ci void schedulePauseOnNextStatement(const std::string& reason) { 12021cb0ef41Sopenharmony_ci for (const auto& id_channel : channels_) { 12031cb0ef41Sopenharmony_ci id_channel.second->schedulePauseOnNextStatement(reason); 12041cb0ef41Sopenharmony_ci } 12051cb0ef41Sopenharmony_ci } 12061cb0ef41Sopenharmony_ci 12071cb0ef41Sopenharmony_ci bool hasConnectedSessions() { 12081cb0ef41Sopenharmony_ci for (const auto& id_channel : channels_) { 12091cb0ef41Sopenharmony_ci // Other sessions are "invisible" more most purposes 12101cb0ef41Sopenharmony_ci if (id_channel.second->preventShutdown()) 12111cb0ef41Sopenharmony_ci return true; 12121cb0ef41Sopenharmony_ci } 12131cb0ef41Sopenharmony_ci return false; 12141cb0ef41Sopenharmony_ci } 12151cb0ef41Sopenharmony_ci 12161cb0ef41Sopenharmony_ci bool notifyWaitingForDisconnect() { 12171cb0ef41Sopenharmony_ci bool retaining_context = false; 12181cb0ef41Sopenharmony_ci for (const auto& id_channel : channels_) { 12191cb0ef41Sopenharmony_ci if (id_channel.second->notifyWaitingForDisconnect()) 12201cb0ef41Sopenharmony_ci retaining_context = true; 12211cb0ef41Sopenharmony_ci } 12221cb0ef41Sopenharmony_ci return retaining_context; 12231cb0ef41Sopenharmony_ci } 12241cb0ef41Sopenharmony_ci 12251cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> getThreadHandle() { 12261cb0ef41Sopenharmony_ci if (!interface_) { 12271cb0ef41Sopenharmony_ci interface_ = std::make_shared<MainThreadInterface>( 12281cb0ef41Sopenharmony_ci env_->inspector_agent()); 12291cb0ef41Sopenharmony_ci } 12301cb0ef41Sopenharmony_ci return interface_->GetHandle(); 12311cb0ef41Sopenharmony_ci } 12321cb0ef41Sopenharmony_ci 12331cb0ef41Sopenharmony_ci bool IsActive() { 12341cb0ef41Sopenharmony_ci return !channels_.empty(); 12351cb0ef41Sopenharmony_ci } 12361cb0ef41Sopenharmony_ci 12371cb0ef41Sopenharmony_ci private: 12381cb0ef41Sopenharmony_ci bool shouldRunMessageLoop() { 12391cb0ef41Sopenharmony_ci if (waiting_for_frontend_) 12401cb0ef41Sopenharmony_ci return true; 12411cb0ef41Sopenharmony_ci if (waiting_for_sessions_disconnect_ || waiting_for_resume_) { 12421cb0ef41Sopenharmony_ci return hasConnectedSessions(); 12431cb0ef41Sopenharmony_ci } 12441cb0ef41Sopenharmony_ci return false; 12451cb0ef41Sopenharmony_ci } 12461cb0ef41Sopenharmony_ci 12471cb0ef41Sopenharmony_ci void runMessageLoop() { 12481cb0ef41Sopenharmony_ci if (running_nested_loop_) 12491cb0ef41Sopenharmony_ci return; 12501cb0ef41Sopenharmony_ci 12511cb0ef41Sopenharmony_ci running_nested_loop_ = true; 12521cb0ef41Sopenharmony_ci 12531cb0ef41Sopenharmony_ci while (shouldRunMessageLoop()) { 12541cb0ef41Sopenharmony_ci if (interface_) interface_->WaitForFrontendEvent(); 12551cb0ef41Sopenharmony_ci env_->RunAndClearInterrupts(); 12561cb0ef41Sopenharmony_ci } 12571cb0ef41Sopenharmony_ci running_nested_loop_ = false; 12581cb0ef41Sopenharmony_ci } 12591cb0ef41Sopenharmony_ci 12601cb0ef41Sopenharmony_ci double currentTimeMS() override { 12611cb0ef41Sopenharmony_ci return env_->platform()->CurrentClockTimeMillis(); 12621cb0ef41Sopenharmony_ci } 12631cb0ef41Sopenharmony_ci 12641cb0ef41Sopenharmony_ci std::unique_ptr<StringBuffer> resourceNameToUrl( 12651cb0ef41Sopenharmony_ci const StringView& resource_name_view) override { 12661cb0ef41Sopenharmony_ci std::string resource_name = 12671cb0ef41Sopenharmony_ci protocol::StringUtil::StringViewToUtf8(resource_name_view); 12681cb0ef41Sopenharmony_ci if (!IsFilePath(resource_name)) 12691cb0ef41Sopenharmony_ci return nullptr; 12701cb0ef41Sopenharmony_ci 12711cb0ef41Sopenharmony_ci std::string url = node::url::FromFilePath(resource_name); 12721cb0ef41Sopenharmony_ci return Utf8ToStringView(url); 12731cb0ef41Sopenharmony_ci } 12741cb0ef41Sopenharmony_ci 12751cb0ef41Sopenharmony_ci Environment* env_; 12761cb0ef41Sopenharmony_ci bool is_main_; 12771cb0ef41Sopenharmony_ci bool running_nested_loop_ = false; 12781cb0ef41Sopenharmony_ci std::unique_ptr<V8Inspector> client_; 12791cb0ef41Sopenharmony_ci std::unordered_map<int, std::unique_ptr<ChannelImpl>> channels_; 12801cb0ef41Sopenharmony_ci int next_session_id_ = 1; 12811cb0ef41Sopenharmony_ci bool waiting_for_resume_ = false; 12821cb0ef41Sopenharmony_ci bool waiting_for_frontend_ = false; 12831cb0ef41Sopenharmony_ci bool waiting_for_sessions_disconnect_ = false; 12841cb0ef41Sopenharmony_ci // Allows accessing Inspector from non-main threads 12851cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadInterface> interface_; 12861cb0ef41Sopenharmony_ci}; 12871cb0ef41Sopenharmony_ci 12881cb0ef41Sopenharmony_ciAgent::Agent(Environment* env) 12891cb0ef41Sopenharmony_ci : parent_env_(env) {} 12901cb0ef41Sopenharmony_ci 12911cb0ef41Sopenharmony_ciAgent::~Agent() = default; 12921cb0ef41Sopenharmony_ci 12931cb0ef41Sopenharmony_cibool Agent::Start(const std::string& path, 12941cb0ef41Sopenharmony_ci std::shared_ptr<ExclusiveAccess<HostPort>> host_port, 12951cb0ef41Sopenharmony_ci bool is_main, 12961cb0ef41Sopenharmony_ci bool wait_for_connect) { 12971cb0ef41Sopenharmony_ci path_ = path; 12981cb0ef41Sopenharmony_ci CHECK_NOT_NULL(host_port); 12991cb0ef41Sopenharmony_ci host_port_ = host_port; 13001cb0ef41Sopenharmony_ci 13011cb0ef41Sopenharmony_ci client_ = std::make_shared<InspectorClient>(parent_env_, is_main); 13021cb0ef41Sopenharmony_ci 13031cb0ef41Sopenharmony_ci if (!StartIoThread()) { 13041cb0ef41Sopenharmony_ci return false; 13051cb0ef41Sopenharmony_ci } 13061cb0ef41Sopenharmony_ci 13071cb0ef41Sopenharmony_ci if (wait_for_connect) { 13081cb0ef41Sopenharmony_ci client_->waitForFrontend(); 13091cb0ef41Sopenharmony_ci } 13101cb0ef41Sopenharmony_ci return true; 13111cb0ef41Sopenharmony_ci} 13121cb0ef41Sopenharmony_ci 13131cb0ef41Sopenharmony_cibool Agent::StartIoThread() { 13141cb0ef41Sopenharmony_ci if (io_ != nullptr) 13151cb0ef41Sopenharmony_ci return true; 13161cb0ef41Sopenharmony_ci 13171cb0ef41Sopenharmony_ci if (!client_) { 13181cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 13191cb0ef41Sopenharmony_ci return false; 13201cb0ef41Sopenharmony_ci } 13211cb0ef41Sopenharmony_ci 13221cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 13231cb0ef41Sopenharmony_ci 13241cb0ef41Sopenharmony_ci io_ = InspectorIo::Start(client_->getThreadHandle(), 13251cb0ef41Sopenharmony_ci path_, 13261cb0ef41Sopenharmony_ci host_port_, 13271cb0ef41Sopenharmony_ci { false, true }); 13281cb0ef41Sopenharmony_ci if (io_ == nullptr) { 13291cb0ef41Sopenharmony_ci return false; 13301cb0ef41Sopenharmony_ci } 13311cb0ef41Sopenharmony_ci return true; 13321cb0ef41Sopenharmony_ci} 13331cb0ef41Sopenharmony_ci 13341cb0ef41Sopenharmony_civoid Agent::Stop() { 13351cb0ef41Sopenharmony_ci io_.reset(); 13361cb0ef41Sopenharmony_ci} 13371cb0ef41Sopenharmony_ci 13381cb0ef41Sopenharmony_cistd::unique_ptr<InspectorSession> Agent::Connect( 13391cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate, 13401cb0ef41Sopenharmony_ci bool prevent_shutdown) { 13411cb0ef41Sopenharmony_ci if (!client_) { 13421cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 13431cb0ef41Sopenharmony_ci return std::unique_ptr<InspectorSession>{}; 13441cb0ef41Sopenharmony_ci } 13451cb0ef41Sopenharmony_ci 13461cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 13471cb0ef41Sopenharmony_ci 13481cb0ef41Sopenharmony_ci int session_id = client_->connectFrontend(std::move(delegate), 13491cb0ef41Sopenharmony_ci prevent_shutdown); 13501cb0ef41Sopenharmony_ci return std::unique_ptr<InspectorSession>( 13511cb0ef41Sopenharmony_ci new SameThreadInspectorSession(session_id, client_)); 13521cb0ef41Sopenharmony_ci} 13531cb0ef41Sopenharmony_ci 13541cb0ef41Sopenharmony_civoid Agent::WaitForDisconnect() { 13551cb0ef41Sopenharmony_ci if (!client_) { 13561cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 13571cb0ef41Sopenharmony_ci return; 13581cb0ef41Sopenharmony_ci } 13591cb0ef41Sopenharmony_ci 13601cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 13611cb0ef41Sopenharmony_ci if (client_->hasConnectedSessions()) { 13621cb0ef41Sopenharmony_ci fprintf(stderr, "Waiting for the debugger to disconnect...\n"); 13631cb0ef41Sopenharmony_ci fflush(stderr); 13641cb0ef41Sopenharmony_ci } 13651cb0ef41Sopenharmony_ci if (!client_->notifyWaitingForDisconnect()) { 13661cb0ef41Sopenharmony_ci client_->contextDestroyed(parent_env_->context()); 13671cb0ef41Sopenharmony_ci } 13681cb0ef41Sopenharmony_ci if (io_ != nullptr) { 13691cb0ef41Sopenharmony_ci io_->StopAcceptingNewConnections(); 13701cb0ef41Sopenharmony_ci client_->waitForSessionsDisconnect(); 13711cb0ef41Sopenharmony_ci } 13721cb0ef41Sopenharmony_ci} 13731cb0ef41Sopenharmony_ci 13741cb0ef41Sopenharmony_civoid Agent::ReportUncaughtException(Local<Value> error, 13751cb0ef41Sopenharmony_ci Local<Message> message) { 13761cb0ef41Sopenharmony_ci if (!IsListening()) 13771cb0ef41Sopenharmony_ci return; 13781cb0ef41Sopenharmony_ci client_->ReportUncaughtException(error, message); 13791cb0ef41Sopenharmony_ci WaitForDisconnect(); 13801cb0ef41Sopenharmony_ci} 13811cb0ef41Sopenharmony_ci 13821cb0ef41Sopenharmony_civoid Agent::PauseOnNextJavascriptStatement(const std::string& reason) { 13831cb0ef41Sopenharmony_ci client_->schedulePauseOnNextStatement(reason); 13841cb0ef41Sopenharmony_ci} 13851cb0ef41Sopenharmony_ci 13861cb0ef41Sopenharmony_civoid Agent::AsyncTaskScheduled(const StringView& task_name, void* task, 13871cb0ef41Sopenharmony_ci bool recurring) { 13881cb0ef41Sopenharmony_ci client_->AsyncTaskScheduled(task_name, task, recurring); 13891cb0ef41Sopenharmony_ci} 13901cb0ef41Sopenharmony_ci 13911cb0ef41Sopenharmony_civoid Agent::AsyncTaskCanceled(void* task) { 13921cb0ef41Sopenharmony_ci client_->AsyncTaskCanceled(task); 13931cb0ef41Sopenharmony_ci} 13941cb0ef41Sopenharmony_ci 13951cb0ef41Sopenharmony_civoid Agent::AsyncTaskStarted(void* task) { 13961cb0ef41Sopenharmony_ci client_->AsyncTaskStarted(task); 13971cb0ef41Sopenharmony_ci} 13981cb0ef41Sopenharmony_ci 13991cb0ef41Sopenharmony_civoid Agent::AsyncTaskFinished(void* task) { 14001cb0ef41Sopenharmony_ci client_->AsyncTaskFinished(task); 14011cb0ef41Sopenharmony_ci} 14021cb0ef41Sopenharmony_ci 14031cb0ef41Sopenharmony_civoid Agent::AllAsyncTasksCanceled() { 14041cb0ef41Sopenharmony_ci client_->AllAsyncTasksCanceled(); 14051cb0ef41Sopenharmony_ci} 14061cb0ef41Sopenharmony_ci 14071cb0ef41Sopenharmony_civoid Agent::ContextCreated(Local<Context> context, const ContextInfo& info) { 14081cb0ef41Sopenharmony_ci if (client_ == nullptr) // This happens for a main context 14091cb0ef41Sopenharmony_ci return; 14101cb0ef41Sopenharmony_ci client_->contextCreated(context, info); 14111cb0ef41Sopenharmony_ci} 14121cb0ef41Sopenharmony_ci 14131cb0ef41Sopenharmony_cibool Agent::IsActive() { 14141cb0ef41Sopenharmony_ci if (client_ == nullptr) 14151cb0ef41Sopenharmony_ci return false; 14161cb0ef41Sopenharmony_ci return io_ != nullptr || client_->IsActive(); 14171cb0ef41Sopenharmony_ci} 14181cb0ef41Sopenharmony_ci 14191cb0ef41Sopenharmony_civoid Agent::WaitForConnect() { 14201cb0ef41Sopenharmony_ci if (!client_) { 14211cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 14221cb0ef41Sopenharmony_ci return; 14231cb0ef41Sopenharmony_ci } 14241cb0ef41Sopenharmony_ci 14251cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 14261cb0ef41Sopenharmony_ci client_->waitForFrontend(); 14271cb0ef41Sopenharmony_ci} 14281cb0ef41Sopenharmony_ci 14291cb0ef41Sopenharmony_cistd::string Agent::GetWsUrl() const { 14301cb0ef41Sopenharmony_ci if (io_ == nullptr) 14311cb0ef41Sopenharmony_ci return ""; 14321cb0ef41Sopenharmony_ci return io_->GetWsUrl(); 14331cb0ef41Sopenharmony_ci} 14341cb0ef41Sopenharmony_ci 14351cb0ef41Sopenharmony_ciSameThreadInspectorSession::~SameThreadInspectorSession() { 14361cb0ef41Sopenharmony_ci auto client = client_.lock(); 14371cb0ef41Sopenharmony_ci if (client) 14381cb0ef41Sopenharmony_ci client->disconnectFrontend(session_id_); 14391cb0ef41Sopenharmony_ci} 14401cb0ef41Sopenharmony_ci 14411cb0ef41Sopenharmony_civoid SameThreadInspectorSession::Dispatch( 14421cb0ef41Sopenharmony_ci const v8_inspector::StringView& message) { 14431cb0ef41Sopenharmony_ci auto client = client_.lock(); 14441cb0ef41Sopenharmony_ci if (client) 14451cb0ef41Sopenharmony_ci client->dispatchMessageFromFrontend(session_id_, message); 14461cb0ef41Sopenharmony_ci} 14471cb0ef41Sopenharmony_ci 14481cb0ef41Sopenharmony_ci} // namespace v8impl 1449