WebKit Bugzilla
Attachment 347331 Details for
Bug 183118
: Web Inspector: support breakpoints for arbitrary event names
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-183118-20180816180901.patch (text/plain), 66.75 KB, created by
Devin Rousso
on 2018-08-16 18:09:04 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Devin Rousso
Created:
2018-08-16 18:09:04 PDT
Size:
66.75 KB
patch
obsolete
>diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index f0bde7d118f7bd2bd57a5a913109c57f591a0457..e26b31c3630d39827f6bc45d42e46294ded7a48a 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,16 @@ >+2018-08-16 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: support breakpoints for arbitrary event names >+ https://bugs.webkit.org/show_bug.cgi?id=183118 >+ >+ Reviewed by Joseph Pecoraro. >+ >+ Tests: inspector/dom-debugger/event-breakpoints.html >+ inspector/dom-debugger/event-breakpoints-with-navigation.html >+ >+ * inspector/agents/InspectorDOMDebuggerAgent.cpp: >+ (WebCore::InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded): >+ > 2018-08-15 Ryosuke Niwa <rniwa@webkit.org> > > Can't share an app on AppStore to WeChat due to a release assert >diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index 03e178312a353f0c526fc249c7e3b97f30828f16..2d94f0319389148dac3ded53535408a11e10dc25 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,97 @@ >+2018-08-16 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: support breakpoints for arbitrary event names >+ https://bugs.webkit.org/show_bug.cgi?id=183118 >+ >+ Reviewed by Joseph Pecoraro. >+ >+ Create UI for setting breakpoints on event names. Ties into renamed DOMDebugger commands, >+ specifically `setEventBreakpoint` and `removeEventBreakpoint`, that will pause execution if >+ any DOM event is fired that matches any previously registered breakpoints. >+ >+ Event breakpoints are distinguished by name, and they currently apply globally, meaning >+ that only one breakpoint per event name can be registered. >+ >+ Event breakpoints are created in the Debugger tab in a new "Event Breakpoints" section in >+ the Navigation sidebar. A new type of popover, EventBreakpointPopover, is used, but right >+ now all it contains is a basic text input for the event name. Similarly, a new TreeElement >+ subclass, EventBreakpointTreeElement, is used when showing the list of event listener >+ breakpoints, but all it shows now is the event name. >+ >+ The majority of the logic in this patch was derived from XHR breakpoints. >+ >+ * Localizations/en.lproj/localizedStrings.js: >+ * UserInterface/Main.html: >+ * UserInterface/Test.html: >+ * UserInterface/Images/EventBreakpoint.svg: Added. >+ >+ * UserInterface/Models/EventBreakpoint.js: Added. >+ (WI.EventBreakpoint): >+ (WI.EventBreakpoint.prototype.get eventName): >+ (WI.EventBreakpoint.prototype.get disabled): >+ (WI.EventBreakpoint.prototype.set disabled): >+ (WI.EventBreakpoint.prototype.get serializableInfo): >+ (WI.EventBreakpoint.prototype.saveIdentityToCookie): >+ >+ * UserInterface/Controllers/DOMDebuggerManager.js: >+ (WI.DOMDebuggerManager): >+ (WI.DOMDebuggerManager.prototype.get eventBreakpoints): Added. >+ (WI.DOMDebuggerManager.prototype.eventBreakpointForEventName): Added. >+ (WI.DOMDebuggerManager.prototype.addEventBreakpoint): Added. >+ (WI.DOMDebuggerManager.prototype.removeEventBreakpoint): Added. >+ (WI.DOMDebuggerManager.prototype._speculativelyResolveBreakpoints): >+ (WI.DOMDebuggerManager.prototype._updateEventBreakpoint.breakpointUpdated): Added. >+ (WI.DOMDebuggerManager.prototype._updateEventBreakpoint): Added. >+ (WI.DOMDebuggerManager.prototype._resolveEventBreakpoint): Added. >+ (WI.DOMDebuggerManager.prototype._saveEventBreakpoints): Added. >+ (WI.DOMDebuggerManager.prototype._eventBreakpointDisabledStateDidChange): Added. >+ >+ * UserInterface/Controllers/DebuggerManager.js: >+ (WI.DebuggerManager.prototype._pauseReasonFromPayload): >+ >+ * UserInterface/Controllers/EventBreakpointTreeController.js: Added. >+ (WI.EventBreakpointTreeController): >+ (WI.EventBreakpointTreeController.prototype.revealAndSelect): >+ (WI.EventBreakpointTreeController.prototype._eventBreakpointAdded): >+ (WI.EventBreakpointTreeController.prototype._eventBreakpointRemoved): >+ (WI.EventBreakpointTreeController.prototype._addTreeElement): >+ >+ * UserInterface/Views/DebuggerSidebarPanel.js: >+ (WI.DebuggerSidebarPanel): >+ (WI.DebuggerSidebarPanel.prototype._updatePauseReasonSection): >+ (WI.DebuggerSidebarPanel.prototype._eventBreakpointAddedOrRemoved): Added. >+ (WI.DebuggerSidebarPanel.prototype._addEventBreakpointButtonClicked): Added. >+ (WI.DebuggerSidebarPanel.prototype.willDismissPopover): >+ >+ * UserInterface/Views/EventBreakpointTreeElement.js: Added. >+ (WI.EventBreakpointTreeElement): >+ (WI.EventBreakpointTreeElement.prototype.onattach): >+ (WI.EventBreakpointTreeElement.prototype.ondetach): >+ (WI.EventBreakpointTreeElement.prototype.ondelete): >+ (WI.EventBreakpointTreeElement.prototype.onenter): >+ (WI.EventBreakpointTreeElement.prototype.onspace): >+ (WI.EventBreakpointTreeElement.prototype.populateContextMenu): >+ (WI.EventBreakpointTreeElement.prototype._statusImageElementClicked): >+ (WI.EventBreakpointTreeElement.prototype._statusImageElementFocused): >+ (WI.EventBreakpointTreeElement.prototype._statusImageElementMouseDown): >+ (WI.EventBreakpointTreeElement.prototype._toggleBreakpoint): >+ (WI.EventBreakpointTreeElement.prototype._updateStatus): >+ * UserInterface/Views/EventBreakpointTreeElement.css: Added. >+ (.breakpoint.event-listener:not(.breakpoint-paused-icon) .icon): >+ >+ * UserInterface/Views/EventBreakpointPopover.js: Added. >+ (WI.EventBreakpointPopover): >+ (WI.EventBreakpointPopover.prototype.get result): >+ (WI.EventBreakpointPopover.prototype.get value): >+ (WI.EventBreakpointPopover.prototype.show): >+ (WI.EventBreakpointPopover.prototype._presentOverTargetElement): >+ * UserInterface/Views/EventBreakpointPopover.css: Added. >+ (.popover .event-listener-breakpoint-content): >+ (.popover .event-listener-breakpoint-content > input): >+ >+ * UserInterface/Views/NavigationSidebarPanel.js: >+ (WI.NavigationSidebarPanel.prototype._isTreeElementWithoutRepresentedObject): >+ > 2018-08-15 Aditya Keerthi <akeerthi@apple.com> > > [Datalist] Add button to TextFieldInputs with a datalist >diff --git a/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp >index fad32f8ce511a801319525a1d1e7296d44d0d9e6..36f8aecc43ecfbb4e99a3545d1296bb8bd039c96 100644 >--- a/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp >+++ b/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp >@@ -371,7 +371,7 @@ void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(bool isDOMEvent, cons > return; > > Ref<JSON::Object> eventData = JSON::Object::create(); >- eventData->setString("eventName"_s, fullEventName); >+ eventData->setString("eventName"_s, eventName); > > if (synchronous) > m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData)); >diff --git a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >index 77e742002f491ccb5c0cf05d44f6abc210820e5a..aa25795db1be469139c29092f92150281f717ee2 100644 >--- a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >+++ b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >@@ -72,6 +72,7 @@ localizedStrings["Add"] = "Add"; > localizedStrings["Add %s Rule"] = "Add %s Rule"; > localizedStrings["Add Action"] = "Add Action"; > localizedStrings["Add Breakpoint"] = "Add Breakpoint"; >+localizedStrings["Add Event Breakpoint"] = "Add Event Breakpoint"; > localizedStrings["Add New"] = "Add New"; > localizedStrings["Add New Class"] = "Add New Class"; > localizedStrings["Add New Probe Expression"] = "Add New Probe Expression"; >@@ -144,6 +145,7 @@ localizedStrings["Bottom"] = "Bottom"; > localizedStrings["Boundary"] = "Boundary"; > localizedStrings["Box Model"] = "Box Model"; > localizedStrings["Box Shadow"] = "Box Shadow"; >+localizedStrings["Break on events with name:"] = "Break on events with name:"; > localizedStrings["Break on request with URL:"] = "Break on request with URL:"; > localizedStrings["Break onâ¦"] = "Break onâ¦"; > localizedStrings["Breakdown"] = "Breakdown"; >@@ -395,6 +397,7 @@ localizedStrings["Errors"] = "Errors"; > localizedStrings["Eval Code"] = "Eval Code"; > localizedStrings["Evaluate JavaScript"] = "Evaluate JavaScript"; > localizedStrings["Event"] = "Event"; >+localizedStrings["Event Breakpoints"] = "Event Breakpoints"; > localizedStrings["Event Dispatched"] = "Event Dispatched"; > localizedStrings["Event Listeners"] = "Event Listeners"; > localizedStrings["Events"] = "Events"; >@@ -1093,6 +1096,7 @@ localizedStrings["times before stopping"] = "times before stopping"; > localizedStrings["toggle"] = "toggle"; > localizedStrings["unsupported version."] = "unsupported version."; > localizedStrings["value"] = "value"; >+localizedStrings["â%sâ Event Fired"] = "â%sâ Event Fired"; > localizedStrings["â%sâ Profile Recorded"] = "â%sâ Profile Recorded"; > localizedStrings["â%sâ is invalid."] = "â%sâ is invalid."; > localizedStrings["â%sâ threw an error."] = "â%sâ threw an error."; >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js b/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js >index 000a3dd9a92c0117bb590823d687ead6b438a053..7371ac013163a697de0ef8ed73324091d99019ff 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js >@@ -33,6 +33,9 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > this._domBreakpointURLMap = new Map; > this._domBreakpointFrameIdentifierMap = new Map; > >+ this._eventBreakpointSetting = new WI.Setting("event-breakpoints", []); >+ this._eventBreakpoints = []; >+ > this._xhrBreakpointsSetting = new WI.Setting("xhr-breakpoints", []); > this._xhrBreakpoints = []; > this._allRequestsBreakpointEnabledSetting = new WI.Setting("break-on-all-requests", false); >@@ -40,6 +43,7 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > this._allRequestsBreakpoint = new WI.XHRBreakpoint(null, null, !this._allRequestsBreakpointEnabledSetting.value); > > WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DisabledStateDidChange, this._domBreakpointDisabledStateDidChange, this); >+ WI.EventBreakpoint.addEventListener(WI.EventBreakpoint.Event.DisabledStateDidChange, this._eventBreakpointDisabledStateDidChange, this); > WI.XHRBreakpoint.addEventListener(WI.XHRBreakpoint.Event.DisabledStateDidChange, this._xhrBreakpointDisabledStateDidChange, this); > > WI.domTreeManager.addEventListener(WI.DOMTreeManager.Event.NodeRemoved, this._nodeRemoved, this); >@@ -58,6 +62,11 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > this.addDOMBreakpoint(breakpoint); > } > >+ for (let cookie of this._eventBreakpointSetting.value) { >+ let breakpoint = new WI.EventBreakpoint(cookie.eventName, cookie.disabled); >+ this.addEventBreakpoint(breakpoint); >+ } >+ > for (let cookie of this._xhrBreakpointsSetting.value) { > let breakpoint = new WI.XHRBreakpoint(cookie.type, cookie.url, cookie.disabled); > this.addXHRBreakpoint(breakpoint); >@@ -102,6 +111,8 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > return resolvedBreakpoints; > } > >+ get eventBreakpoints() { return this._eventBreakpoints; } >+ > get xhrBreakpoints() { return this._xhrBreakpoints; } > > isBreakpointRemovable(breakpoint) >@@ -184,6 +195,51 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > this._saveDOMBreakpoints(); > } > >+ eventBreakpointForEventName(eventName) >+ { >+ return this._eventBreakpoints.find((breakpoint) => breakpoint.eventName === eventName) || null; >+ } >+ >+ addEventBreakpoint(breakpoint) >+ { >+ console.assert(breakpoint instanceof WI.EventBreakpoint); >+ if (!breakpoint) >+ return; >+ >+ if (this._eventBreakpoints.some((item) => item.eventName === breakpoint.eventName)) >+ return; >+ >+ this._eventBreakpoints.push(breakpoint); >+ >+ this.dispatchEventToListeners(WI.DOMDebuggerManager.Event.EventBreakpointAdded, {breakpoint}); >+ >+ this._resolveEventBreakpoint(breakpoint); >+ this._saveEventBreakpoints(); >+ } >+ >+ removeEventBreakpoint(breakpoint) >+ { >+ console.assert(breakpoint instanceof WI.EventBreakpoint); >+ if (!breakpoint) >+ return; >+ >+ if (!this._eventBreakpoints.includes(breakpoint)) >+ return; >+ >+ this._eventBreakpoints.remove(breakpoint); >+ >+ this._saveEventBreakpoints(); >+ this.dispatchEventToListeners(WI.DOMDebuggerManager.Event.EventBreakpointRemoved, {breakpoint}); >+ >+ if (breakpoint.disabled) >+ return; >+ >+ DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, (error) => { >+ if (error) >+ console.error(error); >+ }); >+ } >+ > xhrBreakpointForURL(url) > { > return this._xhrBreakpoints.find((breakpoint) => breakpoint.url === url) || null; >@@ -300,6 +356,9 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > } > } > >+ for (let breakpoint of this._eventBreakpoints) >+ this._resolveEventBreakpoint(breakpoint); >+ > for (let breakpoint of this._xhrBreakpoints) > this._resolveXHRBreakpoint(breakpoint); > } >@@ -347,6 +406,23 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > DOMDebuggerAgent.setDOMBreakpoint(nodeIdentifier, breakpoint.type, breakpointUpdated); > } > >+ _updateEventBreakpoint(breakpoint, callback) >+ { >+ function breakpointUpdated(error) >+ { >+ if (error) >+ console.error(error); >+ >+ if (callback) >+ callback(error); >+ } >+ >+ if (breakpoint.disabled) >+ DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated); >+ else >+ DOMDebuggerAgent.setEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated); >+ } >+ > _updateXHRBreakpoint(breakpoint, callback) > { > function breakpointUpdated(error) >@@ -366,6 +442,16 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > } > } > >+ _resolveEventBreakpoint(breakpoint) >+ { >+ if (breakpoint.disabled) >+ return; >+ >+ this._updateEventBreakpoint(breakpoint, () => { >+ breakpoint.dispatchEventToListeners(WI.EventBreakpoint.Event.ResolvedStateDidChange); >+ }); >+ } >+ > _resolveXHRBreakpoint(breakpoint) > { > if (breakpoint.disabled) >@@ -388,6 +474,14 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > this._domBreakpointsSetting.value = breakpointsToSave.map((breakpoint) => breakpoint.serializableInfo); > } > >+ _saveEventBreakpoints() >+ { >+ if (this._restoringBreakpoints) >+ return; >+ >+ this._eventBreakpointSetting.value = this._eventBreakpoints.map((breakpoint) => breakpoint.serializableInfo); >+ } >+ > _saveXHRBreakpoints() > { > if (this._restoringBreakpoints) >@@ -403,6 +497,13 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > this._saveDOMBreakpoints(); > } > >+ _eventBreakpointDisabledStateDidChange(event) >+ { >+ let breakpoint = event.target; >+ this._updateEventBreakpoint(breakpoint); >+ this._saveEventBreakpoints(); >+ } >+ > _xhrBreakpointDisabledStateDidChange(event) > { > let breakpoint = event.target; >@@ -488,6 +589,8 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > WI.DOMDebuggerManager.Event = { > DOMBreakpointAdded: "dom-debugger-manager-dom-breakpoint-added", > DOMBreakpointRemoved: "dom-debugger-manager-dom-breakpoint-removed", >+ EventBreakpointAdded: "dom-debugger-manager-event-breakpoint-added", >+ EventBreakpointRemoved: "dom-debugger-manager-event-breakpoint-removed", > XHRBreakpointAdded: "dom-debugger-manager-xhr-breakpoint-added", > XHRBreakpointRemoved: "dom-debugger-manager-xhr-breakpoint-removed", > }; >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js b/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >index 6502748a4af1a4f227333fc6a3226a90c3c5b91d..60eef5b1a1a25474f82c9d01d784fd2fa36bebf0 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >@@ -828,6 +828,8 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object > return WI.DebuggerManager.PauseReason.DOM; > case DebuggerAgent.PausedReason.DebuggerStatement: > return WI.DebuggerManager.PauseReason.DebuggerStatement; >+ case DebuggerAgent.PausedReason.EventListener: >+ return WI.DebuggerManager.PauseReason.EventListener; > case DebuggerAgent.PausedReason.Exception: > return WI.DebuggerManager.PauseReason.Exception; > case DebuggerAgent.PausedReason.PauseOnNextStatement: >@@ -1236,6 +1238,7 @@ WI.DebuggerManager.PauseReason = { > CSPViolation: "CSP-violation", > DebuggerStatement: "debugger-statement", > DOM: "DOM", >+ EventListener: "event-listener", > Exception: "exception", > PauseOnNextStatement: "pause-on-next-statement", > XHR: "xhr", >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/EventBreakpointTreeController.js b/Source/WebInspectorUI/UserInterface/Controllers/EventBreakpointTreeController.js >new file mode 100644 >index 0000000000000000000000000000000000000000..8960f2ba53990a44efe23eb337df75861109df7b >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Controllers/EventBreakpointTreeController.js >@@ -0,0 +1,76 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+WI.EventBreakpointTreeController = class EventBreakpointTreeController >+{ >+ constructor(treeOutline) >+ { >+ this._treeOutline = treeOutline; >+ >+ WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointAdded, this._eventBreakpointAdded, this); >+ WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointRemoved, this._eventBreakpointRemoved, this); >+ >+ for (let breakpoint of WI.domDebuggerManager.eventBreakpoints) >+ this._addTreeElement(breakpoint); >+ } >+ >+ // Public >+ >+ revealAndSelect(breakpoint) >+ { >+ let treeElement = this._treeOutline.findTreeElement(breakpoint); >+ if (!treeElement) >+ return; >+ >+ treeElement.revealAndSelect(); >+ } >+ >+ // Private >+ >+ _eventBreakpointAdded(event) >+ { >+ this._addTreeElement(event.data.breakpoint); >+ } >+ >+ _eventBreakpointRemoved(event) >+ { >+ let breakpoint = event.data.breakpoint; >+ let treeElement = this._treeOutline.findTreeElement(breakpoint); >+ if (!treeElement) >+ return; >+ >+ this._treeOutline.removeChild(treeElement); >+ } >+ >+ _addTreeElement(breakpoint) >+ { >+ let treeElement = this._treeOutline.findTreeElement(breakpoint); >+ console.assert(!treeElement); >+ if (treeElement) >+ return; >+ >+ this._treeOutline.appendChild(new WI.EventBreakpointTreeElement(breakpoint)); >+ } >+}; >diff --git a/Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg b/Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg >new file mode 100644 >index 0000000000000000000000000000000000000000..15dacd648fad15184e7ee1e44a7a7b03c61f748c >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg >@@ -0,0 +1,8 @@ >+<?xml version="1.0" encoding="utf-8"?> >+<!-- Copyright © 2018 Apple Inc. All rights reserved. --> >+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16"> >+ <path fill="rgb(148, 183, 219)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 Z"/> >+ <path fill="rgb(106, 136, 170)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 M 13 2 C 13.550781 2 14 2.449219 14 3 L 14 13 C 14 13.550781 13.550781 14 13 14 L 3 14 C 2.449219 14 2 13.550781 2 13 L 2 3 C 2 2.449219 2.449219 2 3 2 L 13 2"/> >+ <path fill="rgb(113, 146, 184)" d="M 5.503906 12.742188 C 4.949219 12.742188 4.503906 12.292969 4.503906 11.742188 L 4.503906 3.792969 C 4.503906 3.242188 4.949219 2.792969 5.503906 2.792969 L 10.472656 2.792969 C 11.023438 2.792969 11.472656 3.242188 11.472656 3.792969 L 11.472656 4.882812 C 11.472656 5.4375 11.023438 5.882812 10.472656 5.882812 C 10.472656 5.882812 9.132812 5.882812 8.15625 5.882812 C 8.15625 5.992188 8.15625 5.996094 8.15625 6.101562 C 8.957031 6.101562 9.875 6.101562 9.875 6.101562 C 10.425781 6.101562 10.875 6.550781 10.875 7.101562 L 10.875 8.164062 C 10.875 8.71875 10.425781 9.164062 9.875 9.164062 C 9.875 9.164062 8.957031 9.164062 8.15625 9.164062 C 8.15625 9.382812 8.15625 9.398438 8.15625 9.613281 C 9.191406 9.613281 10.722656 9.613281 10.722656 9.613281 C 11.277344 9.613281 11.722656 10.0625 11.722656 10.613281 L 11.722656 11.742188 C 11.722656 12.292969 11.277344 12.742188 10.722656 12.742188 L 5.503906 12.742188"/> >+ <path fill="white" d="M 5.503906 11.742188 L 5.503906 3.792969 L 10.46875 3.792969 L 10.46875 4.882812 L 7.15625 4.882812 L 7.15625 7.101562 L 9.875 7.101562 L 9.875 8.164062 L 7.15625 8.164062 L 7.15625 10.613281 L 10.722656 10.613281 L 10.722656 11.742188 Z"/> >+</svg> >diff --git a/Source/WebInspectorUI/UserInterface/Main.html b/Source/WebInspectorUI/UserInterface/Main.html >index 010fc949ac13b04692684c7ba21bcf4b28d1d709..89e49279ce504b66419755b3280d2116fd35f113 100644 >--- a/Source/WebInspectorUI/UserInterface/Main.html >+++ b/Source/WebInspectorUI/UserInterface/Main.html >@@ -83,6 +83,8 @@ > <link rel="stylesheet" href="Views/DetailsSection.css"> > <link rel="stylesheet" href="Views/DividerNavigationItem.css"> > <link rel="stylesheet" href="Views/Editing.css"> >+ <link rel="stylesheet" href="Views/EventBreakpointPopover.css"> >+ <link rel="stylesheet" href="Views/EventBreakpointTreeElement.css"> > <link rel="stylesheet" href="Views/EventListenerSectionGroup.css"> > <link rel="stylesheet" href="Views/ErrorObjectView.css"> > <link rel="stylesheet" href="Views/FilterBar.css"> >@@ -376,6 +378,7 @@ > <script src="Models/DebuggerDashboard.js"></script> > <script src="Models/DebuggerData.js"></script> > <script src="Models/DefaultDashboard.js"></script> >+ <script src="Models/EventBreakpoint.js"></script> > <script src="Models/ExecutionContext.js"></script> > <script src="Models/ExecutionContextList.js"></script> > <script src="Models/FPSInstrument.js"></script> >@@ -622,6 +625,8 @@ > <script src="Views/EditableDataGridNode.js"></script> > <script src="Views/EditingSupport.js"></script> > <script src="Views/ErrorObjectView.js"></script> >+ <script src="Views/EventBreakpointPopover.js"></script> >+ <script src="Views/EventBreakpointTreeElement.js"></script> > <script src="Views/EventListenerSectionGroup.js"></script> > <script src="Views/FilterBar.js"></script> > <script src="Views/FilterBarButton.js"></script> >@@ -843,6 +848,7 @@ > <script src="Controllers/DebuggerManager.js"></script> > <script src="Controllers/DOMBreakpointTreeController.js"></script> > <script src="Controllers/DragToAdjustController.js"></script> >+ <script src="Controllers/EventBreakpointTreeController.js"></script> > <script src="Controllers/Formatter.js"></script> > <script src="Controllers/FormatterSourceMap.js"></script> > <script src="Controllers/FrameResourceManager.js"></script> >diff --git a/Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js b/Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js >new file mode 100644 >index 0000000000000000000000000000000000000000..89c9273c771381d3931e18341784e38f3b90f310 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js >@@ -0,0 +1,79 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+WI.EventBreakpoint = class EventBreakpoint extends WI.Object >+{ >+ constructor(eventName, disabled) >+ { >+ super(); >+ >+ console.assert(typeof eventName === "string"); >+ >+ this._eventName = eventName; >+ this._disabled = disabled || false; >+ } >+ >+ // Public >+ >+ get eventName() { return this._eventName; } >+ >+ get disabled() >+ { >+ return this._disabled; >+ } >+ >+ set disabled(disabled) >+ { >+ if (this._disabled === disabled) >+ return; >+ >+ this._disabled = disabled; >+ >+ this.dispatchEventToListeners(WI.EventBreakpoint.Event.DisabledStateDidChange); >+ } >+ >+ get serializableInfo() >+ { >+ let info = { >+ eventName: this._eventName, >+ }; >+ if (this._disabled) >+ info.disabled = true; >+ >+ return info; >+ } >+ >+ saveIdentityToCookie(cookie) >+ { >+ cookie[WI.EventBreakpoint.EventNameCookieKey] = this._eventName; >+ } >+}; >+ >+WI.EventBreakpoint.EventNameCookieKey = "event-breakpoint-event-name"; >+ >+WI.EventBreakpoint.Event = { >+ DisabledStateDidChange: "event-breakpoint-disabled-state-did-change", >+ ResolvedStateDidChange: "event-breakpoint-resolved-state-did-change", >+}; >diff --git a/Source/WebInspectorUI/UserInterface/Test.html b/Source/WebInspectorUI/UserInterface/Test.html >index 0defd44cb48689f2dc4c770237a316e3520c71bc..831ca73f239486ef72a0f1e69ab808f4bea3053d 100644 >--- a/Source/WebInspectorUI/UserInterface/Test.html >+++ b/Source/WebInspectorUI/UserInterface/Test.html >@@ -133,6 +133,7 @@ > <script src="Models/DOMStorageObject.js"></script> > <script src="Models/DOMTree.js"></script> > <script src="Models/DebuggerData.js"></script> >+ <script src="Models/EventBreakpoint.js"></script> > <script src="Models/ExecutionContext.js"></script> > <script src="Models/ExecutionContextList.js"></script> > <script src="Models/FPSInstrument.js"></script> >diff --git a/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js b/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js >index 5a5362582d137ff07904763bbc524bcf046009cf..63ba0a59b7854dad37d6cc8602e8ed86b913c6ce 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js >+++ b/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js >@@ -176,22 +176,44 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba > this._domBreakpointsSection = new WI.DetailsSection("dom-breakpoints", WI.UIString("DOM Breakpoints"), [domBreakpointsGroup], null, defaultCollapsed); > this.contentView.element.appendChild(this._domBreakpointsSection.element); > >+ this._eventBreakpointsContentTreeOutline = this.createContentTreeOutline(true); >+ this._eventBreakpointsContentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementAdded, this._eventBreakpointAddedOrRemoved, this); >+ this._eventBreakpointsContentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementRemoved, this._eventBreakpointAddedOrRemoved, this); >+ >+ this._eventBreakpointsRow = new WI.DetailsSectionRow(WI.UIString("No Breakpoints")); >+ this._eventBreakpointsRow.element.appendChild(this._eventBreakpointsContentTreeOutline.element); >+ this._eventBreakpointsRow.showEmptyMessage(); >+ >+ let eventBreakpointNavigationBar = new WI.NavigationBar; >+ let eventBreakpointNavigationBarWrapper = document.createElement("div"); >+ eventBreakpointNavigationBarWrapper.appendChild(eventBreakpointNavigationBar.element); >+ >+ let addEventBreakpointButton = new WI.ButtonNavigationItem("add-event-breakpoint", WI.UIString("Add Event Breakpoint"), "Images/Plus13.svg", 13, 13); >+ addEventBreakpointButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._addEventBreakpointButtonClicked, this); >+ eventBreakpointNavigationBar.addNavigationItem(addEventBreakpointButton); >+ >+ let eventBreakpointsGroup = new WI.DetailsSectionGroup([this._eventBreakpointsRow]); >+ this._eventBreakpointsSection = new WI.DetailsSection("event-breakpoints", WI.UIString("Event Breakpoints"), [eventBreakpointsGroup], eventBreakpointNavigationBarWrapper, defaultCollapsed); >+ this.contentView.element.appendChild(this._eventBreakpointsSection.element); >+ >+ this._eventBreakpointTreeController = new WI.EventBreakpointTreeController(this._eventBreakpointsContentTreeOutline); >+ > this._xhrBreakpointsContentTreeOutline = this.createContentTreeOutline(true); > this._xhrBreakpointTreeController = new WI.XHRBreakpointTreeController(this._xhrBreakpointsContentTreeOutline); > > this._xhrBreakpointsRow = new WI.DetailsSectionRow; > this._xhrBreakpointsRow.element.appendChild(this._xhrBreakpointsContentTreeOutline.element); > >- let navigationBar = new WI.NavigationBar; >- let navigationBarWrapper = document.createElement("div"); >- navigationBarWrapper.appendChild(navigationBar.element); >+ let xhrBreakpointNavigationBar = new WI.NavigationBar; >+ let xhrBreakpointNavigationBarWrapper = document.createElement("div"); >+ xhrBreakpointNavigationBarWrapper.appendChild(xhrBreakpointNavigationBar.element); > > let addXHRBreakpointButton = new WI.ButtonNavigationItem("add-xhr-breakpoint", WI.UIString("Add XHR Breakpoint"), "Images/Plus13.svg", 13, 13); > addXHRBreakpointButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._addXHRBreakpointButtonClicked, this); >- navigationBar.addNavigationItem(addXHRBreakpointButton); >+ xhrBreakpointNavigationBar.addNavigationItem(addXHRBreakpointButton); > > let xhrBreakpointsGroup = new WI.DetailsSectionGroup([this._xhrBreakpointsRow]); >- let xhrBreakpointsSection = new WI.DetailsSection("xhr-breakpoints", WI.UIString("XHR Breakpoints"), [xhrBreakpointsGroup], navigationBarWrapper, defaultCollapsed); >+ let xhrBreakpointsSection = new WI.DetailsSection("xhr-breakpoints", WI.UIString("XHR Breakpoints"), [xhrBreakpointsGroup], xhrBreakpointNavigationBarWrapper, defaultCollapsed); > this.contentView.element.appendChild(xhrBreakpointsSection.element); > } > >@@ -1032,6 +1054,24 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba > } > break; > >+ case WI.DebuggerManager.PauseReason.EventListener: >+ console.assert(pauseData, "Expected data with an event listener, but found none."); >+ if (pauseData) { >+ let eventBreakpoint = WI.domDebuggerManager.eventBreakpointForEventName(pauseData.eventName); >+ console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName); >+ >+ this._pauseReasonTreeOutline = this.createContentTreeOutline(true); >+ >+ let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName, WI.UIString("â%sâ Event Fired").format(pauseData.eventName)); >+ this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement); >+ >+ let eventBreakpointRow = new WI.DetailsSectionRow; >+ eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element); >+ >+ this._pauseReasonGroup.rows = [eventBreakpointRow]; >+ } >+ return true; >+ > case WI.DebuggerManager.PauseReason.Exception: > console.assert(pauseData, "Expected data with an exception, but found none."); > if (pauseData) { >@@ -1175,6 +1215,28 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba > this._domBreakpointsSection.collapsed = false; > } > >+ _eventBreakpointAddedOrRemoved(event) >+ { >+ if (!this._eventBreakpointsContentTreeOutline.children.length) { >+ this._eventBreakpointsRow.showEmptyMessage(); >+ return; >+ } >+ >+ if (this._eventBreakpointsContentTreeOutline.element.parent) >+ return; >+ >+ this._eventBreakpointsRow.hideEmptyMessage(); >+ this._eventBreakpointsRow.element.append(this._eventBreakpointsContentTreeOutline.element); >+ >+ this._eventBreakpointsSection.collapsed = false; >+ } >+ >+ _addEventBreakpointButtonClicked(event) >+ { >+ let popover = new WI.EventBreakpointPopover(this); >+ popover.show(event.target.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]); >+ } >+ > _addXHRBreakpointButtonClicked(event) > { > let popover = new WI.XHRBreakpointPopover(this); >@@ -1188,11 +1250,19 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba > if (popover.result !== WI.InputPopover.Result.Committed) > return; > >- let url = popover.value; >- if (!url) >+ if (popover instanceof WI.EventBreakpointPopover) { >+ let eventName = popover.value; >+ if (eventName) >+ WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(eventName)); > return; >+ } > >- WI.domDebuggerManager.addXHRBreakpoint(new WI.XHRBreakpoint(popover.type, url)); >+ if (popover instanceof WI.XHRBreakpointPopover) { >+ let url = popover.value; >+ if (url) >+ WI.domDebuggerManager.addXHRBreakpoint(new WI.XHRBreakpoint(popover.type, url)); >+ return; >+ } > } > }; > >diff --git a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css >new file mode 100644 >index 0000000000000000000000000000000000000000..37a06c6ade0f4a5b06ec075af9919abaa372b05c >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css >@@ -0,0 +1,36 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+.popover .event-breakpoint-content { >+ margin: 2px; >+ padding: 5px; >+} >+ >+.popover .event-breakpoint-content > input { >+ width: 100%; >+ margin-top: 4px; >+ padding: 4px 0 2px 0; >+ outline: none; >+} >diff --git a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js >new file mode 100644 >index 0000000000000000000000000000000000000000..5f75b513d3d6b1f4c0dea9b29699dbdbe189e069 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js >@@ -0,0 +1,89 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover >+{ >+ constructor(delegate) >+ { >+ super(delegate); >+ >+ this._result = WI.InputPopover.Result.None; >+ this._value = null; >+ >+ this._codeMirror = null; >+ this._targetElement = null; >+ this._preferredEdges = null; >+ >+ this.windowResizeHandler = this._presentOverTargetElement.bind(this); >+ } >+ >+ // Public >+ >+ get result() { return this._result; } >+ get value() { return this._value; } >+ >+ show(targetElement, preferredEdges) >+ { >+ this._targetElement = targetElement; >+ this._preferredEdges = preferredEdges; >+ >+ let contentElement = document.createElement("div"); >+ contentElement.classList.add("event-breakpoint-content"); >+ >+ let label = contentElement.appendChild(document.createElement("div")); >+ label.classList.add("label"); >+ label.textContent = WI.UIString("Break on events with name:"); >+ >+ this._inputElement = contentElement.appendChild(document.createElement("input")); >+ this._inputElement.placeholder = "click"; >+ this._inputElement.spellcheck = false; >+ this._inputElement.addEventListener("keydown", (event) => { >+ if (!isEnterKey(event)) >+ return; >+ >+ this._result = WI.InputPopover.Result.Committed; >+ this._value = event.target.value.trim(); >+ >+ this.dismiss(); >+ }); >+ >+ this.content = contentElement; >+ >+ this._presentOverTargetElement(); >+ } >+ >+ // Private >+ >+ _presentOverTargetElement() >+ { >+ if (!this._targetElement) >+ return; >+ >+ let targetFrame = WI.Rect.rectFromClientRect(this._targetElement.getBoundingClientRect()); >+ this.present(targetFrame, this._preferredEdges); >+ >+ this._inputElement.select(); >+ } >+}; >diff --git a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css >new file mode 100644 >index 0000000000000000000000000000000000000000..622f025034b6ff102292223a9f710fa2ed076e9c >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css >@@ -0,0 +1,28 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+.breakpoint.event:not(.breakpoint-paused-icon) .icon { >+ content: url(../Images/EventBreakpoint.svg); >+} >diff --git a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js >new file mode 100644 >index 0000000000000000000000000000000000000000..630ff0bcfc43c420dc47213533b112c7c07baf62 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js >@@ -0,0 +1,139 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+WI.EventBreakpointTreeElement = class EventBreakpointTreeElement extends WI.GeneralTreeElement >+{ >+ constructor(breakpoint, className, title) >+ { >+ console.assert(breakpoint instanceof WI.EventBreakpoint); >+ >+ let classNames = ["breakpoint", "event"]; >+ if (className) >+ classNames.push(className); >+ >+ if (!title) >+ title = breakpoint.eventName; >+ >+ const subtitle = null; >+ super(classNames, title, subtitle, breakpoint); >+ >+ this._statusImageElement = document.createElement("img"); >+ this._statusImageElement.classList.add("status-image", "resolved"); >+ this.status = this._statusImageElement; >+ >+ breakpoint.addEventListener(WI.EventBreakpoint.Event.DisabledStateDidChange, this._updateStatus, this); >+ >+ this._updateStatus(); >+ } >+ >+ // Protected >+ >+ onattach() >+ { >+ super.onattach(); >+ >+ this._boundStatusImageElementClicked = this._statusImageElementClicked.bind(this); >+ this._boundStatusImageElementFocused = this._statusImageElementFocused.bind(this); >+ this._boundStatusImageElementMouseDown = this._statusImageElementMouseDown.bind(this); >+ >+ this._statusImageElement.addEventListener("click", this._boundStatusImageElementClicked); >+ this._statusImageElement.addEventListener("focus", this._boundStatusImageElementFocused); >+ this._statusImageElement.addEventListener("mousedown", this._boundStatusImageElementMouseDown); >+ } >+ >+ ondetach() >+ { >+ super.ondetach(); >+ >+ this._statusImageElement.removeEventListener("click", this._boundStatusImageElementClicked); >+ this._statusImageElement.removeEventListener("focus", this._boundStatusImageElementFocused); >+ this._statusImageElement.removeEventListener("mousedown", this._boundStatusImageElementMouseDown); >+ >+ this._boundStatusImageElementClicked = null; >+ this._boundStatusImageElementFocused = null; >+ this._boundStatusImageElementMouseDown = null; >+ } >+ >+ ondelete() >+ { >+ WI.domDebuggerManager.removeEventBreakpoint(this.representedObject); >+ return true; >+ } >+ >+ onenter() >+ { >+ this._toggleBreakpoint(); >+ return true; >+ } >+ >+ onspace() >+ { >+ this._toggleBreakpoint(); >+ return true; >+ } >+ >+ populateContextMenu(contextMenu, event) >+ { >+ let breakpoint = this.representedObject; >+ let label = breakpoint.disabled ? WI.UIString("Enable Breakpoint") : WI.UIString("Disable Breakpoint"); >+ contextMenu.appendItem(label, this._toggleBreakpoint.bind(this)); >+ >+ if (WI.domDebuggerManager.isBreakpointRemovable(breakpoint)) { >+ contextMenu.appendSeparator(); >+ contextMenu.appendItem(WI.UIString("Delete Breakpoint"), () => { >+ WI.domDebuggerManager.removeEventBreakpoint(breakpoint); >+ }); >+ } >+ } >+ >+ // Private >+ >+ _statusImageElementClicked(event) >+ { >+ this._toggleBreakpoint(); >+ } >+ >+ _statusImageElementFocused(event) >+ { >+ // Prevent tree outline focus. >+ event.stopPropagation(); >+ } >+ >+ _statusImageElementMouseDown(event) >+ { >+ // Prevent tree element selection. >+ event.stopPropagation(); >+ } >+ >+ _toggleBreakpoint() >+ { >+ this.representedObject.disabled = !this.representedObject.disabled; >+ } >+ >+ _updateStatus() >+ { >+ this._statusImageElement.classList.toggle("disabled", this.representedObject.disabled); >+ } >+}; >diff --git a/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js b/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js >index 6574034aaf55ea51f854ec5d8164f2af45051652..3ab1dbaf74a6675b8e690957df7ac8cf5a3729f8 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js >+++ b/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js >@@ -633,6 +633,7 @@ WI.NavigationSidebarPanel = class NavigationSidebarPanel extends WI.SidebarPanel > || treeElement instanceof WI.ThreadTreeElement > || treeElement instanceof WI.IdleTreeElement > || treeElement instanceof WI.DOMBreakpointTreeElement >+ || treeElement instanceof WI.EventBreakpointTreeElement > || treeElement instanceof WI.XHRBreakpointTreeElement > || treeElement instanceof WI.CSSStyleSheetTreeElement > || typeof treeElement.representedObject === "string" >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index c766cb18557abb9387875bbfe5f11c8409870f20..934fea9b9d772c36c32929e5e921e18af4e42014 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,16 @@ >+2018-08-16 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: support breakpoints for arbitrary event names >+ https://bugs.webkit.org/show_bug.cgi?id=183118 >+ >+ Reviewed by Joseph Pecoraro. >+ >+ * inspector/dom-debugger/event-breakpoints-expected.txt: Added. >+ * inspector/dom-debugger/event-breakpoints.html: Added. >+ >+ * inspector/dom-debugger/event-breakpoints-with-navigation-expected.txt: Added. >+ * inspector/dom-debugger/event-breakpoints-with-navigation.html: Added. >+ > 2018-08-15 Christopher Reid <chris.reid@sony.com> > > [Curl] Implement default cookie path handling correctly as outlined in RFC6265. >diff --git a/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation-expected.txt b/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..50ba5c9b6dfc4cc11c77d4d6dcf3f80ef31fe9cb >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation-expected.txt >@@ -0,0 +1,11 @@ >+Tests for Event Listener breakpoints. >+ >+ >+== Running test suite: DOMDebugger.EventWithNavigation >+-- Running test case: DOMDebugger.EventWithNavigation.AddBreakpoint >+Adding "load" Event Breakpoint... >+Reloading WebInspector... >+PASS: Pause reason should be EventListener. >+PASS: Pause data eventName should be "load". >+-- Running test teardown. >+ >diff --git a/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation.html b/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation.html >new file mode 100644 >index 0000000000000000000000000000000000000000..586f59d2f5f3725fa67f329530479a0eb4fc69c3 >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation.html >@@ -0,0 +1,80 @@ >+<!doctype html> >+<html> >+<head> >+<script src="../../http/tests/inspector/resources/inspector-test.js"></script> >+<script> >+function handleLoad(event) { >+ TestPage.dispatchEventToFrontend("TestPageLoad"); >+ >+ runTest(); >+} >+ >+function test() { >+ let suite = InspectorTest.createAsyncSuite("DOMDebugger.EventWithNavigation"); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.EventWithNavigation.AddBreakpoint`, >+ description: "Check that a breakpoint is preserved over navigation.", >+ test(resolve, reject) { >+ let paused = false; >+ >+ let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ paused = true; >+ >+ let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target); >+ InspectorTest.expectEqual(targetData.pauseReason, WI.DebuggerManager.PauseReason.EventListener, "Pause reason should be EventListener."); >+ InspectorTest.expectEqual(targetData.pauseData.eventName, "load", "Pause data eventName should be \"load\"."); >+ >+ WI.debuggerManager.resume() >+ .catch((reason) => { >+ InspectorTest.fail(reason); >+ resolve(); >+ }); >+ }); >+ >+ InspectorTest.singleFireEventListener("TestPageLoad", (event) => { >+ if (!paused) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ InspectorTest.fail("Should pause before \"load\" event handler is run"); >+ } >+ >+ resolve(); >+ }); >+ >+ InspectorTest.log("Adding \"load\" Event Breakpoint..."); >+ >+ let breakpoint = new WI.EventBreakpoint("load"); >+ >+ WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded) >+ .then((event) => { >+ InspectorTest.assert(event.data.breakpoint.eventName, "load", "Breakpoint should be for expected event name."); >+ >+ InspectorTest.log("Reloading WebInspector..."); >+ return InspectorTest.reloadPage(); >+ }) >+ .catch(reject); >+ >+ WI.domDebuggerManager.addEventBreakpoint(breakpoint); >+ }, >+ teardown(resolve, reject) { >+ let breakpoints = WI.domDebuggerManager.eventBreakpoints; >+ for (let breakpoint of breakpoints) >+ WI.domDebuggerManager.removeEventBreakpoint(breakpoint); >+ >+ resolve(); >+ }, >+ }); >+ >+ suite.runTestCasesAndFinish(); >+} >+</script> >+</head> >+<body> >+ <p>Tests for Event Listener breakpoints.</p> >+ <div id="x"></div> >+ <script> >+ window.addEventListener("load", handleLoad); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt b/LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..5114e695b393ced23d65bfe120e43248c25af92a >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt >@@ -0,0 +1,83 @@ >+Tests for Event Listener breakpoints. >+ >+ >+== Running test suite: DOMDebugger.Event >+-- Running test case: DOMDebugger.Event.AddBreakpoint "click" >+Adding "click" Event Breakpoint... >+Firing "click" on body... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleBody_click >+1: [F] bodyFire_click >+2: [P] Global Code >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "click" >+Adding "click" Event Breakpoint... >+Disabling "click" Event Breakpoint... >+Firing "click" on body... >+PASS: Should not pause for disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.RemoveBreakpoint "click" >+Adding "click" Event Breakpoint... >+Removing "click" Event Breakpoint... >+Firing "click" on body... >+PASS: Should not pause for removed breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "click" >+Adding "click" Event Breakpoint... >+Disabling "click" Event Breakpoint... >+Removing "click" Event Breakpoint... >+Firing "click" on body... >+PASS: Should not pause for removed disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.AddBreakpoint "custom" >+Adding "custom" Event Breakpoint... >+Firing "custom" on body... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleBody_custom >+1: [F] bodyFire_custom >+2: [P] Global Code >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "custom" >+Adding "custom" Event Breakpoint... >+Disabling "custom" Event Breakpoint... >+Firing "custom" on body... >+PASS: Should not pause for disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.RemoveBreakpoint "custom" >+Adding "custom" Event Breakpoint... >+Removing "custom" Event Breakpoint... >+Firing "custom" on body... >+PASS: Should not pause for removed breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "custom" >+Adding "custom" Event Breakpoint... >+Disabling "custom" Event Breakpoint... >+Removing "custom" Event Breakpoint... >+Firing "custom" on body... >+PASS: Should not pause for removed disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.AddMultipleBreakpoints >+Adding "click" Event Breakpoint... >+Firing "click" on div#x... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleX_click >+1: [F] xFire_click >+2: [P] Global Code >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleBody_click >+1: [F] xFire_click >+2: [P] Global Code >+-- Running test teardown. >+ >diff --git a/LayoutTests/inspector/dom-debugger/event-breakpoints.html b/LayoutTests/inspector/dom-debugger/event-breakpoints.html >new file mode 100644 >index 0000000000000000000000000000000000000000..29fb9b9752545cbb1ff7ce2ec353979b2b48e6fe >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-breakpoints.html >@@ -0,0 +1,249 @@ >+<!doctype html> >+<html> >+<head> >+<script src="../../http/tests/inspector/resources/inspector-test.js"></script> >+<script src="../debugger/resources/log-active-stack-trace.js"></script> >+<script> >+function handleBody_click(event) { >+ TestPage.dispatchEventToFrontend("TestPageBody-click"); >+} >+ >+function handleBody_custom(event) { >+ TestPage.dispatchEventToFrontend("TestPageBody-custom"); >+} >+ >+function handleX_click(event) { >+ TestPage.dispatchEventToFrontend("TestPageX-click"); >+} >+ >+function bodyFire_click() { >+ document.body.click(); >+} >+ >+function bodyFire_custom() { >+ document.body.dispatchEvent(new Event("custom")); >+} >+ >+function xFire_click() { >+ document.getElementById("x").click(); >+} >+ >+function test() { >+ let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event"); >+ >+ function teardown(resolve, reject) { >+ let breakpoints = WI.domDebuggerManager.eventBreakpoints; >+ for (let breakpoint of breakpoints) >+ WI.domDebuggerManager.removeEventBreakpoint(breakpoint); >+ >+ resolve(); >+ } >+ >+ function awaitBodyEvent(eventName) { >+ return function() { >+ InspectorTest.log(`Firing "${eventName}" on body...`); >+ return InspectorTest.evaluateInPage(`bodyFire_${eventName}()`); >+ }; >+ } >+ >+ function failOnPause(resolve, eventName, message) { >+ let paused = false; >+ >+ let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ paused = true; >+ >+ let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target); >+ InspectorTest.assert(targetData.pauseReason === WI.DebuggerManager.PauseReason.EventListener, "Pause reason should be EventListener."); >+ InspectorTest.assert(targetData.pauseData.eventName === eventName, `Pause data eventName should be "${eventName}".`); >+ >+ InspectorTest.fail(message); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume() >+ .catch((reason) => { >+ InspectorTest.fail(reason); >+ resolve(); >+ }); >+ }); >+ >+ InspectorTest.singleFireEventListener("TestPageBody-" + eventName, (event) => { >+ if (!paused) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ InspectorTest.pass(message); >+ } >+ >+ resolve(); >+ }); >+ } >+ >+ function addBreakpoint(eventName) { >+ InspectorTest.log(`Adding "${eventName}" Event Breakpoint...`); >+ >+ return new Promise((resolve, reject) => { >+ let breakpoint = new WI.EventBreakpoint(eventName); >+ >+ WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded) >+ .then((event) => { >+ InspectorTest.assert(event.data.breakpoint.eventName === eventName, "Breakpoint should be for expected event name."); >+ InspectorTest.assert(!breakpoint.disabled, "Breakpoint should not be disabled initially."); >+ resolve(breakpoint); >+ }); >+ >+ WI.domDebuggerManager.addEventBreakpoint(breakpoint); >+ }); >+ } >+ >+ function removeBreakpoint(breakpoint) { >+ InspectorTest.log(`Removing "${breakpoint.eventName}" Event Breakpoint...`); >+ >+ return new Promise((resolve, reject) => { >+ WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointRemoved) >+ .then((event) => { >+ InspectorTest.assert(event.data.breakpoint === breakpoint, "Removed Breakpoint should be expected object."); >+ InspectorTest.assert(!WI.domDebuggerManager.eventBreakpoints.includes(breakpoint), "Breakpoint should not be in the list of breakpoints."); >+ resolve(breakpoint); >+ }); >+ >+ WI.domDebuggerManager.removeEventBreakpoint(breakpoint); >+ }); >+ } >+ >+ function disableBreakpoint(breakpoint) { >+ InspectorTest.log(`Disabling "${breakpoint.eventName}" Event Breakpoint...`); >+ >+ breakpoint.disabled = true; >+ return breakpoint; >+ } >+ >+ function addTestCasesForEventName(eventName) { >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.AddBreakpoint "${eventName}"`, >+ description: "Check that the debugger pauses for enabled breakpoints.", >+ teardown, >+ test(resolve, reject) { >+ let paused = false; >+ >+ let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ paused = true; >+ >+ InspectorTest.pass("Should pause before event handler is run."); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume(); >+ }); >+ >+ InspectorTest.singleFireEventListener(`TestPageBody-${eventName}`, (event) => { >+ if (!paused) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ InspectorTest.fail("Should pause before event handler is run."); >+ } >+ >+ resolve(); >+ }); >+ >+ addBreakpoint(eventName) >+ .then(awaitBodyEvent(eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.AddDisabledBreakpoint "${eventName}"`, >+ description: "Check that debugger does the not pause for disabled breakpoints.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, eventName, "Should not pause for disabled breakpoint."); >+ >+ addBreakpoint(eventName) >+ .then(disableBreakpoint) >+ .then(awaitBodyEvent(eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.RemoveBreakpoint "${eventName}"`, >+ description: "Check that debugger does not pause for removed breakpoint.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, eventName, "Should not pause for removed breakpoint."); >+ >+ addBreakpoint(eventName) >+ .then(removeBreakpoint) >+ .then(awaitBodyEvent(eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.RemoveDisabledBreakpoint "${eventName}"`, >+ description: "Check that a disabled breakpoint can be removed.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, eventName, "Should not pause for removed disabled breakpoint."); >+ >+ addBreakpoint(eventName) >+ .then(disableBreakpoint) >+ .then(removeBreakpoint) >+ .then(awaitBodyEvent(eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ } >+ >+ addTestCasesForEventName("click"); >+ addTestCasesForEventName("custom"); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.AddMultipleBreakpoints`, >+ description: "Check that a single breakpoint pauses for every event of that type.", >+ teardown, >+ test(resolve, reject) { >+ let pauseCount = 0; >+ >+ let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ ++pauseCount; >+ >+ InspectorTest.pass("Should pause before event handler is run."); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume() >+ .catch((reason) => { >+ InspectorTest.fail(reason); >+ resolve(); >+ }); >+ >+ if (pauseCount >= 2) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ resolve(); >+ } >+ }); >+ >+ addBreakpoint("click") >+ .then(() => { >+ InspectorTest.log("Firing \"click\" on div#x..."); >+ return InspectorTest.evaluateInPage(`xFire_click()`); >+ }) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.runTestCasesAndFinish(); >+} >+</script> >+</head> >+<body onload="runTest()"> >+ <p>Tests for Event Listener breakpoints.</p> >+ <div id="x"></div> >+ <script> >+ document.body.addEventListener("click", handleBody_click); >+ document.body.addEventListener("custom", handleBody_custom); >+ >+ document.getElementById("x").addEventListener("click", handleX_click); >+ </script> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 183118
:
334593
|
334594
|
334596
|
334597
|
334603
|
334633
|
335486
|
335762
|
346100
|
346101
|
346363
|
346367
|
346368
|
346369
|
346384
|
347172
| 347331