From e3ca1f1a734a7ca31f139a128cfdd1bb743c9001 Mon Sep 17 00:00:00 2001 From: Alex Turner Date: Thu, 3 Feb 2022 17:16:45 -0500 Subject: [PATCH] Add V8Inspector::uniqueDebuggerId method This method returns the unique debugger ID for a v8::Context (i.e. the V8DebuggerID), serialized to a pair of int64_ts. Bug: v8:12528 Change-Id: Ib2cdda73447f8233f9afb773fed4a634d4618aef Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3369124 Reviewed-by: Benedikt Meurer Commit-Queue: Alex Turner Cr-Commit-Position: refs/heads/main@{#78958} --- include/v8-inspector.h | 29 +++++++++++++++++++++++++ src/inspector/inspected-context.cc | 2 +- src/inspector/inspected-context.h | 4 ++-- src/inspector/v8-debugger-agent-impl.cc | 8 ++++--- src/inspector/v8-debugger-id.cc | 28 +++++++++++++++++++----- src/inspector/v8-debugger-id.h | 17 ++++++--------- src/inspector/v8-debugger.cc | 5 +++-- src/inspector/v8-debugger.h | 4 ++-- src/inspector/v8-inspector-impl.cc | 11 +++++++++- src/inspector/v8-inspector-impl.h | 3 ++- src/inspector/v8-runtime-agent-impl.cc | 2 +- src/inspector/v8-stack-trace-impl.cc | 12 +++++----- 12 files changed, 91 insertions(+), 34 deletions(-) diff --git a/include/v8-inspector.h b/include/v8-inspector.h index 2a258d505a..b07372ce2b 100644 --- a/include/v8-inspector.h +++ b/include/v8-inspector.h @@ -23,6 +23,10 @@ class Value; namespace v8_inspector { +namespace internal { +class V8DebuggerId; +} // namespace internal + namespace protocol { namespace Debugger { namespace API { @@ -106,6 +110,30 @@ class V8_EXPORT V8ContextInfo { V8ContextInfo& operator=(const V8ContextInfo&) = delete; }; +// This debugger id tries to be unique by generating two random +// numbers, which should most likely avoid collisions. +// Debugger id has a 1:1 mapping to context group. It is used to +// attribute stack traces to a particular debugging, when doing any +// cross-debugger operations (e.g. async step in). +// See also Runtime.UniqueDebuggerId in the protocol. +class V8_EXPORT V8DebuggerId { + public: + V8DebuggerId(const V8DebuggerId&) = default; + V8DebuggerId& operator=(const V8DebuggerId&) = default; + + std::unique_ptr toString() const; + bool isValid() const; + std::pair pair() const; + + private: + friend class internal::V8DebuggerId; + V8DebuggerId() = default; + explicit V8DebuggerId(std::pair); + + int64_t m_first = 0; + int64_t m_second = 0; +}; + class V8_EXPORT V8StackTrace { public: virtual StringView firstNonEmptySourceURL() const = 0; @@ -276,6 +304,7 @@ class V8_EXPORT V8Inspector { virtual void contextDestroyed(v8::Local) = 0; virtual void resetContextGroup(int contextGroupId) = 0; virtual v8::MaybeLocal contextById(int contextId) = 0; + virtual V8DebuggerId uniqueDebuggerId(int contextId) = 0; // Various instrumentation. virtual void idleStarted() = 0; diff --git a/src/inspector/inspected-context.cc b/src/inspector/inspected-context.cc index 8db0a4f5ba..5163950a1f 100644 --- a/src/inspector/inspected-context.cc +++ b/src/inspector/inspected-context.cc @@ -56,7 +56,7 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector, m_origin(toString16(info.origin)), m_humanReadableName(toString16(info.humanReadableName)), m_auxData(toString16(info.auxData)), - m_uniqueId(V8DebuggerId::generate(inspector)) { + m_uniqueId(internal::V8DebuggerId::generate(inspector)) { v8::debug::SetContextId(info.context, contextId); m_weakCallbackData = new WeakCallbackData(this, m_inspector, m_contextGroupId, m_contextId); diff --git a/src/inspector/inspected-context.h b/src/inspector/inspected-context.h index 50e5a87bb3..987d3a7642 100644 --- a/src/inspector/inspected-context.h +++ b/src/inspector/inspected-context.h @@ -43,7 +43,7 @@ class InspectedContext { int contextGroupId() const { return m_contextGroupId; } String16 origin() const { return m_origin; } String16 humanReadableName() const { return m_humanReadableName; } - V8DebuggerId uniqueId() const { return m_uniqueId; } + internal::V8DebuggerId uniqueId() const { return m_uniqueId; } String16 auxData() const { return m_auxData; } bool isReported(int sessionId) const; @@ -73,7 +73,7 @@ class InspectedContext { const String16 m_origin; const String16 m_humanReadableName; const String16 m_auxData; - const V8DebuggerId m_uniqueId; + const internal::V8DebuggerId m_uniqueId; std::unordered_set m_reportedSessionIds; std::unordered_map> m_injectedScripts; WeakCallbackData* m_weakCallbackData; diff --git a/src/inspector/v8-debugger-agent-impl.cc b/src/inspector/v8-debugger-agent-impl.cc index 4f209360f9..1fd241bb7d 100644 --- a/src/inspector/v8-debugger-agent-impl.cc +++ b/src/inspector/v8-debugger-agent-impl.cc @@ -845,9 +845,10 @@ Response V8DebuggerAgentImpl::getStackTrace( int64_t id = inStackTraceId->getId().toInteger64(&isOk); if (!isOk) return Response::ServerError("Invalid stack trace id"); - V8DebuggerId debuggerId; + internal::V8DebuggerId debuggerId; if (inStackTraceId->hasDebuggerId()) { - debuggerId = V8DebuggerId(inStackTraceId->getDebuggerId(String16())); + debuggerId = + internal::V8DebuggerId(inStackTraceId->getDebuggerId(String16())); } else { debuggerId = m_debugger->debuggerIdFor(m_session->contextGroupId()); } @@ -1521,7 +1522,8 @@ V8DebuggerAgentImpl::currentExternalStackTrace() { if (externalParent.IsInvalid()) return nullptr; return protocol::Runtime::StackTraceId::create() .setId(stackTraceIdToString(externalParent.id)) - .setDebuggerId(V8DebuggerId(externalParent.debugger_id).toString()) + .setDebuggerId( + internal::V8DebuggerId(externalParent.debugger_id).toString()) .build(); } diff --git a/src/inspector/v8-debugger-id.cc b/src/inspector/v8-debugger-id.cc index 995df6689f..6989a96e67 100644 --- a/src/inspector/v8-debugger-id.cc +++ b/src/inspector/v8-debugger-id.cc @@ -5,6 +5,7 @@ #include "src/inspector/v8-debugger-id.h" #include "src/debug/debug-interface.h" +#include "src/inspector/string-util.h" #include "src/inspector/v8-inspector-impl.h" namespace v8_inspector { @@ -12,6 +13,22 @@ namespace v8_inspector { V8DebuggerId::V8DebuggerId(std::pair pair) : m_first(pair.first), m_second(pair.second) {} +std::unique_ptr V8DebuggerId::toString() const { + return StringBufferFrom(String16::fromInteger64(m_first) + "." + + String16::fromInteger64(m_second)); +} + +bool V8DebuggerId::isValid() const { return m_first || m_second; } + +std::pair V8DebuggerId::pair() const { + return std::make_pair(m_first, m_second); +} + +namespace internal { + +V8DebuggerId::V8DebuggerId(std::pair pair) + : m_debugger_id(pair) {} + // static V8DebuggerId V8DebuggerId::generate(V8InspectorImpl* inspector) { return V8DebuggerId(std::make_pair(inspector->generateUniqueId(), @@ -27,19 +44,18 @@ V8DebuggerId::V8DebuggerId(const String16& debuggerId) { if (!ok) return; int64_t second = debuggerId.substring(pos + 1).toInteger64(&ok); if (!ok) return; - m_first = first; - m_second = second; + m_debugger_id = v8_inspector::V8DebuggerId(std::make_pair(first, second)); } String16 V8DebuggerId::toString() const { - return String16::fromInteger64(m_first) + "." + - String16::fromInteger64(m_second); + return toString16(m_debugger_id.toString()->string()); } -bool V8DebuggerId::isValid() const { return m_first || m_second; } +bool V8DebuggerId::isValid() const { return m_debugger_id.isValid(); } std::pair V8DebuggerId::pair() const { - return std::make_pair(m_first, m_second); + return m_debugger_id.pair(); } +} // namespace internal } // namespace v8_inspector diff --git a/src/inspector/v8-debugger-id.h b/src/inspector/v8-debugger-id.h index 5f53c02189..757976d5bd 100644 --- a/src/inspector/v8-debugger-id.h +++ b/src/inspector/v8-debugger-id.h @@ -7,38 +7,35 @@ #include +#include "include/v8-inspector.h" #include "src/base/macros.h" #include "src/inspector/protocol/Forward.h" namespace v8_inspector { - class V8InspectorImpl; -// This debugger id tries to be unique by generating two random -// numbers, which should most likely avoid collisions. -// Debugger id has a 1:1 mapping to context group. It is used to -// attribute stack traces to a particular debugging, when doing any -// cross-debugger operations (e.g. async step in). -// See also Runtime.UniqueDebuggerId in the protocol. +namespace internal { + class V8DebuggerId { public: V8DebuggerId() = default; explicit V8DebuggerId(std::pair); explicit V8DebuggerId(const String16&); V8DebuggerId(const V8DebuggerId&) V8_NOEXCEPT = default; - ~V8DebuggerId() = default; + V8DebuggerId& operator=(const V8DebuggerId&) V8_NOEXCEPT = default; static V8DebuggerId generate(V8InspectorImpl*); + v8_inspector::V8DebuggerId toV8DebuggerId() const { return m_debugger_id; } String16 toString() const; bool isValid() const; std::pair pair() const; private: - int64_t m_first = 0; - int64_t m_second = 0; + v8_inspector::V8DebuggerId m_debugger_id; }; +} // namespace internal } // namespace v8_inspector #endif // V8_INSPECTOR_V8_DEBUGGER_ID_H_ diff --git a/src/inspector/v8-debugger.cc b/src/inspector/v8-debugger.cc index 4d156b242b..74fa97a16f 100644 --- a/src/inspector/v8-debugger.cc +++ b/src/inspector/v8-debugger.cc @@ -1159,10 +1159,11 @@ void V8Debugger::setMaxAsyncTaskStacksForTest(int limit) { m_maxAsyncCallStacks = limit; } -V8DebuggerId V8Debugger::debuggerIdFor(int contextGroupId) { +internal::V8DebuggerId V8Debugger::debuggerIdFor(int contextGroupId) { auto it = m_contextGroupIdToDebuggerId.find(contextGroupId); if (it != m_contextGroupIdToDebuggerId.end()) return it->second; - V8DebuggerId debuggerId = V8DebuggerId::generate(m_inspector); + internal::V8DebuggerId debuggerId = + internal::V8DebuggerId::generate(m_inspector); m_contextGroupIdToDebuggerId.insert( it, std::make_pair(contextGroupId, debuggerId)); return debuggerId; diff --git a/src/inspector/v8-debugger.h b/src/inspector/v8-debugger.h index 95e649cc31..de8e3e95f6 100644 --- a/src/inspector/v8-debugger.h +++ b/src/inspector/v8-debugger.h @@ -124,7 +124,7 @@ class V8Debugger : public v8::debug::DebugDelegate, void setMaxAsyncTaskStacksForTest(int limit); void dumpAsyncTaskStacksStateForTest(); - V8DebuggerId debuggerIdFor(int contextGroupId); + internal::V8DebuggerId debuggerIdFor(int contextGroupId); std::shared_ptr stackTraceFor(int contextGroupId, const V8StackTraceId& id); @@ -283,7 +283,7 @@ class V8Debugger : public v8::debug::DebugDelegate, StackTraceIdToStackTrace m_storedStackTraces; uintptr_t m_lastStackTraceId = 0; - std::unordered_map m_contextGroupIdToDebuggerId; + std::unordered_map m_contextGroupIdToDebuggerId; std::unique_ptr m_terminateExecutionCallback; }; diff --git a/src/inspector/v8-inspector-impl.cc b/src/inspector/v8-inspector-impl.cc index 420719e068..edc97d0f39 100644 --- a/src/inspector/v8-inspector-impl.cc +++ b/src/inspector/v8-inspector-impl.cc @@ -44,6 +44,7 @@ #include "src/inspector/v8-console-message.h" #include "src/inspector/v8-console.h" #include "src/inspector/v8-debugger-agent-impl.h" +#include "src/inspector/v8-debugger-id.h" #include "src/inspector/v8-debugger.h" #include "src/inspector/v8-inspector-session-impl.h" #include "src/inspector/v8-profiler-agent-impl.h" @@ -83,7 +84,8 @@ int V8InspectorImpl::contextGroupId(int contextId) const { return it != m_contextIdToGroupIdMap.end() ? it->second : 0; } -int V8InspectorImpl::resolveUniqueContextId(V8DebuggerId uniqueId) const { +int V8InspectorImpl::resolveUniqueContextId( + internal::V8DebuggerId uniqueId) const { auto it = m_uniqueIdToContextId.find(uniqueId.pair()); return it == m_uniqueIdToContextId.end() ? 0 : it->second; } @@ -180,6 +182,13 @@ v8::MaybeLocal V8InspectorImpl::contextById(int contextId) { return context ? context->context() : v8::MaybeLocal(); } +V8DebuggerId V8InspectorImpl::uniqueDebuggerId(int contextId) { + InspectedContext* context = getContext(contextId); + internal::V8DebuggerId unique_id; + if (context) unique_id = context->uniqueId(); + return unique_id.toV8DebuggerId(); +} + void V8InspectorImpl::contextCreated(const V8ContextInfo& info) { int contextId = ++m_lastContextId; auto* context = new InspectedContext(this, info, contextId); diff --git a/src/inspector/v8-inspector-impl.h b/src/inspector/v8-inspector-impl.h index b267f8ec14..731377daf2 100644 --- a/src/inspector/v8-inspector-impl.h +++ b/src/inspector/v8-inspector-impl.h @@ -67,7 +67,7 @@ class V8InspectorImpl : public V8Inspector { int contextGroupId(v8::Local) const; int contextGroupId(int contextId) const; uint64_t isolateId() const { return m_isolateId; } - int resolveUniqueContextId(V8DebuggerId uniqueId) const; + int resolveUniqueContextId(internal::V8DebuggerId uniqueId) const; v8::MaybeLocal compileAndRunInternalScript(v8::Local, v8::Local); @@ -84,6 +84,7 @@ class V8InspectorImpl : public V8Inspector { void contextCreated(const V8ContextInfo&) override; void contextDestroyed(v8::Local) override; v8::MaybeLocal contextById(int contextId) override; + V8DebuggerId uniqueDebuggerId(int contextId) override; void contextCollected(int contextGroupId, int contextId); void resetContextGroup(int contextGroupId) override; void idleStarted() override; diff --git a/src/inspector/v8-runtime-agent-impl.cc b/src/inspector/v8-runtime-agent-impl.cc index 0d8575a6a8..629c24a254 100644 --- a/src/inspector/v8-runtime-agent-impl.cc +++ b/src/inspector/v8-runtime-agent-impl.cc @@ -217,7 +217,7 @@ Response ensureContext(V8InspectorImpl* inspector, int contextGroupId, } *contextId = executionContextId.fromJust(); } else if (uniqueContextId.isJust()) { - V8DebuggerId uniqueId(uniqueContextId.fromJust()); + internal::V8DebuggerId uniqueId(uniqueContextId.fromJust()); if (!uniqueId.isValid()) return Response::InvalidParams("invalid uniqueContextId"); int id = inspector->resolveUniqueContextId(uniqueId); diff --git a/src/inspector/v8-stack-trace-impl.cc b/src/inspector/v8-stack-trace-impl.cc index bd89b0f468..8090c889b5 100644 --- a/src/inspector/v8-stack-trace-impl.cc +++ b/src/inspector/v8-stack-trace-impl.cc @@ -107,7 +107,8 @@ std::unique_ptr buildInspectorObjectCommon( stackTrace->setParentId( protocol::Runtime::StackTraceId::create() .setId(stackTraceIdToString(externalParent.id)) - .setDebuggerId(V8DebuggerId(externalParent.debugger_id).toString()) + .setDebuggerId( + internal::V8DebuggerId(externalParent.debugger_id).toString()) .build()); } return stackTrace; @@ -115,7 +116,8 @@ std::unique_ptr buildInspectorObjectCommon( } // namespace -V8StackTraceId::V8StackTraceId() : id(0), debugger_id(V8DebuggerId().pair()) {} +V8StackTraceId::V8StackTraceId() + : id(0), debugger_id(internal::V8DebuggerId().pair()) {} V8StackTraceId::V8StackTraceId(uintptr_t id, const std::pair debugger_id) @@ -127,7 +129,7 @@ V8StackTraceId::V8StackTraceId(uintptr_t id, : id(id), debugger_id(debugger_id), should_pause(should_pause) {} V8StackTraceId::V8StackTraceId(StringView json) - : id(0), debugger_id(V8DebuggerId().pair()) { + : id(0), debugger_id(internal::V8DebuggerId().pair()) { if (json.length() == 0) return; std::vector cbor; if (json.is8Bit()) { @@ -146,7 +148,7 @@ V8StackTraceId::V8StackTraceId(StringView json) int64_t parsedId = s.toInteger64(&isOk); if (!isOk || !parsedId) return; if (!dict->getString(kDebuggerId, &s)) return; - V8DebuggerId debuggerId(s); + internal::V8DebuggerId debuggerId(s); if (!debuggerId.isValid()) return; if (!dict->getBoolean(kShouldPause, &should_pause)) return; id = parsedId; @@ -159,7 +161,7 @@ std::unique_ptr V8StackTraceId::ToString() { if (IsInvalid()) return nullptr; auto dict = protocol::DictionaryValue::create(); dict->setString(kId, String16::fromInteger64(id)); - dict->setString(kDebuggerId, V8DebuggerId(debugger_id).toString()); + dict->setString(kDebuggerId, internal::V8DebuggerId(debugger_id).toString()); dict->setBoolean(kShouldPause, should_pause); std::vector json; v8_crdtp::json::ConvertCBORToJSON(v8_crdtp::SpanFrom(dict->Serialize()),