| 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 = | 212 m_debugger->setSkipAllPauses( |
| 218 m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false); | 213 m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false)); |
| 219 | 214 |
| 220 int asyncCallStackDepth = 0; | 215 int asyncCallStackDepth = 0; |
| 221 m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, | 216 m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, |
| 222 &asyncCallStackDepth); | 217 &asyncCallStackDepth); |
| 223 m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); | 218 m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); |
| 224 | 219 |
| 225 String16 blackboxPattern; | 220 String16 blackboxPattern; |
| 226 if (m_state->getString(DebuggerAgentState::blackboxPattern, | 221 if (m_state->getString(DebuggerAgentState::blackboxPattern, |
| 227 &blackboxPattern)) { | 222 &blackboxPattern)) { |
| 228 setBlackboxPattern(blackboxPattern); | 223 setBlackboxPattern(blackboxPattern); |
| 229 } | 224 } |
| 230 } | 225 } |
| 231 | 226 |
| 232 Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { | 227 Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { |
| 233 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 228 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 234 m_debugger->setBreakpointsActivated(active); | 229 m_debugger->setBreakpointsActivated(active); |
| 235 return Response::OK(); | 230 return Response::OK(); |
| 236 } | 231 } |
| 237 | 232 |
| 238 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { | 233 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { |
| 239 m_skipAllPauses = skip; | 234 m_state->setBoolean(DebuggerAgentState::skipAllPauses, skip); |
| 240 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses); | 235 m_debugger->setSkipAllPauses(skip); |
| 241 return Response::OK(); | 236 return Response::OK(); |
| 242 } | 237 } |
| 243 | 238 |
| 244 static std::unique_ptr<protocol::DictionaryValue> | 239 static std::unique_ptr<protocol::DictionaryValue> |
| 245 buildObjectForBreakpointCookie(const String16& url, int lineNumber, | 240 buildObjectForBreakpointCookie(const String16& url, int lineNumber, |
| 246 int columnNumber, const String16& condition, | 241 int columnNumber, const String16& condition, |
| 247 bool isRegex) { | 242 bool isRegex) { |
| 248 std::unique_ptr<protocol::DictionaryValue> breakpointObject = | 243 std::unique_ptr<protocol::DictionaryValue> breakpointObject = |
| 249 protocol::DictionaryValue::create(); | 244 protocol::DictionaryValue::create(); |
| 250 breakpointObject->setString(DebuggerAgentState::url, url); | 245 breakpointObject->setString(DebuggerAgentState::url, url); |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 if (!response.isSuccess()) return response; | 536 if (!response.isSuccess()) return response; |
| 542 *newCallFrames = std::move(callFrames); | 537 *newCallFrames = std::move(callFrames); |
| 543 *asyncStackTrace = currentAsyncStackTrace(); | 538 *asyncStackTrace = currentAsyncStackTrace(); |
| 544 return Response::OK(); | 539 return Response::OK(); |
| 545 } | 540 } |
| 546 | 541 |
| 547 Response V8DebuggerAgentImpl::restartFrame( | 542 Response V8DebuggerAgentImpl::restartFrame( |
| 548 const String16& callFrameId, | 543 const String16& callFrameId, |
| 549 std::unique_ptr<Array<CallFrame>>* newCallFrames, | 544 std::unique_ptr<Array<CallFrame>>* newCallFrames, |
| 550 Maybe<StackTrace>* asyncStackTrace) { | 545 Maybe<StackTrace>* asyncStackTrace) { |
| 551 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 546 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 552 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 547 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 553 callFrameId); | 548 callFrameId); |
| 554 Response response = scope.initialize(); | 549 Response response = scope.initialize(); |
| 555 if (!response.isSuccess()) return response; | 550 if (!response.isSuccess()) return response; |
| 556 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) | 551 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
| 557 return Response::Error("Could not find call frame with given id"); | 552 return Response::Error("Could not find call frame with given id"); |
| 558 | 553 |
| 559 v8::Local<v8::Value> resultValue; | 554 v8::Local<v8::Value> resultValue; |
| 560 v8::Local<v8::Boolean> result; | 555 v8::Local<v8::Boolean> result; |
| 561 if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal( | 556 if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal( |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 if (m_javaScriptPauseScheduled || m_debugger->isPaused()) | 612 if (m_javaScriptPauseScheduled || m_debugger->isPaused()) |
| 618 return Response::OK(); | 613 return Response::OK(); |
| 619 clearBreakDetails(); | 614 clearBreakDetails(); |
| 620 m_javaScriptPauseScheduled = true; | 615 m_javaScriptPauseScheduled = true; |
| 621 m_scheduledDebuggerStep = NoStep; | 616 m_scheduledDebuggerStep = NoStep; |
| 622 m_debugger->setPauseOnNextStatement(true); | 617 m_debugger->setPauseOnNextStatement(true); |
| 623 return Response::OK(); | 618 return Response::OK(); |
| 624 } | 619 } |
| 625 | 620 |
| 626 Response V8DebuggerAgentImpl::resume() { | 621 Response V8DebuggerAgentImpl::resume() { |
| 627 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 622 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 628 m_scheduledDebuggerStep = NoStep; | 623 m_scheduledDebuggerStep = NoStep; |
| 629 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 624 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 630 m_debugger->continueProgram(); | 625 m_debugger->continueProgram(); |
| 631 return Response::OK(); | 626 return Response::OK(); |
| 632 } | 627 } |
| 633 | 628 |
| 634 Response V8DebuggerAgentImpl::stepOver() { | 629 Response V8DebuggerAgentImpl::stepOver() { |
| 635 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 630 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 636 // StepOver at function return point should fallback to StepInto. | |
| 637 JavaScriptCallFrame* frame = | |
| 638 !m_pausedCallFrames.empty() ? m_pausedCallFrames[0].get() : nullptr; | |
| 639 if (frame && frame->isAtReturn()) return stepInto(); | |
| 640 m_scheduledDebuggerStep = StepOver; | 631 m_scheduledDebuggerStep = StepOver; |
| 641 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 632 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 642 m_debugger->stepOverStatement(); | 633 m_debugger->stepOverStatement(); |
| 643 return Response::OK(); | 634 return Response::OK(); |
| 644 } | 635 } |
| 645 | 636 |
| 646 Response V8DebuggerAgentImpl::stepInto() { | 637 Response V8DebuggerAgentImpl::stepInto() { |
| 647 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 638 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 648 m_scheduledDebuggerStep = StepInto; | 639 m_scheduledDebuggerStep = StepInto; |
| 649 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 640 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 650 m_debugger->stepIntoStatement(); | 641 m_debugger->stepIntoStatement(); |
| 651 return Response::OK(); | 642 return Response::OK(); |
| 652 } | 643 } |
| 653 | 644 |
| 654 Response V8DebuggerAgentImpl::stepOut() { | 645 Response V8DebuggerAgentImpl::stepOut() { |
| 655 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 646 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 656 m_scheduledDebuggerStep = StepOut; | 647 m_scheduledDebuggerStep = StepOut; |
| 657 m_recursionLevelForStepOut = 1; | 648 m_recursionLevelForStepOut = 1; |
| 658 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 649 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 659 m_debugger->stepOutOfFunction(); | 650 m_debugger->stepOutOfFunction(); |
| 660 return Response::OK(); | 651 return Response::OK(); |
| 661 } | 652 } |
| 662 | 653 |
| 663 Response V8DebuggerAgentImpl::setPauseOnExceptions( | 654 Response V8DebuggerAgentImpl::setPauseOnExceptions( |
| 664 const String16& stringPauseState) { | 655 const String16& stringPauseState) { |
| 665 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 656 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 683 static_cast<v8::debug::ExceptionBreakState>(pauseState)); | 674 static_cast<v8::debug::ExceptionBreakState>(pauseState)); |
| 684 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); | 675 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); |
| 685 } | 676 } |
| 686 | 677 |
| 687 Response V8DebuggerAgentImpl::evaluateOnCallFrame( | 678 Response V8DebuggerAgentImpl::evaluateOnCallFrame( |
| 688 const String16& callFrameId, const String16& expression, | 679 const String16& callFrameId, const String16& expression, |
| 689 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, | 680 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, |
| 690 Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, | 681 Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, |
| 691 std::unique_ptr<RemoteObject>* result, | 682 std::unique_ptr<RemoteObject>* result, |
| 692 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { | 683 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { |
| 693 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 684 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 694 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 685 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 695 callFrameId); | 686 callFrameId); |
| 696 Response response = scope.initialize(); | 687 Response response = scope.initialize(); |
| 697 if (!response.isSuccess()) return response; | 688 if (!response.isSuccess()) return response; |
| 698 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) | 689 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
| 699 return Response::Error("Could not find call frame with given id"); | 690 return Response::Error("Could not find call frame with given id"); |
| 700 | 691 |
| 701 if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); | 692 if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); |
| 702 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); | 693 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); |
| 703 | 694 |
| 704 v8::MaybeLocal<v8::Value> maybeResultValue = | 695 v8::MaybeLocal<v8::Value> maybeResultValue = |
| 705 m_pausedCallFrames[scope.frameOrdinal()]->evaluate( | 696 m_pausedCallFrames[scope.frameOrdinal()]->evaluate( |
| 706 toV8String(m_isolate, expression)); | 697 toV8String(m_isolate, expression)); |
| 707 | 698 |
| 708 // Re-initialize after running client's code, as it could have destroyed | 699 // Re-initialize after running client's code, as it could have destroyed |
| 709 // context or session. | 700 // context or session. |
| 710 response = scope.initialize(); | 701 response = scope.initialize(); |
| 711 if (!response.isSuccess()) return response; | 702 if (!response.isSuccess()) return response; |
| 712 return scope.injectedScript()->wrapEvaluateResult( | 703 return scope.injectedScript()->wrapEvaluateResult( |
| 713 maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), | 704 maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), |
| 714 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, | 705 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, |
| 715 exceptionDetails); | 706 exceptionDetails); |
| 716 } | 707 } |
| 717 | 708 |
| 718 Response V8DebuggerAgentImpl::setVariableValue( | 709 Response V8DebuggerAgentImpl::setVariableValue( |
| 719 int scopeNumber, const String16& variableName, | 710 int scopeNumber, const String16& variableName, |
| 720 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, | 711 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, |
| 721 const String16& callFrameId) { | 712 const String16& callFrameId) { |
| 722 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 713 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 723 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 714 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
| 724 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 715 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 725 callFrameId); | 716 callFrameId); |
| 726 Response response = scope.initialize(); | 717 Response response = scope.initialize(); |
| 727 if (!response.isSuccess()) return response; | 718 if (!response.isSuccess()) return response; |
| 728 v8::Local<v8::Value> newValue; | 719 v8::Local<v8::Value> newValue; |
| 729 response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), | 720 response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), |
| 730 &newValue); | 721 &newValue); |
| 731 if (!response.isSuccess()) return response; | 722 if (!response.isSuccess()) return response; |
| 732 | 723 |
| 733 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) | 724 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."); | 813 "Input positions array is not sorted or contains duplicate values."); |
| 823 } | 814 } |
| 824 | 815 |
| 825 m_blackboxedPositions[scriptId] = positions; | 816 m_blackboxedPositions[scriptId] = positions; |
| 826 it->second->resetBlackboxedStateCache(); | 817 it->second->resetBlackboxedStateCache(); |
| 827 return Response::OK(); | 818 return Response::OK(); |
| 828 } | 819 } |
| 829 | 820 |
| 830 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { | 821 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { |
| 831 changeJavaScriptRecursionLevel(+1); | 822 changeJavaScriptRecursionLevel(+1); |
| 832 // Fast return. | |
| 833 if (m_scheduledDebuggerStep != StepInto) return; | 823 if (m_scheduledDebuggerStep != StepInto) return; |
| 834 schedulePauseOnNextStatementIfSteppingInto(); | 824 schedulePauseOnNextStatementIfSteppingInto(); |
| 835 } | 825 } |
| 836 | 826 |
| 837 void V8DebuggerAgentImpl::didExecuteScript() { | 827 void V8DebuggerAgentImpl::didExecuteScript() { |
| 838 changeJavaScriptRecursionLevel(-1); | 828 changeJavaScriptRecursionLevel(-1); |
| 839 } | 829 } |
| 840 | 830 |
| 841 void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { | 831 void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { |
| 842 if (m_javaScriptPauseScheduled && !m_skipAllPauses && | 832 if (m_javaScriptPauseScheduled && !m_debugger->isPaused()) { |
| 843 !m_debugger->isPaused()) { | |
| 844 // Do not ever loose user's pause request until we have actually paused. | 833 // Do not ever loose user's pause request until we have actually paused. |
| 845 m_debugger->setPauseOnNextStatement(true); | 834 m_debugger->setPauseOnNextStatement(true); |
| 846 } | 835 } |
| 847 if (m_scheduledDebuggerStep == StepOut) { | 836 if (m_scheduledDebuggerStep == StepOut) { |
| 848 m_recursionLevelForStepOut += step; | 837 m_recursionLevelForStepOut += step; |
| 849 if (!m_recursionLevelForStepOut) { | 838 if (!m_recursionLevelForStepOut) { |
| 850 // When StepOut crosses a task boundary (i.e. js -> c++) from where it was | 839 // When StepOut crosses a task boundary (i.e. js -> c++) from where it was |
| 851 // requested, | 840 // requested, |
| 852 // switch stepping to step into a next JS task, as if we exited to a | 841 // switch stepping to step into a next JS task, as if we exited to a |
| 853 // blackboxed framework. | 842 // blackboxed framework. |
| 854 m_scheduledDebuggerStep = StepInto; | 843 m_scheduledDebuggerStep = StepInto; |
| 855 } | 844 } |
| 856 } | 845 } |
| 857 } | 846 } |
| 858 | 847 |
| 859 Response V8DebuggerAgentImpl::currentCallFrames( | 848 Response V8DebuggerAgentImpl::currentCallFrames( |
| 860 std::unique_ptr<Array<CallFrame>>* result) { | 849 std::unique_ptr<Array<CallFrame>>* result) { |
| 861 if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) { | 850 if (!isPaused()) { |
| 862 *result = Array<CallFrame>::create(); | 851 *result = Array<CallFrame>::create(); |
| 863 return Response::OK(); | 852 return Response::OK(); |
| 864 } | 853 } |
| 865 v8::HandleScope handles(m_isolate); | 854 v8::HandleScope handles(m_isolate); |
| 866 v8::Local<v8::Context> debuggerContext = | 855 v8::Local<v8::Context> debuggerContext = |
| 867 v8::debug::GetDebugContext(m_isolate); | 856 v8::debug::GetDebugContext(m_isolate); |
| 868 v8::Context::Scope contextScope(debuggerContext); | 857 v8::Context::Scope contextScope(debuggerContext); |
| 869 | 858 |
| 870 v8::Local<v8::Array> objects = v8::Array::New(m_isolate); | 859 v8::Local<v8::Array> objects = v8::Array::New(m_isolate); |
| 871 | 860 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 if (!response.isSuccess()) return response; | 949 if (!response.isSuccess()) return response; |
| 961 protocol::ErrorSupport errorSupport; | 950 protocol::ErrorSupport errorSupport; |
| 962 *result = Array<CallFrame>::fromValue(protocolValue.get(), &errorSupport); | 951 *result = Array<CallFrame>::fromValue(protocolValue.get(), &errorSupport); |
| 963 if (!*result) return Response::Error(errorSupport.errors()); | 952 if (!*result) return Response::Error(errorSupport.errors()); |
| 964 TranslateWasmStackTraceLocations(result->get(), | 953 TranslateWasmStackTraceLocations(result->get(), |
| 965 m_debugger->wasmTranslation()); | 954 m_debugger->wasmTranslation()); |
| 966 return Response::OK(); | 955 return Response::OK(); |
| 967 } | 956 } |
| 968 | 957 |
| 969 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { | 958 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { |
| 970 if (m_pausedContext.IsEmpty()) return nullptr; | 959 if (!isPaused()) return nullptr; |
| 971 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); | 960 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); |
| 972 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) | 961 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) |
| 973 : nullptr; | 962 : nullptr; |
| 974 } | 963 } |
| 975 | 964 |
| 976 void V8DebuggerAgentImpl::didParseSource( | 965 void V8DebuggerAgentImpl::didParseSource( |
| 977 std::unique_ptr<V8DebuggerScript> script, bool success) { | 966 std::unique_ptr<V8DebuggerScript> script, bool success) { |
| 978 v8::HandleScope handles(m_isolate); | 967 v8::HandleScope handles(m_isolate); |
| 979 String16 scriptSource = script->source(m_isolate); | 968 String16 scriptSource = script->source(m_isolate); |
| 980 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); | 969 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 &breakpoint.column_number); | 1038 &breakpoint.column_number); |
| 1050 breakpointObject->getString(DebuggerAgentState::condition, | 1039 breakpointObject->getString(DebuggerAgentState::condition, |
| 1051 &breakpoint.condition); | 1040 &breakpoint.condition); |
| 1052 std::unique_ptr<protocol::Debugger::Location> location = | 1041 std::unique_ptr<protocol::Debugger::Location> location = |
| 1053 resolveBreakpoint(cookie.first, breakpoint, UserBreakpointSource); | 1042 resolveBreakpoint(cookie.first, breakpoint, UserBreakpointSource); |
| 1054 if (location) | 1043 if (location) |
| 1055 m_frontend.breakpointResolved(cookie.first, std::move(location)); | 1044 m_frontend.breakpointResolved(cookie.first, std::move(location)); |
| 1056 } | 1045 } |
| 1057 } | 1046 } |
| 1058 | 1047 |
| 1059 bool V8DebuggerAgentImpl::didPause(v8::Local<v8::Context> context, | 1048 void V8DebuggerAgentImpl::didPause(int contextId, |
| 1060 v8::Local<v8::Value> exception, | 1049 v8::Local<v8::Value> exception, |
| 1061 const std::vector<String16>& hitBreakpoints, | 1050 const std::vector<String16>& hitBreakpoints, |
| 1062 bool isPromiseRejection, bool isUncaught, | 1051 bool isPromiseRejection, bool isUncaught, |
| 1063 bool isOOMBreak) { | 1052 bool isOOMBreak) { |
| 1064 if (!isOOMBreak) { | 1053 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(); | 1054 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); |
| 1074 m_pausedCallFrames.swap(frames); | 1055 m_pausedCallFrames.swap(frames); |
| 1075 m_pausedContext.Reset(m_isolate, context); | |
| 1076 v8::HandleScope handles(m_isolate); | 1056 v8::HandleScope handles(m_isolate); |
| 1077 | 1057 |
| 1078 if (isOOMBreak) { | 1058 if (isOOMBreak) { |
| 1079 m_breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; | 1059 m_breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; |
| 1080 m_breakAuxData = nullptr; | 1060 m_breakAuxData = nullptr; |
| 1081 } else if (!exception.IsEmpty()) { | 1061 } else if (!exception.IsEmpty()) { |
| 1082 InjectedScript* injectedScript = nullptr; | 1062 InjectedScript* injectedScript = nullptr; |
| 1083 m_session->findInjectedScript(InspectedContext::contextId(context), | 1063 m_session->findInjectedScript(contextId, injectedScript); |
| 1084 injectedScript); | |
| 1085 if (injectedScript) { | 1064 if (injectedScript) { |
| 1086 m_breakReason = | 1065 m_breakReason = |
| 1087 isPromiseRejection | 1066 isPromiseRejection |
| 1088 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection | 1067 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection |
| 1089 : protocol::Debugger::Paused::ReasonEnum::Exception; | 1068 : protocol::Debugger::Paused::ReasonEnum::Exception; |
| 1090 std::unique_ptr<protocol::Runtime::RemoteObject> obj; | 1069 std::unique_ptr<protocol::Runtime::RemoteObject> obj; |
| 1091 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, | 1070 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, |
| 1092 &obj); | 1071 &obj); |
| 1093 if (obj) { | 1072 if (obj) { |
| 1094 m_breakAuxData = obj->toValue(); | 1073 m_breakAuxData = obj->toValue(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1122 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, | 1101 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, |
| 1123 std::move(m_breakAuxData), std::move(hitBreakpointIds), | 1102 std::move(m_breakAuxData), std::move(hitBreakpointIds), |
| 1124 currentAsyncStackTrace()); | 1103 currentAsyncStackTrace()); |
| 1125 m_scheduledDebuggerStep = NoStep; | 1104 m_scheduledDebuggerStep = NoStep; |
| 1126 m_javaScriptPauseScheduled = false; | 1105 m_javaScriptPauseScheduled = false; |
| 1127 | 1106 |
| 1128 if (!m_continueToLocationBreakpointId.isEmpty()) { | 1107 if (!m_continueToLocationBreakpointId.isEmpty()) { |
| 1129 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); | 1108 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); |
| 1130 m_continueToLocationBreakpointId = ""; | 1109 m_continueToLocationBreakpointId = ""; |
| 1131 } | 1110 } |
| 1132 return true; | |
| 1133 } | 1111 } |
| 1134 | 1112 |
| 1135 void V8DebuggerAgentImpl::didContinue() { | 1113 void V8DebuggerAgentImpl::didContinue() { |
| 1136 m_pausedContext.Reset(); | |
| 1137 JavaScriptCallFrames emptyCallFrames; | 1114 JavaScriptCallFrames emptyCallFrames; |
| 1138 m_pausedCallFrames.swap(emptyCallFrames); | 1115 m_pausedCallFrames.swap(emptyCallFrames); |
| 1139 clearBreakDetails(); | 1116 clearBreakDetails(); |
| 1140 m_frontend.resumed(); | 1117 m_frontend.resumed(); |
| 1141 } | 1118 } |
| 1142 | 1119 |
| 1143 void V8DebuggerAgentImpl::breakProgram( | 1120 void V8DebuggerAgentImpl::breakProgram( |
| 1144 const String16& breakReason, | 1121 const String16& breakReason, |
| 1145 std::unique_ptr<protocol::DictionaryValue> data) { | 1122 std::unique_ptr<protocol::DictionaryValue> data) { |
| 1146 if (!enabled() || m_skipAllPauses || !m_pausedContext.IsEmpty() || | 1123 if (!enabled() || !m_debugger->canBreakProgram()) return; |
| 1147 !m_debugger->canBreakProgram()) | |
| 1148 return; | |
| 1149 m_breakReason = breakReason; | 1124 m_breakReason = breakReason; |
| 1150 m_breakAuxData = std::move(data); | 1125 m_breakAuxData = std::move(data); |
| 1151 m_scheduledDebuggerStep = NoStep; | 1126 m_scheduledDebuggerStep = NoStep; |
| 1152 m_debugger->breakProgram(); | 1127 m_debugger->breakProgram(); |
| 1153 } | 1128 } |
| 1154 | 1129 |
| 1155 void V8DebuggerAgentImpl::breakProgramOnException( | 1130 void V8DebuggerAgentImpl::breakProgramOnException( |
| 1156 const String16& breakReason, | 1131 const String16& breakReason, |
| 1157 std::unique_ptr<protocol::DictionaryValue> data) { | 1132 std::unique_ptr<protocol::DictionaryValue> data) { |
| 1158 if (!enabled() || | 1133 if (!enabled() || |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1186 void V8DebuggerAgentImpl::reset() { | 1161 void V8DebuggerAgentImpl::reset() { |
| 1187 if (!enabled()) return; | 1162 if (!enabled()) return; |
| 1188 m_scheduledDebuggerStep = NoStep; | 1163 m_scheduledDebuggerStep = NoStep; |
| 1189 m_blackboxedPositions.clear(); | 1164 m_blackboxedPositions.clear(); |
| 1190 resetBlackboxedStateCache(); | 1165 resetBlackboxedStateCache(); |
| 1191 m_scripts.clear(); | 1166 m_scripts.clear(); |
| 1192 m_breakpointIdToDebuggerBreakpointIds.clear(); | 1167 m_breakpointIdToDebuggerBreakpointIds.clear(); |
| 1193 } | 1168 } |
| 1194 | 1169 |
| 1195 } // namespace v8_inspector | 1170 } // namespace v8_inspector |
| OLD | NEW |