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/DebuggerCallFrame.cpp

    r261755 r266534  
    219219JSValue DebuggerCallFrame::evaluateWithScopeExtension(const String& script, JSObject* scopeExtensionObject, NakedPtr<Exception>& exception)
    220220{
    221     ASSERT(isValid());
    222     CallFrame* callFrame = m_validMachineFrame;
    223     if (!callFrame)
     221    CallFrame* callFrame = nullptr;
     222    CodeBlock* codeBlock = nullptr;
     223
     224    auto* debuggerCallFrame = this;
     225    while (debuggerCallFrame) {
     226        ASSERT(debuggerCallFrame->isValid());
     227
     228        callFrame = debuggerCallFrame->m_validMachineFrame;
     229        if (callFrame) {
     230            if (debuggerCallFrame->isTailDeleted())
     231                codeBlock = debuggerCallFrame->m_shadowChickenFrame.codeBlock;
     232            else
     233                codeBlock = callFrame->codeBlock();
     234        }
     235
     236        if (callFrame && codeBlock)
     237            break;
     238
     239        debuggerCallFrame = debuggerCallFrame->m_caller.get();
     240    }
     241
     242    if (!callFrame || !codeBlock)
    224243        return jsUndefined();
    225244
     
    227246    JSLockHolder lock(vm);
    228247    auto catchScope = DECLARE_CATCH_SCOPE(vm);
    229 
    230     CodeBlock* codeBlock = nullptr;
    231     if (isTailDeleted())
    232         codeBlock = m_shadowChickenFrame.codeBlock;
    233     else
    234         codeBlock = callFrame->codeBlock();
    235     if (!codeBlock)
    236         return jsUndefined();
    237248   
    238249    JSGlobalObject* globalObject = codeBlock->globalObject();
     
    264275    }
    265276
    266     JSValue thisValue = this->thisValue(vm);
    267     JSValue result = vm.interpreter->execute(eval, globalObject, thisValue, scope()->jsScope());
     277    JSValue result = vm.interpreter->execute(eval, globalObject, debuggerCallFrame->thisValue(vm), debuggerCallFrame->scope()->jsScope());
    268278    if (UNLIKELY(catchScope.exception())) {
    269279        exception = catchScope.exception();
Note: See TracChangeset for help on using the changeset viewer.