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 <bmeurer@chromium.org>
Commit-Queue: Alex Turner <alexmt@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78958}
This commit is contained in:
Alex Turner 2022-02-03 17:16:45 -05:00 committed by V8 LUCI CQ
parent 9e9d9142d6
commit e3ca1f1a73
12 changed files with 91 additions and 34 deletions

View File

@ -23,6 +23,10 @@ class Value;
namespace v8_inspector { namespace v8_inspector {
namespace internal {
class V8DebuggerId;
} // namespace internal
namespace protocol { namespace protocol {
namespace Debugger { namespace Debugger {
namespace API { namespace API {
@ -106,6 +110,30 @@ class V8_EXPORT V8ContextInfo {
V8ContextInfo& operator=(const V8ContextInfo&) = delete; 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<StringBuffer> toString() const;
bool isValid() const;
std::pair<int64_t, int64_t> pair() const;
private:
friend class internal::V8DebuggerId;
V8DebuggerId() = default;
explicit V8DebuggerId(std::pair<int64_t, int64_t>);
int64_t m_first = 0;
int64_t m_second = 0;
};
class V8_EXPORT V8StackTrace { class V8_EXPORT V8StackTrace {
public: public:
virtual StringView firstNonEmptySourceURL() const = 0; virtual StringView firstNonEmptySourceURL() const = 0;
@ -276,6 +304,7 @@ class V8_EXPORT V8Inspector {
virtual void contextDestroyed(v8::Local<v8::Context>) = 0; virtual void contextDestroyed(v8::Local<v8::Context>) = 0;
virtual void resetContextGroup(int contextGroupId) = 0; virtual void resetContextGroup(int contextGroupId) = 0;
virtual v8::MaybeLocal<v8::Context> contextById(int contextId) = 0; virtual v8::MaybeLocal<v8::Context> contextById(int contextId) = 0;
virtual V8DebuggerId uniqueDebuggerId(int contextId) = 0;
// Various instrumentation. // Various instrumentation.
virtual void idleStarted() = 0; virtual void idleStarted() = 0;

View File

@ -56,7 +56,7 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector,
m_origin(toString16(info.origin)), m_origin(toString16(info.origin)),
m_humanReadableName(toString16(info.humanReadableName)), m_humanReadableName(toString16(info.humanReadableName)),
m_auxData(toString16(info.auxData)), m_auxData(toString16(info.auxData)),
m_uniqueId(V8DebuggerId::generate(inspector)) { m_uniqueId(internal::V8DebuggerId::generate(inspector)) {
v8::debug::SetContextId(info.context, contextId); v8::debug::SetContextId(info.context, contextId);
m_weakCallbackData = m_weakCallbackData =
new WeakCallbackData(this, m_inspector, m_contextGroupId, m_contextId); new WeakCallbackData(this, m_inspector, m_contextGroupId, m_contextId);

View File

@ -43,7 +43,7 @@ class InspectedContext {
int contextGroupId() const { return m_contextGroupId; } int contextGroupId() const { return m_contextGroupId; }
String16 origin() const { return m_origin; } String16 origin() const { return m_origin; }
String16 humanReadableName() const { return m_humanReadableName; } 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; } String16 auxData() const { return m_auxData; }
bool isReported(int sessionId) const; bool isReported(int sessionId) const;
@ -73,7 +73,7 @@ class InspectedContext {
const String16 m_origin; const String16 m_origin;
const String16 m_humanReadableName; const String16 m_humanReadableName;
const String16 m_auxData; const String16 m_auxData;
const V8DebuggerId m_uniqueId; const internal::V8DebuggerId m_uniqueId;
std::unordered_set<int> m_reportedSessionIds; std::unordered_set<int> m_reportedSessionIds;
std::unordered_map<int, std::unique_ptr<InjectedScript>> m_injectedScripts; std::unordered_map<int, std::unique_ptr<InjectedScript>> m_injectedScripts;
WeakCallbackData* m_weakCallbackData; WeakCallbackData* m_weakCallbackData;

View File

@ -845,9 +845,10 @@ Response V8DebuggerAgentImpl::getStackTrace(
int64_t id = inStackTraceId->getId().toInteger64(&isOk); int64_t id = inStackTraceId->getId().toInteger64(&isOk);
if (!isOk) return Response::ServerError("Invalid stack trace id"); if (!isOk) return Response::ServerError("Invalid stack trace id");
V8DebuggerId debuggerId; internal::V8DebuggerId debuggerId;
if (inStackTraceId->hasDebuggerId()) { if (inStackTraceId->hasDebuggerId()) {
debuggerId = V8DebuggerId(inStackTraceId->getDebuggerId(String16())); debuggerId =
internal::V8DebuggerId(inStackTraceId->getDebuggerId(String16()));
} else { } else {
debuggerId = m_debugger->debuggerIdFor(m_session->contextGroupId()); debuggerId = m_debugger->debuggerIdFor(m_session->contextGroupId());
} }
@ -1521,7 +1522,8 @@ V8DebuggerAgentImpl::currentExternalStackTrace() {
if (externalParent.IsInvalid()) return nullptr; if (externalParent.IsInvalid()) return nullptr;
return protocol::Runtime::StackTraceId::create() return protocol::Runtime::StackTraceId::create()
.setId(stackTraceIdToString(externalParent.id)) .setId(stackTraceIdToString(externalParent.id))
.setDebuggerId(V8DebuggerId(externalParent.debugger_id).toString()) .setDebuggerId(
internal::V8DebuggerId(externalParent.debugger_id).toString())
.build(); .build();
} }

View File

@ -5,6 +5,7 @@
#include "src/inspector/v8-debugger-id.h" #include "src/inspector/v8-debugger-id.h"
#include "src/debug/debug-interface.h" #include "src/debug/debug-interface.h"
#include "src/inspector/string-util.h"
#include "src/inspector/v8-inspector-impl.h" #include "src/inspector/v8-inspector-impl.h"
namespace v8_inspector { namespace v8_inspector {
@ -12,6 +13,22 @@ namespace v8_inspector {
V8DebuggerId::V8DebuggerId(std::pair<int64_t, int64_t> pair) V8DebuggerId::V8DebuggerId(std::pair<int64_t, int64_t> pair)
: m_first(pair.first), m_second(pair.second) {} : m_first(pair.first), m_second(pair.second) {}
std::unique_ptr<StringBuffer> V8DebuggerId::toString() const {
return StringBufferFrom(String16::fromInteger64(m_first) + "." +
String16::fromInteger64(m_second));
}
bool V8DebuggerId::isValid() const { return m_first || m_second; }
std::pair<int64_t, int64_t> V8DebuggerId::pair() const {
return std::make_pair(m_first, m_second);
}
namespace internal {
V8DebuggerId::V8DebuggerId(std::pair<int64_t, int64_t> pair)
: m_debugger_id(pair) {}
// static // static
V8DebuggerId V8DebuggerId::generate(V8InspectorImpl* inspector) { V8DebuggerId V8DebuggerId::generate(V8InspectorImpl* inspector) {
return V8DebuggerId(std::make_pair(inspector->generateUniqueId(), return V8DebuggerId(std::make_pair(inspector->generateUniqueId(),
@ -27,19 +44,18 @@ V8DebuggerId::V8DebuggerId(const String16& debuggerId) {
if (!ok) return; if (!ok) return;
int64_t second = debuggerId.substring(pos + 1).toInteger64(&ok); int64_t second = debuggerId.substring(pos + 1).toInteger64(&ok);
if (!ok) return; if (!ok) return;
m_first = first; m_debugger_id = v8_inspector::V8DebuggerId(std::make_pair(first, second));
m_second = second;
} }
String16 V8DebuggerId::toString() const { String16 V8DebuggerId::toString() const {
return String16::fromInteger64(m_first) + "." + return toString16(m_debugger_id.toString()->string());
String16::fromInteger64(m_second);
} }
bool V8DebuggerId::isValid() const { return m_first || m_second; } bool V8DebuggerId::isValid() const { return m_debugger_id.isValid(); }
std::pair<int64_t, int64_t> V8DebuggerId::pair() const { std::pair<int64_t, int64_t> V8DebuggerId::pair() const {
return std::make_pair(m_first, m_second); return m_debugger_id.pair();
} }
} // namespace internal
} // namespace v8_inspector } // namespace v8_inspector

View File

@ -7,38 +7,35 @@
#include <utility> #include <utility>
#include "include/v8-inspector.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/inspector/protocol/Forward.h" #include "src/inspector/protocol/Forward.h"
namespace v8_inspector { namespace v8_inspector {
class V8InspectorImpl; class V8InspectorImpl;
// This debugger id tries to be unique by generating two random namespace internal {
// 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 V8DebuggerId { class V8DebuggerId {
public: public:
V8DebuggerId() = default; V8DebuggerId() = default;
explicit V8DebuggerId(std::pair<int64_t, int64_t>); explicit V8DebuggerId(std::pair<int64_t, int64_t>);
explicit V8DebuggerId(const String16&); explicit V8DebuggerId(const String16&);
V8DebuggerId(const V8DebuggerId&) V8_NOEXCEPT = default; V8DebuggerId(const V8DebuggerId&) V8_NOEXCEPT = default;
~V8DebuggerId() = default; V8DebuggerId& operator=(const V8DebuggerId&) V8_NOEXCEPT = default;
static V8DebuggerId generate(V8InspectorImpl*); static V8DebuggerId generate(V8InspectorImpl*);
v8_inspector::V8DebuggerId toV8DebuggerId() const { return m_debugger_id; }
String16 toString() const; String16 toString() const;
bool isValid() const; bool isValid() const;
std::pair<int64_t, int64_t> pair() const; std::pair<int64_t, int64_t> pair() const;
private: private:
int64_t m_first = 0; v8_inspector::V8DebuggerId m_debugger_id;
int64_t m_second = 0;
}; };
} // namespace internal
} // namespace v8_inspector } // namespace v8_inspector
#endif // V8_INSPECTOR_V8_DEBUGGER_ID_H_ #endif // V8_INSPECTOR_V8_DEBUGGER_ID_H_

View File

@ -1159,10 +1159,11 @@ void V8Debugger::setMaxAsyncTaskStacksForTest(int limit) {
m_maxAsyncCallStacks = limit; m_maxAsyncCallStacks = limit;
} }
V8DebuggerId V8Debugger::debuggerIdFor(int contextGroupId) { internal::V8DebuggerId V8Debugger::debuggerIdFor(int contextGroupId) {
auto it = m_contextGroupIdToDebuggerId.find(contextGroupId); auto it = m_contextGroupIdToDebuggerId.find(contextGroupId);
if (it != m_contextGroupIdToDebuggerId.end()) return it->second; 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( m_contextGroupIdToDebuggerId.insert(
it, std::make_pair(contextGroupId, debuggerId)); it, std::make_pair(contextGroupId, debuggerId));
return debuggerId; return debuggerId;

View File

@ -124,7 +124,7 @@ class V8Debugger : public v8::debug::DebugDelegate,
void setMaxAsyncTaskStacksForTest(int limit); void setMaxAsyncTaskStacksForTest(int limit);
void dumpAsyncTaskStacksStateForTest(); void dumpAsyncTaskStacksStateForTest();
V8DebuggerId debuggerIdFor(int contextGroupId); internal::V8DebuggerId debuggerIdFor(int contextGroupId);
std::shared_ptr<AsyncStackTrace> stackTraceFor(int contextGroupId, std::shared_ptr<AsyncStackTrace> stackTraceFor(int contextGroupId,
const V8StackTraceId& id); const V8StackTraceId& id);
@ -283,7 +283,7 @@ class V8Debugger : public v8::debug::DebugDelegate,
StackTraceIdToStackTrace m_storedStackTraces; StackTraceIdToStackTrace m_storedStackTraces;
uintptr_t m_lastStackTraceId = 0; uintptr_t m_lastStackTraceId = 0;
std::unordered_map<int, V8DebuggerId> m_contextGroupIdToDebuggerId; std::unordered_map<int, internal::V8DebuggerId> m_contextGroupIdToDebuggerId;
std::unique_ptr<TerminateExecutionCallback> m_terminateExecutionCallback; std::unique_ptr<TerminateExecutionCallback> m_terminateExecutionCallback;
}; };

View File

@ -44,6 +44,7 @@
#include "src/inspector/v8-console-message.h" #include "src/inspector/v8-console-message.h"
#include "src/inspector/v8-console.h" #include "src/inspector/v8-console.h"
#include "src/inspector/v8-debugger-agent-impl.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-debugger.h"
#include "src/inspector/v8-inspector-session-impl.h" #include "src/inspector/v8-inspector-session-impl.h"
#include "src/inspector/v8-profiler-agent-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; 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()); auto it = m_uniqueIdToContextId.find(uniqueId.pair());
return it == m_uniqueIdToContextId.end() ? 0 : it->second; return it == m_uniqueIdToContextId.end() ? 0 : it->second;
} }
@ -180,6 +182,13 @@ v8::MaybeLocal<v8::Context> V8InspectorImpl::contextById(int contextId) {
return context ? context->context() : v8::MaybeLocal<v8::Context>(); return context ? context->context() : v8::MaybeLocal<v8::Context>();
} }
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) { void V8InspectorImpl::contextCreated(const V8ContextInfo& info) {
int contextId = ++m_lastContextId; int contextId = ++m_lastContextId;
auto* context = new InspectedContext(this, info, contextId); auto* context = new InspectedContext(this, info, contextId);

View File

@ -67,7 +67,7 @@ class V8InspectorImpl : public V8Inspector {
int contextGroupId(v8::Local<v8::Context>) const; int contextGroupId(v8::Local<v8::Context>) const;
int contextGroupId(int contextId) const; int contextGroupId(int contextId) const;
uint64_t isolateId() const { return m_isolateId; } uint64_t isolateId() const { return m_isolateId; }
int resolveUniqueContextId(V8DebuggerId uniqueId) const; int resolveUniqueContextId(internal::V8DebuggerId uniqueId) const;
v8::MaybeLocal<v8::Value> compileAndRunInternalScript(v8::Local<v8::Context>, v8::MaybeLocal<v8::Value> compileAndRunInternalScript(v8::Local<v8::Context>,
v8::Local<v8::String>); v8::Local<v8::String>);
@ -84,6 +84,7 @@ class V8InspectorImpl : public V8Inspector {
void contextCreated(const V8ContextInfo&) override; void contextCreated(const V8ContextInfo&) override;
void contextDestroyed(v8::Local<v8::Context>) override; void contextDestroyed(v8::Local<v8::Context>) override;
v8::MaybeLocal<v8::Context> contextById(int contextId) override; v8::MaybeLocal<v8::Context> contextById(int contextId) override;
V8DebuggerId uniqueDebuggerId(int contextId) override;
void contextCollected(int contextGroupId, int contextId); void contextCollected(int contextGroupId, int contextId);
void resetContextGroup(int contextGroupId) override; void resetContextGroup(int contextGroupId) override;
void idleStarted() override; void idleStarted() override;

View File

@ -217,7 +217,7 @@ Response ensureContext(V8InspectorImpl* inspector, int contextGroupId,
} }
*contextId = executionContextId.fromJust(); *contextId = executionContextId.fromJust();
} else if (uniqueContextId.isJust()) { } else if (uniqueContextId.isJust()) {
V8DebuggerId uniqueId(uniqueContextId.fromJust()); internal::V8DebuggerId uniqueId(uniqueContextId.fromJust());
if (!uniqueId.isValid()) if (!uniqueId.isValid())
return Response::InvalidParams("invalid uniqueContextId"); return Response::InvalidParams("invalid uniqueContextId");
int id = inspector->resolveUniqueContextId(uniqueId); int id = inspector->resolveUniqueContextId(uniqueId);

View File

@ -107,7 +107,8 @@ std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectCommon(
stackTrace->setParentId( stackTrace->setParentId(
protocol::Runtime::StackTraceId::create() protocol::Runtime::StackTraceId::create()
.setId(stackTraceIdToString(externalParent.id)) .setId(stackTraceIdToString(externalParent.id))
.setDebuggerId(V8DebuggerId(externalParent.debugger_id).toString()) .setDebuggerId(
internal::V8DebuggerId(externalParent.debugger_id).toString())
.build()); .build());
} }
return stackTrace; return stackTrace;
@ -115,7 +116,8 @@ std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectCommon(
} // namespace } // namespace
V8StackTraceId::V8StackTraceId() : id(0), debugger_id(V8DebuggerId().pair()) {} V8StackTraceId::V8StackTraceId()
: id(0), debugger_id(internal::V8DebuggerId().pair()) {}
V8StackTraceId::V8StackTraceId(uintptr_t id, V8StackTraceId::V8StackTraceId(uintptr_t id,
const std::pair<int64_t, int64_t> debugger_id) const std::pair<int64_t, int64_t> debugger_id)
@ -127,7 +129,7 @@ V8StackTraceId::V8StackTraceId(uintptr_t id,
: id(id), debugger_id(debugger_id), should_pause(should_pause) {} : id(id), debugger_id(debugger_id), should_pause(should_pause) {}
V8StackTraceId::V8StackTraceId(StringView json) V8StackTraceId::V8StackTraceId(StringView json)
: id(0), debugger_id(V8DebuggerId().pair()) { : id(0), debugger_id(internal::V8DebuggerId().pair()) {
if (json.length() == 0) return; if (json.length() == 0) return;
std::vector<uint8_t> cbor; std::vector<uint8_t> cbor;
if (json.is8Bit()) { if (json.is8Bit()) {
@ -146,7 +148,7 @@ V8StackTraceId::V8StackTraceId(StringView json)
int64_t parsedId = s.toInteger64(&isOk); int64_t parsedId = s.toInteger64(&isOk);
if (!isOk || !parsedId) return; if (!isOk || !parsedId) return;
if (!dict->getString(kDebuggerId, &s)) return; if (!dict->getString(kDebuggerId, &s)) return;
V8DebuggerId debuggerId(s); internal::V8DebuggerId debuggerId(s);
if (!debuggerId.isValid()) return; if (!debuggerId.isValid()) return;
if (!dict->getBoolean(kShouldPause, &should_pause)) return; if (!dict->getBoolean(kShouldPause, &should_pause)) return;
id = parsedId; id = parsedId;
@ -159,7 +161,7 @@ std::unique_ptr<StringBuffer> V8StackTraceId::ToString() {
if (IsInvalid()) return nullptr; if (IsInvalid()) return nullptr;
auto dict = protocol::DictionaryValue::create(); auto dict = protocol::DictionaryValue::create();
dict->setString(kId, String16::fromInteger64(id)); 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); dict->setBoolean(kShouldPause, should_pause);
std::vector<uint8_t> json; std::vector<uint8_t> json;
v8_crdtp::json::ConvertCBORToJSON(v8_crdtp::SpanFrom(dict->Serialize()), v8_crdtp::json::ConvertCBORToJSON(v8_crdtp::SpanFrom(dict->Serialize()),