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_V8DEBUGGERAGENTIMPL_H_
6#define V8_INSPECTOR_V8DEBUGGERAGENTIMPL_H_
7
8#include <vector>
9
10#include "src/base/macros.h"
11#include "src/debug/interface-types.h"
12#include "src/inspector/java-script-call-frame.h"
13#include "src/inspector/protocol/Debugger.h"
14#include "src/inspector/protocol/Forward.h"
15
16namespace v8_inspector {
17
18struct ScriptBreakpoint;
19class JavaScriptCallFrame;
20class PromiseTracker;
21class V8Debugger;
22class V8DebuggerScript;
23class V8InspectorImpl;
24class V8InspectorSessionImpl;
25class V8Regex;
26class V8StackTraceImpl;
27
28using protocol::Maybe;
29using protocol::Response;
30
31class 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() override;
46  Response disable() override;
47  Response setBreakpointsActive(bool active) override;
48  Response setSkipAllPauses(bool skip) override;
49  Response setBreakpointByUrl(
50      int lineNumber, Maybe<String16> optionalURL,
51      Maybe<String16> optionalURLRegex, Maybe<int> optionalColumnNumber,
52      Maybe<String16> optionalCondition, String16*,
53      std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
54      override;
55  Response setBreakpoint(
56      std::unique_ptr<protocol::Debugger::Location>,
57      Maybe<String16> optionalCondition, String16*,
58      std::unique_ptr<protocol::Debugger::Location>* actualLocation) override;
59  Response removeBreakpoint(const String16& breakpointId) override;
60  Response continueToLocation(
61      std::unique_ptr<protocol::Debugger::Location>) override;
62  Response searchInContent(
63      const String16& scriptId, const String16& query,
64      Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex,
65      std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*)
66      override;
67  Response getPossibleBreakpoints(
68      std::unique_ptr<protocol::Debugger::Location> start,
69      Maybe<protocol::Debugger::Location> end,
70      std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
71      override;
72  Response setScriptSource(
73      const String16& inScriptId, const String16& inScriptSource,
74      Maybe<bool> dryRun,
75      Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames,
76      Maybe<bool>* optOutStackChanged,
77      Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace,
78      Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override;
79  Response restartFrame(
80      const String16& callFrameId,
81      std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*
82          newCallFrames,
83      Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) override;
84  Response getScriptSource(const String16& scriptId,
85                           String16* scriptSource) override;
86  Response pause() override;
87  Response resume() override;
88  Response stepOver() override;
89  Response stepInto() override;
90  Response stepOut() override;
91  Response setPauseOnExceptions(const String16& pauseState) override;
92  Response evaluateOnCallFrame(
93      const String16& callFrameId, const String16& expression,
94      Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI,
95      Maybe<bool> silent, Maybe<bool> returnByValue,
96      Maybe<bool> generatePreview, Maybe<bool> throwOnSideEffect,
97      std::unique_ptr<protocol::Runtime::RemoteObject>* result,
98      Maybe<protocol::Runtime::ExceptionDetails>*) override;
99  Response setVariableValue(
100      int scopeNumber, const String16& variableName,
101      std::unique_ptr<protocol::Runtime::CallArgument> newValue,
102      const String16& callFrame) override;
103  Response setAsyncCallStackDepth(int depth) override;
104  Response setBlackboxPatterns(
105      std::unique_ptr<protocol::Array<String16>> patterns) override;
106  Response setBlackboxedRanges(
107      const String16& scriptId,
108      std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>>
109          positions) override;
110
111  bool enabled();
112
113  void setBreakpointAt(const String16& scriptId, int lineNumber,
114                       int columnNumber, BreakpointSource,
115                       const String16& condition = String16());
116  void removeBreakpointAt(const String16& scriptId, int lineNumber,
117                          int columnNumber, BreakpointSource);
118  void schedulePauseOnNextStatement(
119      const String16& breakReason,
120      std::unique_ptr<protocol::DictionaryValue> data);
121  void cancelPauseOnNextStatement();
122  void breakProgram(const String16& breakReason,
123                    std::unique_ptr<protocol::DictionaryValue> data);
124  void breakProgramOnException(const String16& breakReason,
125                               std::unique_ptr<protocol::DictionaryValue> data);
126
127  void reset();
128
129  // Interface for V8InspectorImpl
130  void didPause(int contextId, v8::Local<v8::Value> exception,
131                const std::vector<String16>& hitBreakpoints,
132                bool isPromiseRejection, bool isUncaught, bool isOOMBreak);
133  void didContinue();
134  void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success);
135  void willExecuteScript(int scriptId);
136  void didExecuteScript();
137
138  bool isFunctionBlackboxed(const String16& scriptId,
139                            const v8::debug::Location& start,
140                            const v8::debug::Location& end);
141
142  bool skipAllPauses() const { return m_skipAllPauses; }
143
144  v8::Isolate* isolate() { return m_isolate; }
145
146 private:
147  void enableImpl();
148
149  void schedulePauseOnNextStatementIfSteppingInto();
150
151  Response currentCallFrames(
152      std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*);
153  std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace();
154
155  void changeJavaScriptRecursionLevel(int step);
156
157  void setPauseOnExceptionsImpl(int);
158
159  std::unique_ptr<protocol::Debugger::Location> resolveBreakpoint(
160      const String16& breakpointId, const ScriptBreakpoint&, BreakpointSource);
161  void removeBreakpointImpl(const String16& breakpointId);
162  void clearBreakDetails();
163
164  void internalSetAsyncCallStackDepth(int);
165  void increaseCachedSkipStackGeneration();
166
167  Response setBlackboxPattern(const String16& pattern);
168  void resetBlackboxedStateCache();
169
170  bool isPaused() const;
171
172  using ScriptsMap =
173      protocol::HashMap<String16, std::unique_ptr<V8DebuggerScript>>;
174  using BreakpointIdToDebuggerBreakpointIdsMap =
175      protocol::HashMap<String16, std::vector<String16>>;
176  using DebugServerBreakpointToBreakpointIdAndSourceMap =
177      protocol::HashMap<String16, std::pair<String16, BreakpointSource>>;
178  using MuteBreakpoins = protocol::HashMap<String16, std::pair<String16, int>>;
179
180  enum DebuggerStep { NoStep = 0, StepInto, StepOver, StepOut };
181
182  V8InspectorImpl* m_inspector;
183  V8Debugger* m_debugger;
184  V8InspectorSessionImpl* m_session;
185  bool m_enabled;
186  protocol::DictionaryValue* m_state;
187  protocol::Debugger::Frontend m_frontend;
188  v8::Isolate* m_isolate;
189  JavaScriptCallFrames m_pausedCallFrames;
190  ScriptsMap m_scripts;
191  BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds;
192  DebugServerBreakpointToBreakpointIdAndSourceMap m_serverBreakpoints;
193  String16 m_continueToLocationBreakpointId;
194
195  using BreakReason =
196      std::pair<String16, std::unique_ptr<protocol::DictionaryValue>>;
197  std::vector<BreakReason> m_breakReason;
198
199  void pushBreakDetails(
200      const String16& breakReason,
201      std::unique_ptr<protocol::DictionaryValue> breakAuxData);
202  void popBreakDetails();
203
204  DebuggerStep m_scheduledDebuggerStep;
205  bool m_javaScriptPauseScheduled;
206
207  int m_recursionLevelForStepOut;
208  bool m_skipAllPauses = false;
209
210  std::unique_ptr<V8Regex> m_blackboxPattern;
211  protocol::HashMap<String16, std::vector<std::pair<int, int>>>
212      m_blackboxedPositions;
213
214  DISALLOW_COPY_AND_ASSIGN(V8DebuggerAgentImpl);
215};
216
217}  // namespace v8_inspector
218
219#endif  // V8_INSPECTOR_V8DEBUGGERAGENTIMPL_H_
220