// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_INSPECTOR_V8_STACK_TRACE_IMPL_H_ #define V8_INSPECTOR_V8_STACK_TRACE_IMPL_H_ #include <memory> #include <vector> #include "include/v8-inspector.h" #include "include/v8.h" #include "src/base/macros.h" #include "src/inspector/protocol/Runtime.h" #include "src/inspector/string-16.h" namespace v8_inspector { class AsyncStackTrace; class V8Debugger; class WasmTranslation; struct V8StackTraceId; class StackFrame { public: explicit StackFrame(v8::Isolate* isolate, v8::Local<v8::StackFrame> frame); ~StackFrame() = default; void translate(WasmTranslation* wasmTranslation); const String16& functionName() const; const String16& scriptId() const; const String16& sourceURL() const; int lineNumber() const; // 0-based. int columnNumber() const; // 0-based. std::unique_ptr<protocol::Runtime::CallFrame> buildInspectorObject( V8InspectorClient* client) const; bool isEqual(StackFrame* frame) const; private: String16 m_functionName; String16 m_scriptId; String16 m_sourceURL; int m_lineNumber; // 0-based. int m_columnNumber; // 0-based. bool m_hasSourceURLComment; }; class V8StackTraceImpl : public V8StackTrace { public: static void setCaptureStackTraceForUncaughtExceptions(v8::Isolate*, bool capture); static int maxCallStackSizeToCapture; static std::unique_ptr<V8StackTraceImpl> create(V8Debugger*, int contextGroupId, v8::Local<v8::StackTrace>, int maxStackSize); static std::unique_ptr<V8StackTraceImpl> capture(V8Debugger*, int contextGroupId, int maxStackSize); ~V8StackTraceImpl() override; std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectImpl( V8Debugger* debugger) const; std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectImpl( V8Debugger* debugger, int maxAsyncDepth) const; // V8StackTrace implementation. // This method drops the async stack trace. std::unique_ptr<V8StackTrace> clone() override; StringView firstNonEmptySourceURL() const override; bool isEmpty() const override; StringView topSourceURL() const override; int topLineNumber() const override; // 1-based. int topColumnNumber() const override; // 1-based. StringView topScriptId() const override; StringView topFunctionName() const override; std::unique_ptr<protocol::Runtime::API::StackTrace> buildInspectorObject() const override; std::unique_ptr<StringBuffer> toString() const override; bool isEqualIgnoringTopFrame(V8StackTraceImpl* stackTrace) const; private: V8StackTraceImpl(std::vector<std::shared_ptr<StackFrame>> frames, int maxAsyncDepth, std::shared_ptr<AsyncStackTrace> asyncParent, const V8StackTraceId& externalParent); class StackFrameIterator { public: explicit StackFrameIterator(const V8StackTraceImpl* stackTrace); void next(); StackFrame* frame(); bool done(); private: std::vector<std::shared_ptr<StackFrame>>::const_iterator m_currentIt; std::vector<std::shared_ptr<StackFrame>>::const_iterator m_currentEnd; AsyncStackTrace* m_parent; }; std::vector<std::shared_ptr<StackFrame>> m_frames; int m_maxAsyncDepth; std::weak_ptr<AsyncStackTrace> m_asyncParent; V8StackTraceId m_externalParent; DISALLOW_COPY_AND_ASSIGN(V8StackTraceImpl); }; class AsyncStackTrace { public: static std::shared_ptr<AsyncStackTrace> capture(V8Debugger*, int contextGroupId, const String16& description, int maxStackSize); static uintptr_t store(V8Debugger* debugger, std::shared_ptr<AsyncStackTrace> stack); std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObject( V8Debugger* debugger, int maxAsyncDepth) const; // If async stack has suspended task id, it means that at moment when we // capture current stack trace we suspended corresponded asynchronous // execution flow and it is possible to request pause for a momemnt when // that flow is resumed. // E.g. every time when we suspend async function we mark corresponded async // stack as suspended and every time when this function is resumed we remove // suspendedTaskId. void setSuspendedTaskId(void* task); void* suspendedTaskId() const; int contextGroupId() const; const String16& description() const; std::weak_ptr<AsyncStackTrace> parent() const; bool isEmpty() const; const V8StackTraceId& externalParent() const { return m_externalParent; } const std::vector<std::shared_ptr<StackFrame>>& frames() const { return m_frames; } private: AsyncStackTrace(int contextGroupId, const String16& description, std::vector<std::shared_ptr<StackFrame>> frames, std::shared_ptr<AsyncStackTrace> asyncParent, const V8StackTraceId& externalParent); int m_contextGroupId; uintptr_t m_id; void* m_suspendedTaskId; String16 m_description; std::vector<std::shared_ptr<StackFrame>> m_frames; std::weak_ptr<AsyncStackTrace> m_asyncParent; V8StackTraceId m_externalParent; DISALLOW_COPY_AND_ASSIGN(AsyncStackTrace); }; } // namespace v8_inspector #endif // V8_INSPECTOR_V8_STACK_TRACE_IMPL_H_