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.h" 13 #include "src/base/macros.h" 14 #include "src/inspector/protocol/Runtime.h" 15 #include "src/inspector/string-16.h" 16 17 namespace v8_inspector { 18 19 class AsyncStackTrace; 20 class V8Debugger; 21 struct V8StackTraceId; 22 23 class StackFrame { 24 public: 25 explicit StackFrame(v8::Isolate* isolate, v8::Local<v8::StackFrame> frame); 26 ~StackFrame() = default; 27 28 const String16& functionName() const; 29 const String16& scriptId() const; 30 const String16& sourceURL() const; 31 int lineNumber() const; // 0-based. 32 int columnNumber() const; // 0-based. 33 std::unique_ptr<protocol::Runtime::CallFrame> buildInspectorObject( 34 V8InspectorClient* client) const; 35 bool isEqual(StackFrame* frame) const; 36 37 private: 38 String16 m_functionName; 39 String16 m_scriptId; 40 String16 m_sourceURL; 41 int m_lineNumber; // 0-based. 42 int m_columnNumber; // 0-based. 43 bool m_hasSourceURLComment; 44 }; 45 46 class V8StackTraceImpl : public V8StackTrace { 47 public: 48 static void setCaptureStackTraceForUncaughtExceptions(v8::Isolate*, 49 bool capture); 50 static int maxCallStackSizeToCapture; 51 static std::unique_ptr<V8StackTraceImpl> create(V8Debugger*, 52 int contextGroupId, 53 v8::Local<v8::StackTrace>, 54 int maxStackSize); 55 static std::unique_ptr<V8StackTraceImpl> capture(V8Debugger*, 56 int contextGroupId, 57 int maxStackSize); 58 59 ~V8StackTraceImpl() override; 60 std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectImpl( 61 V8Debugger* debugger) const; 62 63 std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectImpl( 64 V8Debugger* debugger, int maxAsyncDepth) const; 65 66 // V8StackTrace implementation. 67 // This method drops the async stack trace. 68 std::unique_ptr<V8StackTrace> clone() override; 69 StringView firstNonEmptySourceURL() const override; 70 bool isEmpty() const override; 71 StringView topSourceURL() const override; 72 int topLineNumber() const override; // 1-based. 73 int topColumnNumber() const override; // 1-based. 74 StringView topScriptId() const override; 75 StringView topFunctionName() const override; 76 std::unique_ptr<protocol::Runtime::API::StackTrace> buildInspectorObject() 77 const override; 78 std::unique_ptr<protocol::Runtime::API::StackTrace> buildInspectorObject( 79 int maxAsyncDepth) const override; 80 std::unique_ptr<StringBuffer> toString() const override; 81 82 bool isEqualIgnoringTopFrame(V8StackTraceImpl* stackTrace) const; 83 84 private: 85 V8StackTraceImpl(std::vector<std::shared_ptr<StackFrame>> frames, 86 int maxAsyncDepth, 87 std::shared_ptr<AsyncStackTrace> asyncParent, 88 const V8StackTraceId& externalParent); 89 90 class StackFrameIterator { 91 public: 92 explicit StackFrameIterator(const V8StackTraceImpl* stackTrace); 93 94 void next(); 95 StackFrame* frame(); 96 bool done(); 97 98 private: 99 std::vector<std::shared_ptr<StackFrame>>::const_iterator m_currentIt; 100 std::vector<std::shared_ptr<StackFrame>>::const_iterator m_currentEnd; 101 AsyncStackTrace* m_parent; 102 }; 103 104 std::vector<std::shared_ptr<StackFrame>> m_frames; 105 int m_maxAsyncDepth; 106 std::weak_ptr<AsyncStackTrace> m_asyncParent; 107 V8StackTraceId m_externalParent; 108 109 DISALLOW_COPY_AND_ASSIGN(V8StackTraceImpl); 110 }; 111 112 class AsyncStackTrace { 113 public: 114 static std::shared_ptr<AsyncStackTrace> capture(V8Debugger*, 115 int contextGroupId, 116 const String16& description, 117 int maxStackSize); 118 static uintptr_t store(V8Debugger* debugger, 119 std::shared_ptr<AsyncStackTrace> stack); 120 121 std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObject( 122 V8Debugger* debugger, int maxAsyncDepth) const; 123 124 // If async stack has suspended task id, it means that at moment when we 125 // capture current stack trace we suspended corresponded asynchronous 126 // execution flow and it is possible to request pause for a momemnt when 127 // that flow is resumed. 128 // E.g. every time when we suspend async function we mark corresponded async 129 // stack as suspended and every time when this function is resumed we remove 130 // suspendedTaskId. 131 void setSuspendedTaskId(void* task); 132 void* suspendedTaskId() const; 133 134 int contextGroupId() const; 135 const String16& description() const; 136 std::weak_ptr<AsyncStackTrace> parent() const; 137 bool isEmpty() const; externalParent()138 const V8StackTraceId& externalParent() const { return m_externalParent; } 139 frames()140 const std::vector<std::shared_ptr<StackFrame>>& frames() const { 141 return m_frames; 142 } 143 144 private: 145 AsyncStackTrace(int contextGroupId, const String16& description, 146 std::vector<std::shared_ptr<StackFrame>> frames, 147 std::shared_ptr<AsyncStackTrace> asyncParent, 148 const V8StackTraceId& externalParent); 149 150 int m_contextGroupId; 151 uintptr_t m_id; 152 void* m_suspendedTaskId; 153 String16 m_description; 154 155 std::vector<std::shared_ptr<StackFrame>> m_frames; 156 std::weak_ptr<AsyncStackTrace> m_asyncParent; 157 V8StackTraceId m_externalParent; 158 159 DISALLOW_COPY_AND_ASSIGN(AsyncStackTrace); 160 }; 161 162 } // namespace v8_inspector 163 164 #endif // V8_INSPECTOR_V8_STACK_TRACE_IMPL_H_ 165