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