Chromium Code Reviews| Index: src/inspector/v8-debugger-agent-impl.cc |
| diff --git a/src/inspector/v8-debugger-agent-impl.cc b/src/inspector/v8-debugger-agent-impl.cc |
| index 09c7b5842be7cc5b9ce57929f8603e6f46c30f3e..7884f87c3835e209bef5056e2485e1a7d77c3ebc 100644 |
| --- a/src/inspector/v8-debugger-agent-impl.cc |
| +++ b/src/inspector/v8-debugger-agent-impl.cc |
| @@ -54,7 +54,6 @@ static const char skipAllPauses[] = "skipAllPauses"; |
| } // namespace DebuggerAgentState |
| -static const int kMaxSkipStepFrameCount = 128; |
| static const char kBacktraceObjectGroup[] = "backtrace"; |
| static const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; |
| static const char kDebuggerNotPaused[] = |
| @@ -134,13 +133,8 @@ V8DebuggerAgentImpl::V8DebuggerAgentImpl( |
| m_isolate(m_inspector->isolate()), |
| m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other), |
| m_scheduledDebuggerStep(NoStep), |
| - m_skipNextDebuggerStepOut(false), |
| m_javaScriptPauseScheduled(false), |
| - m_steppingFromFramework(false), |
| - m_pausingOnNativeEvent(false), |
| - m_skippedStepFrameCount(0), |
| m_recursionLevelForStepOut(0), |
| - m_recursionLevelForStepFrame(0), |
| m_skipAllPauses(false) { |
| clearBreakDetails(); |
| } |
| @@ -190,21 +184,17 @@ Response V8DebuggerAgentImpl::disable() { |
| m_pausedContext.Reset(); |
| JavaScriptCallFrames emptyCallFrames; |
| m_pausedCallFrames.swap(emptyCallFrames); |
| - m_scripts.clear(); |
| m_blackboxedPositions.clear(); |
| + m_blackboxPattern.reset(); |
| + resetBlackboxedStateCache(); |
| + m_scripts.clear(); |
| m_breakpointIdToDebuggerBreakpointIds.clear(); |
| m_debugger->setAsyncCallStackDepth(this, 0); |
| m_continueToLocationBreakpointId = String16(); |
| clearBreakDetails(); |
| m_scheduledDebuggerStep = NoStep; |
| - m_skipNextDebuggerStepOut = false; |
| m_javaScriptPauseScheduled = false; |
| - m_steppingFromFramework = false; |
| - m_pausingOnNativeEvent = false; |
| - m_skippedStepFrameCount = 0; |
| - m_recursionLevelForStepFrame = 0; |
| m_skipAllPauses = false; |
| - m_blackboxPattern = nullptr; |
| m_state->remove(DebuggerAgentState::blackboxPattern); |
| m_enabled = false; |
| m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); |
| @@ -434,28 +424,10 @@ Response V8DebuggerAgentImpl::continueToLocation( |
| return resume(); |
| } |
| -bool V8DebuggerAgentImpl::isCurrentCallStackEmptyOrBlackboxed() { |
| - DCHECK(enabled()); |
| - JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(); |
| - for (size_t index = 0; index < callFrames.size(); ++index) { |
| - if (!isCallFrameWithUnknownScriptOrBlackboxed(callFrames[index].get())) |
| - return false; |
| - } |
| - return true; |
| -} |
| - |
| -bool V8DebuggerAgentImpl::isTopPausedCallFrameBlackboxed() { |
| - DCHECK(enabled()); |
| - JavaScriptCallFrame* frame = |
| - m_pausedCallFrames.size() ? m_pausedCallFrames[0].get() : nullptr; |
| - return isCallFrameWithUnknownScriptOrBlackboxed(frame); |
| -} |
| - |
| -bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed( |
| - JavaScriptCallFrame* frame) { |
| - if (!frame) return true; |
| - ScriptsMap::iterator it = |
| - m_scripts.find(String16::fromInteger(frame->sourceID())); |
| +bool V8DebuggerAgentImpl::isBlackboxed(const String16& scriptId, |
| + const v8::debug::Location& start, |
| + const v8::debug::Location& end) { |
| + ScriptsMap::iterator it = m_scripts.find(scriptId); |
| if (it == m_scripts.end()) { |
| // Unknown scripts are blackboxed. |
| return true; |
| @@ -466,48 +438,24 @@ bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed( |
| m_blackboxPattern->match(scriptSourceURL) != -1) |
| return true; |
| } |
| - auto itBlackboxedPositions = |
| - m_blackboxedPositions.find(String16::fromInteger(frame->sourceID())); |
| + auto itBlackboxedPositions = m_blackboxedPositions.find(scriptId); |
| if (itBlackboxedPositions == m_blackboxedPositions.end()) return false; |
| const std::vector<std::pair<int, int>>& ranges = |
| itBlackboxedPositions->second; |
| - auto itRange = std::lower_bound( |
| + auto itStartRange = std::lower_bound( |
| ranges.begin(), ranges.end(), |
| - std::make_pair(frame->line(), frame->column()), positionComparator); |
| + std::make_pair(start.GetLineNumber(), start.GetColumnNumber()), |
| + positionComparator); |
| + auto itEndRange = std::lower_bound( |
| + itStartRange, ranges.end(), |
| + std::make_pair(end.GetLineNumber(), end.GetColumnNumber()), |
| + positionComparator); |
| // Ranges array contains positions in script where blackbox state is changed. |
| // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is |
| // blackboxed... |
| - return std::distance(ranges.begin(), itRange) % 2; |
| -} |
| - |
| -V8DebuggerAgentImpl::SkipPauseRequest |
| -V8DebuggerAgentImpl::shouldSkipExceptionPause( |
| - JavaScriptCallFrame* topCallFrame) { |
| - if (m_steppingFromFramework) return RequestNoSkip; |
| - if (isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) |
| - return RequestContinue; |
| - return RequestNoSkip; |
| -} |
| - |
| -V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipStepPause( |
| - JavaScriptCallFrame* topCallFrame) { |
| - if (m_steppingFromFramework) return RequestNoSkip; |
| - |
| - if (m_skipNextDebuggerStepOut) { |
| - m_skipNextDebuggerStepOut = false; |
| - if (m_scheduledDebuggerStep == StepOut) return RequestStepOut; |
| - } |
| - |
| - if (!isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) |
| - return RequestNoSkip; |
| - |
| - if (m_skippedStepFrameCount >= kMaxSkipStepFrameCount) return RequestStepOut; |
| - |
| - if (!m_skippedStepFrameCount) m_recursionLevelForStepFrame = 1; |
| - |
| - ++m_skippedStepFrameCount; |
| - return RequestStepFrame; |
| + return std::distance(itStartRange, itEndRange) == 0 && |
|
dgozman
2017/01/24 00:12:08
itStartRange == itEndRange
kozy
2017/01/24 01:11:51
Done.
|
| + std::distance(ranges.begin(), itStartRange) % 2; |
| } |
| std::unique_ptr<protocol::Debugger::Location> |
| @@ -641,8 +589,6 @@ void V8DebuggerAgentImpl::schedulePauseOnNextStatement( |
| return; |
| m_breakReason = breakReason; |
| m_breakAuxData = std::move(data); |
| - m_pausingOnNativeEvent = true; |
| - m_skipNextDebuggerStepOut = false; |
| m_debugger->setPauseOnNextStatement(true); |
| } |
| @@ -652,16 +598,12 @@ void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() { |
| m_debugger->isPaused()) |
| return; |
| clearBreakDetails(); |
| - m_pausingOnNativeEvent = false; |
| - m_skippedStepFrameCount = 0; |
| - m_recursionLevelForStepFrame = 0; |
| m_debugger->setPauseOnNextStatement(true); |
| } |
| void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { |
| if (m_javaScriptPauseScheduled || m_debugger->isPaused()) return; |
| clearBreakDetails(); |
| - m_pausingOnNativeEvent = false; |
| m_debugger->setPauseOnNextStatement(false); |
| } |
| @@ -672,8 +614,6 @@ Response V8DebuggerAgentImpl::pause() { |
| clearBreakDetails(); |
| m_javaScriptPauseScheduled = true; |
| m_scheduledDebuggerStep = NoStep; |
| - m_skippedStepFrameCount = 0; |
| - m_steppingFromFramework = false; |
| m_debugger->setPauseOnNextStatement(true); |
| return Response::OK(); |
| } |
| @@ -681,7 +621,6 @@ Response V8DebuggerAgentImpl::pause() { |
| Response V8DebuggerAgentImpl::resume() { |
| if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| m_scheduledDebuggerStep = NoStep; |
| - m_steppingFromFramework = false; |
| m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| m_debugger->continueProgram(); |
| return Response::OK(); |
| @@ -694,7 +633,6 @@ Response V8DebuggerAgentImpl::stepOver() { |
| !m_pausedCallFrames.empty() ? m_pausedCallFrames[0].get() : nullptr; |
| if (frame && frame->isAtReturn()) return stepInto(); |
| m_scheduledDebuggerStep = StepOver; |
| - m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); |
| m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| m_debugger->stepOverStatement(); |
| return Response::OK(); |
| @@ -703,7 +641,6 @@ Response V8DebuggerAgentImpl::stepOver() { |
| Response V8DebuggerAgentImpl::stepInto() { |
| if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| m_scheduledDebuggerStep = StepInto; |
| - m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); |
| m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| m_debugger->stepIntoStatement(); |
| return Response::OK(); |
| @@ -712,9 +649,7 @@ Response V8DebuggerAgentImpl::stepInto() { |
| Response V8DebuggerAgentImpl::stepOut() { |
| if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| m_scheduledDebuggerStep = StepOut; |
| - m_skipNextDebuggerStepOut = false; |
| m_recursionLevelForStepOut = 1; |
| - m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); |
| m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| m_debugger->stepOutOfFunction(); |
| return Response::OK(); |
| @@ -811,6 +746,7 @@ Response V8DebuggerAgentImpl::setBlackboxPatterns( |
| std::unique_ptr<protocol::Array<String16>> patterns) { |
| if (!patterns->length()) { |
| m_blackboxPattern = nullptr; |
| + resetBlackboxedStateCache(); |
| m_state->remove(DebuggerAgentState::blackboxPattern); |
| return Response::OK(); |
| } |
| @@ -826,6 +762,7 @@ Response V8DebuggerAgentImpl::setBlackboxPatterns( |
| String16 pattern = patternBuilder.toString(); |
| Response response = setBlackboxPattern(pattern); |
| if (!response.isSuccess()) return response; |
| + resetBlackboxedStateCache(); |
| m_state->setString(DebuggerAgentState::blackboxPattern, pattern); |
| return Response::OK(); |
| } |
| @@ -839,15 +776,23 @@ Response V8DebuggerAgentImpl::setBlackboxPattern(const String16& pattern) { |
| return Response::OK(); |
| } |
| +void V8DebuggerAgentImpl::resetBlackboxedStateCache() { |
| + for (const auto& it : m_scripts) { |
| + it.second->resetBlackboxedStateCache(); |
| + } |
| +} |
| + |
| Response V8DebuggerAgentImpl::setBlackboxedRanges( |
| const String16& scriptId, |
| std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> |
| inPositions) { |
| - if (m_scripts.find(scriptId) == m_scripts.end()) |
| + auto it = m_scripts.find(scriptId); |
| + if (it == m_scripts.end()) |
| return Response::Error("No script with passed id."); |
| if (!inPositions->length()) { |
| m_blackboxedPositions.erase(scriptId); |
| + it->second->resetBlackboxedStateCache(); |
| return Response::OK(); |
| } |
| @@ -873,6 +818,7 @@ Response V8DebuggerAgentImpl::setBlackboxedRanges( |
| } |
| m_blackboxedPositions[scriptId] = positions; |
| + it->second->resetBlackboxedStateCache(); |
| return Response::OK(); |
| } |
| @@ -901,27 +847,6 @@ void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { |
| // switch stepping to step into a next JS task, as if we exited to a |
| // blackboxed framework. |
| m_scheduledDebuggerStep = StepInto; |
| - m_skipNextDebuggerStepOut = false; |
| - } |
| - } |
| - if (m_recursionLevelForStepFrame) { |
| - m_recursionLevelForStepFrame += step; |
| - if (!m_recursionLevelForStepFrame) { |
| - // We have walked through a blackboxed framework and got back to where we |
| - // started. |
| - // If there was no stepping scheduled, we should cancel the stepping |
| - // explicitly, |
| - // since there may be a scheduled StepFrame left. |
| - // Otherwise, if we were stepping in/over, the StepFrame will stop at the |
| - // right location, |
| - // whereas if we were stepping out, we should continue doing so after |
| - // debugger pauses |
| - // from the old StepFrame. |
| - m_skippedStepFrameCount = 0; |
| - if (m_scheduledDebuggerStep == NoStep) |
| - m_debugger->clearStepping(); |
| - else if (m_scheduledDebuggerStep == StepOut) |
| - m_skipNextDebuggerStepOut = true; |
| } |
| } |
| } |
| @@ -1072,6 +997,7 @@ void V8DebuggerAgentImpl::didParseSource( |
| ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); |
| DCHECK(scriptIterator != m_scripts.end()); |
| V8DebuggerScript* scriptRef = scriptIterator->second.get(); |
| + scriptRef->resetBlackboxedStateCache(); |
|
dgozman
2017/01/24 00:12:08
This is a new script - do we reset to account for
kozy
2017/01/24 01:11:52
Done.
|
| Maybe<String16> sourceMapURLParam = scriptRef->sourceMappingURL(); |
| Maybe<protocol::DictionaryValue> executionContextAuxDataParam( |
| @@ -1121,35 +1047,19 @@ void V8DebuggerAgentImpl::didParseSource( |
| } |
| } |
| -V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause( |
| - v8::Local<v8::Context> context, v8::Local<v8::Value> exception, |
| - const std::vector<String16>& hitBreakpoints, bool isPromiseRejection, |
| - bool isUncaught, bool isOOMBreak) { |
| - JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(1); |
| - JavaScriptCallFrame* topCallFrame = |
| - !callFrames.empty() ? callFrames.begin()->get() : nullptr; |
| - |
| - V8DebuggerAgentImpl::SkipPauseRequest result; |
| - if (isOOMBreak) |
| - result = RequestNoSkip; |
| - else if (m_skipAllPauses) |
| - result = RequestContinue; |
| - else if (!hitBreakpoints.empty()) |
| - result = RequestNoSkip; // Don't skip explicit breakpoints even if set in |
| - // frameworks. |
| - else if (!exception.IsEmpty()) |
| - result = shouldSkipExceptionPause(topCallFrame); |
| - else if (m_scheduledDebuggerStep != NoStep || m_javaScriptPauseScheduled || |
| - m_pausingOnNativeEvent) |
| - result = shouldSkipStepPause(topCallFrame); |
| - else |
| - result = RequestNoSkip; |
| - |
| - m_skipNextDebuggerStepOut = false; |
| - if (result != RequestNoSkip) return result; |
| - // Skip pauses inside V8 internal scripts and on syntax errors. |
| - if (!topCallFrame) return RequestContinue; |
| - |
| +bool V8DebuggerAgentImpl::didPause(v8::Local<v8::Context> context, |
| + v8::Local<v8::Value> exception, |
| + const std::vector<String16>& hitBreakpoints, |
| + bool isPromiseRejection, bool isUncaught, |
| + bool isOOMBreak) { |
| + if (!isOOMBreak) { |
| + if (m_skipAllPauses) return false; |
| + JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(1); |
| + JavaScriptCallFrame* topCallFrame = |
| + !callFrames.empty() ? callFrames.begin()->get() : nullptr; |
| + // Skip pauses inside V8 internal scripts and on syntax errors. |
| + if (!topCallFrame) return false; |
| + } |
| DCHECK(m_pausedContext.IsEmpty()); |
| JavaScriptCallFrames frames = m_debugger->currentCallFrames(); |
| m_pausedCallFrames.swap(frames); |
| @@ -1205,16 +1115,12 @@ V8DebuggerAgentImpl::SkipPauseRequest V8DebuggerAgentImpl::didPause( |
| currentAsyncStackTrace()); |
| m_scheduledDebuggerStep = NoStep; |
| m_javaScriptPauseScheduled = false; |
| - m_steppingFromFramework = false; |
| - m_pausingOnNativeEvent = false; |
| - m_skippedStepFrameCount = 0; |
| - m_recursionLevelForStepFrame = 0; |
| if (!m_continueToLocationBreakpointId.isEmpty()) { |
| m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); |
| m_continueToLocationBreakpointId = ""; |
| } |
| - return result; |
| + return true; |
| } |
| void V8DebuggerAgentImpl::didContinue() { |
| @@ -1229,14 +1135,11 @@ void V8DebuggerAgentImpl::breakProgram( |
| const String16& breakReason, |
| std::unique_ptr<protocol::DictionaryValue> data) { |
| if (!enabled() || m_skipAllPauses || !m_pausedContext.IsEmpty() || |
| - isCurrentCallStackEmptyOrBlackboxed() || |
| - !m_debugger->breakpointsActivated()) |
| + !m_debugger->canBreakProgram()) |
| return; |
| m_breakReason = breakReason; |
| m_breakAuxData = std::move(data); |
| m_scheduledDebuggerStep = NoStep; |
| - m_steppingFromFramework = false; |
| - m_pausingOnNativeEvent = false; |
| m_debugger->breakProgram(); |
| } |
| @@ -1274,8 +1177,9 @@ void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, |
| void V8DebuggerAgentImpl::reset() { |
| if (!enabled()) return; |
| m_scheduledDebuggerStep = NoStep; |
| - m_scripts.clear(); |
| m_blackboxedPositions.clear(); |
| + resetBlackboxedStateCache(); |
| + m_scripts.clear(); |
| m_breakpointIdToDebuggerBreakpointIds.clear(); |
| } |