11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#if defined(V8_OS_STARBOARD)
61cb0ef41Sopenharmony_ci#include "starboard/system.h"
71cb0ef41Sopenharmony_ci#define __builtin_abort SbSystemBreakIntoDebugger
81cb0ef41Sopenharmony_ci#endif
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/inspector/v8-stack-trace-impl.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include <algorithm>
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci#include "../../third_party/inspector_protocol/crdtp/json.h"
151cb0ef41Sopenharmony_ci#include "src/debug/debug-interface.h"
161cb0ef41Sopenharmony_ci#include "src/inspector/v8-debugger.h"
171cb0ef41Sopenharmony_ci#include "src/inspector/v8-inspector-impl.h"
181cb0ef41Sopenharmony_ci#include "src/tracing/trace-event.h"
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciusing v8_crdtp::SpanFrom;
211cb0ef41Sopenharmony_ciusing v8_crdtp::json::ConvertCBORToJSON;
221cb0ef41Sopenharmony_ciusing v8_crdtp::json::ConvertJSONToCBOR;
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cinamespace v8_inspector {
251cb0ef41Sopenharmony_cinamespace {
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cistatic const char kId[] = "id";
281cb0ef41Sopenharmony_cistatic const char kDebuggerId[] = "debuggerId";
291cb0ef41Sopenharmony_cistatic const char kShouldPause[] = "shouldPause";
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cistatic const v8::StackTrace::StackTraceOptions stackTraceOptions =
321cb0ef41Sopenharmony_ci    static_cast<v8::StackTrace::StackTraceOptions>(
331cb0ef41Sopenharmony_ci        v8::StackTrace::kDetailed |
341cb0ef41Sopenharmony_ci        v8::StackTrace::kExposeFramesAcrossSecurityOrigins);
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_cistd::vector<std::shared_ptr<StackFrame>> toFramesVector(
371cb0ef41Sopenharmony_ci    V8Debugger* debugger, v8::Local<v8::StackTrace> v8StackTrace,
381cb0ef41Sopenharmony_ci    int maxStackSize) {
391cb0ef41Sopenharmony_ci  DCHECK(debugger->isolate()->InContext());
401cb0ef41Sopenharmony_ci  int frameCount = std::min(v8StackTrace->GetFrameCount(), maxStackSize);
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  TRACE_EVENT1(
431cb0ef41Sopenharmony_ci      TRACE_DISABLED_BY_DEFAULT("v8.inspector") "," TRACE_DISABLED_BY_DEFAULT(
441cb0ef41Sopenharmony_ci          "v8.stack_trace"),
451cb0ef41Sopenharmony_ci      "toFramesVector", "frameCount", frameCount);
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  std::vector<std::shared_ptr<StackFrame>> frames(frameCount);
481cb0ef41Sopenharmony_ci  for (int i = 0; i < frameCount; ++i) {
491cb0ef41Sopenharmony_ci    frames[i] =
501cb0ef41Sopenharmony_ci        debugger->symbolize(v8StackTrace->GetFrame(debugger->isolate(), i));
511cb0ef41Sopenharmony_ci  }
521cb0ef41Sopenharmony_ci  return frames;
531cb0ef41Sopenharmony_ci}
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_civoid calculateAsyncChain(V8Debugger* debugger,
561cb0ef41Sopenharmony_ci                         std::shared_ptr<AsyncStackTrace>* asyncParent,
571cb0ef41Sopenharmony_ci                         V8StackTraceId* externalParent, int* maxAsyncDepth) {
581cb0ef41Sopenharmony_ci  *asyncParent = debugger->currentAsyncParent();
591cb0ef41Sopenharmony_ci  *externalParent = debugger->currentExternalParent();
601cb0ef41Sopenharmony_ci  DCHECK(externalParent->IsInvalid() || !*asyncParent);
611cb0ef41Sopenharmony_ci  if (maxAsyncDepth) *maxAsyncDepth = debugger->maxAsyncCallChainDepth();
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  // Only the top stack in the chain may be empty, so ensure that second stack
641cb0ef41Sopenharmony_ci  // is non-empty (it's the top of appended chain).
651cb0ef41Sopenharmony_ci  if (*asyncParent && (*asyncParent)->isEmpty()) {
661cb0ef41Sopenharmony_ci    *asyncParent = (*asyncParent)->parent().lock();
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectCommon(
711cb0ef41Sopenharmony_ci    V8Debugger* debugger,
721cb0ef41Sopenharmony_ci    const std::vector<std::shared_ptr<StackFrame>>& frames,
731cb0ef41Sopenharmony_ci    const String16& description,
741cb0ef41Sopenharmony_ci    const std::shared_ptr<AsyncStackTrace>& asyncParent,
751cb0ef41Sopenharmony_ci    const V8StackTraceId& externalParent, int maxAsyncDepth) {
761cb0ef41Sopenharmony_ci  if (asyncParent && frames.empty() &&
771cb0ef41Sopenharmony_ci      description == asyncParent->description()) {
781cb0ef41Sopenharmony_ci    return asyncParent->buildInspectorObject(debugger, maxAsyncDepth);
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  auto inspectorFrames =
821cb0ef41Sopenharmony_ci      std::make_unique<protocol::Array<protocol::Runtime::CallFrame>>();
831cb0ef41Sopenharmony_ci  for (const std::shared_ptr<StackFrame>& frame : frames) {
841cb0ef41Sopenharmony_ci    V8InspectorClient* client = nullptr;
851cb0ef41Sopenharmony_ci    if (debugger && debugger->inspector())
861cb0ef41Sopenharmony_ci      client = debugger->inspector()->client();
871cb0ef41Sopenharmony_ci    inspectorFrames->emplace_back(frame->buildInspectorObject(client));
881cb0ef41Sopenharmony_ci  }
891cb0ef41Sopenharmony_ci  std::unique_ptr<protocol::Runtime::StackTrace> stackTrace =
901cb0ef41Sopenharmony_ci      protocol::Runtime::StackTrace::create()
911cb0ef41Sopenharmony_ci          .setCallFrames(std::move(inspectorFrames))
921cb0ef41Sopenharmony_ci          .build();
931cb0ef41Sopenharmony_ci  if (!description.isEmpty()) stackTrace->setDescription(description);
941cb0ef41Sopenharmony_ci  if (asyncParent) {
951cb0ef41Sopenharmony_ci    if (maxAsyncDepth > 0) {
961cb0ef41Sopenharmony_ci      stackTrace->setParent(
971cb0ef41Sopenharmony_ci          asyncParent->buildInspectorObject(debugger, maxAsyncDepth - 1));
981cb0ef41Sopenharmony_ci    } else if (debugger) {
991cb0ef41Sopenharmony_ci      stackTrace->setParentId(
1001cb0ef41Sopenharmony_ci          protocol::Runtime::StackTraceId::create()
1011cb0ef41Sopenharmony_ci              .setId(stackTraceIdToString(
1021cb0ef41Sopenharmony_ci                  AsyncStackTrace::store(debugger, asyncParent)))
1031cb0ef41Sopenharmony_ci              .build());
1041cb0ef41Sopenharmony_ci    }
1051cb0ef41Sopenharmony_ci  }
1061cb0ef41Sopenharmony_ci  if (!externalParent.IsInvalid()) {
1071cb0ef41Sopenharmony_ci    stackTrace->setParentId(
1081cb0ef41Sopenharmony_ci        protocol::Runtime::StackTraceId::create()
1091cb0ef41Sopenharmony_ci            .setId(stackTraceIdToString(externalParent.id))
1101cb0ef41Sopenharmony_ci            .setDebuggerId(
1111cb0ef41Sopenharmony_ci                internal::V8DebuggerId(externalParent.debugger_id).toString())
1121cb0ef41Sopenharmony_ci            .build());
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci  return stackTrace;
1151cb0ef41Sopenharmony_ci}
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci}  // namespace
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ciV8StackTraceId::V8StackTraceId()
1201cb0ef41Sopenharmony_ci    : id(0), debugger_id(internal::V8DebuggerId().pair()) {}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ciV8StackTraceId::V8StackTraceId(uintptr_t id,
1231cb0ef41Sopenharmony_ci                               const std::pair<int64_t, int64_t> debugger_id)
1241cb0ef41Sopenharmony_ci    : id(id), debugger_id(debugger_id) {}
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ciV8StackTraceId::V8StackTraceId(uintptr_t id,
1271cb0ef41Sopenharmony_ci                               const std::pair<int64_t, int64_t> debugger_id,
1281cb0ef41Sopenharmony_ci                               bool should_pause)
1291cb0ef41Sopenharmony_ci    : id(id), debugger_id(debugger_id), should_pause(should_pause) {}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ciV8StackTraceId::V8StackTraceId(StringView json)
1321cb0ef41Sopenharmony_ci    : id(0), debugger_id(internal::V8DebuggerId().pair()) {
1331cb0ef41Sopenharmony_ci  if (json.length() == 0) return;
1341cb0ef41Sopenharmony_ci  std::vector<uint8_t> cbor;
1351cb0ef41Sopenharmony_ci  if (json.is8Bit()) {
1361cb0ef41Sopenharmony_ci    ConvertJSONToCBOR(
1371cb0ef41Sopenharmony_ci        v8_crdtp::span<uint8_t>(json.characters8(), json.length()), &cbor);
1381cb0ef41Sopenharmony_ci  } else {
1391cb0ef41Sopenharmony_ci    ConvertJSONToCBOR(
1401cb0ef41Sopenharmony_ci        v8_crdtp::span<uint16_t>(json.characters16(), json.length()), &cbor);
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci  auto dict = protocol::DictionaryValue::cast(
1431cb0ef41Sopenharmony_ci      protocol::Value::parseBinary(cbor.data(), cbor.size()));
1441cb0ef41Sopenharmony_ci  if (!dict) return;
1451cb0ef41Sopenharmony_ci  String16 s;
1461cb0ef41Sopenharmony_ci  if (!dict->getString(kId, &s)) return;
1471cb0ef41Sopenharmony_ci  bool isOk = false;
1481cb0ef41Sopenharmony_ci  int64_t parsedId = s.toInteger64(&isOk);
1491cb0ef41Sopenharmony_ci  if (!isOk || !parsedId) return;
1501cb0ef41Sopenharmony_ci  if (!dict->getString(kDebuggerId, &s)) return;
1511cb0ef41Sopenharmony_ci  internal::V8DebuggerId debuggerId(s);
1521cb0ef41Sopenharmony_ci  if (!debuggerId.isValid()) return;
1531cb0ef41Sopenharmony_ci  if (!dict->getBoolean(kShouldPause, &should_pause)) return;
1541cb0ef41Sopenharmony_ci  id = parsedId;
1551cb0ef41Sopenharmony_ci  debugger_id = debuggerId.pair();
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_cibool V8StackTraceId::IsInvalid() const { return !id; }
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> V8StackTraceId::ToString() {
1611cb0ef41Sopenharmony_ci  if (IsInvalid()) return nullptr;
1621cb0ef41Sopenharmony_ci  auto dict = protocol::DictionaryValue::create();
1631cb0ef41Sopenharmony_ci  dict->setString(kId, String16::fromInteger64(id));
1641cb0ef41Sopenharmony_ci  dict->setString(kDebuggerId, internal::V8DebuggerId(debugger_id).toString());
1651cb0ef41Sopenharmony_ci  dict->setBoolean(kShouldPause, should_pause);
1661cb0ef41Sopenharmony_ci  std::vector<uint8_t> json;
1671cb0ef41Sopenharmony_ci  v8_crdtp::json::ConvertCBORToJSON(v8_crdtp::SpanFrom(dict->Serialize()),
1681cb0ef41Sopenharmony_ci                                    &json);
1691cb0ef41Sopenharmony_ci  return StringBufferFrom(std::move(json));
1701cb0ef41Sopenharmony_ci}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ciStackFrame::StackFrame(String16&& functionName, int scriptId,
1731cb0ef41Sopenharmony_ci                       String16&& sourceURL, int lineNumber, int columnNumber,
1741cb0ef41Sopenharmony_ci                       bool hasSourceURLComment)
1751cb0ef41Sopenharmony_ci    : m_functionName(std::move(functionName)),
1761cb0ef41Sopenharmony_ci      m_scriptId(scriptId),
1771cb0ef41Sopenharmony_ci      m_sourceURL(std::move(sourceURL)),
1781cb0ef41Sopenharmony_ci      m_lineNumber(lineNumber),
1791cb0ef41Sopenharmony_ci      m_columnNumber(columnNumber),
1801cb0ef41Sopenharmony_ci      m_hasSourceURLComment(hasSourceURLComment) {
1811cb0ef41Sopenharmony_ci  DCHECK_NE(v8::Message::kNoLineNumberInfo, m_lineNumber + 1);
1821cb0ef41Sopenharmony_ci  DCHECK_NE(v8::Message::kNoColumnInfo, m_columnNumber + 1);
1831cb0ef41Sopenharmony_ci}
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ciconst String16& StackFrame::functionName() const { return m_functionName; }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ciint StackFrame::scriptId() const { return m_scriptId; }
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ciconst String16& StackFrame::sourceURL() const { return m_sourceURL; }
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ciint StackFrame::lineNumber() const { return m_lineNumber; }
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ciint StackFrame::columnNumber() const { return m_columnNumber; }
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Runtime::CallFrame> StackFrame::buildInspectorObject(
1961cb0ef41Sopenharmony_ci    V8InspectorClient* client) const {
1971cb0ef41Sopenharmony_ci  String16 frameUrl;
1981cb0ef41Sopenharmony_ci  const char* dataURIPrefix = "data:";
1991cb0ef41Sopenharmony_ci  if (m_sourceURL.substring(0, strlen(dataURIPrefix)) != dataURIPrefix) {
2001cb0ef41Sopenharmony_ci    frameUrl = m_sourceURL;
2011cb0ef41Sopenharmony_ci  }
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  if (client && !m_hasSourceURLComment && frameUrl.length() > 0) {
2041cb0ef41Sopenharmony_ci    std::unique_ptr<StringBuffer> url =
2051cb0ef41Sopenharmony_ci        client->resourceNameToUrl(toStringView(m_sourceURL));
2061cb0ef41Sopenharmony_ci    if (url) {
2071cb0ef41Sopenharmony_ci      frameUrl = toString16(url->string());
2081cb0ef41Sopenharmony_ci    }
2091cb0ef41Sopenharmony_ci  }
2101cb0ef41Sopenharmony_ci  return protocol::Runtime::CallFrame::create()
2111cb0ef41Sopenharmony_ci      .setFunctionName(m_functionName)
2121cb0ef41Sopenharmony_ci      .setScriptId(String16::fromInteger(m_scriptId))
2131cb0ef41Sopenharmony_ci      .setUrl(frameUrl)
2141cb0ef41Sopenharmony_ci      .setLineNumber(m_lineNumber)
2151cb0ef41Sopenharmony_ci      .setColumnNumber(m_columnNumber)
2161cb0ef41Sopenharmony_ci      .build();
2171cb0ef41Sopenharmony_ci}
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_cibool StackFrame::isEqual(StackFrame* frame) const {
2201cb0ef41Sopenharmony_ci  return m_scriptId == frame->m_scriptId &&
2211cb0ef41Sopenharmony_ci         m_lineNumber == frame->m_lineNumber &&
2221cb0ef41Sopenharmony_ci         m_columnNumber == frame->m_columnNumber;
2231cb0ef41Sopenharmony_ci}
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci// static
2261cb0ef41Sopenharmony_cistd::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::create(
2271cb0ef41Sopenharmony_ci    V8Debugger* debugger, v8::Local<v8::StackTrace> v8StackTrace,
2281cb0ef41Sopenharmony_ci    int maxStackSize) {
2291cb0ef41Sopenharmony_ci  DCHECK(debugger);
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  v8::Isolate* isolate = debugger->isolate();
2321cb0ef41Sopenharmony_ci  v8::HandleScope scope(isolate);
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  std::vector<std::shared_ptr<StackFrame>> frames;
2351cb0ef41Sopenharmony_ci  if (!v8StackTrace.IsEmpty() && v8StackTrace->GetFrameCount()) {
2361cb0ef41Sopenharmony_ci    frames = toFramesVector(debugger, v8StackTrace, maxStackSize);
2371cb0ef41Sopenharmony_ci  }
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  int maxAsyncDepth = 0;
2401cb0ef41Sopenharmony_ci  std::shared_ptr<AsyncStackTrace> asyncParent;
2411cb0ef41Sopenharmony_ci  V8StackTraceId externalParent;
2421cb0ef41Sopenharmony_ci  calculateAsyncChain(debugger, &asyncParent, &externalParent, &maxAsyncDepth);
2431cb0ef41Sopenharmony_ci  if (frames.empty() && !asyncParent && externalParent.IsInvalid())
2441cb0ef41Sopenharmony_ci    return nullptr;
2451cb0ef41Sopenharmony_ci  return std::unique_ptr<V8StackTraceImpl>(new V8StackTraceImpl(
2461cb0ef41Sopenharmony_ci      std::move(frames), maxAsyncDepth, asyncParent, externalParent));
2471cb0ef41Sopenharmony_ci}
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ci// static
2501cb0ef41Sopenharmony_cistd::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::capture(
2511cb0ef41Sopenharmony_ci    V8Debugger* debugger, int maxStackSize) {
2521cb0ef41Sopenharmony_ci  DCHECK(debugger);
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  TRACE_EVENT1(
2551cb0ef41Sopenharmony_ci      TRACE_DISABLED_BY_DEFAULT("v8.inspector") "," TRACE_DISABLED_BY_DEFAULT(
2561cb0ef41Sopenharmony_ci          "v8.stack_trace"),
2571cb0ef41Sopenharmony_ci      "V8StackTraceImpl::capture", "maxFrameCount", maxStackSize);
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci  v8::Isolate* isolate = debugger->isolate();
2601cb0ef41Sopenharmony_ci  v8::HandleScope handleScope(isolate);
2611cb0ef41Sopenharmony_ci  v8::Local<v8::StackTrace> v8StackTrace;
2621cb0ef41Sopenharmony_ci  if (isolate->InContext()) {
2631cb0ef41Sopenharmony_ci    v8StackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize,
2641cb0ef41Sopenharmony_ci                                                     stackTraceOptions);
2651cb0ef41Sopenharmony_ci  }
2661cb0ef41Sopenharmony_ci  return V8StackTraceImpl::create(debugger, v8StackTrace, maxStackSize);
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ciV8StackTraceImpl::V8StackTraceImpl(
2701cb0ef41Sopenharmony_ci    std::vector<std::shared_ptr<StackFrame>> frames, int maxAsyncDepth,
2711cb0ef41Sopenharmony_ci    std::shared_ptr<AsyncStackTrace> asyncParent,
2721cb0ef41Sopenharmony_ci    const V8StackTraceId& externalParent)
2731cb0ef41Sopenharmony_ci    : m_frames(std::move(frames)),
2741cb0ef41Sopenharmony_ci      m_maxAsyncDepth(maxAsyncDepth),
2751cb0ef41Sopenharmony_ci      m_asyncParent(std::move(asyncParent)),
2761cb0ef41Sopenharmony_ci      m_externalParent(externalParent) {}
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ciV8StackTraceImpl::~V8StackTraceImpl() = default;
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_cistd::unique_ptr<V8StackTrace> V8StackTraceImpl::clone() {
2811cb0ef41Sopenharmony_ci  return std::unique_ptr<V8StackTrace>(new V8StackTraceImpl(
2821cb0ef41Sopenharmony_ci      m_frames, 0, std::shared_ptr<AsyncStackTrace>(), V8StackTraceId()));
2831cb0ef41Sopenharmony_ci}
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ciStringView V8StackTraceImpl::firstNonEmptySourceURL() const {
2861cb0ef41Sopenharmony_ci  StackFrameIterator current(this);
2871cb0ef41Sopenharmony_ci  while (!current.done()) {
2881cb0ef41Sopenharmony_ci    if (current.frame()->sourceURL().length()) {
2891cb0ef41Sopenharmony_ci      return toStringView(current.frame()->sourceURL());
2901cb0ef41Sopenharmony_ci    }
2911cb0ef41Sopenharmony_ci    current.next();
2921cb0ef41Sopenharmony_ci  }
2931cb0ef41Sopenharmony_ci  return StringView();
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_cibool V8StackTraceImpl::isEmpty() const { return m_frames.empty(); }
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ciStringView V8StackTraceImpl::topSourceURL() const {
2991cb0ef41Sopenharmony_ci  return toStringView(m_frames[0]->sourceURL());
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ciint V8StackTraceImpl::topLineNumber() const {
3031cb0ef41Sopenharmony_ci  return m_frames[0]->lineNumber() + 1;
3041cb0ef41Sopenharmony_ci}
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ciint V8StackTraceImpl::topColumnNumber() const {
3071cb0ef41Sopenharmony_ci  return m_frames[0]->columnNumber() + 1;
3081cb0ef41Sopenharmony_ci}
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ciint V8StackTraceImpl::topScriptId() const { return m_frames[0]->scriptId(); }
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ciStringView V8StackTraceImpl::topFunctionName() const {
3131cb0ef41Sopenharmony_ci  return toStringView(m_frames[0]->functionName());
3141cb0ef41Sopenharmony_ci}
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Runtime::StackTrace>
3171cb0ef41Sopenharmony_ciV8StackTraceImpl::buildInspectorObjectImpl(V8Debugger* debugger) const {
3181cb0ef41Sopenharmony_ci  return buildInspectorObjectImpl(debugger, m_maxAsyncDepth);
3191cb0ef41Sopenharmony_ci}
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Runtime::StackTrace>
3221cb0ef41Sopenharmony_ciV8StackTraceImpl::buildInspectorObjectImpl(V8Debugger* debugger,
3231cb0ef41Sopenharmony_ci                                           int maxAsyncDepth) const {
3241cb0ef41Sopenharmony_ci  return buildInspectorObjectCommon(debugger, m_frames, String16(),
3251cb0ef41Sopenharmony_ci                                    m_asyncParent.lock(), m_externalParent,
3261cb0ef41Sopenharmony_ci                                    maxAsyncDepth);
3271cb0ef41Sopenharmony_ci}
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Runtime::API::StackTrace>
3301cb0ef41Sopenharmony_ciV8StackTraceImpl::buildInspectorObject(int maxAsyncDepth) const {
3311cb0ef41Sopenharmony_ci  return buildInspectorObjectImpl(nullptr,
3321cb0ef41Sopenharmony_ci                                  std::min(maxAsyncDepth, m_maxAsyncDepth));
3331cb0ef41Sopenharmony_ci}
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> V8StackTraceImpl::toString() const {
3361cb0ef41Sopenharmony_ci  String16Builder stackTrace;
3371cb0ef41Sopenharmony_ci  for (size_t i = 0; i < m_frames.size(); ++i) {
3381cb0ef41Sopenharmony_ci    const StackFrame& frame = *m_frames[i];
3391cb0ef41Sopenharmony_ci    stackTrace.append("\n    at " + (frame.functionName().length()
3401cb0ef41Sopenharmony_ci                                         ? frame.functionName()
3411cb0ef41Sopenharmony_ci                                         : "(anonymous function)"));
3421cb0ef41Sopenharmony_ci    stackTrace.append(" (");
3431cb0ef41Sopenharmony_ci    stackTrace.append(frame.sourceURL());
3441cb0ef41Sopenharmony_ci    stackTrace.append(':');
3451cb0ef41Sopenharmony_ci    stackTrace.append(String16::fromInteger(frame.lineNumber() + 1));
3461cb0ef41Sopenharmony_ci    stackTrace.append(':');
3471cb0ef41Sopenharmony_ci    stackTrace.append(String16::fromInteger(frame.columnNumber() + 1));
3481cb0ef41Sopenharmony_ci    stackTrace.append(')');
3491cb0ef41Sopenharmony_ci  }
3501cb0ef41Sopenharmony_ci  return StringBufferFrom(stackTrace.toString());
3511cb0ef41Sopenharmony_ci}
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_cibool V8StackTraceImpl::isEqualIgnoringTopFrame(
3541cb0ef41Sopenharmony_ci    V8StackTraceImpl* stackTrace) const {
3551cb0ef41Sopenharmony_ci  StackFrameIterator current(this);
3561cb0ef41Sopenharmony_ci  StackFrameIterator target(stackTrace);
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci  current.next();
3591cb0ef41Sopenharmony_ci  target.next();
3601cb0ef41Sopenharmony_ci  while (!current.done() && !target.done()) {
3611cb0ef41Sopenharmony_ci    if (!current.frame()->isEqual(target.frame())) {
3621cb0ef41Sopenharmony_ci      return false;
3631cb0ef41Sopenharmony_ci    }
3641cb0ef41Sopenharmony_ci    current.next();
3651cb0ef41Sopenharmony_ci    target.next();
3661cb0ef41Sopenharmony_ci  }
3671cb0ef41Sopenharmony_ci  return current.done() == target.done();
3681cb0ef41Sopenharmony_ci}
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ciV8StackTraceImpl::StackFrameIterator::StackFrameIterator(
3711cb0ef41Sopenharmony_ci    const V8StackTraceImpl* stackTrace)
3721cb0ef41Sopenharmony_ci    : m_currentIt(stackTrace->m_frames.begin()),
3731cb0ef41Sopenharmony_ci      m_currentEnd(stackTrace->m_frames.end()),
3741cb0ef41Sopenharmony_ci      m_parent(stackTrace->m_asyncParent.lock().get()) {}
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_civoid V8StackTraceImpl::StackFrameIterator::next() {
3771cb0ef41Sopenharmony_ci  if (m_currentIt == m_currentEnd) return;
3781cb0ef41Sopenharmony_ci  ++m_currentIt;
3791cb0ef41Sopenharmony_ci  while (m_currentIt == m_currentEnd && m_parent) {
3801cb0ef41Sopenharmony_ci    const std::vector<std::shared_ptr<StackFrame>>& frames = m_parent->frames();
3811cb0ef41Sopenharmony_ci    m_currentIt = frames.begin();
3821cb0ef41Sopenharmony_ci    m_currentEnd = frames.end();
3831cb0ef41Sopenharmony_ci    m_parent = m_parent->parent().lock().get();
3841cb0ef41Sopenharmony_ci  }
3851cb0ef41Sopenharmony_ci}
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_cibool V8StackTraceImpl::StackFrameIterator::done() {
3881cb0ef41Sopenharmony_ci  return m_currentIt == m_currentEnd;
3891cb0ef41Sopenharmony_ci}
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ciStackFrame* V8StackTraceImpl::StackFrameIterator::frame() {
3921cb0ef41Sopenharmony_ci  return m_currentIt->get();
3931cb0ef41Sopenharmony_ci}
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_ci// static
3961cb0ef41Sopenharmony_cistd::shared_ptr<AsyncStackTrace> AsyncStackTrace::capture(
3971cb0ef41Sopenharmony_ci    V8Debugger* debugger, const String16& description, bool skipTopFrame) {
3981cb0ef41Sopenharmony_ci  DCHECK(debugger);
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci  int maxStackSize = debugger->maxCallStackSizeToCapture();
4011cb0ef41Sopenharmony_ci  TRACE_EVENT1(
4021cb0ef41Sopenharmony_ci      TRACE_DISABLED_BY_DEFAULT("v8.inspector") "," TRACE_DISABLED_BY_DEFAULT(
4031cb0ef41Sopenharmony_ci          "v8.stack_trace"),
4041cb0ef41Sopenharmony_ci      "AsyncStackTrace::capture", "maxFrameCount", maxStackSize);
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  v8::Isolate* isolate = debugger->isolate();
4071cb0ef41Sopenharmony_ci  v8::HandleScope handleScope(isolate);
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  std::vector<std::shared_ptr<StackFrame>> frames;
4101cb0ef41Sopenharmony_ci  if (isolate->InContext()) {
4111cb0ef41Sopenharmony_ci    v8::Local<v8::StackTrace> v8StackTrace = v8::StackTrace::CurrentStackTrace(
4121cb0ef41Sopenharmony_ci        isolate, maxStackSize, stackTraceOptions);
4131cb0ef41Sopenharmony_ci    frames = toFramesVector(debugger, v8StackTrace, maxStackSize);
4141cb0ef41Sopenharmony_ci    if (skipTopFrame && !frames.empty()) {
4151cb0ef41Sopenharmony_ci      frames.erase(frames.begin());
4161cb0ef41Sopenharmony_ci    }
4171cb0ef41Sopenharmony_ci  }
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci  std::shared_ptr<AsyncStackTrace> asyncParent;
4201cb0ef41Sopenharmony_ci  V8StackTraceId externalParent;
4211cb0ef41Sopenharmony_ci  calculateAsyncChain(debugger, &asyncParent, &externalParent, nullptr);
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci  if (frames.empty() && !asyncParent && externalParent.IsInvalid())
4241cb0ef41Sopenharmony_ci    return nullptr;
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  // When async call chain is empty but doesn't contain useful schedule stack
4271cb0ef41Sopenharmony_ci  // but doesn't synchronous we can merge them together. e.g. Promise
4281cb0ef41Sopenharmony_ci  // ThenableJob.
4291cb0ef41Sopenharmony_ci  if (asyncParent && frames.empty() &&
4301cb0ef41Sopenharmony_ci      (asyncParent->m_description == description || description.isEmpty())) {
4311cb0ef41Sopenharmony_ci    return asyncParent;
4321cb0ef41Sopenharmony_ci  }
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  return std::shared_ptr<AsyncStackTrace>(new AsyncStackTrace(
4351cb0ef41Sopenharmony_ci      description, std::move(frames), asyncParent, externalParent));
4361cb0ef41Sopenharmony_ci}
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ciAsyncStackTrace::AsyncStackTrace(
4391cb0ef41Sopenharmony_ci    const String16& description,
4401cb0ef41Sopenharmony_ci    std::vector<std::shared_ptr<StackFrame>> frames,
4411cb0ef41Sopenharmony_ci    std::shared_ptr<AsyncStackTrace> asyncParent,
4421cb0ef41Sopenharmony_ci    const V8StackTraceId& externalParent)
4431cb0ef41Sopenharmony_ci    : m_id(0),
4441cb0ef41Sopenharmony_ci      m_description(description),
4451cb0ef41Sopenharmony_ci      m_frames(std::move(frames)),
4461cb0ef41Sopenharmony_ci      m_asyncParent(std::move(asyncParent)),
4471cb0ef41Sopenharmony_ci      m_externalParent(externalParent) {}
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Runtime::StackTrace>
4501cb0ef41Sopenharmony_ciAsyncStackTrace::buildInspectorObject(V8Debugger* debugger,
4511cb0ef41Sopenharmony_ci                                      int maxAsyncDepth) const {
4521cb0ef41Sopenharmony_ci  return buildInspectorObjectCommon(debugger, m_frames, m_description,
4531cb0ef41Sopenharmony_ci                                    m_asyncParent.lock(), m_externalParent,
4541cb0ef41Sopenharmony_ci                                    maxAsyncDepth);
4551cb0ef41Sopenharmony_ci}
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ciuintptr_t AsyncStackTrace::store(V8Debugger* debugger,
4581cb0ef41Sopenharmony_ci                                 std::shared_ptr<AsyncStackTrace> stack) {
4591cb0ef41Sopenharmony_ci  if (stack->m_id) return stack->m_id;
4601cb0ef41Sopenharmony_ci  stack->m_id = debugger->storeStackTrace(stack);
4611cb0ef41Sopenharmony_ci  return stack->m_id;
4621cb0ef41Sopenharmony_ci}
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ciconst String16& AsyncStackTrace::description() const { return m_description; }
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_cistd::weak_ptr<AsyncStackTrace> AsyncStackTrace::parent() const {
4671cb0ef41Sopenharmony_ci  return m_asyncParent;
4681cb0ef41Sopenharmony_ci}
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_cibool AsyncStackTrace::isEmpty() const { return m_frames.empty(); }
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci}  // namespace v8_inspector
473