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 : std::vector<std::unique_ptr<V8DebuggerScript>> getCompiledScripts(
77 : int contextGroupId, V8DebuggerAgentImpl* agent);
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 147159 : WasmTranslation* wasmTranslation() { return &m_wasmTranslation; }
120 :
121 : void setMaxAsyncTaskStacksForTest(int limit);
122 : void dumpAsyncTaskStacksStateForTest();
123 :
124 : v8_inspector::V8StackTraceId scheduledAsyncCall() {
125 55458 : 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 : static void terminateExecutionCompletedCallbackIgnoringData(
148 : v8::Isolate* isolate, void*);
149 : void handleProgramBreak(
150 : v8::Local<v8::Context> pausedContext, v8::Local<v8::Value> exception,
151 : const std::vector<v8::debug::BreakpointId>& hitBreakpoints,
152 : v8::debug::ExceptionType exception_type = v8::debug::kException,
153 : bool isUncaught = false);
154 :
155 : enum ScopeTargetKind {
156 : FUNCTION,
157 : GENERATOR,
158 : };
159 : v8::MaybeLocal<v8::Value> getTargetScopes(v8::Local<v8::Context>,
160 : v8::Local<v8::Value>,
161 : ScopeTargetKind);
162 :
163 : v8::MaybeLocal<v8::Value> functionScopes(v8::Local<v8::Context>,
164 : v8::Local<v8::Function>);
165 : v8::MaybeLocal<v8::Value> generatorScopes(v8::Local<v8::Context>,
166 : v8::Local<v8::Value>);
167 : v8::MaybeLocal<v8::Array> collectionsEntries(v8::Local<v8::Context> context,
168 : v8::Local<v8::Value> value);
169 :
170 : void asyncTaskScheduledForStack(const String16& taskName, void* task,
171 : bool recurring);
172 : void asyncTaskCanceledForStack(void* task);
173 : void asyncTaskStartedForStack(void* task);
174 : void asyncTaskFinishedForStack(void* task);
175 :
176 : void asyncTaskCandidateForStepping(void* task, bool isLocal);
177 : void asyncTaskStartedForStepping(void* task);
178 : void asyncTaskFinishedForStepping(void* task);
179 : void asyncTaskCanceledForStepping(void* task);
180 :
181 : // v8::debug::DebugEventListener implementation.
182 : void AsyncEventOccurred(v8::debug::DebugAsyncActionType type, int id,
183 : bool isBlackboxed) override;
184 : void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
185 : bool has_compile_error) override;
186 : void BreakProgramRequested(
187 : v8::Local<v8::Context> paused_context,
188 : const std::vector<v8::debug::BreakpointId>& break_points_hit) override;
189 : void ExceptionThrown(v8::Local<v8::Context> paused_context,
190 : v8::Local<v8::Value> exception,
191 : v8::Local<v8::Value> promise, bool is_uncaught,
192 : v8::debug::ExceptionType exception_type) override;
193 : bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
194 : const v8::debug::Location& start,
195 : const v8::debug::Location& end) override;
196 :
197 : int currentContextGroupId();
198 : bool asyncStepOutOfFunction(int targetContextGroupId, bool onlyAtReturn);
199 :
200 : v8::Isolate* m_isolate;
201 : V8InspectorImpl* m_inspector;
202 : int m_enableCount;
203 :
204 : int m_breakpointsActiveCount = 0;
205 : int m_ignoreScriptParsedEventsCounter;
206 : size_t m_originalHeapLimit = 0;
207 : bool m_scheduledOOMBreak = false;
208 : bool m_scheduledAssertBreak = false;
209 : int m_targetContextGroupId = 0;
210 : int m_pausedContextGroupId = 0;
211 : int m_continueToLocationBreakpointId;
212 : String16 m_continueToLocationTargetCallFrames;
213 : std::unique_ptr<V8StackTraceImpl> m_continueToLocationStack;
214 :
215 : using AsyncTaskToStackTrace =
216 : std::unordered_map<void*, std::weak_ptr<AsyncStackTrace>>;
217 : AsyncTaskToStackTrace m_asyncTaskStacks;
218 : std::unordered_set<void*> m_recurringTasks;
219 :
220 : int m_maxAsyncCallStacks;
221 : int m_maxAsyncCallStackDepth;
222 :
223 : std::vector<void*> m_currentTasks;
224 : std::vector<std::shared_ptr<AsyncStackTrace>> m_currentAsyncParent;
225 : std::vector<V8StackTraceId> m_currentExternalParent;
226 :
227 : void collectOldAsyncStacksIfNeeded();
228 : int m_asyncStacksCount = 0;
229 : // V8Debugger owns all the async stacks, while most of the other references
230 : // are weak, which allows to collect some stacks when there are too many.
231 : std::list<std::shared_ptr<AsyncStackTrace>> m_allAsyncStacks;
232 : std::unordered_map<int, std::weak_ptr<StackFrame>> m_framesCache;
233 :
234 : std::unordered_map<V8DebuggerAgentImpl*, int> m_maxAsyncCallStackDepthMap;
235 : void* m_taskWithScheduledBreak = nullptr;
236 : String16 m_taskWithScheduledBreakDebuggerId;
237 :
238 : bool m_breakRequested = false;
239 :
240 : v8::debug::ExceptionBreakState m_pauseOnExceptionsState;
241 : bool m_pauseOnAsyncCall = false;
242 : v8_inspector::V8StackTraceId m_scheduledAsyncCall;
243 :
244 : using StackTraceIdToStackTrace =
245 : std::unordered_map<uintptr_t, std::weak_ptr<AsyncStackTrace>>;
246 : StackTraceIdToStackTrace m_storedStackTraces;
247 : uintptr_t m_lastStackTraceId = 0;
248 :
249 : std::unordered_map<int, std::pair<int64_t, int64_t>>
250 : m_contextGroupIdToDebuggerId;
251 : std::unordered_map<String16, std::pair<int64_t, int64_t>>
252 : m_serializedDebuggerIdToDebuggerId;
253 :
254 : std::unique_ptr<TerminateExecutionCallback> m_terminateExecutionCallback;
255 :
256 : WasmTranslation m_wasmTranslation;
257 :
258 : DISALLOW_COPY_AND_ASSIGN(V8Debugger);
259 : };
260 :
261 : } // namespace v8_inspector
262 :
263 : #endif // V8_INSPECTOR_V8_DEBUGGER_H_
|