Line data Source code
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 <list>
9 : #include <unordered_map>
10 : #include <unordered_set>
11 : #include <vector>
12 :
13 : #include "src/base/macros.h"
14 : #include "src/inspector/inspected-context.h"
15 : #include "src/inspector/protocol/Debugger.h"
16 : #include "src/inspector/protocol/Forward.h"
17 : #include "src/inspector/protocol/Runtime.h"
18 : #include "src/inspector/v8-debugger-script.h"
19 : #include "src/inspector/wasm-translation.h"
20 :
21 : #include "include/v8-inspector.h"
22 :
23 : namespace v8_inspector {
24 :
25 : class AsyncStackTrace;
26 : class StackFrame;
27 : class V8Debugger;
28 : class V8DebuggerAgentImpl;
29 : class V8InspectorImpl;
30 : class V8StackTraceImpl;
31 : struct V8StackTraceId;
32 :
33 : enum class WrapMode { kForceValue, kNoPreview, kWithPreview };
34 :
35 : using protocol::Response;
36 : using TerminateExecutionCallback =
37 : protocol::Runtime::Backend::TerminateExecutionCallback;
38 :
39 : class V8Debugger : public v8::debug::DebugDelegate,
40 : public v8::debug::AsyncEventDelegate {
41 : public:
42 : V8Debugger(v8::Isolate*, V8InspectorImpl*);
43 : ~V8Debugger() override;
44 :
45 : bool enabled() const;
46 : v8::Isolate* isolate() const { return m_isolate; }
47 :
48 : void setBreakpointsActive(bool);
49 :
50 : v8::debug::ExceptionBreakState getPauseOnExceptionsState();
51 : void setPauseOnExceptionsState(v8::debug::ExceptionBreakState);
52 : bool canBreakProgram();
53 : void breakProgram(int targetContextGroupId);
54 : void interruptAndBreak(int targetContextGroupId);
55 : void continueProgram(int targetContextGroupId);
56 : void breakProgramOnAssert(int targetContextGroupId);
57 :
58 : void setPauseOnNextCall(bool, int targetContextGroupId);
59 : void stepIntoStatement(int targetContextGroupId, bool breakOnAsyncCall);
60 : void stepOverStatement(int targetContextGroupId);
61 : void stepOutOfFunction(int targetContextGroupId);
62 : void pauseOnAsyncCall(int targetContextGroupId, uintptr_t task,
63 : const String16& debuggerId);
64 :
65 : void terminateExecution(std::unique_ptr<TerminateExecutionCallback> callback);
66 :
67 : Response continueToLocation(int targetContextGroupId,
68 : V8DebuggerScript* script,
69 : std::unique_ptr<protocol::Debugger::Location>,
70 : const String16& targetCallFramess);
71 :
72 : // Each script inherits debug data from v8::Context where it has been
73 : // compiled.
74 : // Only scripts whose debug data matches |contextGroupId| will be reported.
75 : // Passing 0 will result in reporting all scripts.
76 : void getCompiledScripts(int contextGroupId,
77 : std::vector<std::unique_ptr<V8DebuggerScript>>&);
78 : void enable();
79 : void disable();
80 :
81 : bool isPaused() const { return m_pausedContextGroupId; }
82 : bool isPausedInContextGroup(int contextGroupId) const;
83 :
84 : int maxAsyncCallChainDepth() { return m_maxAsyncCallStackDepth; }
85 : void setAsyncCallStackDepth(V8DebuggerAgentImpl*, int);
86 :
87 : std::shared_ptr<AsyncStackTrace> currentAsyncParent();
88 : V8StackTraceId currentExternalParent();
89 :
90 : std::shared_ptr<StackFrame> symbolize(v8::Local<v8::StackFrame> v8Frame);
91 :
92 : std::unique_ptr<V8StackTraceImpl> createStackTrace(v8::Local<v8::StackTrace>);
93 : std::unique_ptr<V8StackTraceImpl> captureStackTrace(bool fullStack);
94 :
95 : v8::MaybeLocal<v8::Array> internalProperties(v8::Local<v8::Context>,
96 : v8::Local<v8::Value>);
97 :
98 : v8::Local<v8::Array> queryObjects(v8::Local<v8::Context> context,
99 : v8::Local<v8::Object> prototype);
100 :
101 : void asyncTaskScheduled(const StringView& taskName, void* task,
102 : bool recurring);
103 : void asyncTaskCanceled(void* task);
104 : void asyncTaskStarted(void* task);
105 : void asyncTaskFinished(void* task);
106 : void allAsyncTasksCanceled();
107 :
108 : V8StackTraceId storeCurrentStackTrace(const StringView& description);
109 : void externalAsyncTaskStarted(const V8StackTraceId& parent);
110 : void externalAsyncTaskFinished(const V8StackTraceId& parent);
111 :
112 : uintptr_t storeStackTrace(std::shared_ptr<AsyncStackTrace> stack);
113 :
114 : void muteScriptParsedEvents();
115 : void unmuteScriptParsedEvents();
116 :
117 : V8InspectorImpl* inspector() { return m_inspector; }
118 :
119 : WasmTranslation* wasmTranslation() { return &m_wasmTranslation; }
120 :
121 : void setMaxAsyncTaskStacksForTest(int limit);
122 : void dumpAsyncTaskStacksStateForTest();
123 :
124 : v8_inspector::V8StackTraceId scheduledAsyncCall() {
125 55554 : return m_scheduledAsyncCall;
126 : }
127 :
128 : std::pair<int64_t, int64_t> debuggerIdFor(int contextGroupId);
129 : std::pair<int64_t, int64_t> debuggerIdFor(
130 : const String16& serializedDebuggerId);
131 : std::shared_ptr<AsyncStackTrace> stackTraceFor(int contextGroupId,
132 : const V8StackTraceId& id);
133 :
134 : void reportTermination();
135 :
136 : private:
137 : bool addInternalObject(v8::Local<v8::Context> context,
138 : v8::Local<v8::Object> object,
139 : V8InternalValueType type);
140 :
141 : void clearContinueToLocation();
142 : bool shouldContinueToCurrentLocation();
143 :
144 : static size_t nearHeapLimitCallback(void* data, size_t current_heap_limit,
145 : size_t initial_heap_limit);
146 : static void terminateExecutionCompletedCallback(v8::Isolate* isolate);
147 : void handleProgramBreak(
148 : v8::Local<v8::Context> pausedContext, v8::Local<v8::Value> exception,
149 : const std::vector<v8::debug::BreakpointId>& hitBreakpoints,
150 : v8::debug::ExceptionType exception_type = v8::debug::kException,
151 : bool isUncaught = false);
152 :
153 : enum ScopeTargetKind {
154 : FUNCTION,
155 : GENERATOR,
156 : };
157 : v8::MaybeLocal<v8::Value> getTargetScopes(v8::Local<v8::Context>,
158 : v8::Local<v8::Value>,
159 : ScopeTargetKind);
160 :
161 : v8::MaybeLocal<v8::Value> functionScopes(v8::Local<v8::Context>,
162 : v8::Local<v8::Function>);
163 : v8::MaybeLocal<v8::Value> generatorScopes(v8::Local<v8::Context>,
164 : v8::Local<v8::Value>);
165 : v8::MaybeLocal<v8::Array> collectionsEntries(v8::Local<v8::Context> context,
166 : v8::Local<v8::Value> value);
167 :
168 : void asyncTaskScheduledForStack(const String16& taskName, void* task,
169 : bool recurring);
170 : void asyncTaskCanceledForStack(void* task);
171 : void asyncTaskStartedForStack(void* task);
172 : void asyncTaskFinishedForStack(void* task);
173 :
174 : void asyncTaskCandidateForStepping(void* task, bool isLocal);
175 : void asyncTaskStartedForStepping(void* task);
176 : void asyncTaskFinishedForStepping(void* task);
177 : void asyncTaskCanceledForStepping(void* task);
178 :
179 : // v8::debug::DebugEventListener implementation.
180 : void AsyncEventOccurred(v8::debug::DebugAsyncActionType type, int id,
181 : bool isBlackboxed) override;
182 : void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
183 : bool has_compile_error) override;
184 : void BreakProgramRequested(
185 : v8::Local<v8::Context> paused_context,
186 : const std::vector<v8::debug::BreakpointId>& break_points_hit) override;
187 : void ExceptionThrown(v8::Local<v8::Context> paused_context,
188 : v8::Local<v8::Value> exception,
189 : v8::Local<v8::Value> promise, bool is_uncaught,
190 : v8::debug::ExceptionType exception_type) override;
191 : bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
192 : const v8::debug::Location& start,
193 : const v8::debug::Location& end) override;
194 :
195 : int currentContextGroupId();
196 : bool asyncStepOutOfFunction(int targetContextGroupId, bool onlyAtReturn);
197 :
198 : v8::Isolate* m_isolate;
199 : V8InspectorImpl* m_inspector;
200 : int m_enableCount;
201 :
202 : int m_breakpointsActiveCount = 0;
203 : int m_ignoreScriptParsedEventsCounter;
204 : size_t m_originalHeapLimit = 0;
205 : bool m_scheduledOOMBreak = false;
206 : bool m_scheduledAssertBreak = false;
207 : int m_targetContextGroupId = 0;
208 : int m_pausedContextGroupId = 0;
209 : int m_continueToLocationBreakpointId;
210 : String16 m_continueToLocationTargetCallFrames;
211 : std::unique_ptr<V8StackTraceImpl> m_continueToLocationStack;
212 :
213 : using AsyncTaskToStackTrace =
214 : std::unordered_map<void*, std::weak_ptr<AsyncStackTrace>>;
215 : AsyncTaskToStackTrace m_asyncTaskStacks;
216 : std::unordered_set<void*> m_recurringTasks;
217 :
218 : int m_maxAsyncCallStacks;
219 : int m_maxAsyncCallStackDepth;
220 :
221 : std::vector<void*> m_currentTasks;
222 : std::vector<std::shared_ptr<AsyncStackTrace>> m_currentAsyncParent;
223 : std::vector<V8StackTraceId> m_currentExternalParent;
224 :
225 : void collectOldAsyncStacksIfNeeded();
226 : int m_asyncStacksCount = 0;
227 : // V8Debugger owns all the async stacks, while most of the other references
228 : // are weak, which allows to collect some stacks when there are too many.
229 : std::list<std::shared_ptr<AsyncStackTrace>> m_allAsyncStacks;
230 : std::unordered_map<int, std::weak_ptr<StackFrame>> m_framesCache;
231 :
232 : std::unordered_map<V8DebuggerAgentImpl*, int> m_maxAsyncCallStackDepthMap;
233 : void* m_taskWithScheduledBreak = nullptr;
234 : String16 m_taskWithScheduledBreakDebuggerId;
235 :
236 : bool m_breakRequested = false;
237 :
238 : v8::debug::ExceptionBreakState m_pauseOnExceptionsState;
239 : bool m_pauseOnAsyncCall = false;
240 : v8_inspector::V8StackTraceId m_scheduledAsyncCall;
241 :
242 : using StackTraceIdToStackTrace =
243 : std::unordered_map<uintptr_t, std::weak_ptr<AsyncStackTrace>>;
244 : StackTraceIdToStackTrace m_storedStackTraces;
245 : uintptr_t m_lastStackTraceId = 0;
246 :
247 : std::unordered_map<int, std::pair<int64_t, int64_t>>
248 : m_contextGroupIdToDebuggerId;
249 : std::unordered_map<String16, std::pair<int64_t, int64_t>>
250 : m_serializedDebuggerIdToDebuggerId;
251 :
252 : std::unique_ptr<TerminateExecutionCallback> m_terminateExecutionCallback;
253 :
254 : WasmTranslation m_wasmTranslation;
255 :
256 : DISALLOW_COPY_AND_ASSIGN(V8Debugger);
257 : };
258 :
259 : } // namespace v8_inspector
260 :
261 : #endif // V8_INSPECTOR_V8_DEBUGGER_H_
|