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 |