v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
v8-debugger.h
Go to the documentation of this file.
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_DEBUGGER_H_
6#define V8_INSPECTOR_V8_DEBUGGER_H_
7
8#include <deque>
9#include <list>
10#include <memory>
11#include <unordered_map>
12#include <unordered_set>
13#include <vector>
14
16#include "src/base/macros.h"
18#include "src/inspector/protocol/Debugger.h"
19#include "src/inspector/protocol/Forward.h"
20#include "src/inspector/protocol/Runtime.h"
23
24namespace v8_inspector {
25
26class AsyncStackTrace;
27class StackFrame;
28class V8Debugger;
29class V8DebuggerAgentImpl;
30class V8InspectorImpl;
31class V8RuntimeAgentImpl;
32class V8StackTraceImpl;
33struct V8StackTraceId;
34
36
41
46
47using protocol::Response;
49 protocol::Runtime::Backend::TerminateExecutionCallback;
50
53 public:
55 ~V8Debugger() override;
56 V8Debugger(const V8Debugger&) = delete;
57 V8Debugger& operator=(const V8Debugger&) = delete;
58
59 bool enabled() const;
60 v8::Isolate* isolate() const { return m_isolate; }
61
62 void setBreakpointsActive(bool);
64
67 bool canBreakProgram();
68 bool isInInstrumentationPause() const;
69 void breakProgram(int targetContextGroupId);
70 void interruptAndBreak(int targetContextGroupId);
72 void continueProgram(int targetContextGroupId,
73 bool terminateOnResume = false);
74 void breakProgramOnAssert(int targetContextGroupId);
75
76 void setPauseOnNextCall(bool, int targetContextGroupId);
77 void stepIntoStatement(int targetContextGroupId, bool breakOnAsyncCall);
78 void stepOverStatement(int targetContextGroupId);
79 void stepOutOfFunction(int targetContextGroupId);
80
82 std::unique_ptr<TerminateExecutionCallback> callback);
83
84 Response continueToLocation(int targetContextGroupId,
85 V8DebuggerScript* script,
86 std::unique_ptr<protocol::Debugger::Location>,
87 const String16& targetCallFramess);
88 bool restartFrame(int targetContextGroupId, int callFrameOrdinal);
89
90 // Each script inherits debug data from v8::Context where it has been
91 // compiled.
92 // Only scripts whose debug data matches |contextGroupId| will be reported.
93 // Passing 0 will result in reporting all scripts.
94 std::vector<std::unique_ptr<V8DebuggerScript>> getCompiledScripts(
95 int contextGroupId, V8DebuggerAgentImpl* agent);
96 void enable();
97 void disable();
98
99 bool isPaused() const { return m_pausedContextGroupId; }
100 bool isPausedInContextGroup(int contextGroupId) const;
101
104
107
108 std::shared_ptr<AsyncStackTrace> currentAsyncParent();
110
111 std::shared_ptr<StackFrame> symbolize(v8::Local<v8::StackFrame> v8Frame);
112
113 std::unique_ptr<V8StackTraceImpl> createStackTrace(v8::Local<v8::StackTrace>);
114 std::unique_ptr<V8StackTraceImpl> captureStackTrace(bool fullStack);
115
118
120 v8::Local<v8::Object> prototype);
121
122 void asyncTaskScheduled(const StringView& taskName, void* task,
123 bool recurring);
124 void asyncTaskCanceled(void* task);
125 void asyncTaskStarted(void* task);
126 void asyncTaskFinished(void* task);
128
130 void externalAsyncTaskStarted(const V8StackTraceId& parent);
131 void externalAsyncTaskFinished(const V8StackTraceId& parent);
132
133 uintptr_t storeStackTrace(std::shared_ptr<AsyncStackTrace> stack);
134
137
139
140 void setMaxAsyncTaskStacksForTest(int limit);
142
143 void asyncParentFor(int stackTraceId,
144 std::shared_ptr<AsyncStackTrace>* asyncParent,
145 V8StackTraceId* externalParent) const;
146
147 internal::V8DebuggerId debuggerIdFor(int contextGroupId);
148 std::shared_ptr<AsyncStackTrace> stackTraceFor(int contextGroupId,
149 const V8StackTraceId& id);
150
151 void reportTermination();
152
153 private:
157
160
161 static size_t nearHeapLimitCallback(void* data, size_t current_heap_limit,
162 size_t initial_heap_limit);
165 v8::Isolate* isolate, void*);
167
169 v8::Local<v8::Context> pausedContext, v8::Local<v8::Value> exception,
170 const std::vector<v8::debug::BreakpointId>& hitBreakpoints,
171 v8::debug::BreakReasons break_reasons,
173 bool isUncaught = false);
174
182
191
192 void asyncTaskScheduledForStack(const StringView& taskName, void* task,
193 bool recurring, bool skipTopFrame = false);
194 void asyncTaskCanceledForStack(void* task);
195 void asyncTaskStartedForStack(void* task);
196 void asyncTaskFinishedForStack(void* task);
197
198 void asyncTaskCandidateForStepping(void* task);
199 void asyncTaskStartedForStepping(void* task);
200 void asyncTaskFinishedForStepping(void* task);
201 void asyncTaskCanceledForStepping(void* task);
202 void asyncStackTraceCaptured(int id);
203
204 // v8::debug::DebugEventListener implementation.
206 bool isBlackboxed) override;
207 void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
208 bool has_compile_error) override;
210 v8::Local<v8::Context> paused_context,
211 const std::vector<v8::debug::BreakpointId>& break_points_hit,
212 v8::debug::BreakReasons break_reasons) override;
214 v8::Local<v8::Context> paused_context, v8::debug::BreakpointId) override;
215 void ExceptionThrown(v8::Local<v8::Context> paused_context,
216 v8::Local<v8::Value> exception,
217 v8::Local<v8::Value> promise, bool is_uncaught,
218 v8::debug::ExceptionType exception_type) override;
221 const v8::debug::Location& end) override;
222
223 bool ShouldBeSkipped(v8::Local<v8::debug::Script> script, int line,
224 int column) override;
226 v8::debug::BreakpointId breakpoint_id,
227 bool exception_thrown,
228 v8::Local<v8::Value> exception) override;
229
231
233
235
239
250 std::unique_ptr<V8StackTraceImpl> m_continueToLocationStack;
251
252 // We cache symbolized stack frames by (scriptId,lineNumber,columnNumber)
253 // to reduce memory pressure for huge web apps with lots of deep async
254 // stacks.
259
260 struct Equal {
262 CachedStackFrameKey const& b) const {
263 return a.scriptId == b.scriptId && a.lineNumber == b.lineNumber &&
264 a.columnNumber == b.columnNumber;
265 }
266 };
267
268 struct Hash {
269 size_t operator()(CachedStackFrameKey const& key) const {
270 size_t code = 0;
271 code = code * 31 + key.scriptId;
272 code = code * 31 + key.lineNumber;
273 code = code * 31 + key.columnNumber;
274 return code;
275 }
276 };
277 };
278 std::unordered_map<CachedStackFrameKey, std::weak_ptr<StackFrame>,
279 CachedStackFrameKey::Hash, CachedStackFrameKey::Equal>
281
283 std::unordered_map<void*, std::weak_ptr<AsyncStackTrace>>;
285 std::unordered_set<void*> m_recurringTasks;
286
290
291 std::vector<void*> m_currentTasks;
292 std::vector<std::shared_ptr<AsyncStackTrace>> m_currentAsyncParent;
293 std::vector<V8StackTraceId> m_currentExternalParent;
294
295 // Maps v8::StackTrace IDs to async parents.
297 std::unordered_map<int, std::weak_ptr<AsyncStackTrace>>;
298 using StackTraceToExternalParent = std::deque<std::pair<int, V8StackTraceId>>;
301
303 // V8Debugger owns all the async stacks, while most of the other references
304 // are weak, which allows to collect some stacks when there are too many.
305 std::list<std::shared_ptr<AsyncStackTrace>> m_allAsyncStacks;
306
307 std::unordered_map<V8DebuggerAgentImpl*, int> m_maxAsyncCallStackDepthMap;
308 std::unordered_map<V8RuntimeAgentImpl*, int> m_maxCallStackSizeToCaptureMap;
310
311 // If any of the following three is true, we schedule pause on next JS
312 // execution using SetBreakOnNextFunctionCall.
313 bool m_externalAsyncTaskPauseRequested = false; // External async task.
314 bool m_taskWithScheduledBreakPauseRequested = false; // Local async task.
315 bool m_pauseOnNextCallRequested = false; // setPauseOnNextCall API call.
316
318 // Whether we should pause on async call execution (if any) while stepping in.
319 // See Debugger.stepInto for details.
320 bool m_pauseOnAsyncCall = false;
321
323 std::unordered_map<uintptr_t, std::weak_ptr<AsyncStackTrace>>;
325 uintptr_t m_lastStackTraceId = 0;
326
327 std::unordered_map<int, internal::V8DebuggerId> m_contextGroupIdToDebuggerId;
328
329 std::unique_ptr<TerminateExecutionCallback> m_terminateExecutionCallback;
332};
333
334} // namespace v8_inspector
335
336#endif // V8_INSPECTOR_V8_DEBUGGER_H_
void terminateExecution(v8::Local< v8::Context > context, std::unique_ptr< TerminateExecutionCallback > callback)
static void terminateExecutionCompletedCallbackIgnoringData(v8::Isolate *isolate, void *)
std::unique_ptr< V8StackTraceImpl > createStackTrace(v8::Local< v8::StackTrace >)
v8::debug::ExceptionBreakState getPauseOnExceptionsState()
std::shared_ptr< StackFrame > symbolize(v8::Local< v8::StackFrame > v8Frame)
std::shared_ptr< AsyncStackTrace > stackTraceFor(int contextGroupId, const V8StackTraceId &id)
std::unordered_map< void *, std::weak_ptr< AsyncStackTrace > > AsyncTaskToStackTrace
v8::MaybeLocal< v8::Value > generatorScopes(v8::Local< v8::Context >, v8::Local< v8::Value >)
V8Debugger & operator=(const V8Debugger &)=delete
void asyncTaskCanceledForStack(void *task)
bool isPausedInContextGroup(int contextGroupId) const
void quitMessageLoopIfAgentsFinishedInstrumentation()
std::unordered_map< CachedStackFrameKey, std::weak_ptr< StackFrame >, CachedStackFrameKey::Hash, CachedStackFrameKey::Equal > m_cachedStackFrames
std::unordered_map< uintptr_t, std::weak_ptr< AsyncStackTrace > > StoredStackTraces
void asyncTaskCanceled(void *task)
ActionAfterInstrumentation BreakOnInstrumentation(v8::Local< v8::Context > paused_context, v8::debug::BreakpointId) override
void externalAsyncTaskStarted(const V8StackTraceId &parent)
void removeBreakpoint(v8::debug::BreakpointId id)
void setPauseOnNextCall(bool, int targetContextGroupId)
bool m_taskWithScheduledBreakPauseRequested
void asyncTaskStarted(void *task)
v8::Local< v8::Array > queryObjects(v8::Local< v8::Context > context, v8::Local< v8::Object > prototype)
bool IsFunctionBlackboxed(v8::Local< v8::debug::Script > script, const v8::debug::Location &start, const v8::debug::Location &end) override
internal::V8DebuggerId debuggerIdFor(int contextGroupId)
std::unordered_map< V8DebuggerAgentImpl *, int > m_maxAsyncCallStackDepthMap
v8::debug::ExceptionBreakState m_pauseOnExceptionsState
std::unique_ptr< V8StackTraceImpl > captureStackTrace(bool fullStack)
v8::MaybeLocal< v8::Array > internalProperties(v8::Local< v8::Context >, v8::Local< v8::Value >)
void stepOutOfFunction(int targetContextGroupId)
int maxCallStackSizeToCapture() const
std::vector< std::unique_ptr< V8DebuggerScript > > getCompiledScripts(int contextGroupId, V8DebuggerAgentImpl *agent)
v8::MaybeLocal< v8::Value > getTargetScopes(v8::Local< v8::Context >, v8::Local< v8::Value >, ScopeTargetKind)
void AsyncEventOccurred(v8::debug::DebugAsyncActionType type, int id, bool isBlackboxed) override
std::unordered_map< int, std::weak_ptr< AsyncStackTrace > > StackTraceToAsyncParent
void interruptAndBreak(int targetContextGroupId)
v8::MaybeLocal< v8::Array > privateMethods(v8::Local< v8::Context > context, v8::Local< v8::Value > value)
void installTerminateExecutionCallbacks(v8::Local< v8::Context > context)
void continueProgram(int targetContextGroupId, bool terminateOnResume=false)
void asyncTaskScheduledForStack(const StringView &taskName, void *task, bool recurring, bool skipTopFrame=false)
std::list< std::shared_ptr< AsyncStackTrace > > m_allAsyncStacks
V8StackTraceId storeCurrentStackTrace(const StringView &description)
std::unique_ptr< TerminateExecutionCallback > m_terminateExecutionCallback
void setMaxCallStackSizeToCapture(V8RuntimeAgentImpl *, int)
V8Debugger(v8::Isolate *, V8InspectorImpl *)
void asyncTaskFinishedForStack(void *task)
void handleProgramBreak(v8::Local< v8::Context > pausedContext, v8::Local< v8::Value > exception, const std::vector< v8::debug::BreakpointId > &hitBreakpoints, v8::debug::BreakReasons break_reasons, v8::debug::ExceptionType exception_type=v8::debug::kException, bool isUncaught=false)
std::unordered_map< V8RuntimeAgentImpl *, int > m_maxCallStackSizeToCaptureMap
v8::Global< v8::Context > m_terminateExecutionCallbackContext
bool isInInstrumentationPause() const
void asyncTaskFinishedForStepping(void *task)
StackTraceToExternalParent m_externalParents
void BreakpointConditionEvaluated(v8::Local< v8::Context > context, v8::debug::BreakpointId breakpoint_id, bool exception_thrown, v8::Local< v8::Value > exception) override
std::unordered_set< void * > m_recurringTasks
bool addInternalObject(v8::Local< v8::Context > context, v8::Local< v8::Object > object, V8InternalValueType type)
void externalAsyncTaskFinished(const V8StackTraceId &parent)
bool hasScheduledBreakOnNextFunctionCall() const
V8InspectorImpl * m_inspector
uintptr_t storeStackTrace(std::shared_ptr< AsyncStackTrace > stack)
void ExceptionThrown(v8::Local< v8::Context > paused_context, v8::Local< v8::Value > exception, v8::Local< v8::Value > promise, bool is_uncaught, v8::debug::ExceptionType exception_type) override
StoredStackTraces m_storedStackTraces
v8::MaybeLocal< v8::Array > collectionsEntries(v8::Local< v8::Context > context, v8::Local< v8::Value > value)
StackTraceToAsyncParent m_asyncParents
bool ShouldBeSkipped(v8::Local< v8::debug::Script > script, int line, int column) override
void ScriptCompiled(v8::Local< v8::debug::Script > script, bool is_live_edited, bool has_compile_error) override
std::shared_ptr< AsyncStackTrace > currentAsyncParent()
std::vector< V8StackTraceId > m_currentExternalParent
void asyncTaskCandidateForStepping(void *task)
void setAsyncCallStackDepth(V8DebuggerAgentImpl *, int)
String16 m_continueToLocationTargetCallFrames
void asyncTaskStartedForStepping(void *task)
void breakProgram(int targetContextGroupId)
std::deque< std::pair< int, V8StackTraceId > > StackTraceToExternalParent
std::unique_ptr< V8StackTraceImpl > m_continueToLocationStack
void asyncTaskCanceledForStepping(void *task)
AsyncTaskToStackTrace m_asyncTaskStacks
static size_t nearHeapLimitCallback(void *data, size_t current_heap_limit, size_t initial_heap_limit)
V8StackTraceId currentExternalParent()
v8::MaybeLocal< v8::Value > functionScopes(v8::Local< v8::Context >, v8::Local< v8::Function >)
V8InspectorImpl * inspector()
std::vector< void * > m_currentTasks
void stepIntoStatement(int targetContextGroupId, bool breakOnAsyncCall)
void asyncStackTraceCaptured(int id)
void asyncTaskScheduled(const StringView &taskName, void *task, bool recurring)
v8::Isolate * isolate() const
Definition v8-debugger.h:60
void BreakProgramRequested(v8::Local< v8::Context > paused_context, const std::vector< v8::debug::BreakpointId > &break_points_hit, v8::debug::BreakReasons break_reasons) override
void asyncTaskFinished(void *task)
std::unordered_map< int, internal::V8DebuggerId > m_contextGroupIdToDebuggerId
std::vector< std::shared_ptr< AsyncStackTrace > > m_currentAsyncParent
void stepOverStatement(int targetContextGroupId)
void setPauseOnExceptionsState(v8::debug::ExceptionBreakState)
void asyncParentFor(int stackTraceId, std::shared_ptr< AsyncStackTrace > *asyncParent, V8StackTraceId *externalParent) const
bool restartFrame(int targetContextGroupId, int callFrameOrdinal)
void breakProgramOnAssert(int targetContextGroupId)
void setMaxAsyncTaskStacksForTest(int limit)
Response continueToLocation(int targetContextGroupId, V8DebuggerScript *script, std::unique_ptr< protocol::Debugger::Location >, const String16 &targetCallFramess)
void asyncTaskStartedForStack(void *task)
V8Debugger(const V8Debugger &)=delete
static void terminateExecutionCompletedCallback(v8::Isolate *isolate)
Handle< Code > code
int start
int end
TNode< Object > callback
constexpr int kMaxInt
Definition globals.h:374
protocol::Runtime::Backend::TerminateExecutionCallback TerminateExecutionCallback
Definition v8-debugger.h:48
bool operator()(CachedStackFrameKey const &a, CachedStackFrameKey const &b) const
size_t operator()(CachedStackFrameKey const &key) const
WrapSerializationOptions serializationOptions
Definition v8-debugger.h:44
v8::Global< v8::Object > additionalParameters
Definition v8-debugger.h:39
std::unique_ptr< ValueMirror > key