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; | 193 m_skipAllPauses = false; |
| 194 m_state->setBoolean(DebuggerAgentState::skipAllPauses, false); |
198 m_state->remove(DebuggerAgentState::blackboxPattern); | 195 m_state->remove(DebuggerAgentState::blackboxPattern); |
199 m_enabled = false; | 196 m_enabled = false; |
200 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); | 197 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); |
201 return Response::OK(); | 198 return Response::OK(); |
202 } | 199 } |
203 | 200 |
204 void V8DebuggerAgentImpl::restore() { | 201 void V8DebuggerAgentImpl::restore() { |
205 DCHECK(!m_enabled); | 202 DCHECK(!m_enabled); |
206 if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) | 203 if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) |
207 return; | 204 return; |
(...skipping 21 matching lines...) Expand all Loading... |
229 } | 226 } |
230 } | 227 } |
231 | 228 |
232 Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { | 229 Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { |
233 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 230 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
234 m_debugger->setBreakpointsActivated(active); | 231 m_debugger->setBreakpointsActivated(active); |
235 return Response::OK(); | 232 return Response::OK(); |
236 } | 233 } |
237 | 234 |
238 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { | 235 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { |
| 236 m_state->setBoolean(DebuggerAgentState::skipAllPauses, skip); |
239 m_skipAllPauses = skip; | 237 m_skipAllPauses = skip; |
240 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses); | |
241 return Response::OK(); | 238 return Response::OK(); |
242 } | 239 } |
243 | 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); |
(...skipping 290 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(); |
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()) return stepInto(); |
640 m_scheduledDebuggerStep = StepOver; | 636 m_scheduledDebuggerStep = StepOver; |
641 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 637 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
642 m_debugger->stepOverStatement(); | 638 m_debugger->stepOverStatement(); |
643 return Response::OK(); | 639 return Response::OK(); |
644 } | 640 } |
645 | 641 |
646 Response V8DebuggerAgentImpl::stepInto() { | 642 Response V8DebuggerAgentImpl::stepInto() { |
647 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 643 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
648 m_scheduledDebuggerStep = StepInto; | 644 m_scheduledDebuggerStep = StepInto; |
649 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 645 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
650 m_debugger->stepIntoStatement(); | 646 m_debugger->stepIntoStatement(); |
651 return Response::OK(); | 647 return Response::OK(); |
652 } | 648 } |
653 | 649 |
654 Response V8DebuggerAgentImpl::stepOut() { | 650 Response V8DebuggerAgentImpl::stepOut() { |
655 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 651 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
656 m_scheduledDebuggerStep = StepOut; | 652 m_scheduledDebuggerStep = StepOut; |
657 m_recursionLevelForStepOut = 1; | 653 m_recursionLevelForStepOut = 1; |
658 m_session->releaseObjectGroup(kBacktraceObjectGroup); | 654 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
659 m_debugger->stepOutOfFunction(); | 655 m_debugger->stepOutOfFunction(); |
660 return Response::OK(); | 656 return Response::OK(); |
661 } | 657 } |
662 | 658 |
663 Response V8DebuggerAgentImpl::setPauseOnExceptions( | 659 Response V8DebuggerAgentImpl::setPauseOnExceptions( |
664 const String16& stringPauseState) { | 660 const String16& stringPauseState) { |
665 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 661 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
(...skipping 17 matching lines...) Expand all Loading... |
683 static_cast<v8::debug::ExceptionBreakState>(pauseState)); | 679 static_cast<v8::debug::ExceptionBreakState>(pauseState)); |
684 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); | 680 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); |
685 } | 681 } |
686 | 682 |
687 Response V8DebuggerAgentImpl::evaluateOnCallFrame( | 683 Response V8DebuggerAgentImpl::evaluateOnCallFrame( |
688 const String16& callFrameId, const String16& expression, | 684 const String16& callFrameId, const String16& expression, |
689 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, | 685 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, |
690 Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, | 686 Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, |
691 std::unique_ptr<RemoteObject>* result, | 687 std::unique_ptr<RemoteObject>* result, |
692 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { | 688 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { |
693 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 689 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
694 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 690 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
695 callFrameId); | 691 callFrameId); |
696 Response response = scope.initialize(); | 692 Response response = scope.initialize(); |
697 if (!response.isSuccess()) return response; | 693 if (!response.isSuccess()) return response; |
698 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) | 694 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
699 return Response::Error("Could not find call frame with given id"); | 695 return Response::Error("Could not find call frame with given id"); |
700 | 696 |
701 if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); | 697 if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); |
702 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); | 698 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); |
703 | 699 |
704 v8::MaybeLocal<v8::Value> maybeResultValue = | 700 v8::MaybeLocal<v8::Value> maybeResultValue = |
705 m_pausedCallFrames[scope.frameOrdinal()]->evaluate( | 701 m_pausedCallFrames[scope.frameOrdinal()]->evaluate( |
706 toV8String(m_isolate, expression)); | 702 toV8String(m_isolate, expression)); |
707 | 703 |
708 // Re-initialize after running client's code, as it could have destroyed | 704 // Re-initialize after running client's code, as it could have destroyed |
709 // context or session. | 705 // context or session. |
710 response = scope.initialize(); | 706 response = scope.initialize(); |
711 if (!response.isSuccess()) return response; | 707 if (!response.isSuccess()) return response; |
712 return scope.injectedScript()->wrapEvaluateResult( | 708 return scope.injectedScript()->wrapEvaluateResult( |
713 maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), | 709 maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), |
714 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, | 710 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, |
715 exceptionDetails); | 711 exceptionDetails); |
716 } | 712 } |
717 | 713 |
718 Response V8DebuggerAgentImpl::setVariableValue( | 714 Response V8DebuggerAgentImpl::setVariableValue( |
719 int scopeNumber, const String16& variableName, | 715 int scopeNumber, const String16& variableName, |
720 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, | 716 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, |
721 const String16& callFrameId) { | 717 const String16& callFrameId) { |
722 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 718 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
723 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); | 719 if (!isPaused()) return Response::Error(kDebuggerNotPaused); |
724 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 720 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
725 callFrameId); | 721 callFrameId); |
726 Response response = scope.initialize(); | 722 Response response = scope.initialize(); |
727 if (!response.isSuccess()) return response; | 723 if (!response.isSuccess()) return response; |
728 v8::Local<v8::Value> newValue; | 724 v8::Local<v8::Value> newValue; |
729 response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), | 725 response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), |
730 &newValue); | 726 &newValue); |
731 if (!response.isSuccess()) return response; | 727 if (!response.isSuccess()) return response; |
732 | 728 |
733 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) | 729 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."); | 818 "Input positions array is not sorted or contains duplicate values."); |
823 } | 819 } |
824 | 820 |
825 m_blackboxedPositions[scriptId] = positions; | 821 m_blackboxedPositions[scriptId] = positions; |
826 it->second->resetBlackboxedStateCache(); | 822 it->second->resetBlackboxedStateCache(); |
827 return Response::OK(); | 823 return Response::OK(); |
828 } | 824 } |
829 | 825 |
830 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { | 826 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { |
831 changeJavaScriptRecursionLevel(+1); | 827 changeJavaScriptRecursionLevel(+1); |
832 // Fast return. | |
833 if (m_scheduledDebuggerStep != StepInto) return; | 828 if (m_scheduledDebuggerStep != StepInto) return; |
834 schedulePauseOnNextStatementIfSteppingInto(); | 829 schedulePauseOnNextStatementIfSteppingInto(); |
835 } | 830 } |
836 | 831 |
837 void V8DebuggerAgentImpl::didExecuteScript() { | 832 void V8DebuggerAgentImpl::didExecuteScript() { |
838 changeJavaScriptRecursionLevel(-1); | 833 changeJavaScriptRecursionLevel(-1); |
839 } | 834 } |
840 | 835 |
841 void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { | 836 void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { |
842 if (m_javaScriptPauseScheduled && !m_skipAllPauses && | 837 if (m_javaScriptPauseScheduled && !m_skipAllPauses && !isPaused()) { |
843 !m_debugger->isPaused()) { | |
844 // Do not ever loose user's pause request until we have actually paused. | 838 // Do not ever loose user's pause request until we have actually paused. |
845 m_debugger->setPauseOnNextStatement(true); | 839 m_debugger->setPauseOnNextStatement(true); |
846 } | 840 } |
847 if (m_scheduledDebuggerStep == StepOut) { | 841 if (m_scheduledDebuggerStep == StepOut) { |
848 m_recursionLevelForStepOut += step; | 842 m_recursionLevelForStepOut += step; |
849 if (!m_recursionLevelForStepOut) { | 843 if (!m_recursionLevelForStepOut) { |
850 // When StepOut crosses a task boundary (i.e. js -> c++) from where it was | 844 // When StepOut crosses a task boundary (i.e. js -> c++) from where it was |
851 // requested, | 845 // requested, |
852 // switch stepping to step into a next JS task, as if we exited to a | 846 // switch stepping to step into a next JS task, as if we exited to a |
853 // blackboxed framework. | 847 // blackboxed framework. |
854 m_scheduledDebuggerStep = StepInto; | 848 m_scheduledDebuggerStep = StepInto; |
855 } | 849 } |
856 } | 850 } |
857 } | 851 } |
858 | 852 |
859 Response V8DebuggerAgentImpl::currentCallFrames( | 853 Response V8DebuggerAgentImpl::currentCallFrames( |
860 std::unique_ptr<Array<CallFrame>>* result) { | 854 std::unique_ptr<Array<CallFrame>>* result) { |
861 if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) { | 855 if (!isPaused()) { |
862 *result = Array<CallFrame>::create(); | 856 *result = Array<CallFrame>::create(); |
863 return Response::OK(); | 857 return Response::OK(); |
864 } | 858 } |
865 v8::HandleScope handles(m_isolate); | 859 v8::HandleScope handles(m_isolate); |
866 v8::Local<v8::Context> debuggerContext = | 860 v8::Local<v8::Context> debuggerContext = |
867 v8::debug::GetDebugContext(m_isolate); | 861 v8::debug::GetDebugContext(m_isolate); |
868 v8::Context::Scope contextScope(debuggerContext); | 862 v8::Context::Scope contextScope(debuggerContext); |
869 | 863 |
870 v8::Local<v8::Array> objects = v8::Array::New(m_isolate); | 864 v8::Local<v8::Array> objects = v8::Array::New(m_isolate); |
871 | 865 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 if (!response.isSuccess()) return response; | 954 if (!response.isSuccess()) return response; |
961 protocol::ErrorSupport errorSupport; | 955 protocol::ErrorSupport errorSupport; |
962 *result = Array<CallFrame>::fromValue(protocolValue.get(), &errorSupport); | 956 *result = Array<CallFrame>::fromValue(protocolValue.get(), &errorSupport); |
963 if (!*result) return Response::Error(errorSupport.errors()); | 957 if (!*result) return Response::Error(errorSupport.errors()); |
964 TranslateWasmStackTraceLocations(result->get(), | 958 TranslateWasmStackTraceLocations(result->get(), |
965 m_debugger->wasmTranslation()); | 959 m_debugger->wasmTranslation()); |
966 return Response::OK(); | 960 return Response::OK(); |
967 } | 961 } |
968 | 962 |
969 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { | 963 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { |
970 if (m_pausedContext.IsEmpty()) return nullptr; | 964 if (!isPaused()) return nullptr; |
971 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); | 965 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); |
972 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) | 966 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) |
973 : nullptr; | 967 : nullptr; |
974 } | 968 } |
975 | 969 |
| 970 bool V8DebuggerAgentImpl::isPaused() const { return m_debugger->isPaused(); } |
| 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)); |
981 if (!success) | 977 if (!success) |
982 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); | 978 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); |
983 | 979 |
984 int contextId = script->executionContextId(); | 980 int contextId = script->executionContextId(); |
985 int contextGroupId = m_inspector->contextGroupId(contextId); | 981 int contextGroupId = m_inspector->contextGroupId(contextId); |
(...skipping 63 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) { | |
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(); | 1060 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); |
1074 m_pausedCallFrames.swap(frames); | 1061 m_pausedCallFrames.swap(frames); |
1075 m_pausedContext.Reset(m_isolate, context); | |
1076 v8::HandleScope handles(m_isolate); | 1062 v8::HandleScope handles(m_isolate); |
1077 | 1063 |
1078 if (isOOMBreak) { | 1064 if (isOOMBreak) { |
1079 m_breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; | 1065 m_breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; |
1080 m_breakAuxData = nullptr; | 1066 m_breakAuxData = nullptr; |
1081 } else if (!exception.IsEmpty()) { | 1067 } else if (!exception.IsEmpty()) { |
1082 InjectedScript* injectedScript = nullptr; | 1068 InjectedScript* injectedScript = nullptr; |
1083 m_session->findInjectedScript(InspectedContext::contextId(context), | 1069 m_session->findInjectedScript(contextId, injectedScript); |
1084 injectedScript); | |
1085 if (injectedScript) { | 1070 if (injectedScript) { |
1086 m_breakReason = | 1071 m_breakReason = |
1087 isPromiseRejection | 1072 isPromiseRejection |
1088 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection | 1073 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection |
1089 : protocol::Debugger::Paused::ReasonEnum::Exception; | 1074 : protocol::Debugger::Paused::ReasonEnum::Exception; |
1090 std::unique_ptr<protocol::Runtime::RemoteObject> obj; | 1075 std::unique_ptr<protocol::Runtime::RemoteObject> obj; |
1091 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, | 1076 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, |
1092 &obj); | 1077 &obj); |
1093 if (obj) { | 1078 if (obj) { |
1094 m_breakAuxData = obj->toValue(); | 1079 m_breakAuxData = obj->toValue(); |
(...skipping 27 matching lines...) Expand all Loading... |
1122 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, | 1107 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, |
1123 std::move(m_breakAuxData), std::move(hitBreakpointIds), | 1108 std::move(m_breakAuxData), std::move(hitBreakpointIds), |
1124 currentAsyncStackTrace()); | 1109 currentAsyncStackTrace()); |
1125 m_scheduledDebuggerStep = NoStep; | 1110 m_scheduledDebuggerStep = NoStep; |
1126 m_javaScriptPauseScheduled = false; | 1111 m_javaScriptPauseScheduled = false; |
1127 | 1112 |
1128 if (!m_continueToLocationBreakpointId.isEmpty()) { | 1113 if (!m_continueToLocationBreakpointId.isEmpty()) { |
1129 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); | 1114 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); |
1130 m_continueToLocationBreakpointId = ""; | 1115 m_continueToLocationBreakpointId = ""; |
1131 } | 1116 } |
1132 return true; | |
1133 } | 1117 } |
1134 | 1118 |
1135 void V8DebuggerAgentImpl::didContinue() { | 1119 void V8DebuggerAgentImpl::didContinue() { |
1136 m_pausedContext.Reset(); | |
1137 JavaScriptCallFrames emptyCallFrames; | 1120 JavaScriptCallFrames emptyCallFrames; |
1138 m_pausedCallFrames.swap(emptyCallFrames); | 1121 m_pausedCallFrames.swap(emptyCallFrames); |
1139 clearBreakDetails(); | 1122 clearBreakDetails(); |
1140 m_frontend.resumed(); | 1123 m_frontend.resumed(); |
1141 } | 1124 } |
1142 | 1125 |
1143 void V8DebuggerAgentImpl::breakProgram( | 1126 void V8DebuggerAgentImpl::breakProgram( |
1144 const String16& breakReason, | 1127 const String16& breakReason, |
1145 std::unique_ptr<protocol::DictionaryValue> data) { | 1128 std::unique_ptr<protocol::DictionaryValue> data) { |
1146 if (!enabled() || m_skipAllPauses || !m_pausedContext.IsEmpty() || | 1129 if (!enabled() || !m_debugger->canBreakProgram() || m_skipAllPauses) return; |
1147 !m_debugger->canBreakProgram()) | |
1148 return; | |
1149 m_breakReason = breakReason; | 1130 m_breakReason = breakReason; |
1150 m_breakAuxData = std::move(data); | 1131 m_breakAuxData = std::move(data); |
1151 m_scheduledDebuggerStep = NoStep; | 1132 m_scheduledDebuggerStep = NoStep; |
1152 m_debugger->breakProgram(); | 1133 m_debugger->breakProgram(); |
1153 } | 1134 } |
1154 | 1135 |
1155 void V8DebuggerAgentImpl::breakProgramOnException( | 1136 void V8DebuggerAgentImpl::breakProgramOnException( |
1156 const String16& breakReason, | 1137 const String16& breakReason, |
1157 std::unique_ptr<protocol::DictionaryValue> data) { | 1138 std::unique_ptr<protocol::DictionaryValue> data) { |
1158 if (!enabled() || | 1139 if (!enabled() || |
(...skipping 27 matching lines...) Expand all Loading... |
1186 void V8DebuggerAgentImpl::reset() { | 1167 void V8DebuggerAgentImpl::reset() { |
1187 if (!enabled()) return; | 1168 if (!enabled()) return; |
1188 m_scheduledDebuggerStep = NoStep; | 1169 m_scheduledDebuggerStep = NoStep; |
1189 m_blackboxedPositions.clear(); | 1170 m_blackboxedPositions.clear(); |
1190 resetBlackboxedStateCache(); | 1171 resetBlackboxedStateCache(); |
1191 m_scripts.clear(); | 1172 m_scripts.clear(); |
1192 m_breakpointIdToDebuggerBreakpointIds.clear(); | 1173 m_breakpointIdToDebuggerBreakpointIds.clear(); |
1193 } | 1174 } |
1194 | 1175 |
1195 } // namespace v8_inspector | 1176 } // namespace v8_inspector |
OLD | NEW |