Changeset 290720 in webkit for trunk/Source/JavaScriptCore/debugger/Debugger.cpp
- Timestamp:
- Mar 1, 2022, 10:42:27 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/debugger/Debugger.cpp
r290575 r290720 114 114 Debugger::Debugger(VM& vm) 115 115 : m_vm(vm) 116 , m_blackboxBreakpointEvaluations(false) 116 117 , m_pauseAtNextOpportunity(false) 117 118 , m_pastFirstExpressionInStatement(false) … … 544 545 } 545 546 546 RefPtr<Breakpoint> Debugger::didHitBreakpoint( JSGlobalObject* globalObject,SourceID sourceID, const TextPosition& position)547 RefPtr<Breakpoint> Debugger::didHitBreakpoint(SourceID sourceID, const TextPosition& position) 547 548 { 548 549 if (!m_breakpointsActivated) … … 566 567 // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0). 567 568 ASSERT(this == m_currentCallFrame->codeBlock()->globalObject()->debugger()); 568 if ((line != m_lastExecutedLine && line == breakLine && !breakColumn) || (line == breakLine && column == breakColumn)) { 569 if (breakpoint->shouldPause(*this, globalObject)) 570 return breakpoint.copyRef(); 571 break; 572 } 569 if ((line != m_lastExecutedLine && line == breakLine && !breakColumn) || (line == breakLine && column == breakColumn)) 570 return breakpoint.copyRef(); 573 571 } 574 572 … … 607 605 bool Debugger::evaluateBreakpointCondition(Breakpoint& breakpoint, JSGlobalObject* globalObject) 608 606 { 607 ASSERT(m_isPaused); 608 ASSERT(isAttached(globalObject)); 609 609 610 const String& condition = breakpoint.condition(); 610 611 if (condition.isEmpty()) 611 612 return true; 612 613 // We cannot stop in the debugger while executing condition code,614 // so make it looks like the debugger is already paused.615 TemporaryPausedState pausedState(*this);616 613 617 614 NakedPtr<Exception> exception; … … 782 779 { 783 780 clearNextPauseState(); 781 m_deferredBreakpoints.clear(); 784 782 785 783 if (!m_isPaused) … … 884 882 DebuggerPausedScope debuggerPausedScope(*this); 885 883 886 bool pauseNow = m_pauseAtNextOpportunity; 887 pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame); 888 889 bool didPauseForStep = pauseNow; 884 bool afterBlackboxedScript = m_afterBlackboxedScript; 885 bool pauseNow = false; 886 bool didPauseForStep = false; 887 if (m_pauseAtNextOpportunity) { 888 pauseNow = true; 889 didPauseForStep = !afterBlackboxedScript; 890 } else if (m_pauseOnStepNext || m_pauseOnStepOut || (m_pauseOnCallFrame == m_currentCallFrame)) { 891 pauseNow = true; 892 didPauseForStep = true; 893 } 890 894 891 895 TextPosition position = DebuggerCallFrame::positionForCallFrame(vm, m_currentCallFrame); 892 896 893 auto breakpoint = didHitBreakpoint(globalObject, sourceID, position); 894 if (breakpoint) 897 if (auto breakpoint = didHitBreakpoint(sourceID, position)) { 895 898 pauseNow = true; 899 m_deferredBreakpoints.add(breakpoint.releaseNonNull()); 900 } 896 901 897 902 // Special breakpoints are only given one opportunity to pause. 898 auto specialBreakpoint = WTFMove(m_specialBreakpoint); 899 if (specialBreakpoint && specialBreakpoint->shouldPause(*this, globalObject)) 903 if (m_specialBreakpoint) { 900 904 pauseNow = true; 905 m_deferredBreakpoints.add(m_specialBreakpoint.releaseNonNull()); 906 } 901 907 902 908 m_lastExecutedLine = position.m_line.zeroBasedInt(); … … 904 910 return; 905 911 906 bool afterBlackboxedScript = m_afterBlackboxedScript;907 912 clearNextPauseState(); 908 913 … … 911 916 TemporaryPausedState pausedState(*this); 912 917 913 if (breakpoint || specialBreakpoint) { 914 // Note that the actions can potentially stop the debugger, so we need to check that 915 // we still have a current call frame when we get back. 916 917 bool autoContinue = false; 918 919 if (breakpoint) { 920 evaluateBreakpointActions(*breakpoint, globalObject); 921 918 auto shouldDeferPause = [&] () { 919 if (blackboxTypeIterator == m_blackboxedScripts.end()) 920 return false; 921 922 if (blackboxTypeIterator->value != BlackboxType::Deferred) 923 return false; 924 925 m_afterBlackboxedScript = true; 926 927 if (m_pausingBreakpointID != noBreakpointID) { 928 dispatchFunctionToObservers([&] (Observer& observer) { 929 observer.didDeferBreakpointPause(m_pausingBreakpointID); 930 }); 931 932 m_pausingBreakpointID = noBreakpointID; 933 } 934 935 schedulePauseAtNextOpportunity(); 936 return true; 937 }; 938 939 if (m_blackboxBreakpointEvaluations && shouldDeferPause()) 940 return; 941 942 if (!m_deferredBreakpoints.isEmpty()) { 943 std::optional<BreakpointID> pausingBreakpointID; 944 bool hasEvaluatedSpecialBreakpoint = false; 945 bool shouldContinue = true; 946 947 for (auto&& deferredBreakpoint : std::exchange(m_deferredBreakpoints, { })) { 948 // Note that breakpoint evaluations can potentially stop the debugger, so we need to 949 // check that we still have a current call frame after evaluating them. 950 951 bool shouldPause = deferredBreakpoint->shouldPause(*this, globalObject); 922 952 if (!m_currentCallFrame) 923 953 return; 924 925 if (breakpoint->isAutoContinue()) 926 autoContinue = true; 927 } 928 929 if (specialBreakpoint) { 930 evaluateBreakpointActions(*specialBreakpoint, globalObject); 931 954 if (!shouldPause) 955 continue; 956 957 evaluateBreakpointActions(deferredBreakpoint, globalObject); 932 958 if (!m_currentCallFrame) 933 959 return; 934 960 935 if (specialBreakpoint->isAutoContinue()) 936 autoContinue = true; 961 if (deferredBreakpoint->isAutoContinue()) 962 continue; 963 964 shouldContinue = false; 965 966 // Only propagate `PausedForBreakpoint` to the `InspectorDebuggerAgent` if the first 967 // line:column breakpoint hit was before the first special breakpoint, as the latter 968 // would already have set a unique reason before attempting to pause. 969 if (!deferredBreakpoint->isLinked()) 970 hasEvaluatedSpecialBreakpoint = true; 971 else if (!hasEvaluatedSpecialBreakpoint && !pausingBreakpointID) 972 pausingBreakpointID = deferredBreakpoint->id(); 937 973 } 938 974 939 if ( autoContinue) {975 if (shouldContinue) { 940 976 if (!didPauseForStep) 941 977 return; 942 943 breakpoint = nullptr; 944 specialBreakpoint = nullptr; 945 } else if (breakpoint) 946 m_pausingBreakpointID = breakpoint->id(); 947 } 948 949 if (blackboxTypeIterator != m_blackboxedScripts.end() && blackboxTypeIterator->value == BlackboxType::Deferred) { 950 m_afterBlackboxedScript = true; 951 schedulePauseAtNextOpportunity(); 952 return; 953 } 978 } else if (pausingBreakpointID) 979 m_pausingBreakpointID = *pausingBreakpointID; 980 } 981 982 if (!m_blackboxBreakpointEvaluations && shouldDeferPause()) 983 return; 954 984 955 985 { … … 957 987 if (afterBlackboxedScript) 958 988 reason = PausedAfterBlackboxedScript; 959 else if ( breakpoint)989 else if (m_pausingBreakpointID) 960 990 reason = PausedForBreakpoint; 961 991 PauseReasonDeclaration rauseReasonDeclaration(*this, reason); … … 1155 1185 1156 1186 // Do not continue stepping into an unknown future program. 1157 if (!m_currentCallFrame) 1187 if (!m_currentCallFrame) { 1158 1188 clearNextPauseState(); 1189 m_deferredBreakpoints.clear(); 1190 } 1159 1191 } 1160 1192 … … 1212 1244 } 1213 1245 1246 void Debugger::setBlackboxBreakpointEvaluations(bool blackboxBreakpointEvaluations) 1247 { 1248 m_blackboxBreakpointEvaluations = blackboxBreakpointEvaluations; 1249 } 1250 1214 1251 void Debugger::clearBlackbox() 1215 1252 {
Note:
See TracChangeset
for help on using the changeset viewer.