11cb0ef41Sopenharmony_ci#include "inspector_agent.h" 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ci#include "env-inl.h" 41cb0ef41Sopenharmony_ci#include "inspector/main_thread_interface.h" 51cb0ef41Sopenharmony_ci#include "inspector/node_string.h" 61cb0ef41Sopenharmony_ci#include "inspector/runtime_agent.h" 71cb0ef41Sopenharmony_ci#include "inspector/tracing_agent.h" 81cb0ef41Sopenharmony_ci#include "inspector/worker_agent.h" 91cb0ef41Sopenharmony_ci#include "inspector/worker_inspector.h" 101cb0ef41Sopenharmony_ci#include "inspector_io.h" 111cb0ef41Sopenharmony_ci#include "node/inspector/protocol/Protocol.h" 121cb0ef41Sopenharmony_ci#include "node_errors.h" 131cb0ef41Sopenharmony_ci#include "node_internals.h" 141cb0ef41Sopenharmony_ci#include "node_options-inl.h" 151cb0ef41Sopenharmony_ci#include "node_process-inl.h" 161cb0ef41Sopenharmony_ci#include "node_url.h" 171cb0ef41Sopenharmony_ci#include "util-inl.h" 181cb0ef41Sopenharmony_ci#include "timer_wrap-inl.h" 191cb0ef41Sopenharmony_ci#include "v8-inspector.h" 201cb0ef41Sopenharmony_ci#include "v8-platform.h" 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#include "libplatform/libplatform.h" 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci#ifdef __POSIX__ 251cb0ef41Sopenharmony_ci#include <pthread.h> 261cb0ef41Sopenharmony_ci#include <climits> // PTHREAD_STACK_MIN 271cb0ef41Sopenharmony_ci#endif // __POSIX__ 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci#include <algorithm> 301cb0ef41Sopenharmony_ci#include <cstring> 311cb0ef41Sopenharmony_ci#include <sstream> 321cb0ef41Sopenharmony_ci#include <unordered_map> 331cb0ef41Sopenharmony_ci#include <vector> 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_cinamespace node { 361cb0ef41Sopenharmony_cinamespace inspector { 371cb0ef41Sopenharmony_cinamespace { 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ciusing node::OnFatalError; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciusing v8::Context; 421cb0ef41Sopenharmony_ciusing v8::Function; 431cb0ef41Sopenharmony_ciusing v8::HandleScope; 441cb0ef41Sopenharmony_ciusing v8::Isolate; 451cb0ef41Sopenharmony_ciusing v8::Local; 461cb0ef41Sopenharmony_ciusing v8::Message; 471cb0ef41Sopenharmony_ciusing v8::Object; 481cb0ef41Sopenharmony_ciusing v8::Value; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ciusing v8_inspector::StringBuffer; 511cb0ef41Sopenharmony_ciusing v8_inspector::StringView; 521cb0ef41Sopenharmony_ciusing v8_inspector::V8Inspector; 531cb0ef41Sopenharmony_ciusing v8_inspector::V8InspectorClient; 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci#ifdef __POSIX__ 561cb0ef41Sopenharmony_cistatic uv_sem_t start_io_thread_semaphore; 571cb0ef41Sopenharmony_ci#endif // __POSIX__ 581cb0ef41Sopenharmony_cistatic uv_async_t start_io_thread_async; 591cb0ef41Sopenharmony_ci// This is just an additional check to make sure start_io_thread_async 601cb0ef41Sopenharmony_ci// is not accidentally re-used or used when uninitialized. 611cb0ef41Sopenharmony_cistatic std::atomic_bool start_io_thread_async_initialized { false }; 621cb0ef41Sopenharmony_ci// Protects the Agent* stored in start_io_thread_async.data. 631cb0ef41Sopenharmony_cistatic Mutex start_io_thread_async_mutex; 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> ToProtocolString(Isolate* isolate, 661cb0ef41Sopenharmony_ci Local<Value> value) { 671cb0ef41Sopenharmony_ci TwoByteValue buffer(isolate, value); 681cb0ef41Sopenharmony_ci return StringBuffer::create(StringView(*buffer, buffer.length())); 691cb0ef41Sopenharmony_ci} 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci// Called on the main thread. 721cb0ef41Sopenharmony_civoid StartIoThreadAsyncCallback(uv_async_t* handle) { 731cb0ef41Sopenharmony_ci static_cast<Agent*>(handle->data)->StartIoThread(); 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci#ifdef __POSIX__ 781cb0ef41Sopenharmony_cistatic void StartIoThreadWakeup(int signo, siginfo_t* info, void* ucontext) { 791cb0ef41Sopenharmony_ci uv_sem_post(&start_io_thread_semaphore); 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciinline void* StartIoThreadMain(void* unused) { 831cb0ef41Sopenharmony_ci for (;;) { 841cb0ef41Sopenharmony_ci uv_sem_wait(&start_io_thread_semaphore); 851cb0ef41Sopenharmony_ci Mutex::ScopedLock lock(start_io_thread_async_mutex); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci CHECK(start_io_thread_async_initialized); 881cb0ef41Sopenharmony_ci Agent* agent = static_cast<Agent*>(start_io_thread_async.data); 891cb0ef41Sopenharmony_ci if (agent != nullptr) 901cb0ef41Sopenharmony_ci agent->RequestIoThreadStart(); 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci} 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_cistatic int StartDebugSignalHandler() { 951cb0ef41Sopenharmony_ci // Start a watchdog thread for calling v8::Debug::DebugBreak() because 961cb0ef41Sopenharmony_ci // it's not safe to call directly from the signal handler, it can 971cb0ef41Sopenharmony_ci // deadlock with the thread it interrupts. 981cb0ef41Sopenharmony_ci CHECK_EQ(0, uv_sem_init(&start_io_thread_semaphore, 0)); 991cb0ef41Sopenharmony_ci pthread_attr_t attr; 1001cb0ef41Sopenharmony_ci CHECK_EQ(0, pthread_attr_init(&attr)); 1011cb0ef41Sopenharmony_ci#if defined(PTHREAD_STACK_MIN) && !defined(__FreeBSD__) 1021cb0ef41Sopenharmony_ci // PTHREAD_STACK_MIN is 2 KiB with musl libc, which is too small to safely 1031cb0ef41Sopenharmony_ci // receive signals. PTHREAD_STACK_MIN + MINSIGSTKSZ is 8 KiB on arm64, which 1041cb0ef41Sopenharmony_ci // is the musl architecture with the biggest MINSIGSTKSZ so let's use that 1051cb0ef41Sopenharmony_ci // as a lower bound and let's quadruple it just in case. The goal is to avoid 1061cb0ef41Sopenharmony_ci // creating a big 2 or 4 MiB address space gap (problematic on 32 bits 1071cb0ef41Sopenharmony_ci // because of fragmentation), not squeeze out every last byte. 1081cb0ef41Sopenharmony_ci // Omitted on FreeBSD because it doesn't seem to like small stacks. 1091cb0ef41Sopenharmony_ci const size_t stack_size = std::max(static_cast<size_t>(4 * 8192), 1101cb0ef41Sopenharmony_ci static_cast<size_t>(PTHREAD_STACK_MIN)); 1111cb0ef41Sopenharmony_ci CHECK_EQ(0, pthread_attr_setstacksize(&attr, stack_size)); 1121cb0ef41Sopenharmony_ci#endif // defined(PTHREAD_STACK_MIN) && !defined(__FreeBSD__) 1131cb0ef41Sopenharmony_ci CHECK_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)); 1141cb0ef41Sopenharmony_ci sigset_t sigmask; 1151cb0ef41Sopenharmony_ci // Mask all signals. 1161cb0ef41Sopenharmony_ci sigfillset(&sigmask); 1171cb0ef41Sopenharmony_ci sigset_t savemask; 1181cb0ef41Sopenharmony_ci CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, &savemask)); 1191cb0ef41Sopenharmony_ci sigmask = savemask; 1201cb0ef41Sopenharmony_ci pthread_t thread; 1211cb0ef41Sopenharmony_ci const int err = pthread_create(&thread, &attr, 1221cb0ef41Sopenharmony_ci StartIoThreadMain, nullptr); 1231cb0ef41Sopenharmony_ci // Restore original mask 1241cb0ef41Sopenharmony_ci CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, nullptr)); 1251cb0ef41Sopenharmony_ci CHECK_EQ(0, pthread_attr_destroy(&attr)); 1261cb0ef41Sopenharmony_ci if (err != 0) { 1271cb0ef41Sopenharmony_ci fprintf(stderr, "node[%u]: pthread_create: %s\n", 1281cb0ef41Sopenharmony_ci uv_os_getpid(), strerror(err)); 1291cb0ef41Sopenharmony_ci fflush(stderr); 1301cb0ef41Sopenharmony_ci // Leave SIGUSR1 blocked. We don't install a signal handler, 1311cb0ef41Sopenharmony_ci // receiving the signal would terminate the process. 1321cb0ef41Sopenharmony_ci return -err; 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci RegisterSignalHandler(SIGUSR1, StartIoThreadWakeup); 1351cb0ef41Sopenharmony_ci // Unblock SIGUSR1. A pending SIGUSR1 signal will now be delivered. 1361cb0ef41Sopenharmony_ci sigemptyset(&sigmask); 1371cb0ef41Sopenharmony_ci sigaddset(&sigmask, SIGUSR1); 1381cb0ef41Sopenharmony_ci CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr)); 1391cb0ef41Sopenharmony_ci return 0; 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci#endif // __POSIX__ 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci#ifdef _WIN32 1451cb0ef41Sopenharmony_ciDWORD WINAPI StartIoThreadProc(void* arg) { 1461cb0ef41Sopenharmony_ci Mutex::ScopedLock lock(start_io_thread_async_mutex); 1471cb0ef41Sopenharmony_ci CHECK(start_io_thread_async_initialized); 1481cb0ef41Sopenharmony_ci Agent* agent = static_cast<Agent*>(start_io_thread_async.data); 1491cb0ef41Sopenharmony_ci if (agent != nullptr) 1501cb0ef41Sopenharmony_ci agent->RequestIoThreadStart(); 1511cb0ef41Sopenharmony_ci return 0; 1521cb0ef41Sopenharmony_ci} 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_cistatic int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf, 1551cb0ef41Sopenharmony_ci size_t buf_len) { 1561cb0ef41Sopenharmony_ci return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid); 1571cb0ef41Sopenharmony_ci} 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_cistatic int StartDebugSignalHandler() { 1601cb0ef41Sopenharmony_ci wchar_t mapping_name[32]; 1611cb0ef41Sopenharmony_ci HANDLE mapping_handle; 1621cb0ef41Sopenharmony_ci DWORD pid; 1631cb0ef41Sopenharmony_ci LPTHREAD_START_ROUTINE* handler; 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci pid = uv_os_getpid(); 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci if (GetDebugSignalHandlerMappingName(pid, 1681cb0ef41Sopenharmony_ci mapping_name, 1691cb0ef41Sopenharmony_ci arraysize(mapping_name)) < 0) { 1701cb0ef41Sopenharmony_ci return -1; 1711cb0ef41Sopenharmony_ci } 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE, 1741cb0ef41Sopenharmony_ci nullptr, 1751cb0ef41Sopenharmony_ci PAGE_READWRITE, 1761cb0ef41Sopenharmony_ci 0, 1771cb0ef41Sopenharmony_ci sizeof *handler, 1781cb0ef41Sopenharmony_ci mapping_name); 1791cb0ef41Sopenharmony_ci if (mapping_handle == nullptr) { 1801cb0ef41Sopenharmony_ci return -1; 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>( 1841cb0ef41Sopenharmony_ci MapViewOfFile(mapping_handle, 1851cb0ef41Sopenharmony_ci FILE_MAP_ALL_ACCESS, 1861cb0ef41Sopenharmony_ci 0, 1871cb0ef41Sopenharmony_ci 0, 1881cb0ef41Sopenharmony_ci sizeof *handler)); 1891cb0ef41Sopenharmony_ci if (handler == nullptr) { 1901cb0ef41Sopenharmony_ci CloseHandle(mapping_handle); 1911cb0ef41Sopenharmony_ci return -1; 1921cb0ef41Sopenharmony_ci } 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci *handler = StartIoThreadProc; 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci UnmapViewOfFile(static_cast<void*>(handler)); 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci return 0; 1991cb0ef41Sopenharmony_ci} 2001cb0ef41Sopenharmony_ci#endif // _WIN32 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ciconst int CONTEXT_GROUP_ID = 1; 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_cistd::string GetWorkerLabel(node::Environment* env) { 2061cb0ef41Sopenharmony_ci std::ostringstream result; 2071cb0ef41Sopenharmony_ci result << "Worker[" << env->thread_id() << "]"; 2081cb0ef41Sopenharmony_ci return result.str(); 2091cb0ef41Sopenharmony_ci} 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_ciclass ChannelImpl final : public v8_inspector::V8Inspector::Channel, 2121cb0ef41Sopenharmony_ci public protocol::FrontendChannel { 2131cb0ef41Sopenharmony_ci public: 2141cb0ef41Sopenharmony_ci explicit ChannelImpl(Environment* env, 2151cb0ef41Sopenharmony_ci const std::unique_ptr<V8Inspector>& inspector, 2161cb0ef41Sopenharmony_ci std::shared_ptr<WorkerManager> worker_manager, 2171cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate, 2181cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> main_thread_, 2191cb0ef41Sopenharmony_ci bool prevent_shutdown) 2201cb0ef41Sopenharmony_ci : delegate_(std::move(delegate)), prevent_shutdown_(prevent_shutdown), 2211cb0ef41Sopenharmony_ci retaining_context_(false) { 2221cb0ef41Sopenharmony_ci session_ = inspector->connect(CONTEXT_GROUP_ID, this, StringView(), 2231cb0ef41Sopenharmony_ci V8Inspector::ClientTrustLevel::kFullyTrusted); 2241cb0ef41Sopenharmony_ci node_dispatcher_ = std::make_unique<protocol::UberDispatcher>(this); 2251cb0ef41Sopenharmony_ci tracing_agent_ = 2261cb0ef41Sopenharmony_ci std::make_unique<protocol::TracingAgent>(env, main_thread_); 2271cb0ef41Sopenharmony_ci tracing_agent_->Wire(node_dispatcher_.get()); 2281cb0ef41Sopenharmony_ci if (worker_manager) { 2291cb0ef41Sopenharmony_ci worker_agent_ = std::make_unique<protocol::WorkerAgent>(worker_manager); 2301cb0ef41Sopenharmony_ci worker_agent_->Wire(node_dispatcher_.get()); 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci runtime_agent_ = std::make_unique<protocol::RuntimeAgent>(); 2331cb0ef41Sopenharmony_ci runtime_agent_->Wire(node_dispatcher_.get()); 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci ~ChannelImpl() override { 2371cb0ef41Sopenharmony_ci tracing_agent_->disable(); 2381cb0ef41Sopenharmony_ci tracing_agent_.reset(); // Dispose before the dispatchers 2391cb0ef41Sopenharmony_ci if (worker_agent_) { 2401cb0ef41Sopenharmony_ci worker_agent_->disable(); 2411cb0ef41Sopenharmony_ci worker_agent_.reset(); // Dispose before the dispatchers 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci runtime_agent_->disable(); 2441cb0ef41Sopenharmony_ci runtime_agent_.reset(); // Dispose before the dispatchers 2451cb0ef41Sopenharmony_ci } 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci void dispatchProtocolMessage(const StringView& message) { 2481cb0ef41Sopenharmony_ci std::string raw_message = protocol::StringUtil::StringViewToUtf8(message); 2491cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::INSPECTOR_SERVER, 2501cb0ef41Sopenharmony_ci "[inspector received] %s\n", 2511cb0ef41Sopenharmony_ci raw_message); 2521cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> value = 2531cb0ef41Sopenharmony_ci protocol::DictionaryValue::cast(protocol::StringUtil::parseMessage( 2541cb0ef41Sopenharmony_ci raw_message, false)); 2551cb0ef41Sopenharmony_ci int call_id; 2561cb0ef41Sopenharmony_ci std::string method; 2571cb0ef41Sopenharmony_ci node_dispatcher_->parseCommand(value.get(), &call_id, &method); 2581cb0ef41Sopenharmony_ci if (v8_inspector::V8InspectorSession::canDispatchMethod( 2591cb0ef41Sopenharmony_ci Utf8ToStringView(method)->string())) { 2601cb0ef41Sopenharmony_ci session_->dispatchProtocolMessage(message); 2611cb0ef41Sopenharmony_ci } else { 2621cb0ef41Sopenharmony_ci node_dispatcher_->dispatch(call_id, method, std::move(value), 2631cb0ef41Sopenharmony_ci raw_message); 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci } 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci void schedulePauseOnNextStatement(const std::string& reason) { 2681cb0ef41Sopenharmony_ci std::unique_ptr<StringBuffer> buffer = Utf8ToStringView(reason); 2691cb0ef41Sopenharmony_ci session_->schedulePauseOnNextStatement(buffer->string(), buffer->string()); 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci bool preventShutdown() { 2731cb0ef41Sopenharmony_ci return prevent_shutdown_; 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci bool notifyWaitingForDisconnect() { 2771cb0ef41Sopenharmony_ci retaining_context_ = runtime_agent_->notifyWaitingForDisconnect(); 2781cb0ef41Sopenharmony_ci return retaining_context_; 2791cb0ef41Sopenharmony_ci } 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci bool retainingContext() { 2821cb0ef41Sopenharmony_ci return retaining_context_; 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci private: 2861cb0ef41Sopenharmony_ci void sendResponse( 2871cb0ef41Sopenharmony_ci int callId, 2881cb0ef41Sopenharmony_ci std::unique_ptr<v8_inspector::StringBuffer> message) override { 2891cb0ef41Sopenharmony_ci sendMessageToFrontend(message->string()); 2901cb0ef41Sopenharmony_ci } 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci void sendNotification( 2931cb0ef41Sopenharmony_ci std::unique_ptr<v8_inspector::StringBuffer> message) override { 2941cb0ef41Sopenharmony_ci sendMessageToFrontend(message->string()); 2951cb0ef41Sopenharmony_ci } 2961cb0ef41Sopenharmony_ci 2971cb0ef41Sopenharmony_ci void flushProtocolNotifications() override { } 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci void sendMessageToFrontend(const StringView& message) { 3001cb0ef41Sopenharmony_ci if (per_process::enabled_debug_list.enabled( 3011cb0ef41Sopenharmony_ci DebugCategory::INSPECTOR_SERVER)) { 3021cb0ef41Sopenharmony_ci std::string raw_message = protocol::StringUtil::StringViewToUtf8(message); 3031cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::INSPECTOR_SERVER, 3041cb0ef41Sopenharmony_ci "[inspector send] %s\n", 3051cb0ef41Sopenharmony_ci raw_message); 3061cb0ef41Sopenharmony_ci } 3071cb0ef41Sopenharmony_ci delegate_->SendMessageToFrontend(message); 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci void sendMessageToFrontend(const std::string& message) { 3111cb0ef41Sopenharmony_ci sendMessageToFrontend(Utf8ToStringView(message)->string()); 3121cb0ef41Sopenharmony_ci } 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci using Serializable = protocol::Serializable; 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci void sendProtocolResponse(int callId, 3171cb0ef41Sopenharmony_ci std::unique_ptr<Serializable> message) override { 3181cb0ef41Sopenharmony_ci sendMessageToFrontend(message->serializeToJSON()); 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci void sendProtocolNotification( 3211cb0ef41Sopenharmony_ci std::unique_ptr<Serializable> message) override { 3221cb0ef41Sopenharmony_ci sendMessageToFrontend(message->serializeToJSON()); 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci void fallThrough(int callId, 3261cb0ef41Sopenharmony_ci const std::string& method, 3271cb0ef41Sopenharmony_ci const std::string& message) override { 3281cb0ef41Sopenharmony_ci DCHECK(false); 3291cb0ef41Sopenharmony_ci } 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci std::unique_ptr<protocol::RuntimeAgent> runtime_agent_; 3321cb0ef41Sopenharmony_ci std::unique_ptr<protocol::TracingAgent> tracing_agent_; 3331cb0ef41Sopenharmony_ci std::unique_ptr<protocol::WorkerAgent> worker_agent_; 3341cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate_; 3351cb0ef41Sopenharmony_ci std::unique_ptr<v8_inspector::V8InspectorSession> session_; 3361cb0ef41Sopenharmony_ci std::unique_ptr<protocol::UberDispatcher> node_dispatcher_; 3371cb0ef41Sopenharmony_ci bool prevent_shutdown_; 3381cb0ef41Sopenharmony_ci bool retaining_context_; 3391cb0ef41Sopenharmony_ci}; 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ciclass SameThreadInspectorSession : public InspectorSession { 3421cb0ef41Sopenharmony_ci public: 3431cb0ef41Sopenharmony_ci SameThreadInspectorSession( 3441cb0ef41Sopenharmony_ci int session_id, std::shared_ptr<NodeInspectorClient> client) 3451cb0ef41Sopenharmony_ci : session_id_(session_id), client_(client) {} 3461cb0ef41Sopenharmony_ci ~SameThreadInspectorSession() override; 3471cb0ef41Sopenharmony_ci void Dispatch(const v8_inspector::StringView& message) override; 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci private: 3501cb0ef41Sopenharmony_ci int session_id_; 3511cb0ef41Sopenharmony_ci std::weak_ptr<NodeInspectorClient> client_; 3521cb0ef41Sopenharmony_ci}; 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_civoid NotifyClusterWorkersDebugEnabled(Environment* env) { 3551cb0ef41Sopenharmony_ci Isolate* isolate = env->isolate(); 3561cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 3571cb0ef41Sopenharmony_ci Local<Context> context = env->context(); 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci // Send message to enable debug in cluster workers 3601cb0ef41Sopenharmony_ci Local<Object> message = Object::New(isolate); 3611cb0ef41Sopenharmony_ci message->Set(context, FIXED_ONE_BYTE_STRING(isolate, "cmd"), 3621cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(isolate, "NODE_DEBUG_ENABLED")).Check(); 3631cb0ef41Sopenharmony_ci ProcessEmit(env, "internalMessage", message); 3641cb0ef41Sopenharmony_ci} 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci#ifdef _WIN32 3671cb0ef41Sopenharmony_cibool IsFilePath(const std::string& path) { 3681cb0ef41Sopenharmony_ci // '\\' 3691cb0ef41Sopenharmony_ci if (path.length() > 2 && path[0] == '\\' && path[1] == '\\') 3701cb0ef41Sopenharmony_ci return true; 3711cb0ef41Sopenharmony_ci // '[A-Z]:[/\\]' 3721cb0ef41Sopenharmony_ci if (path.length() < 3) 3731cb0ef41Sopenharmony_ci return false; 3741cb0ef41Sopenharmony_ci if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) 3751cb0ef41Sopenharmony_ci return path[1] == ':' && (path[2] == '/' || path[2] == '\\'); 3761cb0ef41Sopenharmony_ci return false; 3771cb0ef41Sopenharmony_ci} 3781cb0ef41Sopenharmony_ci#else 3791cb0ef41Sopenharmony_cibool IsFilePath(const std::string& path) { 3801cb0ef41Sopenharmony_ci return !path.empty() && path[0] == '/'; 3811cb0ef41Sopenharmony_ci} 3821cb0ef41Sopenharmony_ci#endif // __POSIX__ 3831cb0ef41Sopenharmony_ci 3841cb0ef41Sopenharmony_civoid ThrowUninitializedInspectorError(Environment* env) { 3851cb0ef41Sopenharmony_ci HandleScope scope(env->isolate()); 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci const char* msg = "This Environment was initialized without a V8::Inspector"; 3881cb0ef41Sopenharmony_ci Local<Value> exception = 3891cb0ef41Sopenharmony_ci v8::String::NewFromUtf8(env->isolate(), msg).ToLocalChecked(); 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci env->isolate()->ThrowException(exception); 3921cb0ef41Sopenharmony_ci} 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ci} // namespace 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ciclass NodeInspectorClient : public V8InspectorClient { 3971cb0ef41Sopenharmony_ci public: 3981cb0ef41Sopenharmony_ci explicit NodeInspectorClient(node::Environment* env, bool is_main) 3991cb0ef41Sopenharmony_ci : env_(env), is_main_(is_main) { 4001cb0ef41Sopenharmony_ci client_ = V8Inspector::create(env->isolate(), this); 4011cb0ef41Sopenharmony_ci // TODO(bnoordhuis) Make name configurable from src/node.cc. 4021cb0ef41Sopenharmony_ci std::string name = 4031cb0ef41Sopenharmony_ci is_main_ ? GetHumanReadableProcessName() : GetWorkerLabel(env); 4041cb0ef41Sopenharmony_ci ContextInfo info(name); 4051cb0ef41Sopenharmony_ci info.is_default = true; 4061cb0ef41Sopenharmony_ci contextCreated(env->context(), info); 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci void runMessageLoopOnPause(int context_group_id) override { 4101cb0ef41Sopenharmony_ci waiting_for_resume_ = true; 4111cb0ef41Sopenharmony_ci runMessageLoop(); 4121cb0ef41Sopenharmony_ci } 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci void waitForSessionsDisconnect() { 4151cb0ef41Sopenharmony_ci waiting_for_sessions_disconnect_ = true; 4161cb0ef41Sopenharmony_ci runMessageLoop(); 4171cb0ef41Sopenharmony_ci } 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci void waitForFrontend() { 4201cb0ef41Sopenharmony_ci waiting_for_frontend_ = true; 4211cb0ef41Sopenharmony_ci runMessageLoop(); 4221cb0ef41Sopenharmony_ci } 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci void maxAsyncCallStackDepthChanged(int depth) override { 4251cb0ef41Sopenharmony_ci if (waiting_for_sessions_disconnect_) { 4261cb0ef41Sopenharmony_ci // V8 isolate is mostly done and is only letting Inspector protocol 4271cb0ef41Sopenharmony_ci // clients gather data. 4281cb0ef41Sopenharmony_ci return; 4291cb0ef41Sopenharmony_ci } 4301cb0ef41Sopenharmony_ci if (auto agent = env_->inspector_agent()) { 4311cb0ef41Sopenharmony_ci if (depth == 0) { 4321cb0ef41Sopenharmony_ci agent->DisableAsyncHook(); 4331cb0ef41Sopenharmony_ci } else { 4341cb0ef41Sopenharmony_ci agent->EnableAsyncHook(); 4351cb0ef41Sopenharmony_ci } 4361cb0ef41Sopenharmony_ci } 4371cb0ef41Sopenharmony_ci } 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci void contextCreated(Local<Context> context, const ContextInfo& info) { 4401cb0ef41Sopenharmony_ci auto name_buffer = Utf8ToStringView(info.name); 4411cb0ef41Sopenharmony_ci auto origin_buffer = Utf8ToStringView(info.origin); 4421cb0ef41Sopenharmony_ci std::unique_ptr<StringBuffer> aux_data_buffer; 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci v8_inspector::V8ContextInfo v8info( 4451cb0ef41Sopenharmony_ci context, CONTEXT_GROUP_ID, name_buffer->string()); 4461cb0ef41Sopenharmony_ci v8info.origin = origin_buffer->string(); 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci if (info.is_default) { 4491cb0ef41Sopenharmony_ci aux_data_buffer = Utf8ToStringView("{\"isDefault\":true}"); 4501cb0ef41Sopenharmony_ci } else { 4511cb0ef41Sopenharmony_ci aux_data_buffer = Utf8ToStringView("{\"isDefault\":false}"); 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci v8info.auxData = aux_data_buffer->string(); 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci client_->contextCreated(v8info); 4561cb0ef41Sopenharmony_ci } 4571cb0ef41Sopenharmony_ci 4581cb0ef41Sopenharmony_ci void contextDestroyed(Local<Context> context) { 4591cb0ef41Sopenharmony_ci client_->contextDestroyed(context); 4601cb0ef41Sopenharmony_ci } 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci void quitMessageLoopOnPause() override { 4631cb0ef41Sopenharmony_ci waiting_for_resume_ = false; 4641cb0ef41Sopenharmony_ci } 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci void runIfWaitingForDebugger(int context_group_id) override { 4671cb0ef41Sopenharmony_ci waiting_for_frontend_ = false; 4681cb0ef41Sopenharmony_ci } 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci int connectFrontend(std::unique_ptr<InspectorSessionDelegate> delegate, 4711cb0ef41Sopenharmony_ci bool prevent_shutdown) { 4721cb0ef41Sopenharmony_ci int session_id = next_session_id_++; 4731cb0ef41Sopenharmony_ci channels_[session_id] = std::make_unique<ChannelImpl>(env_, 4741cb0ef41Sopenharmony_ci client_, 4751cb0ef41Sopenharmony_ci getWorkerManager(), 4761cb0ef41Sopenharmony_ci std::move(delegate), 4771cb0ef41Sopenharmony_ci getThreadHandle(), 4781cb0ef41Sopenharmony_ci prevent_shutdown); 4791cb0ef41Sopenharmony_ci return session_id; 4801cb0ef41Sopenharmony_ci } 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ci void disconnectFrontend(int session_id) { 4831cb0ef41Sopenharmony_ci auto it = channels_.find(session_id); 4841cb0ef41Sopenharmony_ci if (it == channels_.end()) 4851cb0ef41Sopenharmony_ci return; 4861cb0ef41Sopenharmony_ci bool retaining_context = it->second->retainingContext(); 4871cb0ef41Sopenharmony_ci channels_.erase(it); 4881cb0ef41Sopenharmony_ci if (retaining_context) { 4891cb0ef41Sopenharmony_ci for (const auto& id_channel : channels_) { 4901cb0ef41Sopenharmony_ci if (id_channel.second->retainingContext()) 4911cb0ef41Sopenharmony_ci return; 4921cb0ef41Sopenharmony_ci } 4931cb0ef41Sopenharmony_ci contextDestroyed(env_->context()); 4941cb0ef41Sopenharmony_ci } 4951cb0ef41Sopenharmony_ci if (waiting_for_sessions_disconnect_ && !is_main_) 4961cb0ef41Sopenharmony_ci waiting_for_sessions_disconnect_ = false; 4971cb0ef41Sopenharmony_ci } 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci void dispatchMessageFromFrontend(int session_id, const StringView& message) { 5001cb0ef41Sopenharmony_ci channels_[session_id]->dispatchProtocolMessage(message); 5011cb0ef41Sopenharmony_ci } 5021cb0ef41Sopenharmony_ci 5031cb0ef41Sopenharmony_ci Local<Context> ensureDefaultContextInGroup(int contextGroupId) override { 5041cb0ef41Sopenharmony_ci return env_->context(); 5051cb0ef41Sopenharmony_ci } 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci void installAdditionalCommandLineAPI(Local<Context> context, 5081cb0ef41Sopenharmony_ci Local<Object> target) override { 5091cb0ef41Sopenharmony_ci Local<Function> installer = env_->inspector_console_extension_installer(); 5101cb0ef41Sopenharmony_ci if (!installer.IsEmpty()) { 5111cb0ef41Sopenharmony_ci Local<Value> argv[] = {target}; 5121cb0ef41Sopenharmony_ci // If there is an exception, proceed in JS land 5131cb0ef41Sopenharmony_ci USE(installer->Call(context, target, arraysize(argv), argv)); 5141cb0ef41Sopenharmony_ci } 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci void ReportUncaughtException(Local<Value> error, Local<Message> message) { 5181cb0ef41Sopenharmony_ci Isolate* isolate = env_->isolate(); 5191cb0ef41Sopenharmony_ci Local<Context> context = env_->context(); 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci int script_id = message->GetScriptOrigin().ScriptId(); 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_ci Local<v8::StackTrace> stack_trace = message->GetStackTrace(); 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_ci if (!stack_trace.IsEmpty() && stack_trace->GetFrameCount() > 0 && 5261cb0ef41Sopenharmony_ci script_id == stack_trace->GetFrame(isolate, 0)->GetScriptId()) { 5271cb0ef41Sopenharmony_ci script_id = 0; 5281cb0ef41Sopenharmony_ci } 5291cb0ef41Sopenharmony_ci 5301cb0ef41Sopenharmony_ci const uint8_t DETAILS[] = "Uncaught"; 5311cb0ef41Sopenharmony_ci 5321cb0ef41Sopenharmony_ci client_->exceptionThrown( 5331cb0ef41Sopenharmony_ci context, 5341cb0ef41Sopenharmony_ci StringView(DETAILS, sizeof(DETAILS) - 1), 5351cb0ef41Sopenharmony_ci error, 5361cb0ef41Sopenharmony_ci ToProtocolString(isolate, message->Get())->string(), 5371cb0ef41Sopenharmony_ci ToProtocolString(isolate, message->GetScriptResourceName())->string(), 5381cb0ef41Sopenharmony_ci message->GetLineNumber(context).FromMaybe(0), 5391cb0ef41Sopenharmony_ci message->GetStartColumn(context).FromMaybe(0), 5401cb0ef41Sopenharmony_ci client_->createStackTrace(stack_trace), 5411cb0ef41Sopenharmony_ci script_id); 5421cb0ef41Sopenharmony_ci } 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_ci void startRepeatingTimer(double interval_s, 5451cb0ef41Sopenharmony_ci TimerCallback callback, 5461cb0ef41Sopenharmony_ci void* data) override { 5471cb0ef41Sopenharmony_ci auto result = 5481cb0ef41Sopenharmony_ci timers_.emplace(std::piecewise_construct, std::make_tuple(data), 5491cb0ef41Sopenharmony_ci std::make_tuple(env_, [=]() { callback(data); })); 5501cb0ef41Sopenharmony_ci CHECK(result.second); 5511cb0ef41Sopenharmony_ci uint64_t interval = static_cast<uint64_t>(1000 * interval_s); 5521cb0ef41Sopenharmony_ci result.first->second.Update(interval, interval); 5531cb0ef41Sopenharmony_ci } 5541cb0ef41Sopenharmony_ci 5551cb0ef41Sopenharmony_ci void cancelTimer(void* data) override { 5561cb0ef41Sopenharmony_ci timers_.erase(data); 5571cb0ef41Sopenharmony_ci } 5581cb0ef41Sopenharmony_ci 5591cb0ef41Sopenharmony_ci // Async stack traces instrumentation. 5601cb0ef41Sopenharmony_ci void AsyncTaskScheduled(const StringView& task_name, void* task, 5611cb0ef41Sopenharmony_ci bool recurring) { 5621cb0ef41Sopenharmony_ci client_->asyncTaskScheduled(task_name, task, recurring); 5631cb0ef41Sopenharmony_ci } 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci void AsyncTaskCanceled(void* task) { 5661cb0ef41Sopenharmony_ci client_->asyncTaskCanceled(task); 5671cb0ef41Sopenharmony_ci } 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_ci void AsyncTaskStarted(void* task) { 5701cb0ef41Sopenharmony_ci client_->asyncTaskStarted(task); 5711cb0ef41Sopenharmony_ci } 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci void AsyncTaskFinished(void* task) { 5741cb0ef41Sopenharmony_ci client_->asyncTaskFinished(task); 5751cb0ef41Sopenharmony_ci } 5761cb0ef41Sopenharmony_ci 5771cb0ef41Sopenharmony_ci void AllAsyncTasksCanceled() { 5781cb0ef41Sopenharmony_ci client_->allAsyncTasksCanceled(); 5791cb0ef41Sopenharmony_ci } 5801cb0ef41Sopenharmony_ci 5811cb0ef41Sopenharmony_ci void schedulePauseOnNextStatement(const std::string& reason) { 5821cb0ef41Sopenharmony_ci for (const auto& id_channel : channels_) { 5831cb0ef41Sopenharmony_ci id_channel.second->schedulePauseOnNextStatement(reason); 5841cb0ef41Sopenharmony_ci } 5851cb0ef41Sopenharmony_ci } 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_ci bool hasConnectedSessions() { 5881cb0ef41Sopenharmony_ci for (const auto& id_channel : channels_) { 5891cb0ef41Sopenharmony_ci // Other sessions are "invisible" more most purposes 5901cb0ef41Sopenharmony_ci if (id_channel.second->preventShutdown()) 5911cb0ef41Sopenharmony_ci return true; 5921cb0ef41Sopenharmony_ci } 5931cb0ef41Sopenharmony_ci return false; 5941cb0ef41Sopenharmony_ci } 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci bool notifyWaitingForDisconnect() { 5971cb0ef41Sopenharmony_ci bool retaining_context = false; 5981cb0ef41Sopenharmony_ci for (const auto& id_channel : channels_) { 5991cb0ef41Sopenharmony_ci if (id_channel.second->notifyWaitingForDisconnect()) 6001cb0ef41Sopenharmony_ci retaining_context = true; 6011cb0ef41Sopenharmony_ci } 6021cb0ef41Sopenharmony_ci return retaining_context; 6031cb0ef41Sopenharmony_ci } 6041cb0ef41Sopenharmony_ci 6051cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadHandle> getThreadHandle() { 6061cb0ef41Sopenharmony_ci if (!interface_) { 6071cb0ef41Sopenharmony_ci interface_ = std::make_shared<MainThreadInterface>( 6081cb0ef41Sopenharmony_ci env_->inspector_agent()); 6091cb0ef41Sopenharmony_ci } 6101cb0ef41Sopenharmony_ci return interface_->GetHandle(); 6111cb0ef41Sopenharmony_ci } 6121cb0ef41Sopenharmony_ci 6131cb0ef41Sopenharmony_ci std::shared_ptr<WorkerManager> getWorkerManager() { 6141cb0ef41Sopenharmony_ci if (!is_main_) { 6151cb0ef41Sopenharmony_ci return nullptr; 6161cb0ef41Sopenharmony_ci } 6171cb0ef41Sopenharmony_ci if (worker_manager_ == nullptr) { 6181cb0ef41Sopenharmony_ci worker_manager_ = 6191cb0ef41Sopenharmony_ci std::make_shared<WorkerManager>(getThreadHandle()); 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci return worker_manager_; 6221cb0ef41Sopenharmony_ci } 6231cb0ef41Sopenharmony_ci 6241cb0ef41Sopenharmony_ci bool IsActive() { 6251cb0ef41Sopenharmony_ci return !channels_.empty(); 6261cb0ef41Sopenharmony_ci } 6271cb0ef41Sopenharmony_ci 6281cb0ef41Sopenharmony_ci private: 6291cb0ef41Sopenharmony_ci bool shouldRunMessageLoop() { 6301cb0ef41Sopenharmony_ci if (waiting_for_frontend_) 6311cb0ef41Sopenharmony_ci return true; 6321cb0ef41Sopenharmony_ci if (waiting_for_sessions_disconnect_ || waiting_for_resume_) { 6331cb0ef41Sopenharmony_ci return hasConnectedSessions(); 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci return false; 6361cb0ef41Sopenharmony_ci } 6371cb0ef41Sopenharmony_ci 6381cb0ef41Sopenharmony_ci void runMessageLoop() { 6391cb0ef41Sopenharmony_ci if (running_nested_loop_) 6401cb0ef41Sopenharmony_ci return; 6411cb0ef41Sopenharmony_ci 6421cb0ef41Sopenharmony_ci running_nested_loop_ = true; 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci while (shouldRunMessageLoop()) { 6451cb0ef41Sopenharmony_ci if (interface_) interface_->WaitForFrontendEvent(); 6461cb0ef41Sopenharmony_ci env_->RunAndClearInterrupts(); 6471cb0ef41Sopenharmony_ci } 6481cb0ef41Sopenharmony_ci running_nested_loop_ = false; 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci 6511cb0ef41Sopenharmony_ci double currentTimeMS() override { 6521cb0ef41Sopenharmony_ci return env_->isolate_data()->platform()->CurrentClockTimeMillis(); 6531cb0ef41Sopenharmony_ci } 6541cb0ef41Sopenharmony_ci 6551cb0ef41Sopenharmony_ci std::unique_ptr<StringBuffer> resourceNameToUrl( 6561cb0ef41Sopenharmony_ci const StringView& resource_name_view) override { 6571cb0ef41Sopenharmony_ci std::string resource_name = 6581cb0ef41Sopenharmony_ci protocol::StringUtil::StringViewToUtf8(resource_name_view); 6591cb0ef41Sopenharmony_ci if (!IsFilePath(resource_name)) 6601cb0ef41Sopenharmony_ci return nullptr; 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ci std::string url = node::url::FromFilePath(resource_name); 6631cb0ef41Sopenharmony_ci return Utf8ToStringView(url); 6641cb0ef41Sopenharmony_ci } 6651cb0ef41Sopenharmony_ci 6661cb0ef41Sopenharmony_ci node::Environment* env_; 6671cb0ef41Sopenharmony_ci bool is_main_; 6681cb0ef41Sopenharmony_ci bool running_nested_loop_ = false; 6691cb0ef41Sopenharmony_ci std::unique_ptr<V8Inspector> client_; 6701cb0ef41Sopenharmony_ci // Note: ~ChannelImpl may access timers_ so timers_ has to come first. 6711cb0ef41Sopenharmony_ci std::unordered_map<void*, TimerWrapHandle> timers_; 6721cb0ef41Sopenharmony_ci std::unordered_map<int, std::unique_ptr<ChannelImpl>> channels_; 6731cb0ef41Sopenharmony_ci int next_session_id_ = 1; 6741cb0ef41Sopenharmony_ci bool waiting_for_resume_ = false; 6751cb0ef41Sopenharmony_ci bool waiting_for_frontend_ = false; 6761cb0ef41Sopenharmony_ci bool waiting_for_sessions_disconnect_ = false; 6771cb0ef41Sopenharmony_ci // Allows accessing Inspector from non-main threads 6781cb0ef41Sopenharmony_ci std::shared_ptr<MainThreadInterface> interface_; 6791cb0ef41Sopenharmony_ci std::shared_ptr<WorkerManager> worker_manager_; 6801cb0ef41Sopenharmony_ci}; 6811cb0ef41Sopenharmony_ci 6821cb0ef41Sopenharmony_ciAgent::Agent(Environment* env) 6831cb0ef41Sopenharmony_ci : parent_env_(env), 6841cb0ef41Sopenharmony_ci debug_options_(env->options()->debug_options()), 6851cb0ef41Sopenharmony_ci host_port_(env->inspector_host_port()) {} 6861cb0ef41Sopenharmony_ci 6871cb0ef41Sopenharmony_ciAgent::~Agent() {} 6881cb0ef41Sopenharmony_ci 6891cb0ef41Sopenharmony_cibool Agent::Start(const std::string& path, 6901cb0ef41Sopenharmony_ci const DebugOptions& options, 6911cb0ef41Sopenharmony_ci std::shared_ptr<ExclusiveAccess<HostPort>> host_port, 6921cb0ef41Sopenharmony_ci bool is_main) { 6931cb0ef41Sopenharmony_ci path_ = path; 6941cb0ef41Sopenharmony_ci debug_options_ = options; 6951cb0ef41Sopenharmony_ci CHECK_NOT_NULL(host_port); 6961cb0ef41Sopenharmony_ci host_port_ = host_port; 6971cb0ef41Sopenharmony_ci 6981cb0ef41Sopenharmony_ci client_ = std::make_shared<NodeInspectorClient>(parent_env_, is_main); 6991cb0ef41Sopenharmony_ci if (parent_env_->owns_inspector()) { 7001cb0ef41Sopenharmony_ci Mutex::ScopedLock lock(start_io_thread_async_mutex); 7011cb0ef41Sopenharmony_ci CHECK_EQ(start_io_thread_async_initialized.exchange(true), false); 7021cb0ef41Sopenharmony_ci CHECK_EQ(0, uv_async_init(parent_env_->event_loop(), 7031cb0ef41Sopenharmony_ci &start_io_thread_async, 7041cb0ef41Sopenharmony_ci StartIoThreadAsyncCallback)); 7051cb0ef41Sopenharmony_ci uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async)); 7061cb0ef41Sopenharmony_ci start_io_thread_async.data = this; 7071cb0ef41Sopenharmony_ci // Ignore failure, SIGUSR1 won't work, but that should not block node start. 7081cb0ef41Sopenharmony_ci StartDebugSignalHandler(); 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ci parent_env_->AddCleanupHook([](void* data) { 7111cb0ef41Sopenharmony_ci Environment* env = static_cast<Environment*>(data); 7121cb0ef41Sopenharmony_ci 7131cb0ef41Sopenharmony_ci { 7141cb0ef41Sopenharmony_ci Mutex::ScopedLock lock(start_io_thread_async_mutex); 7151cb0ef41Sopenharmony_ci start_io_thread_async.data = nullptr; 7161cb0ef41Sopenharmony_ci } 7171cb0ef41Sopenharmony_ci 7181cb0ef41Sopenharmony_ci // This is global, will never get freed 7191cb0ef41Sopenharmony_ci env->CloseHandle(&start_io_thread_async, [](uv_async_t*) { 7201cb0ef41Sopenharmony_ci CHECK(start_io_thread_async_initialized.exchange(false)); 7211cb0ef41Sopenharmony_ci }); 7221cb0ef41Sopenharmony_ci }, parent_env_); 7231cb0ef41Sopenharmony_ci } 7241cb0ef41Sopenharmony_ci 7251cb0ef41Sopenharmony_ci AtExit(parent_env_, [](void* env) { 7261cb0ef41Sopenharmony_ci Agent* agent = static_cast<Environment*>(env)->inspector_agent(); 7271cb0ef41Sopenharmony_ci if (agent->IsActive()) { 7281cb0ef41Sopenharmony_ci agent->WaitForDisconnect(); 7291cb0ef41Sopenharmony_ci } 7301cb0ef41Sopenharmony_ci }, parent_env_); 7311cb0ef41Sopenharmony_ci 7321cb0ef41Sopenharmony_ci bool wait_for_connect = options.wait_for_connect(); 7331cb0ef41Sopenharmony_ci if (parent_handle_) { 7341cb0ef41Sopenharmony_ci wait_for_connect = parent_handle_->WaitForConnect(); 7351cb0ef41Sopenharmony_ci parent_handle_->WorkerStarted(client_->getThreadHandle(), wait_for_connect); 7361cb0ef41Sopenharmony_ci } else if (!options.inspector_enabled || !options.allow_attaching_debugger || 7371cb0ef41Sopenharmony_ci !StartIoThread()) { 7381cb0ef41Sopenharmony_ci return false; 7391cb0ef41Sopenharmony_ci } 7401cb0ef41Sopenharmony_ci 7411cb0ef41Sopenharmony_ci // Patch the debug options to implement waitForDebuggerOnStart for 7421cb0ef41Sopenharmony_ci // the NodeWorker.enable method. 7431cb0ef41Sopenharmony_ci if (wait_for_connect) { 7441cb0ef41Sopenharmony_ci CHECK(!parent_env_->has_serialized_options()); 7451cb0ef41Sopenharmony_ci debug_options_.EnableBreakFirstLine(); 7461cb0ef41Sopenharmony_ci parent_env_->options()->get_debug_options()->EnableBreakFirstLine(); 7471cb0ef41Sopenharmony_ci client_->waitForFrontend(); 7481cb0ef41Sopenharmony_ci } 7491cb0ef41Sopenharmony_ci return true; 7501cb0ef41Sopenharmony_ci} 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_cibool Agent::StartIoThread() { 7531cb0ef41Sopenharmony_ci if (io_ != nullptr) 7541cb0ef41Sopenharmony_ci return true; 7551cb0ef41Sopenharmony_ci 7561cb0ef41Sopenharmony_ci if (!parent_env_->should_create_inspector() && !client_) { 7571cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 7581cb0ef41Sopenharmony_ci return false; 7591cb0ef41Sopenharmony_ci } 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 7621cb0ef41Sopenharmony_ci 7631cb0ef41Sopenharmony_ci io_ = InspectorIo::Start(client_->getThreadHandle(), 7641cb0ef41Sopenharmony_ci path_, 7651cb0ef41Sopenharmony_ci host_port_, 7661cb0ef41Sopenharmony_ci debug_options_.inspect_publish_uid); 7671cb0ef41Sopenharmony_ci if (io_ == nullptr) { 7681cb0ef41Sopenharmony_ci return false; 7691cb0ef41Sopenharmony_ci } 7701cb0ef41Sopenharmony_ci NotifyClusterWorkersDebugEnabled(parent_env_); 7711cb0ef41Sopenharmony_ci return true; 7721cb0ef41Sopenharmony_ci} 7731cb0ef41Sopenharmony_ci 7741cb0ef41Sopenharmony_civoid Agent::Stop() { 7751cb0ef41Sopenharmony_ci io_.reset(); 7761cb0ef41Sopenharmony_ci} 7771cb0ef41Sopenharmony_ci 7781cb0ef41Sopenharmony_cistd::unique_ptr<InspectorSession> Agent::Connect( 7791cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate, 7801cb0ef41Sopenharmony_ci bool prevent_shutdown) { 7811cb0ef41Sopenharmony_ci if (!parent_env_->should_create_inspector() && !client_) { 7821cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 7831cb0ef41Sopenharmony_ci return std::unique_ptr<InspectorSession>{}; 7841cb0ef41Sopenharmony_ci } 7851cb0ef41Sopenharmony_ci 7861cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 7871cb0ef41Sopenharmony_ci 7881cb0ef41Sopenharmony_ci int session_id = client_->connectFrontend(std::move(delegate), 7891cb0ef41Sopenharmony_ci prevent_shutdown); 7901cb0ef41Sopenharmony_ci return std::unique_ptr<InspectorSession>( 7911cb0ef41Sopenharmony_ci new SameThreadInspectorSession(session_id, client_)); 7921cb0ef41Sopenharmony_ci} 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_cistd::unique_ptr<InspectorSession> Agent::ConnectToMainThread( 7951cb0ef41Sopenharmony_ci std::unique_ptr<InspectorSessionDelegate> delegate, 7961cb0ef41Sopenharmony_ci bool prevent_shutdown) { 7971cb0ef41Sopenharmony_ci if (!parent_env_->should_create_inspector() && !client_) { 7981cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 7991cb0ef41Sopenharmony_ci return std::unique_ptr<InspectorSession>{}; 8001cb0ef41Sopenharmony_ci } 8011cb0ef41Sopenharmony_ci 8021cb0ef41Sopenharmony_ci CHECK_NOT_NULL(parent_handle_); 8031cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 8041cb0ef41Sopenharmony_ci auto thread_safe_delegate = 8051cb0ef41Sopenharmony_ci client_->getThreadHandle()->MakeDelegateThreadSafe(std::move(delegate)); 8061cb0ef41Sopenharmony_ci return parent_handle_->Connect(std::move(thread_safe_delegate), 8071cb0ef41Sopenharmony_ci prevent_shutdown); 8081cb0ef41Sopenharmony_ci} 8091cb0ef41Sopenharmony_ci 8101cb0ef41Sopenharmony_civoid Agent::WaitForDisconnect() { 8111cb0ef41Sopenharmony_ci if (!parent_env_->should_create_inspector() && !client_) { 8121cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 8131cb0ef41Sopenharmony_ci return; 8141cb0ef41Sopenharmony_ci } 8151cb0ef41Sopenharmony_ci 8161cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 8171cb0ef41Sopenharmony_ci bool is_worker = parent_handle_ != nullptr; 8181cb0ef41Sopenharmony_ci parent_handle_.reset(); 8191cb0ef41Sopenharmony_ci if (client_->hasConnectedSessions() && !is_worker) { 8201cb0ef41Sopenharmony_ci fprintf(stderr, "Waiting for the debugger to disconnect...\n"); 8211cb0ef41Sopenharmony_ci fflush(stderr); 8221cb0ef41Sopenharmony_ci } 8231cb0ef41Sopenharmony_ci if (!client_->notifyWaitingForDisconnect()) { 8241cb0ef41Sopenharmony_ci client_->contextDestroyed(parent_env_->context()); 8251cb0ef41Sopenharmony_ci } else if (is_worker) { 8261cb0ef41Sopenharmony_ci client_->waitForSessionsDisconnect(); 8271cb0ef41Sopenharmony_ci } 8281cb0ef41Sopenharmony_ci if (io_ != nullptr) { 8291cb0ef41Sopenharmony_ci io_->StopAcceptingNewConnections(); 8301cb0ef41Sopenharmony_ci client_->waitForSessionsDisconnect(); 8311cb0ef41Sopenharmony_ci } 8321cb0ef41Sopenharmony_ci} 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_civoid Agent::ReportUncaughtException(Local<Value> error, 8351cb0ef41Sopenharmony_ci Local<Message> message) { 8361cb0ef41Sopenharmony_ci if (!IsListening()) 8371cb0ef41Sopenharmony_ci return; 8381cb0ef41Sopenharmony_ci client_->ReportUncaughtException(error, message); 8391cb0ef41Sopenharmony_ci WaitForDisconnect(); 8401cb0ef41Sopenharmony_ci} 8411cb0ef41Sopenharmony_ci 8421cb0ef41Sopenharmony_civoid Agent::PauseOnNextJavascriptStatement(const std::string& reason) { 8431cb0ef41Sopenharmony_ci client_->schedulePauseOnNextStatement(reason); 8441cb0ef41Sopenharmony_ci} 8451cb0ef41Sopenharmony_ci 8461cb0ef41Sopenharmony_civoid Agent::RegisterAsyncHook(Isolate* isolate, 8471cb0ef41Sopenharmony_ci Local<Function> enable_function, 8481cb0ef41Sopenharmony_ci Local<Function> disable_function) { 8491cb0ef41Sopenharmony_ci parent_env_->set_inspector_enable_async_hooks(enable_function); 8501cb0ef41Sopenharmony_ci parent_env_->set_inspector_disable_async_hooks(disable_function); 8511cb0ef41Sopenharmony_ci if (pending_enable_async_hook_) { 8521cb0ef41Sopenharmony_ci CHECK(!pending_disable_async_hook_); 8531cb0ef41Sopenharmony_ci pending_enable_async_hook_ = false; 8541cb0ef41Sopenharmony_ci EnableAsyncHook(); 8551cb0ef41Sopenharmony_ci } else if (pending_disable_async_hook_) { 8561cb0ef41Sopenharmony_ci CHECK(!pending_enable_async_hook_); 8571cb0ef41Sopenharmony_ci pending_disable_async_hook_ = false; 8581cb0ef41Sopenharmony_ci DisableAsyncHook(); 8591cb0ef41Sopenharmony_ci } 8601cb0ef41Sopenharmony_ci} 8611cb0ef41Sopenharmony_ci 8621cb0ef41Sopenharmony_civoid Agent::EnableAsyncHook() { 8631cb0ef41Sopenharmony_ci HandleScope scope(parent_env_->isolate()); 8641cb0ef41Sopenharmony_ci Local<Function> enable = parent_env_->inspector_enable_async_hooks(); 8651cb0ef41Sopenharmony_ci if (!enable.IsEmpty()) { 8661cb0ef41Sopenharmony_ci ToggleAsyncHook(parent_env_->isolate(), enable); 8671cb0ef41Sopenharmony_ci } else if (pending_disable_async_hook_) { 8681cb0ef41Sopenharmony_ci CHECK(!pending_enable_async_hook_); 8691cb0ef41Sopenharmony_ci pending_disable_async_hook_ = false; 8701cb0ef41Sopenharmony_ci } else { 8711cb0ef41Sopenharmony_ci pending_enable_async_hook_ = true; 8721cb0ef41Sopenharmony_ci } 8731cb0ef41Sopenharmony_ci} 8741cb0ef41Sopenharmony_ci 8751cb0ef41Sopenharmony_civoid Agent::DisableAsyncHook() { 8761cb0ef41Sopenharmony_ci HandleScope scope(parent_env_->isolate()); 8771cb0ef41Sopenharmony_ci Local<Function> disable = parent_env_->inspector_enable_async_hooks(); 8781cb0ef41Sopenharmony_ci if (!disable.IsEmpty()) { 8791cb0ef41Sopenharmony_ci ToggleAsyncHook(parent_env_->isolate(), disable); 8801cb0ef41Sopenharmony_ci } else if (pending_enable_async_hook_) { 8811cb0ef41Sopenharmony_ci CHECK(!pending_disable_async_hook_); 8821cb0ef41Sopenharmony_ci pending_enable_async_hook_ = false; 8831cb0ef41Sopenharmony_ci } else { 8841cb0ef41Sopenharmony_ci pending_disable_async_hook_ = true; 8851cb0ef41Sopenharmony_ci } 8861cb0ef41Sopenharmony_ci} 8871cb0ef41Sopenharmony_ci 8881cb0ef41Sopenharmony_civoid Agent::ToggleAsyncHook(Isolate* isolate, Local<Function> fn) { 8891cb0ef41Sopenharmony_ci // Guard against running this during cleanup -- no async events will be 8901cb0ef41Sopenharmony_ci // emitted anyway at that point anymore, and calling into JS is not possible. 8911cb0ef41Sopenharmony_ci // This should probably not be something we're attempting in the first place, 8921cb0ef41Sopenharmony_ci // Refs: https://github.com/nodejs/node/pull/34362#discussion_r456006039 8931cb0ef41Sopenharmony_ci if (!parent_env_->can_call_into_js()) return; 8941cb0ef41Sopenharmony_ci CHECK(parent_env_->has_run_bootstrapping_code()); 8951cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 8961cb0ef41Sopenharmony_ci CHECK(!fn.IsEmpty()); 8971cb0ef41Sopenharmony_ci auto context = parent_env_->context(); 8981cb0ef41Sopenharmony_ci v8::TryCatch try_catch(isolate); 8991cb0ef41Sopenharmony_ci USE(fn->Call(context, Undefined(isolate), 0, nullptr)); 9001cb0ef41Sopenharmony_ci if (try_catch.HasCaught() && !try_catch.HasTerminated()) { 9011cb0ef41Sopenharmony_ci PrintCaughtException(isolate, context, try_catch); 9021cb0ef41Sopenharmony_ci OnFatalError("\nnode::inspector::Agent::ToggleAsyncHook", 9031cb0ef41Sopenharmony_ci "Cannot toggle Inspector's AsyncHook, please report this."); 9041cb0ef41Sopenharmony_ci } 9051cb0ef41Sopenharmony_ci} 9061cb0ef41Sopenharmony_ci 9071cb0ef41Sopenharmony_civoid Agent::AsyncTaskScheduled(const StringView& task_name, void* task, 9081cb0ef41Sopenharmony_ci bool recurring) { 9091cb0ef41Sopenharmony_ci client_->AsyncTaskScheduled(task_name, task, recurring); 9101cb0ef41Sopenharmony_ci} 9111cb0ef41Sopenharmony_ci 9121cb0ef41Sopenharmony_civoid Agent::AsyncTaskCanceled(void* task) { 9131cb0ef41Sopenharmony_ci client_->AsyncTaskCanceled(task); 9141cb0ef41Sopenharmony_ci} 9151cb0ef41Sopenharmony_ci 9161cb0ef41Sopenharmony_civoid Agent::AsyncTaskStarted(void* task) { 9171cb0ef41Sopenharmony_ci client_->AsyncTaskStarted(task); 9181cb0ef41Sopenharmony_ci} 9191cb0ef41Sopenharmony_ci 9201cb0ef41Sopenharmony_civoid Agent::AsyncTaskFinished(void* task) { 9211cb0ef41Sopenharmony_ci client_->AsyncTaskFinished(task); 9221cb0ef41Sopenharmony_ci} 9231cb0ef41Sopenharmony_ci 9241cb0ef41Sopenharmony_civoid Agent::AllAsyncTasksCanceled() { 9251cb0ef41Sopenharmony_ci client_->AllAsyncTasksCanceled(); 9261cb0ef41Sopenharmony_ci} 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_civoid Agent::RequestIoThreadStart() { 9291cb0ef41Sopenharmony_ci // We need to attempt to interrupt V8 flow (in case Node is running 9301cb0ef41Sopenharmony_ci // continuous JS code) and to wake up libuv thread (in case Node is waiting 9311cb0ef41Sopenharmony_ci // for IO events) 9321cb0ef41Sopenharmony_ci if (!options().allow_attaching_debugger) { 9331cb0ef41Sopenharmony_ci return; 9341cb0ef41Sopenharmony_ci } 9351cb0ef41Sopenharmony_ci CHECK(start_io_thread_async_initialized); 9361cb0ef41Sopenharmony_ci uv_async_send(&start_io_thread_async); 9371cb0ef41Sopenharmony_ci parent_env_->RequestInterrupt([this](Environment*) { 9381cb0ef41Sopenharmony_ci StartIoThread(); 9391cb0ef41Sopenharmony_ci }); 9401cb0ef41Sopenharmony_ci 9411cb0ef41Sopenharmony_ci CHECK(start_io_thread_async_initialized); 9421cb0ef41Sopenharmony_ci uv_async_send(&start_io_thread_async); 9431cb0ef41Sopenharmony_ci} 9441cb0ef41Sopenharmony_ci 9451cb0ef41Sopenharmony_civoid Agent::ContextCreated(Local<Context> context, const ContextInfo& info) { 9461cb0ef41Sopenharmony_ci if (client_ == nullptr) // This happens for a main context 9471cb0ef41Sopenharmony_ci return; 9481cb0ef41Sopenharmony_ci client_->contextCreated(context, info); 9491cb0ef41Sopenharmony_ci} 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_cibool Agent::IsActive() { 9521cb0ef41Sopenharmony_ci if (client_ == nullptr) 9531cb0ef41Sopenharmony_ci return false; 9541cb0ef41Sopenharmony_ci return io_ != nullptr || client_->IsActive(); 9551cb0ef41Sopenharmony_ci} 9561cb0ef41Sopenharmony_ci 9571cb0ef41Sopenharmony_civoid Agent::SetParentHandle( 9581cb0ef41Sopenharmony_ci std::unique_ptr<ParentInspectorHandle> parent_handle) { 9591cb0ef41Sopenharmony_ci parent_handle_ = std::move(parent_handle); 9601cb0ef41Sopenharmony_ci} 9611cb0ef41Sopenharmony_ci 9621cb0ef41Sopenharmony_cistd::unique_ptr<ParentInspectorHandle> Agent::GetParentHandle( 9631cb0ef41Sopenharmony_ci uint64_t thread_id, const std::string& url, const std::string& name) { 9641cb0ef41Sopenharmony_ci if (!parent_env_->should_create_inspector() && !client_) { 9651cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 9661cb0ef41Sopenharmony_ci return std::unique_ptr<ParentInspectorHandle>{}; 9671cb0ef41Sopenharmony_ci } 9681cb0ef41Sopenharmony_ci 9691cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 9701cb0ef41Sopenharmony_ci if (!parent_handle_) { 9711cb0ef41Sopenharmony_ci return client_->getWorkerManager()->NewParentHandle(thread_id, url, name); 9721cb0ef41Sopenharmony_ci } else { 9731cb0ef41Sopenharmony_ci return parent_handle_->NewParentInspectorHandle(thread_id, url, name); 9741cb0ef41Sopenharmony_ci } 9751cb0ef41Sopenharmony_ci} 9761cb0ef41Sopenharmony_ci 9771cb0ef41Sopenharmony_civoid Agent::WaitForConnect() { 9781cb0ef41Sopenharmony_ci if (!parent_env_->should_create_inspector() && !client_) { 9791cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 9801cb0ef41Sopenharmony_ci return; 9811cb0ef41Sopenharmony_ci } 9821cb0ef41Sopenharmony_ci 9831cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 9841cb0ef41Sopenharmony_ci client_->waitForFrontend(); 9851cb0ef41Sopenharmony_ci} 9861cb0ef41Sopenharmony_ci 9871cb0ef41Sopenharmony_cistd::shared_ptr<WorkerManager> Agent::GetWorkerManager() { 9881cb0ef41Sopenharmony_ci if (!parent_env_->should_create_inspector() && !client_) { 9891cb0ef41Sopenharmony_ci ThrowUninitializedInspectorError(parent_env_); 9901cb0ef41Sopenharmony_ci return std::unique_ptr<WorkerManager>{}; 9911cb0ef41Sopenharmony_ci } 9921cb0ef41Sopenharmony_ci 9931cb0ef41Sopenharmony_ci CHECK_NOT_NULL(client_); 9941cb0ef41Sopenharmony_ci return client_->getWorkerManager(); 9951cb0ef41Sopenharmony_ci} 9961cb0ef41Sopenharmony_ci 9971cb0ef41Sopenharmony_cistd::string Agent::GetWsUrl() const { 9981cb0ef41Sopenharmony_ci if (io_ == nullptr) 9991cb0ef41Sopenharmony_ci return ""; 10001cb0ef41Sopenharmony_ci return io_->GetWsUrl(); 10011cb0ef41Sopenharmony_ci} 10021cb0ef41Sopenharmony_ci 10031cb0ef41Sopenharmony_ciSameThreadInspectorSession::~SameThreadInspectorSession() { 10041cb0ef41Sopenharmony_ci auto client = client_.lock(); 10051cb0ef41Sopenharmony_ci if (client) 10061cb0ef41Sopenharmony_ci client->disconnectFrontend(session_id_); 10071cb0ef41Sopenharmony_ci} 10081cb0ef41Sopenharmony_ci 10091cb0ef41Sopenharmony_civoid SameThreadInspectorSession::Dispatch( 10101cb0ef41Sopenharmony_ci const v8_inspector::StringView& message) { 10111cb0ef41Sopenharmony_ci auto client = client_.lock(); 10121cb0ef41Sopenharmony_ci if (client) 10131cb0ef41Sopenharmony_ci client->dispatchMessageFromFrontend(session_id_, message); 10141cb0ef41Sopenharmony_ci} 10151cb0ef41Sopenharmony_ci 10161cb0ef41Sopenharmony_ci} // namespace inspector 10171cb0ef41Sopenharmony_ci} // namespace node 1018