v8-debugger-agent-impl.h 10.4 KB
Newer Older
1 2 3 4
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_
#define V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_
7

8
#include <deque>
9
#include <memory>
10
#include <unordered_map>
11 12
#include <vector>

13
#include "src/base/enum-set.h"
14
#include "src/base/macros.h"
15
#include "src/debug/debug-interface.h"
16 17 18 19 20 21 22 23 24 25 26 27 28
#include "src/inspector/protocol/Debugger.h"
#include "src/inspector/protocol/Forward.h"

namespace v8_inspector {

struct ScriptBreakpoint;
class V8Debugger;
class V8DebuggerScript;
class V8InspectorImpl;
class V8InspectorSessionImpl;
class V8Regex;

using protocol::Maybe;
29
using protocol::Response;
30 31 32 33 34 35 36 37 38 39 40 41

class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
 public:
  enum BreakpointSource {
    UserBreakpointSource,
    DebugCommandBreakpointSource,
    MonitorCommandBreakpointSource
  };

  V8DebuggerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*,
                      protocol::DictionaryValue* state);
  ~V8DebuggerAgentImpl() override;
42 43
  V8DebuggerAgentImpl(const V8DebuggerAgentImpl&) = delete;
  V8DebuggerAgentImpl& operator=(const V8DebuggerAgentImpl&) = delete;
44 45 46
  void restore();

  // Part of the protocol.
47 48
  Response enable(Maybe<double> maxScriptsCacheSize,
                  String16* outDebuggerId) override;
49 50 51 52 53
  Response disable() override;
  Response setBreakpointsActive(bool active) override;
  Response setSkipAllPauses(bool skip) override;
  Response setBreakpointByUrl(
      int lineNumber, Maybe<String16> optionalURL,
54 55 56
      Maybe<String16> optionalURLRegex, Maybe<String16> optionalScriptHash,
      Maybe<int> optionalColumnNumber, Maybe<String16> optionalCondition,
      String16*,
57 58
      std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
      override;
59 60 61
  Response setBreakpoint(
      std::unique_ptr<protocol::Debugger::Location>,
      Maybe<String16> optionalCondition, String16*,
62
      std::unique_ptr<protocol::Debugger::Location>* actualLocation) override;
63 64 65
  Response setBreakpointOnFunctionCall(const String16& functionObjectId,
                                       Maybe<String16> optionalCondition,
                                       String16* outBreakpointId) override;
66 67
  Response setInstrumentationBreakpoint(const String16& instrumentation,
                                        String16* outBreakpointId) override;
68
  Response removeBreakpoint(const String16& breakpointId) override;
69 70
  Response continueToLocation(std::unique_ptr<protocol::Debugger::Location>,
                              Maybe<String16> targetCallFrames) override;
71 72 73
  Response getStackTrace(
      std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId,
      std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) override;
74 75 76
  Response searchInContent(
      const String16& scriptId, const String16& query,
      Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex,
77 78
      std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*)
      override;
79 80
  Response getPossibleBreakpoints(
      std::unique_ptr<protocol::Debugger::Location> start,
81
      Maybe<protocol::Debugger::Location> end, Maybe<bool> restrictToFunction,
82 83
      std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>*
          locations) override;
84 85 86
  Response setScriptSource(
      const String16& inScriptId, const String16& inScriptSource,
      Maybe<bool> dryRun,
87 88 89
      Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames,
      Maybe<bool>* optOutStackChanged,
      Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace,
90
      Maybe<protocol::Runtime::StackTraceId>* optOutAsyncStackTraceId,
91
      Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override;
92
  Response restartFrame(
93
      const String16& callFrameId, Maybe<String16> mode,
94 95
      std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*
          newCallFrames,
96 97
      Maybe<protocol::Runtime::StackTrace>* asyncStackTrace,
      Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId) override;
98 99
  Response getScriptSource(const String16& scriptId, String16* scriptSource,
                           Maybe<protocol::Binary>* bytecode) override;
100 101
  Response getWasmBytecode(const String16& scriptId,
                           protocol::Binary* bytecode) override;
102
  Response pause() override;
103
  Response resume(Maybe<bool> terminateOnResume) override;
104 105 106 107 108
  Response stepOver(Maybe<protocol::Array<protocol::Debugger::LocationRange>>
                        inSkipList) override;
  Response stepInto(Maybe<bool> inBreakOnAsyncCall,
                    Maybe<protocol::Array<protocol::Debugger::LocationRange>>
                        inSkipList) override;
109
  Response stepOut() override;
110 111
  Response pauseOnAsyncCall(std::unique_ptr<protocol::Runtime::StackTraceId>
                                inParentStackTraceId) override;
112 113 114 115 116
  Response setPauseOnExceptions(const String16& pauseState) override;
  Response evaluateOnCallFrame(
      const String16& callFrameId, const String16& expression,
      Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI,
      Maybe<bool> silent, Maybe<bool> returnByValue,
117
      Maybe<bool> generatePreview, Maybe<bool> throwOnSideEffect,
118
      Maybe<double> timeout,
119 120
      std::unique_ptr<protocol::Runtime::RemoteObject>* result,
      Maybe<protocol::Runtime::ExceptionDetails>*) override;
121 122
  Response setVariableValue(
      int scopeNumber, const String16& variableName,
123 124
      std::unique_ptr<protocol::Runtime::CallArgument> newValue,
      const String16& callFrame) override;
125 126
  Response setReturnValue(
      std::unique_ptr<protocol::Runtime::CallArgument> newValue) override;
127 128
  Response setAsyncCallStackDepth(int depth) override;
  Response setBlackboxPatterns(
129
      std::unique_ptr<protocol::Array<String16>> patterns) override;
130 131
  Response setBlackboxedRanges(
      const String16& scriptId,
132 133 134
      std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>>
          positions) override;

135
  bool enabled() const { return m_enabled; }
136

137 138 139 140 141
  void setBreakpointFor(v8::Local<v8::Function> function,
                        v8::Local<v8::String> condition,
                        BreakpointSource source);
  void removeBreakpointFor(v8::Local<v8::Function> function,
                           BreakpointSource source);
142 143 144 145 146 147 148 149 150 151
  void schedulePauseOnNextStatement(
      const String16& breakReason,
      std::unique_ptr<protocol::DictionaryValue> data);
  void cancelPauseOnNextStatement();
  void breakProgram(const String16& breakReason,
                    std::unique_ptr<protocol::DictionaryValue> data);

  void reset();

  // Interface for V8InspectorImpl
152 153
  void didPauseOnInstrumentation(v8::debug::BreakpointId instrumentationId);

154
  void didPause(int contextId, v8::Local<v8::Value> exception,
155
                const std::vector<v8::debug::BreakpointId>& hitBreakpoints,
156
                v8::debug::ExceptionType exceptionType, bool isUncaught,
157
                v8::debug::BreakReasons breakReasons);
158 159 160
  void didContinue();
  void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success);

161 162 163
  bool isFunctionBlackboxed(const String16& scriptId,
                            const v8::debug::Location& start,
                            const v8::debug::Location& end);
164
  bool shouldBeSkipped(const String16& scriptId, int line, int column);
165

166
  bool acceptsPause(bool isOOMBreak) const;
167

168 169
  void ScriptCollected(const V8DebuggerScript* script);

170 171
  v8::Isolate* isolate() { return m_isolate; }

172
  void clearBreakDetails();
173

174
 private:
175
  void enableImpl();
176

177 178
  Response currentCallFrames(
      std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*);
179
  std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace();
180
  std::unique_ptr<protocol::Runtime::StackTraceId> currentExternalStackTrace();
181

182
  void setPauseOnExceptionsImpl(int);
183

184 185 186
  std::unique_ptr<protocol::Debugger::Location> setBreakpointImpl(
      const String16& breakpointId, const String16& scriptId,
      const String16& condition, int lineNumber, int columnNumber);
187 188 189
  void setBreakpointImpl(const String16& breakpointId,
                         v8::Local<v8::Function> function,
                         v8::Local<v8::String> condition);
190 191
  void removeBreakpointImpl(const String16& breakpointId,
                            const std::vector<V8DebuggerScript*>& scripts);
192 193 194 195

  void internalSetAsyncCallStackDepth(int);
  void increaseCachedSkipStackGeneration();

196
  Response setBlackboxPattern(const String16& pattern);
197
  void resetBlackboxedStateCache();
198

199 200
  bool isPaused() const;

201 202
  void setScriptInstrumentationBreakpointIfNeeded(V8DebuggerScript* script);

203 204 205
  Response processSkipList(
      protocol::Array<protocol::Debugger::LocationRange>* skipList);

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 214 215 216 217 218 219 220 221

  V8InspectorImpl* m_inspector;
  V8Debugger* m_debugger;
  V8InspectorSessionImpl* m_session;
  bool m_enabled;
  protocol::DictionaryValue* m_state;
  protocol::Debugger::Frontend m_frontend;
  v8::Isolate* m_isolate;
  ScriptsMap m_scripts;
  BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds;
222
  DebuggerBreakpointIdToBreakpointIdMap m_debuggerBreakpointIdToBreakpointId;
223 224 225
  std::unordered_map<v8::debug::BreakpointId,
                     std::unique_ptr<protocol::DictionaryValue>>
      m_breakpointsOnScriptRun;
226

227 228
  size_t m_maxScriptCacheSize = 0;
  size_t m_cachedScriptSize = 0;
229 230 231 232 233 234 235 236 237 238
  struct CachedScript {
    String16 scriptId;
    String16 source;
    std::vector<uint8_t> bytecode;

    size_t size() const {
      return source.length() * sizeof(UChar) + bytecode.size();
    }
  };
  std::deque<CachedScript> m_cachedScripts;
239

240 241 242 243 244 245 246 247 248
  using BreakReason =
      std::pair<String16, std::unique_ptr<protocol::DictionaryValue>>;
  std::vector<BreakReason> m_breakReason;

  void pushBreakDetails(
      const String16& breakReason,
      std::unique_ptr<protocol::DictionaryValue> breakAuxData);
  void popBreakDetails();

249
  bool m_skipAllPauses = false;
250
  bool m_breakpointsActive = false;
251 252

  std::unique_ptr<V8Regex> m_blackboxPattern;
253
  std::unordered_map<String16, std::vector<std::pair<int, int>>>
254
      m_blackboxedPositions;
255
  std::unordered_map<String16, std::vector<std::pair<int, int>>> m_skipList;
256 257 258 259
};

}  // namespace v8_inspector

260
#endif  // V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_