Ignore:
Timestamp:
Sep 3, 2020, 10:53:21 AM (5 years ago)
Author:
Devin Rousso
Message:

Web Inspector: allow special JavaScript breakpoints to be configured
https://bugs.webkit.org/show_bug.cgi?id=215794

Reviewed by Brian Burg.

Source/JavaScriptCore:

  • inspector/protocol/Debugger.json:

Add an options parameter to the following commands for configuring the related breakpoint:

  • Debugger.setPauseOnDebuggerStatements
  • Debugger.setPauseOnExceptions
  • Debugger.setPauseOnAssertions
  • Debugger.setPauseOnMicrotasks
  • debugger/Debugger.h:

(JSC::Debugger::needsExceptionCallbacks const):
(JSC::Debugger::pauseOnAllExceptionsBreakpoint const): Added.
(JSC::Debugger::setPauseOnAllExceptionsBreakpoint): Added.
(JSC::Debugger::pauseOnUncaughtExceptionsBreakpoint const): Added.
(JSC::Debugger::setPauseOnUncaughtExceptionsBreakpoint): Added.
(JSC::Debugger::setPauseOnDebuggerStatementsBreakpoint): Added.
(JSC::Debugger::pauseOnExceptionsState const): Deleted.
(JSC::Debugger::setPauseOnDebuggerStatements): Deleted.

  • debugger/Debugger.cpp:

(JSC::Debugger::TemporarilyDisableExceptionBreakpoints::TemporarilyDisableExceptionBreakpoints): Added.
(JSC::Debugger::TemporarilyDisableExceptionBreakpoints::~TemporarilyDisableExceptionBreakpoints): Added.
(JSC::Debugger::TemporarilyDisableExceptionBreakpoints::replace): Added.
(JSC::Debugger::TemporarilyDisableExceptionBreakpoints::restore): Added.
(JSC::Debugger::Debugger):
(JSC::Debugger::breakProgram):
(JSC::Debugger::exception):
(JSC::Debugger::didReachDebuggerStatement):
(JSC::Debugger::setPauseOnExceptionsState): Deleted.
Add JSC::Breakpoint member variables for the Debugger Statements and Exceptions
breakpoints. Split the Exceptions breakpoint into two JSC::Breakpoint now that
All Exceptions and Uncaught Exceptions can be independently configured (the All
Exceptions breakpoint still takes precedence).

  • debugger/DebuggerCallFrame.h:
  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::evaluateWithScopeExtension):
If there is no CallFrame, climb the backtrace until the first valid CallFrame is reached.
This is needed when pausing in native code, such as for assertions/exceptions.

  • debugger/Breakpoint.h:

Export JSC::Breakpoint::create so that other parts of WebKit can create breakpoints.

  • inspector/agents/InspectorDebuggerAgent.h:
  • inspector/agents/InspectorDebuggerAgent.cpp:

(Inspector::InspectorDebuggerAgent::disable):
(Inspector::InspectorDebuggerAgent::handleConsoleAssert):
(Inspector::InspectorDebuggerAgent::setPauseOnDebuggerStatements):
(Inspector::InspectorDebuggerAgent::setPauseOnExceptions):
(Inspector::InspectorDebuggerAgent::setPauseOnAssertions):
(Inspector::InspectorDebuggerAgent::setPauseOnMicrotasks):
(Inspector::InspectorDebuggerAgent::evaluateOnCallFrame):
(Inspector::InspectorDebuggerAgent::scriptExecutionBlockedByCSP):
(Inspector::InspectorDebuggerAgent::willRunMicrotask):
(Inspector::InspectorDebuggerAgent::didRunMicrotask):
(Inspector::InspectorDebuggerAgent::breakProgram):
Add JSC::Breakpoint member variables for the Assertion Failures and All Microtasks
breakpoints. Pass them to the JSC::Debugger when they are hit.

  • inspector/agents/InspectorAuditAgent.cpp:

(Inspector::InspectorAuditAgent::run):

  • inspector/agents/InspectorRuntimeAgent.cpp:

(Inspector::InspectorRuntimeAgent::evaluate):
(Inspector::InspectorRuntimeAgent::callFunctionOn):
(Inspector::InspectorRuntimeAgent::getPreview):
(Inspector::InspectorRuntimeAgent::getProperties):
(Inspector::InspectorRuntimeAgent::getDisplayableProperties):
(Inspector::setPauseOnExceptionsState): Deleted.
Use TemporarilyDisableExceptionBreakpoints to save, override, and restore the exceptions
breakpoints now that they've been separated into two JSC::Breakpoint instead of an enum.

Source/WebInspectorUI:

  • UserInterface/Models/Breakpoint.js:

(WI.Breakpoint.prototype.reset): Added.
Provide a way to consistently clear the current configuration.

  • UserInterface/Models/JavaScriptBreakpoint.js:

(WI.JavaScriptBreakpoint.supportsMicrotasks): Added.
(WI.JavaScriptBreakpoint.supportsDebuggerStatements): Added.
(WI.JavaScriptBreakpoint.fromJSON):
(WI.JavaScriptBreakpoint.prototype.toJSON):
(WI.JavaScriptBreakpoint.prototype.get editable):
(WI.JavaScriptBreakpoint.prototype._isSpecial):

  • UserInterface/Models/SourceCodeLocation.js:

(WI.SourceCodeLocation.get specialBreakpointLocation): Added.
Add a helper for the special null:Infinity:Infinity breakpoint location for consistency.

  • UserInterface/Controllers/DebuggerManager.js:

(WI.DebuggerManager):
(WI.DebuggerManager.prototype.async initializeTarget):
(WI.DebuggerManager.prototype.createAssertionFailuresBreakpoint): Added.
(WI.DebuggerManager.prototype.createAllMicrotasksBreakpoint): Added.
(WI.DebuggerManager.prototype.set breakpointsEnabled):
(WI.DebuggerManager.prototype.addBreakpoint):
(WI.DebuggerManager.prototype.removeBreakpoint):
(WI.DebuggerManager.prototype._setPauseOnExceptions): Added.
(WI.DebuggerManager.prototype._createSpecialBreakpoint): Added.
(WI.DebuggerManager.prototype._updateSpecialBreakpoint): Added.
(WI.DebuggerManager.prototype._breakpointDisabledStateDidChange):
(WI.DebuggerManager.prototype._breakpointEditablePropertyDidChange):
(WI.DebuggerManager.prototype._updateBreakOnExceptionsState): Deleted.
Maintain a WI.Setting for the configuration of each special WI.JavaScriptBreakpoint.
Have a common path for updating all special WI.JavaScriptBreakpoint to avoid duplicated
code.
Add methods for creating the Assertion Failures and All Microtasks WI.JavaScriptBreakpoint
since they can be removed (in addition to being disabled) and re-added.

  • UserInterface/Views/BreakpointPopover.js:

(WI.BreakpointPopover.appendContextMenuItems):

  • UserInterface/Views/BreakpointTreeElement.js:

(WI.BreakpointTreeElement.prototype.ondelete):
If the WI.Breakpoint is not removable, make sure to reset it in addition to disabling
it so that no configuration persists if the WI.Breakpoint is later enabled.

  • UserInterface/Views/SourcesNavigationSidebarPanel.js:

(WI.SourcesNavigationSidebarPanel):
(WI.SourcesNavigationSidebarPanel.prototype._handleBreakpointTreeOutlineElementRemoved): Added.
(WI.SourcesNavigationSidebarPanel.prototype._handleBreakpointElementAddedOrRemoved): Deleted.
Eliminate the need to listen for when breakpoints are added to the WI.TreeOutline, which
was previously used to update the WI.Setting for whether special WI.JavaScriptBreakpoint
are visible.
Don't assume that a WI.Breakpoint exists for each special WI.JavaScriptBreakpoint.

  • UserInterface/Base/Setting.js:

(WI.Setting):
(WI.Setting.migrateValue):
(WI.Setting.reset):
(WI.Setting.prototype.get value):
(WI.Setting.prototype.save):
(WI.Setting._localStorageKeyPrefix): Added.
(WI.Setting._localStorageKey): Deleted.
Eagerly compute the key prefix as it shouldn't change through the lifetime of Web Inspector
and is used early on too.
Add a static member isFirstLaunch which can be used by other WI.Setting to adjust their
value when Web Inspector is in a clean state (e.g. show the Assertion Failures breakpoint by
default, but only for the first launch). This is needed because WI.Setting clears the key
from localStorage if the current value matches the _defaultValue.

  • UserInterface/Models/ProbeSet.js:

(WI.ProbeSet):
(WI.ProbeSet.prototype.willRemove):
(WI.ProbeSet.prototype._sampleCollected):
(WI.ProbeSet.prototype._breakpointResolvedStateDidChange): Deleted.
Drive-by: remove an unused event.

  • Localizations/en.lproj/localizedStrings.js:

Source/WebKitLegacy/mac:

  • WebView/WebScriptDebugger.mm:

(WebScriptDebugger::WebScriptDebugger):

LayoutTests:

  • inspector/debugger/resources/breakpoint-options-utilities.js: Added.

(TestPage.registerInitializer.InspectorTest.BreakpointOptions.addTestCases):
(TestPage.registerInitializer.InspectorTest.BreakpointOptions.addTestCases.removeBreakpoint):

  • inspector/debugger/break-on-exception.html:
  • inspector/debugger/break-on-exception-expected.txt:
  • inspector/debugger/break-on-uncaught-exception.html:
  • inspector/debugger/break-on-uncaught-exception-expected.txt:
  • inspector/debugger/setPauseOnAssertions.html:
  • inspector/debugger/setPauseOnAssertions-expected.txt:
  • inspector/debugger/setPauseOnDebuggerStatements.html:
  • inspector/debugger/setPauseOnDebuggerStatements-expected.txt:
  • inspector/debugger/setPauseOnMicrotasks.html:
  • inspector/debugger/setPauseOnMicrotasks-expected.txt:

Add tests for global JavaScript breakpoint configuration options.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/debugger/Debugger.cpp

    r266074 r266534  
    7878};
    7979
     80Debugger::TemporarilyDisableExceptionBreakpoints::TemporarilyDisableExceptionBreakpoints(Debugger& debugger)
     81    : m_debugger(debugger)
     82{
     83}
     84
     85Debugger::TemporarilyDisableExceptionBreakpoints::~TemporarilyDisableExceptionBreakpoints()
     86{
     87    restore();
     88}
     89
     90void Debugger::TemporarilyDisableExceptionBreakpoints::replace()
     91{
     92    if (m_debugger.m_pauseOnAllExceptionsBreakpoint)
     93        m_pauseOnAllExceptionsBreakpoint = WTFMove(m_debugger.m_pauseOnAllExceptionsBreakpoint);
     94
     95    if (m_debugger.m_pauseOnUncaughtExceptionsBreakpoint)
     96        m_pauseOnUncaughtExceptionsBreakpoint = WTFMove(m_debugger.m_pauseOnUncaughtExceptionsBreakpoint);
     97}
     98
     99void Debugger::TemporarilyDisableExceptionBreakpoints::restore()
     100{
     101    if (m_pauseOnAllExceptionsBreakpoint)
     102        m_debugger.m_pauseOnAllExceptionsBreakpoint = WTFMove(m_pauseOnAllExceptionsBreakpoint);
     103
     104    if (m_pauseOnUncaughtExceptionsBreakpoint)
     105        m_debugger.m_pauseOnUncaughtExceptionsBreakpoint = WTFMove(m_pauseOnUncaughtExceptionsBreakpoint);
     106}
     107
    80108
    81109Debugger::ProfilingClient::~ProfilingClient()
     
    85113Debugger::Debugger(VM& vm)
    86114    : m_vm(vm)
    87     , m_pauseOnExceptionsState(DontPauseOnExceptions)
    88115    , m_pauseAtNextOpportunity(false)
    89116    , m_pastFirstExpressionInStatement(false)
     
    689716}
    690717
    691 void Debugger::setPauseOnExceptionsState(PauseOnExceptionsState pause)
    692 {
    693     m_pauseOnExceptionsState = pause;
    694 }
    695 
    696718void Debugger::schedulePauseAtNextOpportunity()
    697719{
     
    725747}
    726748
    727 void Debugger::breakProgram()
     749void Debugger::breakProgram(RefPtr<Breakpoint>&& specialBreakpoint)
    728750{
    729751    if (m_isPaused)
     
    733755        return;
    734756
    735     m_pauseAtNextOpportunity = true;
     757    if (specialBreakpoint) {
     758        ASSERT(!m_specialBreakpoint);
     759        m_specialBreakpoint = WTFMove(specialBreakpoint);
     760    } else
     761        m_pauseAtNextOpportunity = true;
     762
    736763    setSteppingMode(SteppingModeEnabled);
    737764    m_currentCallFrame = m_vm.topCallFrame;
     
    9811008
    9821009    PauseReasonDeclaration reason(*this, PausedForException);
    983     if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasCatchHandler)) {
    984         m_pauseAtNextOpportunity = true;
     1010    if (m_pauseOnAllExceptionsBreakpoint || (m_pauseOnUncaughtExceptionsBreakpoint && !hasCatchHandler)) {
     1011        m_specialBreakpoint = m_pauseOnAllExceptionsBreakpoint ? m_pauseOnAllExceptionsBreakpoint.copyRef() : m_pauseOnUncaughtExceptionsBreakpoint.copyRef();
    9851012        setSteppingMode(SteppingModeEnabled);
    9861013    }
     
    11331160        return;
    11341161
    1135     if (!m_pauseOnDebuggerStatements)
     1162    if (!m_pauseOnDebuggerStatementsBreakpoint)
    11361163        return;
    11371164
    11381165    PauseReasonDeclaration reason(*this, PausedForDebuggerStatement);
    1139     m_pauseAtNextOpportunity = true;
     1166    m_specialBreakpoint = m_pauseOnDebuggerStatementsBreakpoint.copyRef();
    11401167    setSteppingMode(SteppingModeEnabled);
    11411168    updateCallFrame(lexicalGlobalObjectForCallFrame(m_vm, callFrame), callFrame, AttemptPause);
Note: See TracChangeset for help on using the changeset viewer.