• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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_AGENT_IMPL_H_
6 #define V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_
7 
8 #include <deque>
9 #include <memory>
10 #include <unordered_map>
11 #include <vector>
12 
13 #include "src/base/macros.h"
14 #include "src/debug/debug-interface.h"
15 #include "src/debug/interface-types.h"
16 #include "src/inspector/protocol/Debugger.h"
17 #include "src/inspector/protocol/Forward.h"
18 
19 namespace v8_inspector {
20 
21 struct ScriptBreakpoint;
22 class V8Debugger;
23 class V8DebuggerScript;
24 class V8InspectorImpl;
25 class V8InspectorSessionImpl;
26 class V8Regex;
27 
28 using protocol::Maybe;
29 using protocol::Response;
30 
31 class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
32  public:
33   enum BreakpointSource {
34     UserBreakpointSource,
35     DebugCommandBreakpointSource,
36     MonitorCommandBreakpointSource
37   };
38 
39   V8DebuggerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*,
40                       protocol::DictionaryValue* state);
41   ~V8DebuggerAgentImpl() override;
42   void restore();
43 
44   // Part of the protocol.
45   Response enable(Maybe<double> maxScriptsCacheSize,
46                   String16* outDebuggerId) override;
47   Response disable() override;
48   Response setBreakpointsActive(bool active) override;
49   Response setSkipAllPauses(bool skip) override;
50   Response setBreakpointByUrl(
51       int lineNumber, Maybe<String16> optionalURL,
52       Maybe<String16> optionalURLRegex, Maybe<String16> optionalScriptHash,
53       Maybe<int> optionalColumnNumber, Maybe<String16> optionalCondition,
54       String16*,
55       std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
56       override;
57   Response setBreakpoint(
58       std::unique_ptr<protocol::Debugger::Location>,
59       Maybe<String16> optionalCondition, String16*,
60       std::unique_ptr<protocol::Debugger::Location>* actualLocation) override;
61   Response setBreakpointOnFunctionCall(const String16& functionObjectId,
62                                        Maybe<String16> optionalCondition,
63                                        String16* outBreakpointId) override;
64   Response setInstrumentationBreakpoint(const String16& instrumentation,
65                                         String16* outBreakpointId) override;
66   Response removeBreakpoint(const String16& breakpointId) override;
67   Response continueToLocation(std::unique_ptr<protocol::Debugger::Location>,
68                               Maybe<String16> targetCallFrames) override;
69   Response getStackTrace(
70       std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId,
71       std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) override;
72   Response searchInContent(
73       const String16& scriptId, const String16& query,
74       Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex,
75       std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*)
76       override;
77   Response getPossibleBreakpoints(
78       std::unique_ptr<protocol::Debugger::Location> start,
79       Maybe<protocol::Debugger::Location> end, Maybe<bool> restrictToFunction,
80       std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>*
81           locations) override;
82   Response setScriptSource(
83       const String16& inScriptId, const String16& inScriptSource,
84       Maybe<bool> dryRun,
85       Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames,
86       Maybe<bool>* optOutStackChanged,
87       Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace,
88       Maybe<protocol::Runtime::StackTraceId>* optOutAsyncStackTraceId,
89       Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override;
90   Response restartFrame(
91       const String16& callFrameId,
92       std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*
93           newCallFrames,
94       Maybe<protocol::Runtime::StackTrace>* asyncStackTrace,
95       Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId) override;
96   Response getScriptSource(const String16& scriptId, String16* scriptSource,
97                            Maybe<protocol::Binary>* bytecode) override;
98   Response getWasmBytecode(const String16& scriptId,
99                            protocol::Binary* bytecode) override;
100   Response pause() override;
101   Response resume(Maybe<bool> terminateOnResume) override;
102   Response stepOver(Maybe<protocol::Array<protocol::Debugger::LocationRange>>
103                         inSkipList) override;
104   Response stepInto(Maybe<bool> inBreakOnAsyncCall,
105                     Maybe<protocol::Array<protocol::Debugger::LocationRange>>
106                         inSkipList) override;
107   Response stepOut() override;
108   Response pauseOnAsyncCall(std::unique_ptr<protocol::Runtime::StackTraceId>
109                                 inParentStackTraceId) override;
110   Response setPauseOnExceptions(const String16& pauseState) override;
111   Response evaluateOnCallFrame(
112       const String16& callFrameId, const String16& expression,
113       Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI,
114       Maybe<bool> silent, Maybe<bool> returnByValue,
115       Maybe<bool> generatePreview, Maybe<bool> throwOnSideEffect,
116       Maybe<double> timeout,
117       std::unique_ptr<protocol::Runtime::RemoteObject>* result,
118       Maybe<protocol::Runtime::ExceptionDetails>*) override;
119   Response executeWasmEvaluator(
120       const String16& callFrameId, const protocol::Binary& evaluator,
121       Maybe<double> timeout,
122       std::unique_ptr<protocol::Runtime::RemoteObject>* result,
123       Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) override;
124   Response setVariableValue(
125       int scopeNumber, const String16& variableName,
126       std::unique_ptr<protocol::Runtime::CallArgument> newValue,
127       const String16& callFrame) override;
128   Response setReturnValue(
129       std::unique_ptr<protocol::Runtime::CallArgument> newValue) override;
130   Response setAsyncCallStackDepth(int depth) override;
131   Response setBlackboxPatterns(
132       std::unique_ptr<protocol::Array<String16>> patterns) override;
133   Response setBlackboxedRanges(
134       const String16& scriptId,
135       std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>>
136           positions) override;
137 
enabled()138   bool enabled() const { return m_enabled; }
139 
140   void setBreakpointFor(v8::Local<v8::Function> function,
141                         v8::Local<v8::String> condition,
142                         BreakpointSource source);
143   void removeBreakpointFor(v8::Local<v8::Function> function,
144                            BreakpointSource source);
145   void schedulePauseOnNextStatement(
146       const String16& breakReason,
147       std::unique_ptr<protocol::DictionaryValue> data);
148   void cancelPauseOnNextStatement();
149   void breakProgram(const String16& breakReason,
150                     std::unique_ptr<protocol::DictionaryValue> data);
151 
152   void reset();
153 
154   // Interface for V8InspectorImpl
155   void didPause(int contextId, v8::Local<v8::Value> exception,
156                 const std::vector<v8::debug::BreakpointId>& hitBreakpoints,
157                 v8::debug::ExceptionType exceptionType, bool isUncaught,
158                 bool isOOMBreak, bool isAssert);
159   void didContinue();
160   void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success);
161 
162   bool isFunctionBlackboxed(const String16& scriptId,
163                             const v8::debug::Location& start,
164                             const v8::debug::Location& end);
165   bool shouldBeSkipped(const String16& scriptId, int line, int column);
166 
167   bool acceptsPause(bool isOOMBreak) const;
168 
169   void ScriptCollected(const V8DebuggerScript* script);
170 
isolate()171   v8::Isolate* isolate() { return m_isolate; }
172 
173  private:
174   void enableImpl();
175 
176   Response currentCallFrames(
177       std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*);
178   std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace();
179   std::unique_ptr<protocol::Runtime::StackTraceId> currentExternalStackTrace();
180 
181   void setPauseOnExceptionsImpl(int);
182 
183   std::unique_ptr<protocol::Debugger::Location> setBreakpointImpl(
184       const String16& breakpointId, const String16& scriptId,
185       const String16& condition, int lineNumber, int columnNumber);
186   void setBreakpointImpl(const String16& breakpointId,
187                          v8::Local<v8::Function> function,
188                          v8::Local<v8::String> condition);
189   void removeBreakpointImpl(const String16& breakpointId,
190                             const std::vector<V8DebuggerScript*>& scripts);
191   void clearBreakDetails();
192 
193   void internalSetAsyncCallStackDepth(int);
194   void increaseCachedSkipStackGeneration();
195 
196   Response setBlackboxPattern(const String16& pattern);
197   void resetBlackboxedStateCache();
198 
199   bool isPaused() const;
200 
201   void setScriptInstrumentationBreakpointIfNeeded(V8DebuggerScript* script);
202 
203   Response processSkipList(
204       protocol::Array<protocol::Debugger::LocationRange>* skipList);
205 
206   using ScriptsMap =
207       std::unordered_map<String16, std::unique_ptr<V8DebuggerScript>>;
208   using BreakpointIdToDebuggerBreakpointIdsMap =
209       std::unordered_map<String16, std::vector<v8::debug::BreakpointId>>;
210   using DebuggerBreakpointIdToBreakpointIdMap =
211       std::unordered_map<v8::debug::BreakpointId, String16>;
212 
213   V8InspectorImpl* m_inspector;
214   V8Debugger* m_debugger;
215   V8InspectorSessionImpl* m_session;
216   bool m_enabled;
217   protocol::DictionaryValue* m_state;
218   protocol::Debugger::Frontend m_frontend;
219   v8::Isolate* m_isolate;
220   ScriptsMap m_scripts;
221   BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds;
222   DebuggerBreakpointIdToBreakpointIdMap m_debuggerBreakpointIdToBreakpointId;
223   std::unordered_map<v8::debug::BreakpointId,
224                      std::unique_ptr<protocol::DictionaryValue>>
225       m_breakpointsOnScriptRun;
226 
227   size_t m_maxScriptCacheSize = 0;
228   size_t m_cachedScriptSize = 0;
229   std::deque<String16> m_cachedScriptIds;
230 
231   using BreakReason =
232       std::pair<String16, std::unique_ptr<protocol::DictionaryValue>>;
233   std::vector<BreakReason> m_breakReason;
234 
235   void pushBreakDetails(
236       const String16& breakReason,
237       std::unique_ptr<protocol::DictionaryValue> breakAuxData);
238   void popBreakDetails();
239 
240   bool m_skipAllPauses = false;
241   bool m_breakpointsActive = false;
242 
243   std::unique_ptr<V8Regex> m_blackboxPattern;
244   std::unordered_map<String16, std::vector<std::pair<int, int>>>
245       m_blackboxedPositions;
246   std::unordered_map<String16, std::vector<std::pair<int, int>>> m_skipList;
247 
248   DISALLOW_COPY_AND_ASSIGN(V8DebuggerAgentImpl);
249 };
250 
251 }  // namespace v8_inspector
252 
253 #endif  // V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_
254