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