Commit 31662cc3 authored by dgozman's avatar dgozman Committed by Commit Bot

[inspector] Make breakpoints active state per-agent

... as opposite to a global per-isolate one.
Also streamlined multiple checks into a single acceptsPause() method.

BUG=chromium:590878

Review-Url: https://codereview.chromium.org/2925903002
Cr-Commit-Position: refs/heads/master@{#45749}
parent 199dc950
...@@ -211,13 +211,10 @@ void V8DebuggerAgentImpl::enableImpl() { ...@@ -211,13 +211,10 @@ void V8DebuggerAgentImpl::enableImpl() {
for (size_t i = 0; i < compiledScripts.size(); i++) for (size_t i = 0; i < compiledScripts.size(); i++)
didParseSource(std::move(compiledScripts[i]), true); didParseSource(std::move(compiledScripts[i]), true);
// FIXME(WK44513): breakpoints activated flag should be synchronized between m_breakpointsActive = true;
// all front-ends m_debugger->setBreakpointsActive(true);
m_debugger->setBreakpointsActivated(true);
} }
bool V8DebuggerAgentImpl::enabled() { return m_enabled; }
Response V8DebuggerAgentImpl::enable() { Response V8DebuggerAgentImpl::enable() {
if (enabled()) return Response::OK(); if (enabled()) return Response::OK();
...@@ -238,6 +235,10 @@ Response V8DebuggerAgentImpl::disable() { ...@@ -238,6 +235,10 @@ Response V8DebuggerAgentImpl::disable() {
m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0);
if (isPaused()) m_debugger->continueProgram(m_session->contextGroupId()); if (isPaused()) m_debugger->continueProgram(m_session->contextGroupId());
if (m_breakpointsActive) {
m_debugger->setBreakpointsActive(false);
m_breakpointsActive = false;
}
m_debugger->disable(); m_debugger->disable();
JavaScriptCallFrames emptyCallFrames; JavaScriptCallFrames emptyCallFrames;
m_pausedCallFrames.swap(emptyCallFrames); m_pausedCallFrames.swap(emptyCallFrames);
...@@ -286,8 +287,9 @@ void V8DebuggerAgentImpl::restore() { ...@@ -286,8 +287,9 @@ void V8DebuggerAgentImpl::restore() {
Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) {
if (!enabled()) return Response::Error(kDebuggerNotEnabled); if (!enabled()) return Response::Error(kDebuggerNotEnabled);
// TODO(dgozman): this state should be per-session, not global per debugger. if (m_breakpointsActive == active) return Response::OK();
m_debugger->setBreakpointsActivated(active); m_breakpointsActive = active;
m_debugger->setBreakpointsActive(active);
if (!active && !m_breakReason.empty()) { if (!active && !m_breakReason.empty()) {
clearBreakDetails(); clearBreakDetails();
m_debugger->setPauseOnNextStatement(false, m_session->contextGroupId()); m_debugger->setPauseOnNextStatement(false, m_session->contextGroupId());
...@@ -528,6 +530,10 @@ bool V8DebuggerAgentImpl::isFunctionBlackboxed(const String16& scriptId, ...@@ -528,6 +530,10 @@ bool V8DebuggerAgentImpl::isFunctionBlackboxed(const String16& scriptId,
std::distance(ranges.begin(), itStartRange) % 2; std::distance(ranges.begin(), itStartRange) % 2;
} }
bool V8DebuggerAgentImpl::acceptsPause(bool isOOMBreak) const {
return enabled() && (isOOMBreak || !m_skipAllPauses);
}
std::unique_ptr<protocol::Debugger::Location> std::unique_ptr<protocol::Debugger::Location>
V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId,
const ScriptBreakpoint& breakpoint, const ScriptBreakpoint& breakpoint,
...@@ -683,7 +689,7 @@ void V8DebuggerAgentImpl::clearBreakDetails() { ...@@ -683,7 +689,7 @@ void V8DebuggerAgentImpl::clearBreakDetails() {
void V8DebuggerAgentImpl::schedulePauseOnNextStatement( void V8DebuggerAgentImpl::schedulePauseOnNextStatement(
const String16& breakReason, const String16& breakReason,
std::unique_ptr<protocol::DictionaryValue> data) { std::unique_ptr<protocol::DictionaryValue> data) {
if (!enabled() || isPaused() || !m_debugger->breakpointsActivated()) return; if (isPaused() || !acceptsPause(false) || !m_breakpointsActive) return;
if (m_breakReason.empty()) { if (m_breakReason.empty()) {
m_debugger->setPauseOnNextStatement(true, m_session->contextGroupId()); m_debugger->setPauseOnNextStatement(true, m_session->contextGroupId());
} }
...@@ -691,7 +697,7 @@ void V8DebuggerAgentImpl::schedulePauseOnNextStatement( ...@@ -691,7 +697,7 @@ void V8DebuggerAgentImpl::schedulePauseOnNextStatement(
} }
void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { void V8DebuggerAgentImpl::cancelPauseOnNextStatement() {
if (!enabled() || isPaused() || !m_debugger->breakpointsActivated()) return; if (isPaused() || !acceptsPause(false) || !m_breakpointsActive) return;
if (m_breakReason.size() == 1) { if (m_breakReason.size() == 1) {
m_debugger->setPauseOnNextStatement(false, m_session->contextGroupId()); m_debugger->setPauseOnNextStatement(false, m_session->contextGroupId());
} }
...@@ -1242,7 +1248,7 @@ void V8DebuggerAgentImpl::didContinue() { ...@@ -1242,7 +1248,7 @@ void V8DebuggerAgentImpl::didContinue() {
void V8DebuggerAgentImpl::breakProgram( void V8DebuggerAgentImpl::breakProgram(
const String16& breakReason, const String16& breakReason,
std::unique_ptr<protocol::DictionaryValue> data) { std::unique_ptr<protocol::DictionaryValue> data) {
if (!enabled() || !m_debugger->canBreakProgram() || m_skipAllPauses) return; if (!enabled() || m_skipAllPauses || !m_debugger->canBreakProgram()) return;
std::vector<BreakReason> currentScheduledReason; std::vector<BreakReason> currentScheduledReason;
currentScheduledReason.swap(m_breakReason); currentScheduledReason.swap(m_breakReason);
pushBreakDetails(breakReason, std::move(data)); pushBreakDetails(breakReason, std::move(data));
......
...@@ -109,7 +109,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend { ...@@ -109,7 +109,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>>
positions) override; positions) override;
bool enabled(); bool enabled() const { return m_enabled; }
void setBreakpointAt(const String16& scriptId, int lineNumber, void setBreakpointAt(const String16& scriptId, int lineNumber,
int columnNumber, BreakpointSource, int columnNumber, BreakpointSource,
...@@ -137,7 +137,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend { ...@@ -137,7 +137,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
const v8::debug::Location& start, const v8::debug::Location& start,
const v8::debug::Location& end); const v8::debug::Location& end);
bool skipAllPauses() const { return m_skipAllPauses; } bool acceptsPause(bool isOOMBreak) const;
v8::Isolate* isolate() { return m_isolate; } v8::Isolate* isolate() { return m_isolate; }
...@@ -194,6 +194,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend { ...@@ -194,6 +194,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
void popBreakDetails(); void popBreakDetails();
bool m_skipAllPauses = false; bool m_skipAllPauses = false;
bool m_breakpointsActive = false;
std::unique_ptr<V8Regex> m_blackboxPattern; std::unique_ptr<V8Regex> m_blackboxPattern;
protocol::HashMap<String16, std::vector<std::pair<int, int>>> protocol::HashMap<String16, std::vector<std::pair<int, int>>>
......
...@@ -161,7 +161,6 @@ V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) ...@@ -161,7 +161,6 @@ V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector)
: m_isolate(isolate), : m_isolate(isolate),
m_inspector(inspector), m_inspector(inspector),
m_enableCount(0), m_enableCount(0),
m_breakpointsActivated(true),
m_ignoreScriptParsedEventsCounter(0), m_ignoreScriptParsedEventsCounter(0),
m_maxAsyncCallStacks(kMaxAsyncTaskStacks), m_maxAsyncCallStacks(kMaxAsyncTaskStacks),
m_maxAsyncCallStackDepth(0), m_maxAsyncCallStackDepth(0),
...@@ -309,13 +308,13 @@ void V8Debugger::clearBreakpoints() { ...@@ -309,13 +308,13 @@ void V8Debugger::clearBreakpoints() {
v8::debug::Call(debuggerContext(), clearBreakpoints).ToLocalChecked(); v8::debug::Call(debuggerContext(), clearBreakpoints).ToLocalChecked();
} }
void V8Debugger::setBreakpointsActivated(bool activated) { void V8Debugger::setBreakpointsActive(bool active) {
if (!enabled()) { if (!enabled()) {
UNREACHABLE(); UNREACHABLE();
return; return;
} }
v8::debug::SetBreakPointsActive(m_isolate, activated); m_breakpointsActiveCount += active ? 1 : -1;
m_breakpointsActivated = activated; v8::debug::SetBreakPointsActive(m_isolate, m_breakpointsActiveCount);
} }
v8::debug::ExceptionBreakState V8Debugger::getPauseOnExceptionsState() { v8::debug::ExceptionBreakState V8Debugger::getPauseOnExceptionsState() {
...@@ -347,14 +346,13 @@ void V8Debugger::setPauseOnNextStatement(bool pause, int targetContextGroupId) { ...@@ -347,14 +346,13 @@ void V8Debugger::setPauseOnNextStatement(bool pause, int targetContextGroupId) {
} }
bool V8Debugger::canBreakProgram() { bool V8Debugger::canBreakProgram() {
if (!m_breakpointsActivated) return false;
return !v8::debug::AllFramesOnStackAreBlackboxed(m_isolate); return !v8::debug::AllFramesOnStackAreBlackboxed(m_isolate);
} }
void V8Debugger::breakProgram(int targetContextGroupId) { void V8Debugger::breakProgram(int targetContextGroupId) {
DCHECK(canBreakProgram());
// Don't allow nested breaks. // Don't allow nested breaks.
if (isPaused()) return; if (isPaused()) return;
if (!canBreakProgram()) return;
DCHECK(targetContextGroupId); DCHECK(targetContextGroupId);
m_targetContextGroupId = targetContextGroupId; m_targetContextGroupId = targetContextGroupId;
v8::debug::BreakRightNow(m_isolate); v8::debug::BreakRightNow(m_isolate);
...@@ -616,15 +614,12 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext, ...@@ -616,15 +614,12 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext,
bool scheduledOOMBreak = m_scheduledOOMBreak; bool scheduledOOMBreak = m_scheduledOOMBreak;
bool scheduledAssertBreak = m_scheduledAssertBreak; bool scheduledAssertBreak = m_scheduledAssertBreak;
auto agentCheck = [&scheduledOOMBreak](V8DebuggerAgentImpl* agent) {
return agent->enabled() && (scheduledOOMBreak || !agent->skipAllPauses());
};
bool hasAgents = false; bool hasAgents = false;
m_inspector->forEachSession( m_inspector->forEachSession(
contextGroupId, contextGroupId,
[&agentCheck, &hasAgents](V8InspectorSessionImpl* session) { [&scheduledOOMBreak, &hasAgents](V8InspectorSessionImpl* session) {
if (agentCheck(session->debuggerAgent())) hasAgents = true; if (session->debuggerAgent()->acceptsPause(scheduledOOMBreak))
hasAgents = true;
}); });
if (!hasAgents) return; if (!hasAgents) return;
...@@ -652,10 +647,10 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext, ...@@ -652,10 +647,10 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext,
m_pausedContextGroupId = contextGroupId; m_pausedContextGroupId = contextGroupId;
m_inspector->forEachSession( m_inspector->forEachSession(
contextGroupId, [&agentCheck, &pausedContext, &exception, &breakpointIds, contextGroupId, [&pausedContext, &exception, &breakpointIds,
&isPromiseRejection, &isUncaught, &scheduledOOMBreak, &isPromiseRejection, &isUncaught, &scheduledOOMBreak,
&scheduledAssertBreak](V8InspectorSessionImpl* session) { &scheduledAssertBreak](V8InspectorSessionImpl* session) {
if (agentCheck(session->debuggerAgent())) { if (session->debuggerAgent()->acceptsPause(scheduledOOMBreak)) {
session->debuggerAgent()->didPause( session->debuggerAgent()->didPause(
InspectedContext::contextId(pausedContext), exception, InspectedContext::contextId(pausedContext), exception,
breakpointIds, isPromiseRejection, isUncaught, scheduledOOMBreak, breakpointIds, isPromiseRejection, isUncaught, scheduledOOMBreak,
......
...@@ -44,8 +44,7 @@ class V8Debugger : public v8::debug::DebugDelegate { ...@@ -44,8 +44,7 @@ class V8Debugger : public v8::debug::DebugDelegate {
String16 setBreakpoint(const ScriptBreakpoint&, int* actualLineNumber, String16 setBreakpoint(const ScriptBreakpoint&, int* actualLineNumber,
int* actualColumnNumber); int* actualColumnNumber);
void removeBreakpoint(const String16& breakpointId); void removeBreakpoint(const String16& breakpointId);
void setBreakpointsActivated(bool); void setBreakpointsActive(bool);
bool breakpointsActivated() const { return m_breakpointsActivated; }
v8::debug::ExceptionBreakState getPauseOnExceptionsState(); v8::debug::ExceptionBreakState getPauseOnExceptionsState();
void setPauseOnExceptionsState(v8::debug::ExceptionBreakState); void setPauseOnExceptionsState(v8::debug::ExceptionBreakState);
...@@ -183,7 +182,7 @@ class V8Debugger : public v8::debug::DebugDelegate { ...@@ -183,7 +182,7 @@ class V8Debugger : public v8::debug::DebugDelegate {
v8::Isolate* m_isolate; v8::Isolate* m_isolate;
V8InspectorImpl* m_inspector; V8InspectorImpl* m_inspector;
int m_enableCount; int m_enableCount;
bool m_breakpointsActivated; int m_breakpointsActiveCount = 0;
v8::Global<v8::Object> m_debuggerScript; v8::Global<v8::Object> m_debuggerScript;
v8::Global<v8::Context> m_debuggerContext; v8::Global<v8::Context> m_debuggerContext;
v8::Local<v8::Object> m_executionState; v8::Local<v8::Object> m_executionState;
......
...@@ -188,3 +188,16 @@ Resuming in 2 ...@@ -188,3 +188,16 @@ Resuming in 2
Resumed in 2 Resumed in 2
Skipping pauses in 2 Skipping pauses in 2
Evaluating common breakpoint in 1 Evaluating common breakpoint in 1
Unskipping pauses in 1
Unskipping pauses in 2
Deactivating breakpoints in 1
Evaluating common breakpoint in 1
Paused in 2:
reason: other
hit breakpoints: test.js:11:0
location: foo@11
data: null
Resuming in 2
Resumed in 2
Deactivating breakpoints in 2
Evaluating common breakpoint in 1
...@@ -143,6 +143,25 @@ function bar() { ...@@ -143,6 +143,25 @@ function bar() {
InspectorTest.log('Evaluating common breakpoint in 1'); InspectorTest.log('Evaluating common breakpoint in 1');
await session1.Protocol.Runtime.evaluate({expression: 'foo();'}); await session1.Protocol.Runtime.evaluate({expression: 'foo();'});
InspectorTest.log('Unskipping pauses in 1');
await session1.Protocol.Debugger.setSkipAllPauses({skip: false});
InspectorTest.log('Unskipping pauses in 2');
await session2.Protocol.Debugger.setSkipAllPauses({skip: false});
InspectorTest.log('Deactivating breakpoints in 1');
await session1.Protocol.Debugger.setBreakpointsActive({active: false});
InspectorTest.log('Evaluating common breakpoint in 1');
session1.Protocol.Runtime.evaluate({expression: 'foo();'});
await waitForPaused(session2, 2);
InspectorTest.log('Resuming in 2');
session2.Protocol.Debugger.resume();
await waitForResumed(session2, 2);
InspectorTest.log('Deactivating breakpoints in 2');
await session2.Protocol.Debugger.setBreakpointsActive({active: false});
InspectorTest.log('Evaluating common breakpoint in 1');
await session1.Protocol.Runtime.evaluate({expression: 'foo();'});
InspectorTest.completeTest(); InspectorTest.completeTest();
function waitForBothPaused() { function waitForBothPaused() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment