blob: c32e6e28899e7d0efba75f7bf98907014e085790 [file] [log] [blame]
// 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.
#ifndef V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_
#define V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_
#include <deque>
#include <memory>
#include <unordered_map>
#include <vector>
#include "src/base/macros.h"
#include "src/debug/debug-interface.h"
#include "src/debug/interface-types.h"
#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;
using protocol::Response;
class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
public:
enum BreakpointSource {
UserBreakpointSource,
DebugCommandBreakpointSource,
MonitorCommandBreakpointSource
};
V8DebuggerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*,
protocol::DictionaryValue* state);
~V8DebuggerAgentImpl() override;
V8DebuggerAgentImpl(const V8DebuggerAgentImpl&) = delete;
V8DebuggerAgentImpl& operator=(const V8DebuggerAgentImpl&) = delete;
void restore();
// Part of the protocol.
Response enable(Maybe<double> maxScriptsCacheSize,
String16* outDebuggerId) override;
Response disable() override;
Response setBreakpointsActive(bool active) override;
Response setSkipAllPauses(bool skip) override;
Response setBreakpointByUrl(
int lineNumber, Maybe<String16> optionalURL,
Maybe<String16> optionalURLRegex, Maybe<String16> optionalScriptHash,
Maybe<int> optionalColumnNumber, Maybe<String16> optionalCondition,
String16*,
std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
override;
Response setBreakpoint(
std::unique_ptr<protocol::Debugger::Location>,
Maybe<String16> optionalCondition, String16*,
std::unique_ptr<protocol::Debugger::Location>* actualLocation) override;
Response setBreakpointOnFunctionCall(const String16& functionObjectId,
Maybe<String16> optionalCondition,
String16* outBreakpointId) override;
Response setInstrumentationBreakpoint(const String16& instrumentation,
String16* outBreakpointId) override;
Response removeBreakpoint(const String16& breakpointId) override;
Response continueToLocation(std::unique_ptr<protocol::Debugger::Location>,
Maybe<String16> targetCallFrames) override;
Response getStackTrace(
std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId,
std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) override;
Response searchInContent(
const String16& scriptId, const String16& query,
Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex,
std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*)
override;
Response getPossibleBreakpoints(
std::unique_ptr<protocol::Debugger::Location> start,
Maybe<protocol::Debugger::Location> end, Maybe<bool> restrictToFunction,
std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>*
locations) override;
Response setScriptSource(
const String16& inScriptId, const String16& inScriptSource,
Maybe<bool> dryRun,
Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames,
Maybe<bool>* optOutStackChanged,
Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace,
Maybe<protocol::Runtime::StackTraceId>* optOutAsyncStackTraceId,
Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override;
Response restartFrame(
const String16& callFrameId,
std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*
newCallFrames,
Maybe<protocol::Runtime::StackTrace>* asyncStackTrace,
Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId) override;
Response getScriptSource(const String16& scriptId, String16* scriptSource,
Maybe<protocol::Binary>* bytecode) override;
Response getWasmBytecode(const String16& scriptId,
protocol::Binary* bytecode) override;
Response pause() override;
Response resume(Maybe<bool> terminateOnResume) override;
Response stepOver(Maybe<protocol::Array<protocol::Debugger::LocationRange>>
inSkipList) override;
Response stepInto(Maybe<bool> inBreakOnAsyncCall,
Maybe<protocol::Array<protocol::Debugger::LocationRange>>
inSkipList) override;
Response stepOut() override;
Response pauseOnAsyncCall(std::unique_ptr<protocol::Runtime::StackTraceId>
inParentStackTraceId) override;
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,
Maybe<bool> generatePreview, Maybe<bool> throwOnSideEffect,
Maybe<double> timeout,
std::unique_ptr<protocol::Runtime::RemoteObject>* result,
Maybe<protocol::Runtime::ExceptionDetails>*) override;
Response executeWasmEvaluator(
const String16& callFrameId, const protocol::Binary& evaluator,
Maybe<double> timeout,
std::unique_ptr<protocol::Runtime::RemoteObject>* result,
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) override;
Response setVariableValue(
int scopeNumber, const String16& variableName,
std::unique_ptr<protocol::Runtime::CallArgument> newValue,
const String16& callFrame) override;
Response setReturnValue(
std::unique_ptr<protocol::Runtime::CallArgument> newValue) override;
Response setAsyncCallStackDepth(int depth) override;
Response setBlackboxPatterns(
std::unique_ptr<protocol::Array<String16>> patterns) override;
Response setBlackboxedRanges(
const String16& scriptId,
std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>>
positions) override;
bool enabled() const { return m_enabled; }
void setBreakpointFor(v8::Local<v8::Function> function,
v8::Local<v8::String> condition,
BreakpointSource source);
void removeBreakpointFor(v8::Local<v8::Function> function,
BreakpointSource source);
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
void didPause(int contextId, v8::Local<v8::Value> exception,
const std::vector<v8::debug::BreakpointId>& hitBreakpoints,
v8::debug::ExceptionType exceptionType, bool isUncaught,
bool isOOMBreak, bool isAssert);
void didContinue();
void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success);
bool isFunctionBlackboxed(const String16& scriptId,
const v8::debug::Location& start,
const v8::debug::Location& end);
bool shouldBeSkipped(const String16& scriptId, int line, int column);
bool acceptsPause(bool isOOMBreak) const;
void ScriptCollected(const V8DebuggerScript* script);
v8::Isolate* isolate() { return m_isolate; }
private:
void enableImpl();
Response currentCallFrames(
std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*);
std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace();
std::unique_ptr<protocol::Runtime::StackTraceId> currentExternalStackTrace();
void setPauseOnExceptionsImpl(int);
std::unique_ptr<protocol::Debugger::Location> setBreakpointImpl(
const String16& breakpointId, const String16& scriptId,
const String16& condition, int lineNumber, int columnNumber);
void setBreakpointImpl(const String16& breakpointId,
v8::Local<v8::Function> function,
v8::Local<v8::String> condition);
void removeBreakpointImpl(const String16& breakpointId,
const std::vector<V8DebuggerScript*>& scripts);
void clearBreakDetails();
void internalSetAsyncCallStackDepth(int);
void increaseCachedSkipStackGeneration();
Response setBlackboxPattern(const String16& pattern);
void resetBlackboxedStateCache();
bool isPaused() const;
void setScriptInstrumentationBreakpointIfNeeded(V8DebuggerScript* script);
Response processSkipList(
protocol::Array<protocol::Debugger::LocationRange>* skipList);
using ScriptsMap =
std::unordered_map<String16, std::unique_ptr<V8DebuggerScript>>;
using BreakpointIdToDebuggerBreakpointIdsMap =
std::unordered_map<String16, std::vector<v8::debug::BreakpointId>>;
using DebuggerBreakpointIdToBreakpointIdMap =
std::unordered_map<v8::debug::BreakpointId, String16>;
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;
DebuggerBreakpointIdToBreakpointIdMap m_debuggerBreakpointIdToBreakpointId;
std::unordered_map<v8::debug::BreakpointId,
std::unique_ptr<protocol::DictionaryValue>>
m_breakpointsOnScriptRun;
size_t m_maxScriptCacheSize = 0;
size_t m_cachedScriptSize = 0;
std::deque<String16> m_cachedScriptIds;
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();
bool m_skipAllPauses = false;
bool m_breakpointsActive = false;
std::unique_ptr<V8Regex> m_blackboxPattern;
std::unordered_map<String16, std::vector<std::pair<int, int>>>
m_blackboxedPositions;
std::unordered_map<String16, std::vector<std::pair<int, int>>> m_skipList;
};
} // namespace v8_inspector
#endif // V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_