Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/inspector/v8-debugger-agent-impl.h" | 5 #include "src/inspector/v8-debugger-agent-impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "src/debug/debug-interface.h" | 9 #include "src/debug/debug-interface.h" |
| 10 #include "src/inspector/injected-script.h" | 10 #include "src/inspector/injected-script.h" |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 : m_inspector(session->inspector()), | 127 : m_inspector(session->inspector()), |
| 128 m_debugger(m_inspector->debugger()), | 128 m_debugger(m_inspector->debugger()), |
| 129 m_session(session), | 129 m_session(session), |
| 130 m_enabled(false), | 130 m_enabled(false), |
| 131 m_state(state), | 131 m_state(state), |
| 132 m_frontend(frontendChannel), | 132 m_frontend(frontendChannel), |
| 133 m_isolate(m_inspector->isolate()), | 133 m_isolate(m_inspector->isolate()), |
| 134 m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other), | 134 m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other), |
| 135 m_scheduledDebuggerStep(NoStep), | 135 m_scheduledDebuggerStep(NoStep), |
| 136 m_javaScriptPauseScheduled(false), | 136 m_javaScriptPauseScheduled(false), |
| 137 m_recursionLevelForStepOut(0), | 137 m_recursionLevelForStepOut(0) { |
| 138 m_skipAllPauses(false) { | |
| 139 clearBreakDetails(); | 138 clearBreakDetails(); |
| 140 } | 139 } |
| 141 | 140 |
| 142 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} | 141 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} |
| 143 | 142 |
| 144 void V8DebuggerAgentImpl::enableImpl() { | 143 void V8DebuggerAgentImpl::enableImpl() { |
| 145 // m_inspector->addListener may result in reporting all parsed scripts to | |
| 146 // the agent so it should already be in enabled state by then. | |
| 147 m_enabled = true; | 144 m_enabled = true; |
| 148 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); | 145 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); |
| 149 m_debugger->enable(); | 146 m_debugger->enable(); |
| 150 | 147 |
| 151 std::vector<std::unique_ptr<V8DebuggerScript>> compiledScripts; | 148 std::vector<std::unique_ptr<V8DebuggerScript>> compiledScripts; |
| 152 m_debugger->getCompiledScripts(m_session->contextGroupId(), compiledScripts); | 149 m_debugger->getCompiledScripts(m_session->contextGroupId(), compiledScripts); |
| 153 for (size_t i = 0; i < compiledScripts.size(); i++) | 150 for (size_t i = 0; i < compiledScripts.size(); i++) |
| 154 didParseSource(std::move(compiledScripts[i]), true); | 151 didParseSource(std::move(compiledScripts[i]), true); |
| 155 | 152 |
| 156 // FIXME(WK44513): breakpoints activated flag should be synchronized between | 153 // FIXME(WK44513): breakpoints activated flag should be synchronized between |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 172 | 169 |
| 173 Response V8DebuggerAgentImpl::disable() { | 170 Response V8DebuggerAgentImpl::disable() { |
| 174 if (!enabled()) return Response::OK(); | 171 if (!enabled()) return Response::OK(); |
| 175 | 172 |
| 176 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, | 173 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, |
| 177 protocol::DictionaryValue::create()); | 174 protocol::DictionaryValue::create()); |
| 178 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, | 175 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, |
| 179 v8::debug::NoBreakOnException); | 176 v8::debug::NoBreakOnException); |
| 180 m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); | 177 m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); |
| 181 | 178 |
| 182 if (!m_pausedContext.IsEmpty()) m_debugger->continueProgram(); | 179 if (isPaused()) m_debugger->continueProgram(); |
| 183 m_debugger->disable(); | 180 m_debugger->disable(); |
| 184 m_pausedContext.Reset(); | |
| 185 JavaScriptCallFrames emptyCallFrames; | 181 JavaScriptCallFrames emptyCallFrames; |
| 186 m_pausedCallFrames.swap(emptyCallFrames); | 182 m_pausedCallFrames.swap(emptyCallFrames); |
| 187 m_blackboxedPositions.clear(); | 183 m_blackboxedPositions.clear(); |
| 188 m_blackboxPattern.reset(); | 184 m_blackboxPattern.reset(); |
| 189 resetBlackboxedStateCache(); | 185 resetBlackboxedStateCache(); |
| 190 m_scripts.clear(); | 186 m_scripts.clear(); |
| 191 m_breakpointIdToDebuggerBreakpointIds.clear(); | 187 m_breakpointIdToDebuggerBreakpointIds.clear(); |
| 192 m_debugger->setAsyncCallStackDepth(this, 0); | 188 m_debugger->setAsyncCallStackDepth(this, 0); |
| 193 m_continueToLocationBreakpointId = String16(); | 189 m_continueToLocationBreakpointId = String16(); |
| 194 clearBreakDetails(); | 190 clearBreakDetails(); |
| 195 m_scheduledDebuggerStep = NoStep; | 191 m_scheduledDebuggerStep = NoStep; |
| 196 m_javaScriptPauseScheduled = false; | 192 m_javaScriptPauseScheduled = false; |
| 197 m_skipAllPauses = false; | |
| 198 m_state->remove(DebuggerAgentState::blackboxPattern); | 193 m_state->remove(DebuggerAgentState::blackboxPattern); |
| 199 m_enabled = false; | 194 m_enabled = false; |
| 200 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); | 195 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); |
| 201 return Response::OK(); | 196 return Response::OK(); |
| 202 } | 197 } |
| 203 | 198 |
| 204 void V8DebuggerAgentImpl::restore() { | 199 void V8DebuggerAgentImpl::restore() { |
| 205 DCHECK(!m_enabled); | 200 DCHECK(!m_enabled); |
| 206 if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) | 201 if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) |
| 207 return; | 202 return; |
| 208 if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) | 203 if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) |
| 209 return; | 204 return; |
| 210 | 205 |
| 211 enableImpl(); | 206 enableImpl(); |
| 212 | 207 |
| 213 int pauseState = v8::debug::NoBreakOnException; | 208 int pauseState = v8::debug::NoBreakOnException; |
| 214 m_state->getInteger(DebuggerAgentState::pauseOnExceptionsState, &pauseState); | 209 m_state->getInteger(DebuggerAgentState::pauseOnExceptionsState, &pauseState); |
| 215 setPauseOnExceptionsImpl(pauseState); | 210 setPauseOnExceptionsImpl(pauseState); |
| 216 | 211 |
| 217 m_skipAllPauses = | |
| 218 m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false); | |
| 219 | |
| 220 int asyncCallStackDepth = 0; | 212 int asyncCallStackDepth = 0; |
| 221 m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, | 213 m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, |
| 222 &asyncCallStackDepth); | 214 &asyncCallStackDepth); |
| 223 m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); | 215 m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); |
| 224 | 216 |
| 225 String16 blackboxPattern; | 217 String16 blackboxPattern; |
| 226 if (m_state->getString(DebuggerAgentState::blackboxPattern, | 218 if (m_state->getString(DebuggerAgentState::blackboxPattern, |
| 227 &blackboxPattern)) { | 219 &blackboxPattern)) { |
| 228 setBlackboxPattern(blackboxPattern); | 220 setBlackboxPattern(blackboxPattern); |
| 229 } | 221 } |
| 230 } | 222 } |
| 231 | 223 |
| 232 Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { | 224 Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { |
| 233 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 225 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 234 m_debugger->setBreakpointsActivated(active); | 226 m_debugger->setBreakpointsActivated(active); |
| 235 return Response::OK(); | 227 return Response::OK(); |
| 236 } | 228 } |
| 237 | 229 |
| 238 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { | 230 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { |
| 239 m_skipAllPauses = skip; | 231 m_state->setBoolean(DebuggerAgentState::skipAllPauses, skip); |
| 240 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses); | |
| 241 return Response::OK(); | 232 return Response::OK(); |
| 242 } | 233 } |
| 243 | 234 |
| 235 bool V8DebuggerAgentImpl::skipAllPauses() const { | |
| 236 bool value = false; | |
| 237 return m_state->getBoolean(DebuggerAgentState::skipAllPauses, &value) && | |
|
dgozman
2017/02/02 23:40:36
Let's have m_skipAllPauses, as this is slow but me
kozy
2017/02/03 01:04:08
Done.
| |
| 238 value; | |
| 239 } | |
| 240 | |
| 244 static std::unique_ptr<protocol::DictionaryValue> | 241 static std::unique_ptr<protocol::DictionaryValue> |
| 245 buildObjectForBreakpointCookie(const String16& url, int lineNumber, | 242 buildObjectForBreakpointCookie(const String16& url, int lineNumber, |
| 246 int columnNumber, const String16& condition, | 243 int columnNumber, const String16& condition, |
| 247 bool isRegex) { | 244 bool isRegex) { |
| 248 std::unique_ptr<protocol::DictionaryValue> breakpointObject = | 245 std::unique_ptr<protocol::DictionaryValue> breakpointObject = |
| 249 protocol::DictionaryValue::create(); | 246 protocol::DictionaryValue::create(); |
| 250 breakpointObject->setString(DebuggerAgentState::url, url); | 247 breakpointObject->setString(DebuggerAgentState::url, url); |
| 251 breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); | 248 breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); |
| 252 breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); | 249 breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); |
| 253 breakpointObject->setString(DebuggerAgentState::condition, condition); | 250 breakpointObject->setString(DebuggerAgentState::condition, condition); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 if (!response.isSuccess()) return response; | 538 if (!response.isSuccess()) return response; |
| 542 *newCallFrames = std::move(callFrames); | 539 *newCallFrames = std::move(callFrames); |
| 543 *asyncStackTrace = currentAsyncStackTrace(); | 540 *asyncStackTrace = currentAsyncStackTrace(); |
| 544 return Response::OK(); | 541 return Response::OK(); |
| 545 } | 542 } |
| 546 | 543 |
| 547 Response V8DebuggerAgentImpl::restartFrame( | 544 Response V8DebuggerAgentImpl::restartFrame( |
| 548 const String16& callFrameId, | 545 const String16& callFrameId, |
| 549 std::unique_ptr<Array<CallFrame>>* newCallFrames, | 546 std::unique_ptr<Array<CallFrame>>* newCallFrames, |
| 550 Maybe<StackTrace>* asyncStackTrace) { | 547 Maybe<StackTrace>* asyncStackTrace) { |
| 551 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 548 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 552 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 549 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 553 callFrameId); | 550 callFrameId); |
| 554 Response response = scope.initialize(); | 551 Response response = scope.initialize(); |
| 555 if (!response.isSuccess()) return response; | 552 if (!response.isSuccess()) return response; |
| 556 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) | 553 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
| 557 return Response::Error("Could not find call frame with given id"); | 554 return Response::Error("Could not find call frame with given id"); |
| 558 | 555 |
| 559 v8::Local<v8::Value> resultValue; | 556 v8::Local<v8::Value> resultValue; |
| 560 v8::Local<v8::Boolean> result; | 557 v8::Local<v8::Boolean> result; |
| 561 if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal( | 558 if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal( |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 582 return Response::Error("No script for id: " + scriptId); | 579 return Response::Error("No script for id: " + scriptId); |
| 583 v8::HandleScope handles(m_isolate); | 580 v8::HandleScope handles(m_isolate); |
| 584 *scriptSource = it->second->source(m_isolate); | 581 *scriptSource = it->second->source(m_isolate); |
| 585 return Response::OK(); | 582 return Response::OK(); |
| 586 } | 583 } |
| 587 | 584 |
| 588 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( | 585 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( |
| 589 const String16& breakReason, | 586 const String16& breakReason, |
| 590 std::unique_ptr<protocol::DictionaryValue> data) { | 587 std::unique_ptr<protocol::DictionaryValue> data) { |
| 591 if (!enabled() || m_scheduledDebuggerStep == StepInto || | 588 if (!enabled() || m_scheduledDebuggerStep == StepInto || |
| 592 m_javaScriptPauseScheduled || m_debugger->isPaused() || | 589 m_javaScriptPauseScheduled || isPaused() || |
| 593 !m_debugger->breakpointsActivated()) | 590 !m_debugger->breakpointsActivated()) |
| 594 return; | 591 return; |
| 595 m_breakReason = breakReason; | 592 m_breakReason = breakReason; |
| 596 m_breakAuxData = std::move(data); | 593 m_breakAuxData = std::move(data); |
| 597 m_debugger->setPauseOnNextStatement(true); | 594 m_debugger->setPauseOnNextStatement(true); |
| 598 } | 595 } |
| 599 | 596 |
| 600 void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() { | 597 void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() { |
| 601 DCHECK(enabled()); | 598 DCHECK(enabled()); |
| 602 if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || | 599 if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || |
| 603 m_debugger->isPaused()) | 600 isPaused()) |
| 604 return; | 601 return; |
| 605 clearBreakDetails(); | 602 clearBreakDetails(); |
| 606 m_debugger->setPauseOnNextStatement(true); | 603 m_debugger->setPauseOnNextStatement(true); |
| 607 } | 604 } |
| 608 | 605 |
| 609 void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { | 606 void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { |
| 610 if (m_javaScriptPauseScheduled || m_debugger->isPaused()) return; | 607 if (m_javaScriptPauseScheduled || isPaused()) return; |
| 611 clearBreakDetails(); | 608 clearBreakDetails(); |
| 612 m_debugger->setPauseOnNextStatement(false); | 609 m_debugger->setPauseOnNextStatement(false); |
| 613 } | 610 } |
| 614 | 611 |
| 615 Response V8DebuggerAgentImpl::pause() { | 612 Response V8DebuggerAgentImpl::pause() { |
| 616 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 613 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 617 if (m_javaScriptPauseScheduled || m_debugger->isPaused()) | 614 if (m_javaScriptPauseScheduled || isPaused()) return Response::OK(); |
|
dgozman
2017/02/02 23:40:36
Let's merge V8Debugger::isPaused() with m_runningN
kozy
2017/02/03 01:04:08
Done.
| |
| 618 return Response::OK(); | |
| 619 clearBreakDetails(); | 615 clearBreakDetails(); |
| 620 m_javaScriptPauseScheduled = true; | 616 m_javaScriptPauseScheduled = true; |
| 621 m_scheduledDebuggerStep = NoStep; | 617 m_scheduledDebuggerStep = NoStep; |
| 622 m_debugger->setPauseOnNextStatement(true); | 618 m_debugger->setPauseOnNextStatement(true); |
| 623 return Response::OK(); | 619 return Response::OK(); |
| 624 } | 620 } |
| 625 | 621 |
| 626 Response V8DebuggerAgentImpl::resume() { | 622 Response V8DebuggerAgentImpl::resume() { |
| 627 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 623 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 628 m_scheduledDebuggerStep = NoStep; | 624 m_scheduledDebuggerStep = NoStep; |
| 629 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 625 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 630 m_debugger->continueProgram(); | 626 m_debugger->continueProgram(); |
| 631 return Response::OK(); | 627 return Response::OK(); |
| 632 } | 628 } |
| 633 | 629 |
| 634 Response V8DebuggerAgentImpl::stepOver() { | 630 Response V8DebuggerAgentImpl::stepOver() { |
| 635 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 631 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 636 // StepOver at function return point should fallback to StepInto. | 632 // StepOver at function return point should fallback to StepInto. |
| 637 JavaScriptCallFrame* frame = | 633 JavaScriptCallFrame* frame = |
| 638 !m_pausedCallFrames.empty() ? m_pausedCallFrames[0].get() : nullptr; | 634 !m_pausedCallFrames.empty() ? m_pausedCallFrames[0].get() : nullptr; |
| 639 if (frame && frame->isAtReturn()) return stepInto(); | 635 if (frame && frame->isAtReturn()) { |
| 636 return stepInto(); | |
|
dgozman
2017/02/02 23:40:36
Please undo.
kozy
2017/02/03 01:04:08
Done.
| |
| 637 } | |
| 640 m_scheduledDebuggerStep = StepOver; | 638 m_scheduledDebuggerStep = StepOver; |
| 641 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 639 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 642 m_debugger->stepOverStatement(); | 640 m_debugger->stepOverStatement(); |
| 643 return Response::OK(); | 641 return Response::OK(); |
| 644 } | 642 } |
| 645 | 643 |
| 646 Response V8DebuggerAgentImpl::stepInto() { | 644 Response V8DebuggerAgentImpl::stepInto() { |
| 647 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 645 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 648 m_scheduledDebuggerStep = StepInto; | 646 m_scheduledDebuggerStep = StepInto; |
| 649 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 647 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 650 m_debugger->stepIntoStatement(); | 648 m_debugger->stepIntoStatement(); |
| 651 return Response::OK(); | 649 return Response::OK(); |
| 652 } | 650 } |
| 653 | 651 |
| 654 Response V8DebuggerAgentImpl::stepOut() { | 652 Response V8DebuggerAgentImpl::stepOut() { |
| 655 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 653 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 656 m_scheduledDebuggerStep = StepOut; | 654 m_scheduledDebuggerStep = StepOut; |
| 657 m_recursionLevelForStepOut = 1; | 655 m_recursionLevelForStepOut = 1; |
| 658 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 656 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 659 m_debugger->stepOutOfFunction(); | 657 m_debugger->stepOutOfFunction(); |
| 660 return Response::OK(); | 658 return Response::OK(); |
| 661 } | 659 } |
| 662 | 660 |
| 663 Response V8DebuggerAgentImpl::setPauseOnExceptions( | 661 Response V8DebuggerAgentImpl::setPauseOnExceptions( |
| 664 const String16& stringPauseState) { | 662 const String16& stringPauseState) { |
| 665 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 663 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 683 static_cast<v8::debug::ExceptionBreakState>(pauseState)); | 681 static_cast<v8::debug::ExceptionBreakState>(pauseState)); |
| 684 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); | 682 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); |
| 685 } | 683 } |
| 686 | 684 |
| 687 Response V8DebuggerAgentImpl::evaluateOnCallFrame( | 685 Response V8DebuggerAgentImpl::evaluateOnCallFrame( |
| 688 const String16& callFrameId, const String16& expression, | 686 const String16& callFrameId, const String16& expression, |
| 689 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, | 687 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, |
| 690 Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, | 688 Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, |
| 691 std::unique_ptr<RemoteObject>* result, | 689 std::unique_ptr<RemoteObject>* result, |
| 692 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { | 690 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { |
| 693 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 691 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 694 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 692 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 695 callFrameId); | 693 callFrameId); |
| 696 Response response = scope.initialize(); | 694 Response response = scope.initialize(); |
| 697 if (!response.isSuccess()) return response; | 695 if (!response.isSuccess()) return response; |
| 698 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) | 696 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
| 699 return Response::Error("Could not find call frame with given id"); | 697 return Response::Error("Could not find call frame with given id"); |
| 700 | 698 |
| 701 if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); | 699 if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); |
| 702 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); | 700 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); |
| 703 | 701 |
| 704 v8::MaybeLocal<v8::Value> maybeResultValue = | 702 v8::MaybeLocal<v8::Value> maybeResultValue = |
| 705 m_pausedCallFrames[scope.frameOrdinal()]->evaluate( | 703 m_pausedCallFrames[scope.frameOrdinal()]->evaluate( |
| 706 toV8String(m_isolate, expression)); | 704 toV8String(m_isolate, expression)); |
| 707 | 705 |
| 708 // Re-initialize after running client's code, as it could have destroyed | 706 // Re-initialize after running client's code, as it could have destroyed |
| 709 // context or session. | 707 // context or session. |
| 710 response = scope.initialize(); | 708 response = scope.initialize(); |
| 711 if (!response.isSuccess()) return response; | 709 if (!response.isSuccess()) return response; |
| 712 return scope.injectedScript()->wrapEvaluateResult( | 710 return scope.injectedScript()->wrapEvaluateResult( |
| 713 maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), | 711 maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), |
| 714 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, | 712 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, |
| 715 exceptionDetails); | 713 exceptionDetails); |
| 716 } | 714 } |
| 717 | 715 |
| 718 Response V8DebuggerAgentImpl::setVariableValue( | 716 Response V8DebuggerAgentImpl::setVariableValue( |
| 719 int scopeNumber, const String16& variableName, | 717 int scopeNumber, const String16& variableName, |
| 720 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, | 718 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, |
| 721 const String16& callFrameId) { | 719 const String16& callFrameId) { |
| 722 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 720 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 723 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 721 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 724 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 722 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 725 callFrameId); | 723 callFrameId); |
| 726 Response response = scope.initialize(); | 724 Response response = scope.initialize(); |
| 727 if (!response.isSuccess()) return response; | 725 if (!response.isSuccess()) return response; |
| 728 v8::Local<v8::Value> newValue; | 726 v8::Local<v8::Value> newValue; |
| 729 response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), | 727 response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), |
| 730 &newValue); | 728 &newValue); |
| 731 if (!response.isSuccess()) return response; | 729 if (!response.isSuccess()) return response; |
| 732 | 730 |
| 733 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) | 731 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 822 "Input positions array is not sorted or contains duplicate values."); | 820 "Input positions array is not sorted or contains duplicate values."); |
| 823 } | 821 } |
| 824 | 822 |
| 825 m_blackboxedPositions[scriptId] = positions; | 823 m_blackboxedPositions[scriptId] = positions; |
| 826 it->second->resetBlackboxedStateCache(); | 824 it->second->resetBlackboxedStateCache(); |
| 827 return Response::OK(); | 825 return Response::OK(); |
| 828 } | 826 } |
| 829 | 827 |
| 830 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { | 828 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { |
| 831 changeJavaScriptRecursionLevel(+1); | 829 changeJavaScriptRecursionLevel(+1); |
| 832 // Fast return. | |
| 833 if (m_scheduledDebuggerStep != StepInto) return; | 830 if (m_scheduledDebuggerStep != StepInto) return; |
| 834 schedulePauseOnNextStatementIfSteppingInto(); | 831 schedulePauseOnNextStatementIfSteppingInto(); |
| 835 } | 832 } |
| 836 | 833 |
| 837 void V8DebuggerAgentImpl::didExecuteScript() { | 834 void V8DebuggerAgentImpl::didExecuteScript() { |
| 838 changeJavaScriptRecursionLevel(-1); | 835 changeJavaScriptRecursionLevel(-1); |
| 839 } | 836 } |
| 840 | 837 |
| 841 void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { | 838 void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { |
| 842 if (m_javaScriptPauseScheduled && !m_skipAllPauses && | 839 if (m_javaScriptPauseScheduled && !isPaused()) { |
| 843 !m_debugger->isPaused()) { | |
| 844 // Do not ever loose user's pause request until we have actually paused. | 840 // Do not ever loose user's pause request until we have actually paused. |
| 845 m_debugger->setPauseOnNextStatement(true); | 841 m_debugger->setPauseOnNextStatement(true); |
| 846 } | 842 } |
| 847 if (m_scheduledDebuggerStep == StepOut) { | 843 if (m_scheduledDebuggerStep == StepOut) { |
| 848 m_recursionLevelForStepOut += step; | 844 m_recursionLevelForStepOut += step; |
| 849 if (!m_recursionLevelForStepOut) { | 845 if (!m_recursionLevelForStepOut) { |
| 850 // When StepOut crosses a task boundary (i.e. js -> c++) from where it was | 846 // When StepOut crosses a task boundary (i.e. js -> c++) from where it was |
| 851 // requested, | 847 // requested, |
| 852 // switch stepping to step into a next JS task, as if we exited to a | 848 // switch stepping to step into a next JS task, as if we exited to a |
| 853 // blackboxed framework. | 849 // blackboxed framework. |
| 854 m_scheduledDebuggerStep = StepInto; | 850 m_scheduledDebuggerStep = StepInto; |
| 855 } | 851 } |
| 856 } | 852 } |
| 857 } | 853 } |
| 858 | 854 |
| 859 Response V8DebuggerAgentImpl::currentCallFrames( | 855 Response V8DebuggerAgentImpl::currentCallFrames( |
| 860 std::unique_ptr<Array<CallFrame>>* result) { | 856 std::unique_ptr<Array<CallFrame>>* result) { |
| 861 if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) { | 857 if (!isPaused()) { |
| 862 *result = Array<CallFrame>::create(); | 858 *result = Array<CallFrame>::create(); |
| 863 return Response::OK(); | 859 return Response::OK(); |
| 864 } | 860 } |
| 865 v8::HandleScope handles(m_isolate); | 861 v8::HandleScope handles(m_isolate); |
| 866 v8::Local<v8::Context> debuggerContext = | 862 v8::Local<v8::Context> debuggerContext = |
| 867 v8::debug::GetDebugContext(m_isolate); | 863 v8::debug::GetDebugContext(m_isolate); |
| 868 v8::Context::Scope contextScope(debuggerContext); | 864 v8::Context::Scope contextScope(debuggerContext); |
| 869 | 865 |
| 870 v8::Local<v8::Array> objects = v8::Array::New(m_isolate); | 866 v8::Local<v8::Array> objects = v8::Array::New(m_isolate); |
| 871 | 867 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 960 if (!response.isSuccess()) return response; | 956 if (!response.isSuccess()) return response; |
| 961 protocol::ErrorSupport errorSupport; | 957 protocol::ErrorSupport errorSupport; |
| 962 *result = Array<CallFrame>::fromValue(protocolValue.get(), &errorSupport); | 958 *result = Array<CallFrame>::fromValue(protocolValue.get(), &errorSupport); |
| 963 if (!*result) return Response::Error(errorSupport.errors()); | 959 if (!*result) return Response::Error(errorSupport.errors()); |
| 964 TranslateWasmStackTraceLocations(result->get(), | 960 TranslateWasmStackTraceLocations(result->get(), |
| 965 m_debugger->wasmTranslation()); | 961 m_debugger->wasmTranslation()); |
| 966 return Response::OK(); | 962 return Response::OK(); |
| 967 } | 963 } |
| 968 | 964 |
| 969 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { | 965 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { |
| 970 if (m_pausedContext.IsEmpty()) return nullptr; | 966 if (!isPaused()) return nullptr; |
| 971 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); | 967 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); |
| 972 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) | 968 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) |
| 973 : nullptr; | 969 : nullptr; |
| 974 } | 970 } |
| 975 | 971 |
| 976 void V8DebuggerAgentImpl::didParseSource( | 972 void V8DebuggerAgentImpl::didParseSource( |
| 977 std::unique_ptr<V8DebuggerScript> script, bool success) { | 973 std::unique_ptr<V8DebuggerScript> script, bool success) { |
| 978 v8::HandleScope handles(m_isolate); | 974 v8::HandleScope handles(m_isolate); |
| 979 String16 scriptSource = script->source(m_isolate); | 975 String16 scriptSource = script->source(m_isolate); |
| 980 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); | 976 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1049 &breakpoint.column_number); | 1045 &breakpoint.column_number); |
| 1050 breakpointObject->getString(DebuggerAgentState::condition, | 1046 breakpointObject->getString(DebuggerAgentState::condition, |
| 1051 &breakpoint.condition); | 1047 &breakpoint.condition); |
| 1052 std::unique_ptr<protocol::Debugger::Location> location = | 1048 std::unique_ptr<protocol::Debugger::Location> location = |
| 1053 resolveBreakpoint(cookie.first, breakpoint, UserBreakpointSource); | 1049 resolveBreakpoint(cookie.first, breakpoint, UserBreakpointSource); |
| 1054 if (location) | 1050 if (location) |
| 1055 m_frontend.breakpointResolved(cookie.first, std::move(location)); | 1051 m_frontend.breakpointResolved(cookie.first, std::move(location)); |
| 1056 } | 1052 } |
| 1057 } | 1053 } |
| 1058 | 1054 |
| 1059 bool V8DebuggerAgentImpl::didPause(v8::Local<v8::Context> context, | 1055 void V8DebuggerAgentImpl::didPause(int contextId, |
| 1060 v8::Local<v8::Value> exception, | 1056 v8::Local<v8::Value> exception, |
| 1061 const std::vector<String16>& hitBreakpoints, | 1057 const std::vector<String16>& hitBreakpoints, |
| 1062 bool isPromiseRejection, bool isUncaught, | 1058 bool isPromiseRejection, bool isUncaught, |
| 1063 bool isOOMBreak) { | 1059 bool isOOMBreak) { |
| 1064 if (!isOOMBreak) { | 1060 DCHECK(!isPaused()); |
| 1065 if (m_skipAllPauses) return false; | |
| 1066 JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(1); | |
| 1067 JavaScriptCallFrame* topCallFrame = | |
| 1068 !callFrames.empty() ? callFrames.begin()->get() : nullptr; | |
| 1069 // Skip pauses inside V8 internal scripts and on syntax errors. | |
| 1070 if (!topCallFrame) return false; | |
| 1071 } | |
| 1072 DCHECK(m_pausedContext.IsEmpty()); | |
| 1073 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); | 1061 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); |
| 1074 m_pausedCallFrames.swap(frames); | 1062 m_pausedCallFrames.swap(frames); |
| 1075 m_pausedContext.Reset(m_isolate, context); | |
| 1076 v8::HandleScope handles(m_isolate); | 1063 v8::HandleScope handles(m_isolate); |
| 1077 | 1064 |
| 1078 if (isOOMBreak) { | 1065 if (isOOMBreak) { |
| 1079 m_breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; | 1066 m_breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; |
| 1080 m_breakAuxData = nullptr; | 1067 m_breakAuxData = nullptr; |
| 1081 } else if (!exception.IsEmpty()) { | 1068 } else if (!exception.IsEmpty()) { |
| 1082 InjectedScript* injectedScript = nullptr; | 1069 InjectedScript* injectedScript = nullptr; |
| 1083 m_session->findInjectedScript(InspectedContext::contextId(context), | 1070 m_session->findInjectedScript(contextId, injectedScript); |
| 1084 injectedScript); | |
| 1085 if (injectedScript) { | 1071 if (injectedScript) { |
| 1086 m_breakReason = | 1072 m_breakReason = |
| 1087 isPromiseRejection | 1073 isPromiseRejection |
| 1088 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection | 1074 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection |
| 1089 : protocol::Debugger::Paused::ReasonEnum::Exception; | 1075 : protocol::Debugger::Paused::ReasonEnum::Exception; |
| 1090 std::unique_ptr<protocol::Runtime::RemoteObject> obj; | 1076 std::unique_ptr<protocol::Runtime::RemoteObject> obj; |
| 1091 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, | 1077 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, |
| 1092 &obj); | 1078 &obj); |
| 1093 if (obj) { | 1079 if (obj) { |
| 1094 m_breakAuxData = obj->toValue(); | 1080 m_breakAuxData = obj->toValue(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1122 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, | 1108 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, |
| 1123 std::move(m_breakAuxData), std::move(hitBreakpointIds), | 1109 std::move(m_breakAuxData), std::move(hitBreakpointIds), |
| 1124 currentAsyncStackTrace()); | 1110 currentAsyncStackTrace()); |
| 1125 m_scheduledDebuggerStep = NoStep; | 1111 m_scheduledDebuggerStep = NoStep; |
| 1126 m_javaScriptPauseScheduled = false; | 1112 m_javaScriptPauseScheduled = false; |
| 1127 | 1113 |
| 1128 if (!m_continueToLocationBreakpointId.isEmpty()) { | 1114 if (!m_continueToLocationBreakpointId.isEmpty()) { |
| 1129 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); | 1115 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); |
| 1130 m_continueToLocationBreakpointId = ""; | 1116 m_continueToLocationBreakpointId = ""; |
| 1131 } | 1117 } |
| 1132 return true; | |
| 1133 } | 1118 } |
| 1134 | 1119 |
| 1135 void V8DebuggerAgentImpl::didContinue() { | 1120 void V8DebuggerAgentImpl::didContinue() { |
| 1136 m_pausedContext.Reset(); | |
| 1137 JavaScriptCallFrames emptyCallFrames; | 1121 JavaScriptCallFrames emptyCallFrames; |
| 1138 m_pausedCallFrames.swap(emptyCallFrames); | 1122 m_pausedCallFrames.swap(emptyCallFrames); |
| 1139 clearBreakDetails(); | 1123 clearBreakDetails(); |
| 1140 m_frontend.resumed(); | 1124 m_frontend.resumed(); |
| 1141 } | 1125 } |
| 1142 | 1126 |
| 1143 void V8DebuggerAgentImpl::breakProgram( | 1127 void V8DebuggerAgentImpl::breakProgram( |
| 1144 const String16& breakReason, | 1128 const String16& breakReason, |
| 1145 std::unique_ptr<protocol::DictionaryValue> data) { | 1129 std::unique_ptr<protocol::DictionaryValue> data) { |
| 1146 if (!enabled() || m_skipAllPauses || !m_pausedContext.IsEmpty() || | 1130 if (!enabled() || !m_debugger->canBreakProgram()) return; |
|
dgozman
2017/02/02 23:40:36
Check for skipAllPauses.
kozy
2017/02/03 01:04:08
Done.
| |
| 1147 !m_debugger->canBreakProgram()) | |
| 1148 return; | |
| 1149 m_breakReason = breakReason; | 1131 m_breakReason = breakReason; |
| 1150 m_breakAuxData = std::move(data); | 1132 m_breakAuxData = std::move(data); |
| 1151 m_scheduledDebuggerStep = NoStep; | 1133 m_scheduledDebuggerStep = NoStep; |
| 1152 m_debugger->breakProgram(); | 1134 m_debugger->breakProgram(); |
| 1153 } | 1135 } |
| 1154 | 1136 |
| 1155 void V8DebuggerAgentImpl::breakProgramOnException( | 1137 void V8DebuggerAgentImpl::breakProgramOnException( |
| 1156 const String16& breakReason, | 1138 const String16& breakReason, |
| 1157 std::unique_ptr<protocol::DictionaryValue> data) { | 1139 std::unique_ptr<protocol::DictionaryValue> data) { |
| 1158 if (!enabled() || | 1140 if (!enabled() || |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1186 void V8DebuggerAgentImpl::reset() { | 1168 void V8DebuggerAgentImpl::reset() { |
| 1187 if (!enabled()) return; | 1169 if (!enabled()) return; |
| 1188 m_scheduledDebuggerStep = NoStep; | 1170 m_scheduledDebuggerStep = NoStep; |
| 1189 m_blackboxedPositions.clear(); | 1171 m_blackboxedPositions.clear(); |
| 1190 resetBlackboxedStateCache(); | 1172 resetBlackboxedStateCache(); |
| 1191 m_scripts.clear(); | 1173 m_scripts.clear(); |
| 1192 m_breakpointIdToDebuggerBreakpointIds.clear(); | 1174 m_breakpointIdToDebuggerBreakpointIds.clear(); |
| 1193 } | 1175 } |
| 1194 | 1176 |
| 1195 } // namespace v8_inspector | 1177 } // namespace v8_inspector |
| OLD | NEW |