1// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_INSPECTOR_V8_STACK_TRACE_IMPL_H_
6#define V8_INSPECTOR_V8_STACK_TRACE_IMPL_H_
7
8#include <memory>
9#include <vector>
10
11#include "include/v8-inspector.h"
12#include "include/v8-local-handle.h"
13#include "src/base/macros.h"
14#include "src/inspector/protocol/Runtime.h"
15#include "src/inspector/string-16.h"
16
17namespace v8 {
18class StackFrame;
19class StackTrace;
20}  // namespace v8
21
22namespace v8_inspector {
23
24class AsyncStackTrace;
25class V8Debugger;
26struct V8StackTraceId;
27
28class StackFrame {
29 public:
30  StackFrame(String16&& functionName, int scriptId, String16&& sourceURL,
31             int lineNumber, int columnNumber, bool hasSourceURLComment);
32  ~StackFrame() = default;
33
34  const String16& functionName() const;
35  int scriptId() const;
36  const String16& sourceURL() const;
37  int lineNumber() const;    // 0-based.
38  int columnNumber() const;  // 0-based.
39  std::unique_ptr<protocol::Runtime::CallFrame> buildInspectorObject(
40      V8InspectorClient* client) const;
41  bool isEqual(StackFrame* frame) const;
42
43 private:
44  String16 m_functionName;
45  int m_scriptId;
46  String16 m_sourceURL;
47  int m_lineNumber;    // 0-based.
48  int m_columnNumber;  // 0-based.
49  bool m_hasSourceURLComment;
50};
51
52class V8StackTraceImpl : public V8StackTrace {
53 public:
54  static constexpr int kDefaultMaxCallStackSizeToCapture = 200;
55
56  static std::unique_ptr<V8StackTraceImpl> create(V8Debugger*,
57                                                  v8::Local<v8::StackTrace>,
58                                                  int maxStackSize);
59  static std::unique_ptr<V8StackTraceImpl> capture(V8Debugger*,
60                                                   int maxStackSize);
61
62  ~V8StackTraceImpl() override;
63  V8StackTraceImpl(const V8StackTraceImpl&) = delete;
64  V8StackTraceImpl& operator=(const V8StackTraceImpl&) = delete;
65  std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectImpl(
66      V8Debugger* debugger) const;
67
68  std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectImpl(
69      V8Debugger* debugger, int maxAsyncDepth) const;
70
71  // V8StackTrace implementation.
72  // This method drops the async stack trace.
73  std::unique_ptr<V8StackTrace> clone() override;
74  StringView firstNonEmptySourceURL() const override;
75  bool isEmpty() const override;
76  StringView topSourceURL() const override;
77  int topLineNumber() const override;    // 1-based.
78  int topColumnNumber() const override;  // 1-based.
79  int topScriptId() const override;
80  StringView topFunctionName() const override;
81  std::unique_ptr<protocol::Runtime::API::StackTrace> buildInspectorObject(
82      int maxAsyncDepth) const override;
83  std::unique_ptr<StringBuffer> toString() const override;
84
85  bool isEqualIgnoringTopFrame(V8StackTraceImpl* stackTrace) const;
86
87 private:
88  V8StackTraceImpl(std::vector<std::shared_ptr<StackFrame>> frames,
89                   int maxAsyncDepth,
90                   std::shared_ptr<AsyncStackTrace> asyncParent,
91                   const V8StackTraceId& externalParent);
92
93  class StackFrameIterator {
94   public:
95    explicit StackFrameIterator(const V8StackTraceImpl* stackTrace);
96
97    void next();
98    StackFrame* frame();
99    bool done();
100
101   private:
102    std::vector<std::shared_ptr<StackFrame>>::const_iterator m_currentIt;
103    std::vector<std::shared_ptr<StackFrame>>::const_iterator m_currentEnd;
104    AsyncStackTrace* m_parent;
105  };
106
107  std::vector<std::shared_ptr<StackFrame>> m_frames;
108  int m_maxAsyncDepth;
109  std::weak_ptr<AsyncStackTrace> m_asyncParent;
110  V8StackTraceId m_externalParent;
111};
112
113class AsyncStackTrace {
114 public:
115  AsyncStackTrace(const AsyncStackTrace&) = delete;
116  AsyncStackTrace& operator=(const AsyncStackTrace&) = delete;
117  static std::shared_ptr<AsyncStackTrace> capture(V8Debugger*,
118                                                  const String16& description,
119                                                  bool skipTopFrame = false);
120  static uintptr_t store(V8Debugger* debugger,
121                         std::shared_ptr<AsyncStackTrace> stack);
122
123  std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObject(
124      V8Debugger* debugger, int maxAsyncDepth) const;
125
126  const String16& description() const;
127  std::weak_ptr<AsyncStackTrace> parent() const;
128  bool isEmpty() const;
129  const V8StackTraceId& externalParent() const { return m_externalParent; }
130
131  const std::vector<std::shared_ptr<StackFrame>>& frames() const {
132    return m_frames;
133  }
134
135 private:
136  AsyncStackTrace(const String16& description,
137                  std::vector<std::shared_ptr<StackFrame>> frames,
138                  std::shared_ptr<AsyncStackTrace> asyncParent,
139                  const V8StackTraceId& externalParent);
140
141  uintptr_t m_id;
142  String16 m_description;
143
144  std::vector<std::shared_ptr<StackFrame>> m_frames;
145  std::weak_ptr<AsyncStackTrace> m_asyncParent;
146  V8StackTraceId m_externalParent;
147};
148
149}  // namespace v8_inspector
150
151#endif  // V8_INSPECTOR_V8_STACK_TRACE_IMPL_H_
152