6#if defined(V8_OS_STARBOARD)
7#include "starboard/system.h"
8#define __builtin_abort SbSystemBreakIntoDebugger
17#include "../../third_party/inspector_protocol/crdtp/json.h"
23using v8_crdtp::json::ConvertJSONToCBOR;
28static const char kId[] =
"id";
29static const char kDebuggerId[] =
"debuggerId";
30static const char kShouldPause[] =
"shouldPause";
37std::vector<std::shared_ptr<StackFrame>> toFramesVector(
40 DCHECK(debugger->isolate()->InContext());
41 int frameCount = std::min(v8StackTrace->GetFrameCount(), maxStackSize);
46 "toFramesVector",
"frameCount", frameCount);
48 std::vector<std::shared_ptr<StackFrame>> frames(frameCount);
49 for (
int i = 0;
i < frameCount; ++
i) {
51 debugger->symbolize(v8StackTrace->GetFrame(debugger->isolate(),
i));
56std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectCommon(
58 const std::vector<std::shared_ptr<StackFrame>>& frames,
59 const String16& description,
60 const std::shared_ptr<AsyncStackTrace>& asyncParent,
61 const V8StackTraceId& externalParent,
int maxAsyncDepth) {
62 if (asyncParent && frames.empty() &&
63 description == asyncParent->description()) {
64 return asyncParent->buildInspectorObject(debugger, maxAsyncDepth);
67 auto inspectorFrames =
68 std::make_unique<protocol::Array<protocol::Runtime::CallFrame>>();
69 for (
const std::shared_ptr<StackFrame>& frame : frames) {
70 V8InspectorClient* client =
nullptr;
71 if (debugger && debugger->inspector())
72 client = debugger->inspector()->client();
73 inspectorFrames->emplace_back(frame->buildInspectorObject(client));
75 std::unique_ptr<protocol::Runtime::StackTrace> stackTrace =
76 protocol::Runtime::StackTrace::create()
77 .setCallFrames(std::move(inspectorFrames))
79 if (!description.isEmpty()) stackTrace->setDescription(description);
81 if (maxAsyncDepth > 0) {
82 stackTrace->setParent(
83 asyncParent->buildInspectorObject(debugger, maxAsyncDepth - 1));
84 }
else if (debugger) {
85 stackTrace->setParentId(
86 protocol::Runtime::StackTraceId::create()
92 if (!externalParent.IsInvalid()) {
93 stackTrace->setParentId(
94 protocol::Runtime::StackTraceId::create()
97 internal::V8DebuggerId(externalParent.debugger_id).toString())
106 : id(0), debugger_id(internal::
V8DebuggerId().pair()) {}
109 const std::pair<int64_t, int64_t> debugger_id)
110 : id(id), debugger_id(debugger_id) {}
113 const std::pair<int64_t, int64_t> debugger_id,
115 : id(id), debugger_id(debugger_id), should_pause(should_pause) {}
119 if (json.
length() == 0)
return;
120 std::vector<uint8_t> cbor;
123 v8_crdtp::span<uint8_t>(json.characters8(), json.length()), &cbor);
126 v8_crdtp::span<uint16_t>(json.characters16(), json.length()), &cbor);
128 auto dict = protocol::DictionaryValue::cast(
129 protocol::Value::parseBinary(cbor.data(), cbor.size()));
132 if (!dict->getString(
kId, &s))
return;
135 if (!isOk || !parsedId)
return;
136 if (!dict->getString(kDebuggerId, &s))
return;
138 if (!debuggerId.isValid())
return;
139 if (!dict->getBoolean(kShouldPause, &
should_pause))
return;
148 auto dict = protocol::DictionaryValue::create();
152 std::vector<uint8_t> json;
153 v8_crdtp::json::ConvertCBORToJSON(v8_crdtp::SpanFrom(dict->Serialize()),
159 String16&& sourceURL,
int lineNumber,
int columnNumber,
160 bool hasSourceURLComment)
161 : m_functionName(
std::move(functionName)),
163 m_sourceURL(
std::move(sourceURL)),
166 m_hasSourceURLComment(hasSourceURLComment) {
184 const char* dataURIPrefix =
"data:";
190 std::unique_ptr<StringBuffer> url =
196 return protocol::Runtime::CallFrame::create()
220 std::vector<std::shared_ptr<StackFrame>>
frames;
221 if (!v8StackTrace.
IsEmpty() && v8StackTrace->GetFrameCount()) {
222 frames = toFramesVector(debugger, v8StackTrace, maxStackSize);
226 std::shared_ptr<AsyncStackTrace> asyncParent;
232 if (frames.empty() && !asyncParent && externalParent.
IsInvalid())
return {};
234 std::move(frames), maxAsyncDepth, asyncParent, externalParent));
245 "V8StackTraceImpl::capture",
"maxFrameCount", maxStackSize);
250 if (isolate->InContext()) {
258 std::vector<std::shared_ptr<StackFrame>> frames,
int maxAsyncDepth,
259 std::shared_ptr<AsyncStackTrace> asyncParent,
261 : m_frames(
std::move(frames)),
262 m_maxAsyncDepth(maxAsyncDepth),
263 m_asyncParent(
std::move(asyncParent)),
264 m_externalParent(externalParent) {}
275 while (!current.done()) {
276 if (current.frame()->sourceURL().length()) {
291 return m_frames[0]->lineNumber() + 1;
295 return m_frames[0]->columnNumber() + 1;
305 std::vector<V8StackFrame> ret;
308 for (
const auto& frame :
m_frames) {
312 frame->lineNumber() + 1, frame->columnNumber() + 1,
320std::unique_ptr<protocol::Runtime::StackTrace>
325std::unique_ptr<protocol::Runtime::StackTrace>
327 int maxAsyncDepth)
const {
333std::unique_ptr<protocol::Runtime::API::StackTrace>
345 :
"(anonymous function)"));
364 while (!current.done() && !target.done()) {
365 if (!current.frame()->isEqual(target.frame())) {
371 return current.done() == target.done();
376 : m_currentIt(stackTrace->m_frames.begin()),
377 m_currentEnd(stackTrace->m_frames.
end()),
378 m_parent(stackTrace->m_asyncParent.lock().get()) {}
381 if (m_currentIt == m_currentEnd)
return;
383 while (m_currentIt == m_currentEnd && m_parent) {
384 const std::vector<std::shared_ptr<StackFrame>>& frames = m_parent->frames();
385 m_currentIt = frames.begin();
386 m_currentEnd = frames.end();
387 m_parent = m_parent->parent().lock().get();
392 return m_currentIt == m_currentEnd;
396 return m_currentIt->get();
408 "AsyncStackTrace::capture",
"maxFrameCount", maxStackSize);
413 std::vector<std::shared_ptr<StackFrame>>
frames;
414 std::shared_ptr<AsyncStackTrace> asyncParent;
416 if (isolate->InContext()) {
418 isolate, maxStackSize, stackTraceOptions);
419 frames = toFramesVector(debugger, v8StackTrace, maxStackSize);
420 if (skipTopFrame && !frames.empty()) {
421 frames.erase(frames.begin());
428 if (frames.empty() && !asyncParent && externalParent.
IsInvalid())
431 if (asyncParent && frames.empty() &&
432 (asyncParent->m_description == description || description.
isEmpty())) {
437 description, std::move(frames), asyncParent, externalParent));
442 std::vector<std::shared_ptr<StackFrame>> frames,
443 std::shared_ptr<AsyncStackTrace> asyncParent,
451std::unique_ptr<protocol::Runtime::StackTrace>
453 int maxAsyncDepth)
const {
460 std::shared_ptr<AsyncStackTrace> stack) {
461 if (stack->m_id)
return stack->m_id;
static const int kNoLineNumberInfo
static const int kNoColumnInfo
static Local< StackTrace > CurrentStackTrace(Isolate *isolate, int frame_limit, StackTraceOptions options=kDetailed)
@ kExposeFramesAcrossSecurityOrigins
V8_INLINE bool IsEmpty() const
std::weak_ptr< AsyncStackTrace > parent() const
static std::shared_ptr< AsyncStackTrace > capture(V8Debugger *, const String16 &description, bool skipTopFrame=false)
const String16 & description() const
std::vector< std::shared_ptr< StackFrame > > m_frames
static uintptr_t store(V8Debugger *debugger, std::shared_ptr< AsyncStackTrace > stack)
std::unique_ptr< protocol::Runtime::StackTrace > buildInspectorObject(V8Debugger *debugger, int maxAsyncDepth) const
AsyncStackTrace(const AsyncStackTrace &)=delete
V8StackTraceId m_externalParent
std::weak_ptr< AsyncStackTrace > m_asyncParent
StackFrame(String16 &&functionName, int scriptId, String16 &&sourceURL, int lineNumber, int columnNumber, bool hasSourceURLComment)
bool isEqual(StackFrame *frame) const
std::unique_ptr< protocol::Runtime::CallFrame > buildInspectorObject(V8InspectorClient *client) const
const String16 & functionName() const
bool m_hasSourceURLComment
const String16 & sourceURL() const
void append(const String16 &)
String16 substring(size_t pos, size_t len=UINT_MAX) const
static String16 fromInteger(int)
static String16 fromInteger64(int64_t)
int64_t toInteger64(bool *ok=nullptr) const
int maxAsyncCallChainDepth()
int maxCallStackSizeToCapture() const
uintptr_t storeStackTrace(std::shared_ptr< AsyncStackTrace > stack)
v8::Isolate * isolate() const
void asyncParentFor(int stackTraceId, std::shared_ptr< AsyncStackTrace > *asyncParent, V8StackTraceId *externalParent) const
virtual std::unique_ptr< StringBuffer > resourceNameToUrl(const StringView &resourceName)
StackFrameIterator(const V8StackTraceImpl *stackTrace)
int topScriptId() const override
static std::unique_ptr< V8StackTraceImpl > capture(V8Debugger *, int maxStackSize)
StringView firstNonEmptySourceURL() const override
std::unique_ptr< protocol::Runtime::StackTrace > buildInspectorObjectImpl(V8Debugger *debugger) const
std::unique_ptr< StringBuffer > toString() const override
static std::unique_ptr< V8StackTraceImpl > create(V8Debugger *, v8::Local< v8::StackTrace >, int maxStackSize)
bool isEmpty() const override
V8StackTraceId m_externalParent
StringView topSourceURL() const override
V8StackTraceImpl(const V8StackTraceImpl &)=delete
std::unique_ptr< protocol::Runtime::API::StackTrace > buildInspectorObject(int maxAsyncDepth) const override
bool isEqualIgnoringTopFrame(V8StackTraceImpl *stackTrace) const
int topColumnNumber() const override
~V8StackTraceImpl() override
std::unique_ptr< V8StackTrace > clone() override
std::vector< V8StackFrame > frames() const override
StringView topFunctionName() const override
int topLineNumber() const override
std::weak_ptr< AsyncStackTrace > m_asyncParent
std::vector< std::shared_ptr< StackFrame > > m_frames
static constexpr DebugProxyId kId
String16 stackTraceIdToString(uintptr_t id)
StringView toStringView(const String16 &string)
std::unique_ptr< StringBuffer > StringBufferFrom(String16 str)
String16 toString16(const StringView &string)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
std::unique_ptr< StringBuffer > ToString()
std::pair< int64_t, int64_t > debugger_id
#define TRACE_DISABLED_BY_DEFAULT(name)
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)