Source/WebCore/ChangeLog

 12018-08-16 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: support breakpoints for arbitrary event names
 4 https://bugs.webkit.org/show_bug.cgi?id=183118
 5
 6 Reviewed by Joseph Pecoraro.
 7
 8 Tests: inspector/dom-debugger/event-breakpoints.html
 9 inspector/dom-debugger/event-breakpoints-with-navigation.html
 10
 11 * inspector/agents/InspectorDOMDebuggerAgent.cpp:
 12 (WebCore::InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded):
 13
1142018-08-15 Ryosuke Niwa <rniwa@webkit.org>
215
316 Can't share an app on AppStore to WeChat due to a release assert

Source/WebInspectorUI/ChangeLog

 12018-08-16 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: support breakpoints for arbitrary event names
 4 https://bugs.webkit.org/show_bug.cgi?id=183118
 5
 6 Reviewed by Joseph Pecoraro.
 7
 8 Create UI for setting breakpoints on event names. Ties into renamed DOMDebugger commands,
 9 specifically `setEventBreakpoint` and `removeEventBreakpoint`, that will pause execution if
 10 any DOM event is fired that matches any previously registered breakpoints.
 11
 12 Event breakpoints are distinguished by name, and they currently apply globally, meaning
 13 that only one breakpoint per event name can be registered.
 14
 15 Event breakpoints are created in the Debugger tab in a new "Event Breakpoints" section in
 16 the Navigation sidebar. A new type of popover, EventBreakpointPopover, is used, but right
 17 now all it contains is a basic text input for the event name. Similarly, a new TreeElement
 18 subclass, EventBreakpointTreeElement, is used when showing the list of event listener
 19 breakpoints, but all it shows now is the event name.
 20
 21 The majority of the logic in this patch was derived from XHR breakpoints.
 22
 23 * Localizations/en.lproj/localizedStrings.js:
 24 * UserInterface/Main.html:
 25 * UserInterface/Test.html:
 26 * UserInterface/Images/EventBreakpoint.svg: Added.
 27
 28 * UserInterface/Models/EventBreakpoint.js: Added.
 29 (WI.EventBreakpoint):
 30 (WI.EventBreakpoint.prototype.get eventName):
 31 (WI.EventBreakpoint.prototype.get disabled):
 32 (WI.EventBreakpoint.prototype.set disabled):
 33 (WI.EventBreakpoint.prototype.get serializableInfo):
 34 (WI.EventBreakpoint.prototype.saveIdentityToCookie):
 35
 36 * UserInterface/Controllers/DOMDebuggerManager.js:
 37 (WI.DOMDebuggerManager):
 38 (WI.DOMDebuggerManager.prototype.get eventBreakpoints): Added.
 39 (WI.DOMDebuggerManager.prototype.eventBreakpointForEventName): Added.
 40 (WI.DOMDebuggerManager.prototype.addEventBreakpoint): Added.
 41 (WI.DOMDebuggerManager.prototype.removeEventBreakpoint): Added.
 42 (WI.DOMDebuggerManager.prototype._speculativelyResolveBreakpoints):
 43 (WI.DOMDebuggerManager.prototype._updateEventBreakpoint.breakpointUpdated): Added.
 44 (WI.DOMDebuggerManager.prototype._updateEventBreakpoint): Added.
 45 (WI.DOMDebuggerManager.prototype._resolveEventBreakpoint): Added.
 46 (WI.DOMDebuggerManager.prototype._saveEventBreakpoints): Added.
 47 (WI.DOMDebuggerManager.prototype._eventBreakpointDisabledStateDidChange): Added.
 48
 49 * UserInterface/Controllers/DebuggerManager.js:
 50 (WI.DebuggerManager.prototype._pauseReasonFromPayload):
 51
 52 * UserInterface/Controllers/EventBreakpointTreeController.js: Added.
 53 (WI.EventBreakpointTreeController):
 54 (WI.EventBreakpointTreeController.prototype.revealAndSelect):
 55 (WI.EventBreakpointTreeController.prototype._eventBreakpointAdded):
 56 (WI.EventBreakpointTreeController.prototype._eventBreakpointRemoved):
 57 (WI.EventBreakpointTreeController.prototype._addTreeElement):
 58
 59 * UserInterface/Views/DebuggerSidebarPanel.js:
 60 (WI.DebuggerSidebarPanel):
 61 (WI.DebuggerSidebarPanel.prototype._updatePauseReasonSection):
 62 (WI.DebuggerSidebarPanel.prototype._eventBreakpointAddedOrRemoved): Added.
 63 (WI.DebuggerSidebarPanel.prototype._addEventBreakpointButtonClicked): Added.
 64 (WI.DebuggerSidebarPanel.prototype.willDismissPopover):
 65
 66 * UserInterface/Views/EventBreakpointTreeElement.js: Added.
 67 (WI.EventBreakpointTreeElement):
 68 (WI.EventBreakpointTreeElement.prototype.onattach):
 69 (WI.EventBreakpointTreeElement.prototype.ondetach):
 70 (WI.EventBreakpointTreeElement.prototype.ondelete):
 71 (WI.EventBreakpointTreeElement.prototype.onenter):
 72 (WI.EventBreakpointTreeElement.prototype.onspace):
 73 (WI.EventBreakpointTreeElement.prototype.populateContextMenu):
 74 (WI.EventBreakpointTreeElement.prototype._statusImageElementClicked):
 75 (WI.EventBreakpointTreeElement.prototype._statusImageElementFocused):
 76 (WI.EventBreakpointTreeElement.prototype._statusImageElementMouseDown):
 77 (WI.EventBreakpointTreeElement.prototype._toggleBreakpoint):
 78 (WI.EventBreakpointTreeElement.prototype._updateStatus):
 79 * UserInterface/Views/EventBreakpointTreeElement.css: Added.
 80 (.breakpoint.event-listener:not(.breakpoint-paused-icon) .icon):
 81
 82 * UserInterface/Views/EventBreakpointPopover.js: Added.
 83 (WI.EventBreakpointPopover):
 84 (WI.EventBreakpointPopover.prototype.get result):
 85 (WI.EventBreakpointPopover.prototype.get value):
 86 (WI.EventBreakpointPopover.prototype.show):
 87 (WI.EventBreakpointPopover.prototype._presentOverTargetElement):
 88 * UserInterface/Views/EventBreakpointPopover.css: Added.
 89 (.popover .event-listener-breakpoint-content):
 90 (.popover .event-listener-breakpoint-content > input):
 91
 92 * UserInterface/Views/NavigationSidebarPanel.js:
 93 (WI.NavigationSidebarPanel.prototype._isTreeElementWithoutRepresentedObject):
 94
1952018-08-15 Aditya Keerthi <akeerthi@apple.com>
296
397 [Datalist] Add button to TextFieldInputs with a datalist

Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp

@@void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(bool isDOMEvent, cons
371371 return;
372372
373373 Ref<JSON::Object> eventData = JSON::Object::create();
374  eventData->setString("eventName"_s, fullEventName);
 374 eventData->setString("eventName"_s, eventName);
375375
376376 if (synchronous)
377377 m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData));

Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

@@localizedStrings["Add"] = "Add";
7272localizedStrings["Add %s Rule"] = "Add %s Rule";
7373localizedStrings["Add Action"] = "Add Action";
7474localizedStrings["Add Breakpoint"] = "Add Breakpoint";
 75localizedStrings["Add Event Breakpoint"] = "Add Event Breakpoint";
7576localizedStrings["Add New"] = "Add New";
7677localizedStrings["Add New Class"] = "Add New Class";
7778localizedStrings["Add New Probe Expression"] = "Add New Probe Expression";

@@localizedStrings["Bottom"] = "Bottom";
144145localizedStrings["Boundary"] = "Boundary";
145146localizedStrings["Box Model"] = "Box Model";
146147localizedStrings["Box Shadow"] = "Box Shadow";
 148localizedStrings["Break on events with name:"] = "Break on events with name:";
147149localizedStrings["Break on request with URL:"] = "Break on request with URL:";
148150localizedStrings["Break on…"] = "Break on…";
149151localizedStrings["Breakdown"] = "Breakdown";

@@localizedStrings["Errors"] = "Errors";
395397localizedStrings["Eval Code"] = "Eval Code";
396398localizedStrings["Evaluate JavaScript"] = "Evaluate JavaScript";
397399localizedStrings["Event"] = "Event";
 400localizedStrings["Event Breakpoints"] = "Event Breakpoints";
398401localizedStrings["Event Dispatched"] = "Event Dispatched";
399402localizedStrings["Event Listeners"] = "Event Listeners";
400403localizedStrings["Events"] = "Events";

@@localizedStrings["times before stopping"] = "times before stopping";
10931096localizedStrings["toggle"] = "toggle";
10941097localizedStrings["unsupported version."] = "unsupported version.";
10951098localizedStrings["value"] = "value";
 1099localizedStrings["“%s“ Event Fired"] = "“%s“ Event Fired";
10961100localizedStrings["“%s” Profile Recorded"] = "“%s” Profile Recorded";
10971101localizedStrings["“%s” is invalid."] = "“%s” is invalid.";
10981102localizedStrings["“%s” threw an error."] = "“%s” threw an error.";

Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
3333 this._domBreakpointURLMap = new Map;
3434 this._domBreakpointFrameIdentifierMap = new Map;
3535
 36 this._eventBreakpointSetting = new WI.Setting("event-breakpoints", []);
 37 this._eventBreakpoints = [];
 38
3639 this._xhrBreakpointsSetting = new WI.Setting("xhr-breakpoints", []);
3740 this._xhrBreakpoints = [];
3841 this._allRequestsBreakpointEnabledSetting = new WI.Setting("break-on-all-requests", false);

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
4043 this._allRequestsBreakpoint = new WI.XHRBreakpoint(null, null, !this._allRequestsBreakpointEnabledSetting.value);
4144
4245 WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DisabledStateDidChange, this._domBreakpointDisabledStateDidChange, this);
 46 WI.EventBreakpoint.addEventListener(WI.EventBreakpoint.Event.DisabledStateDidChange, this._eventBreakpointDisabledStateDidChange, this);
4347 WI.XHRBreakpoint.addEventListener(WI.XHRBreakpoint.Event.DisabledStateDidChange, this._xhrBreakpointDisabledStateDidChange, this);
4448
4549 WI.domTreeManager.addEventListener(WI.DOMTreeManager.Event.NodeRemoved, this._nodeRemoved, this);

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
5862 this.addDOMBreakpoint(breakpoint);
5963 }
6064
 65 for (let cookie of this._eventBreakpointSetting.value) {
 66 let breakpoint = new WI.EventBreakpoint(cookie.eventName, cookie.disabled);
 67 this.addEventBreakpoint(breakpoint);
 68 }
 69
6170 for (let cookie of this._xhrBreakpointsSetting.value) {
6271 let breakpoint = new WI.XHRBreakpoint(cookie.type, cookie.url, cookie.disabled);
6372 this.addXHRBreakpoint(breakpoint);

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
102111 return resolvedBreakpoints;
103112 }
104113
 114 get eventBreakpoints() { return this._eventBreakpoints; }
 115
105116 get xhrBreakpoints() { return this._xhrBreakpoints; }
106117
107118 isBreakpointRemovable(breakpoint)

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
184195 this._saveDOMBreakpoints();
185196 }
186197
 198 eventBreakpointForEventName(eventName)
 199 {
 200 return this._eventBreakpoints.find((breakpoint) => breakpoint.eventName === eventName) || null;
 201 }
 202
 203 addEventBreakpoint(breakpoint)
 204 {
 205 console.assert(breakpoint instanceof WI.EventBreakpoint);
 206 if (!breakpoint)
 207 return;
 208
 209 if (this._eventBreakpoints.some((item) => item.eventName === breakpoint.eventName))
 210 return;
 211
 212 this._eventBreakpoints.push(breakpoint);
 213
 214 this.dispatchEventToListeners(WI.DOMDebuggerManager.Event.EventBreakpointAdded, {breakpoint});
 215
 216 this._resolveEventBreakpoint(breakpoint);
 217 this._saveEventBreakpoints();
 218 }
 219
 220 removeEventBreakpoint(breakpoint)
 221 {
 222 console.assert(breakpoint instanceof WI.EventBreakpoint);
 223 if (!breakpoint)
 224 return;
 225
 226 if (!this._eventBreakpoints.includes(breakpoint))
 227 return;
 228
 229 this._eventBreakpoints.remove(breakpoint);
 230
 231 this._saveEventBreakpoints();
 232 this.dispatchEventToListeners(WI.DOMDebuggerManager.Event.EventBreakpointRemoved, {breakpoint});
 233
 234 if (breakpoint.disabled)
 235 return;
 236
 237 DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, (error) => {
 238 if (error)
 239 console.error(error);
 240 });
 241 }
 242
187243 xhrBreakpointForURL(url)
188244 {
189245 return this._xhrBreakpoints.find((breakpoint) => breakpoint.url === url) || null;

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
300356 }
301357 }
302358
 359 for (let breakpoint of this._eventBreakpoints)
 360 this._resolveEventBreakpoint(breakpoint);
 361
303362 for (let breakpoint of this._xhrBreakpoints)
304363 this._resolveXHRBreakpoint(breakpoint);
305364 }

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
347406 DOMDebuggerAgent.setDOMBreakpoint(nodeIdentifier, breakpoint.type, breakpointUpdated);
348407 }
349408
 409 _updateEventBreakpoint(breakpoint, callback)
 410 {
 411 function breakpointUpdated(error)
 412 {
 413 if (error)
 414 console.error(error);
 415
 416 if (callback)
 417 callback(error);
 418 }
 419
 420 if (breakpoint.disabled)
 421 DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
 422 else
 423 DOMDebuggerAgent.setEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
 424 }
 425
350426 _updateXHRBreakpoint(breakpoint, callback)
351427 {
352428 function breakpointUpdated(error)

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
366442 }
367443 }
368444
 445 _resolveEventBreakpoint(breakpoint)
 446 {
 447 if (breakpoint.disabled)
 448 return;
 449
 450 this._updateEventBreakpoint(breakpoint, () => {
 451 breakpoint.dispatchEventToListeners(WI.EventBreakpoint.Event.ResolvedStateDidChange);
 452 });
 453 }
 454
369455 _resolveXHRBreakpoint(breakpoint)
370456 {
371457 if (breakpoint.disabled)

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
388474 this._domBreakpointsSetting.value = breakpointsToSave.map((breakpoint) => breakpoint.serializableInfo);
389475 }
390476
 477 _saveEventBreakpoints()
 478 {
 479 if (this._restoringBreakpoints)
 480 return;
 481
 482 this._eventBreakpointSetting.value = this._eventBreakpoints.map((breakpoint) => breakpoint.serializableInfo);
 483 }
 484
391485 _saveXHRBreakpoints()
392486 {
393487 if (this._restoringBreakpoints)

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
403497 this._saveDOMBreakpoints();
404498 }
405499
 500 _eventBreakpointDisabledStateDidChange(event)
 501 {
 502 let breakpoint = event.target;
 503 this._updateEventBreakpoint(breakpoint);
 504 this._saveEventBreakpoints();
 505 }
 506
406507 _xhrBreakpointDisabledStateDidChange(event)
407508 {
408509 let breakpoint = event.target;

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
488589WI.DOMDebuggerManager.Event = {
489590 DOMBreakpointAdded: "dom-debugger-manager-dom-breakpoint-added",
490591 DOMBreakpointRemoved: "dom-debugger-manager-dom-breakpoint-removed",
 592 EventBreakpointAdded: "dom-debugger-manager-event-breakpoint-added",
 593 EventBreakpointRemoved: "dom-debugger-manager-event-breakpoint-removed",
491594 XHRBreakpointAdded: "dom-debugger-manager-xhr-breakpoint-added",
492595 XHRBreakpointRemoved: "dom-debugger-manager-xhr-breakpoint-removed",
493596};

Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js

@@WI.DebuggerManager = class DebuggerManager extends WI.Object
828828 return WI.DebuggerManager.PauseReason.DOM;
829829 case DebuggerAgent.PausedReason.DebuggerStatement:
830830 return WI.DebuggerManager.PauseReason.DebuggerStatement;
 831 case DebuggerAgent.PausedReason.EventListener:
 832 return WI.DebuggerManager.PauseReason.EventListener;
831833 case DebuggerAgent.PausedReason.Exception:
832834 return WI.DebuggerManager.PauseReason.Exception;
833835 case DebuggerAgent.PausedReason.PauseOnNextStatement:

@@WI.DebuggerManager.PauseReason = {
12361238 CSPViolation: "CSP-violation",
12371239 DebuggerStatement: "debugger-statement",
12381240 DOM: "DOM",
 1241 EventListener: "event-listener",
12391242 Exception: "exception",
12401243 PauseOnNextStatement: "pause-on-next-statement",
12411244 XHR: "xhr",

Source/WebInspectorUI/UserInterface/Controllers/EventBreakpointTreeController.js

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.EventBreakpointTreeController = class EventBreakpointTreeController
 27{
 28 constructor(treeOutline)
 29 {
 30 this._treeOutline = treeOutline;
 31
 32 WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointAdded, this._eventBreakpointAdded, this);
 33 WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointRemoved, this._eventBreakpointRemoved, this);
 34
 35 for (let breakpoint of WI.domDebuggerManager.eventBreakpoints)
 36 this._addTreeElement(breakpoint);
 37 }
 38
 39 // Public
 40
 41 revealAndSelect(breakpoint)
 42 {
 43 let treeElement = this._treeOutline.findTreeElement(breakpoint);
 44 if (!treeElement)
 45 return;
 46
 47 treeElement.revealAndSelect();
 48 }
 49
 50 // Private
 51
 52 _eventBreakpointAdded(event)
 53 {
 54 this._addTreeElement(event.data.breakpoint);
 55 }
 56
 57 _eventBreakpointRemoved(event)
 58 {
 59 let breakpoint = event.data.breakpoint;
 60 let treeElement = this._treeOutline.findTreeElement(breakpoint);
 61 if (!treeElement)
 62 return;
 63
 64 this._treeOutline.removeChild(treeElement);
 65 }
 66
 67 _addTreeElement(breakpoint)
 68 {
 69 let treeElement = this._treeOutline.findTreeElement(breakpoint);
 70 console.assert(!treeElement);
 71 if (treeElement)
 72 return;
 73
 74 this._treeOutline.appendChild(new WI.EventBreakpointTreeElement(breakpoint));
 75 }
 76};

Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg

 1<?xml version="1.0" encoding="utf-8"?>
 2<!-- Copyright © 2018 Apple Inc. All rights reserved. -->
 3<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16">
 4 <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"/>
 5 <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"/>
 6 <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"/>
 7 <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"/>
 8</svg>

Source/WebInspectorUI/UserInterface/Main.html

8383 <link rel="stylesheet" href="Views/DetailsSection.css">
8484 <link rel="stylesheet" href="Views/DividerNavigationItem.css">
8585 <link rel="stylesheet" href="Views/Editing.css">
 86 <link rel="stylesheet" href="Views/EventBreakpointPopover.css">
 87 <link rel="stylesheet" href="Views/EventBreakpointTreeElement.css">
8688 <link rel="stylesheet" href="Views/EventListenerSectionGroup.css">
8789 <link rel="stylesheet" href="Views/ErrorObjectView.css">
8890 <link rel="stylesheet" href="Views/FilterBar.css">

376378 <script src="Models/DebuggerDashboard.js"></script>
377379 <script src="Models/DebuggerData.js"></script>
378380 <script src="Models/DefaultDashboard.js"></script>
 381 <script src="Models/EventBreakpoint.js"></script>
379382 <script src="Models/ExecutionContext.js"></script>
380383 <script src="Models/ExecutionContextList.js"></script>
381384 <script src="Models/FPSInstrument.js"></script>

622625 <script src="Views/EditableDataGridNode.js"></script>
623626 <script src="Views/EditingSupport.js"></script>
624627 <script src="Views/ErrorObjectView.js"></script>
 628 <script src="Views/EventBreakpointPopover.js"></script>
 629 <script src="Views/EventBreakpointTreeElement.js"></script>
625630 <script src="Views/EventListenerSectionGroup.js"></script>
626631 <script src="Views/FilterBar.js"></script>
627632 <script src="Views/FilterBarButton.js"></script>

843848 <script src="Controllers/DebuggerManager.js"></script>
844849 <script src="Controllers/DOMBreakpointTreeController.js"></script>
845850 <script src="Controllers/DragToAdjustController.js"></script>
 851 <script src="Controllers/EventBreakpointTreeController.js"></script>
846852 <script src="Controllers/Formatter.js"></script>
847853 <script src="Controllers/FormatterSourceMap.js"></script>
848854 <script src="Controllers/FrameResourceManager.js"></script>

Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.EventBreakpoint = class EventBreakpoint extends WI.Object
 27{
 28 constructor(eventName, disabled)
 29 {
 30 super();
 31
 32 console.assert(typeof eventName === "string");
 33
 34 this._eventName = eventName;
 35 this._disabled = disabled || false;
 36 }
 37
 38 // Public
 39
 40 get eventName() { return this._eventName; }
 41
 42 get disabled()
 43 {
 44 return this._disabled;
 45 }
 46
 47 set disabled(disabled)
 48 {
 49 if (this._disabled === disabled)
 50 return;
 51
 52 this._disabled = disabled;
 53
 54 this.dispatchEventToListeners(WI.EventBreakpoint.Event.DisabledStateDidChange);
 55 }
 56
 57 get serializableInfo()
 58 {
 59 let info = {
 60 eventName: this._eventName,
 61 };
 62 if (this._disabled)
 63 info.disabled = true;
 64
 65 return info;
 66 }
 67
 68 saveIdentityToCookie(cookie)
 69 {
 70 cookie[WI.EventBreakpoint.EventNameCookieKey] = this._eventName;
 71 }
 72};
 73
 74WI.EventBreakpoint.EventNameCookieKey = "event-breakpoint-event-name";
 75
 76WI.EventBreakpoint.Event = {
 77 DisabledStateDidChange: "event-breakpoint-disabled-state-did-change",
 78 ResolvedStateDidChange: "event-breakpoint-resolved-state-did-change",
 79};

Source/WebInspectorUI/UserInterface/Test.html

133133 <script src="Models/DOMStorageObject.js"></script>
134134 <script src="Models/DOMTree.js"></script>
135135 <script src="Models/DebuggerData.js"></script>
 136 <script src="Models/EventBreakpoint.js"></script>
136137 <script src="Models/ExecutionContext.js"></script>
137138 <script src="Models/ExecutionContextList.js"></script>
138139 <script src="Models/FPSInstrument.js"></script>

Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js

@@WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
176176 this._domBreakpointsSection = new WI.DetailsSection("dom-breakpoints", WI.UIString("DOM Breakpoints"), [domBreakpointsGroup], null, defaultCollapsed);
177177 this.contentView.element.appendChild(this._domBreakpointsSection.element);
178178
 179 this._eventBreakpointsContentTreeOutline = this.createContentTreeOutline(true);
 180 this._eventBreakpointsContentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementAdded, this._eventBreakpointAddedOrRemoved, this);
 181 this._eventBreakpointsContentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementRemoved, this._eventBreakpointAddedOrRemoved, this);
 182
 183 this._eventBreakpointsRow = new WI.DetailsSectionRow(WI.UIString("No Breakpoints"));
 184 this._eventBreakpointsRow.element.appendChild(this._eventBreakpointsContentTreeOutline.element);
 185 this._eventBreakpointsRow.showEmptyMessage();
 186
 187 let eventBreakpointNavigationBar = new WI.NavigationBar;
 188 let eventBreakpointNavigationBarWrapper = document.createElement("div");
 189 eventBreakpointNavigationBarWrapper.appendChild(eventBreakpointNavigationBar.element);
 190
 191 let addEventBreakpointButton = new WI.ButtonNavigationItem("add-event-breakpoint", WI.UIString("Add Event Breakpoint"), "Images/Plus13.svg", 13, 13);
 192 addEventBreakpointButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._addEventBreakpointButtonClicked, this);
 193 eventBreakpointNavigationBar.addNavigationItem(addEventBreakpointButton);
 194
 195 let eventBreakpointsGroup = new WI.DetailsSectionGroup([this._eventBreakpointsRow]);
 196 this._eventBreakpointsSection = new WI.DetailsSection("event-breakpoints", WI.UIString("Event Breakpoints"), [eventBreakpointsGroup], eventBreakpointNavigationBarWrapper, defaultCollapsed);
 197 this.contentView.element.appendChild(this._eventBreakpointsSection.element);
 198
 199 this._eventBreakpointTreeController = new WI.EventBreakpointTreeController(this._eventBreakpointsContentTreeOutline);
 200
179201 this._xhrBreakpointsContentTreeOutline = this.createContentTreeOutline(true);
180202 this._xhrBreakpointTreeController = new WI.XHRBreakpointTreeController(this._xhrBreakpointsContentTreeOutline);
181203
182204 this._xhrBreakpointsRow = new WI.DetailsSectionRow;
183205 this._xhrBreakpointsRow.element.appendChild(this._xhrBreakpointsContentTreeOutline.element);
184206
185  let navigationBar = new WI.NavigationBar;
186  let navigationBarWrapper = document.createElement("div");
187  navigationBarWrapper.appendChild(navigationBar.element);
 207 let xhrBreakpointNavigationBar = new WI.NavigationBar;
 208 let xhrBreakpointNavigationBarWrapper = document.createElement("div");
 209 xhrBreakpointNavigationBarWrapper.appendChild(xhrBreakpointNavigationBar.element);
188210
189211 let addXHRBreakpointButton = new WI.ButtonNavigationItem("add-xhr-breakpoint", WI.UIString("Add XHR Breakpoint"), "Images/Plus13.svg", 13, 13);
190212 addXHRBreakpointButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._addXHRBreakpointButtonClicked, this);
191  navigationBar.addNavigationItem(addXHRBreakpointButton);
 213 xhrBreakpointNavigationBar.addNavigationItem(addXHRBreakpointButton);
192214
193215 let xhrBreakpointsGroup = new WI.DetailsSectionGroup([this._xhrBreakpointsRow]);
194  let xhrBreakpointsSection = new WI.DetailsSection("xhr-breakpoints", WI.UIString("XHR Breakpoints"), [xhrBreakpointsGroup], navigationBarWrapper, defaultCollapsed);
 216 let xhrBreakpointsSection = new WI.DetailsSection("xhr-breakpoints", WI.UIString("XHR Breakpoints"), [xhrBreakpointsGroup], xhrBreakpointNavigationBarWrapper, defaultCollapsed);
195217 this.contentView.element.appendChild(xhrBreakpointsSection.element);
196218 }
197219

@@WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
10321054 }
10331055 break;
10341056
 1057 case WI.DebuggerManager.PauseReason.EventListener:
 1058 console.assert(pauseData, "Expected data with an event listener, but found none.");
 1059 if (pauseData) {
 1060 let eventBreakpoint = WI.domDebuggerManager.eventBreakpointForEventName(pauseData.eventName);
 1061 console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName);
 1062
 1063 this._pauseReasonTreeOutline = this.createContentTreeOutline(true);
 1064
 1065 let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName, WI.UIString("“%s“ Event Fired").format(pauseData.eventName));
 1066 this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
 1067
 1068 let eventBreakpointRow = new WI.DetailsSectionRow;
 1069 eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
 1070
 1071 this._pauseReasonGroup.rows = [eventBreakpointRow];
 1072 }
 1073 return true;
 1074
10351075 case WI.DebuggerManager.PauseReason.Exception:
10361076 console.assert(pauseData, "Expected data with an exception, but found none.");
10371077 if (pauseData) {

@@WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
11751215 this._domBreakpointsSection.collapsed = false;
11761216 }
11771217
 1218 _eventBreakpointAddedOrRemoved(event)
 1219 {
 1220 if (!this._eventBreakpointsContentTreeOutline.children.length) {
 1221 this._eventBreakpointsRow.showEmptyMessage();
 1222 return;
 1223 }
 1224
 1225 if (this._eventBreakpointsContentTreeOutline.element.parent)
 1226 return;
 1227
 1228 this._eventBreakpointsRow.hideEmptyMessage();
 1229 this._eventBreakpointsRow.element.append(this._eventBreakpointsContentTreeOutline.element);
 1230
 1231 this._eventBreakpointsSection.collapsed = false;
 1232 }
 1233
 1234 _addEventBreakpointButtonClicked(event)
 1235 {
 1236 let popover = new WI.EventBreakpointPopover(this);
 1237 popover.show(event.target.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
 1238 }
 1239
11781240 _addXHRBreakpointButtonClicked(event)
11791241 {
11801242 let popover = new WI.XHRBreakpointPopover(this);

@@WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
11881250 if (popover.result !== WI.InputPopover.Result.Committed)
11891251 return;
11901252
1191  let url = popover.value;
1192  if (!url)
 1253 if (popover instanceof WI.EventBreakpointPopover) {
 1254 let eventName = popover.value;
 1255 if (eventName)
 1256 WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(eventName));
11931257 return;
 1258 }
11941259
1195  WI.domDebuggerManager.addXHRBreakpoint(new WI.XHRBreakpoint(popover.type, url));
 1260 if (popover instanceof WI.XHRBreakpointPopover) {
 1261 let url = popover.value;
 1262 if (url)
 1263 WI.domDebuggerManager.addXHRBreakpoint(new WI.XHRBreakpoint(popover.type, url));
 1264 return;
 1265 }
11961266 }
11971267};
11981268

Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26.popover .event-breakpoint-content {
 27 margin: 2px;
 28 padding: 5px;
 29}
 30
 31.popover .event-breakpoint-content > input {
 32 width: 100%;
 33 margin-top: 4px;
 34 padding: 4px 0 2px 0;
 35 outline: none;
 36}

Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover
 27{
 28 constructor(delegate)
 29 {
 30 super(delegate);
 31
 32 this._result = WI.InputPopover.Result.None;
 33 this._value = null;
 34
 35 this._codeMirror = null;
 36 this._targetElement = null;
 37 this._preferredEdges = null;
 38
 39 this.windowResizeHandler = this._presentOverTargetElement.bind(this);
 40 }
 41
 42 // Public
 43
 44 get result() { return this._result; }
 45 get value() { return this._value; }
 46
 47 show(targetElement, preferredEdges)
 48 {
 49 this._targetElement = targetElement;
 50 this._preferredEdges = preferredEdges;
 51
 52 let contentElement = document.createElement("div");
 53 contentElement.classList.add("event-breakpoint-content");
 54
 55 let label = contentElement.appendChild(document.createElement("div"));
 56 label.classList.add("label");
 57 label.textContent = WI.UIString("Break on events with name:");
 58
 59 this._inputElement = contentElement.appendChild(document.createElement("input"));
 60 this._inputElement.placeholder = "click";
 61 this._inputElement.spellcheck = false;
 62 this._inputElement.addEventListener("keydown", (event) => {
 63 if (!isEnterKey(event))
 64 return;
 65
 66 this._result = WI.InputPopover.Result.Committed;
 67 this._value = event.target.value.trim();
 68
 69 this.dismiss();
 70 });
 71
 72 this.content = contentElement;
 73
 74 this._presentOverTargetElement();
 75 }
 76
 77 // Private
 78
 79 _presentOverTargetElement()
 80 {
 81 if (!this._targetElement)
 82 return;
 83
 84 let targetFrame = WI.Rect.rectFromClientRect(this._targetElement.getBoundingClientRect());
 85 this.present(targetFrame, this._preferredEdges);
 86
 87 this._inputElement.select();
 88 }
 89};

Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26.breakpoint.event:not(.breakpoint-paused-icon) .icon {
 27 content: url(../Images/EventBreakpoint.svg);
 28}

Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js

 1/*
 2 * Copyright (C) 2018 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.EventBreakpointTreeElement = class EventBreakpointTreeElement extends WI.GeneralTreeElement
 27{
 28 constructor(breakpoint, className, title)
 29 {
 30 console.assert(breakpoint instanceof WI.EventBreakpoint);
 31
 32 let classNames = ["breakpoint", "event"];
 33 if (className)
 34 classNames.push(className);
 35
 36 if (!title)
 37 title = breakpoint.eventName;
 38
 39 const subtitle = null;
 40 super(classNames, title, subtitle, breakpoint);
 41
 42 this._statusImageElement = document.createElement("img");
 43 this._statusImageElement.classList.add("status-image", "resolved");
 44 this.status = this._statusImageElement;
 45
 46 breakpoint.addEventListener(WI.EventBreakpoint.Event.DisabledStateDidChange, this._updateStatus, this);
 47
 48 this._updateStatus();
 49 }
 50
 51 // Protected
 52
 53 onattach()
 54 {
 55 super.onattach();
 56
 57 this._boundStatusImageElementClicked = this._statusImageElementClicked.bind(this);
 58 this._boundStatusImageElementFocused = this._statusImageElementFocused.bind(this);
 59 this._boundStatusImageElementMouseDown = this._statusImageElementMouseDown.bind(this);
 60
 61 this._statusImageElement.addEventListener("click", this._boundStatusImageElementClicked);
 62 this._statusImageElement.addEventListener("focus", this._boundStatusImageElementFocused);
 63 this._statusImageElement.addEventListener("mousedown", this._boundStatusImageElementMouseDown);
 64 }
 65
 66 ondetach()
 67 {
 68 super.ondetach();
 69
 70 this._statusImageElement.removeEventListener("click", this._boundStatusImageElementClicked);
 71 this._statusImageElement.removeEventListener("focus", this._boundStatusImageElementFocused);
 72 this._statusImageElement.removeEventListener("mousedown", this._boundStatusImageElementMouseDown);
 73
 74 this._boundStatusImageElementClicked = null;
 75 this._boundStatusImageElementFocused = null;
 76 this._boundStatusImageElementMouseDown = null;
 77 }
 78
 79 ondelete()
 80 {
 81 WI.domDebuggerManager.removeEventBreakpoint(this.representedObject);
 82 return true;
 83 }
 84
 85 onenter()
 86 {
 87 this._toggleBreakpoint();
 88 return true;
 89 }
 90
 91 onspace()
 92 {
 93 this._toggleBreakpoint();
 94 return true;
 95 }
 96
 97 populateContextMenu(contextMenu, event)
 98 {
 99 let breakpoint = this.representedObject;
 100 let label = breakpoint.disabled ? WI.UIString("Enable Breakpoint") : WI.UIString("Disable Breakpoint");
 101 contextMenu.appendItem(label, this._toggleBreakpoint.bind(this));
 102
 103 if (WI.domDebuggerManager.isBreakpointRemovable(breakpoint)) {
 104 contextMenu.appendSeparator();
 105 contextMenu.appendItem(WI.UIString("Delete Breakpoint"), () => {
 106 WI.domDebuggerManager.removeEventBreakpoint(breakpoint);
 107 });
 108 }
 109 }
 110
 111 // Private
 112
 113 _statusImageElementClicked(event)
 114 {
 115 this._toggleBreakpoint();
 116 }
 117
 118 _statusImageElementFocused(event)
 119 {
 120 // Prevent tree outline focus.
 121 event.stopPropagation();
 122 }
 123
 124 _statusImageElementMouseDown(event)
 125 {
 126 // Prevent tree element selection.
 127 event.stopPropagation();
 128 }
 129
 130 _toggleBreakpoint()
 131 {
 132 this.representedObject.disabled = !this.representedObject.disabled;
 133 }
 134
 135 _updateStatus()
 136 {
 137 this._statusImageElement.classList.toggle("disabled", this.representedObject.disabled);
 138 }
 139};

Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js

@@WI.NavigationSidebarPanel = class NavigationSidebarPanel extends WI.SidebarPanel
633633 || treeElement instanceof WI.ThreadTreeElement
634634 || treeElement instanceof WI.IdleTreeElement
635635 || treeElement instanceof WI.DOMBreakpointTreeElement
 636 || treeElement instanceof WI.EventBreakpointTreeElement
636637 || treeElement instanceof WI.XHRBreakpointTreeElement
637638 || treeElement instanceof WI.CSSStyleSheetTreeElement
638639 || typeof treeElement.representedObject === "string"

LayoutTests/ChangeLog

 12018-08-16 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: support breakpoints for arbitrary event names
 4 https://bugs.webkit.org/show_bug.cgi?id=183118
 5
 6 Reviewed by Joseph Pecoraro.
 7
 8 * inspector/dom-debugger/event-breakpoints-expected.txt: Added.
 9 * inspector/dom-debugger/event-breakpoints.html: Added.
 10
 11 * inspector/dom-debugger/event-breakpoints-with-navigation-expected.txt: Added.
 12 * inspector/dom-debugger/event-breakpoints-with-navigation.html: Added.
 13
1142018-08-15 Christopher Reid <chris.reid@sony.com>
215
316 [Curl] Implement default cookie path handling correctly as outlined in RFC6265.

LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation-expected.txt

 1Tests for Event Listener breakpoints.
 2
 3
 4== Running test suite: DOMDebugger.EventWithNavigation
 5-- Running test case: DOMDebugger.EventWithNavigation.AddBreakpoint
 6Adding "load" Event Breakpoint...
 7Reloading WebInspector...
 8PASS: Pause reason should be EventListener.
 9PASS: Pause data eventName should be "load".
 10-- Running test teardown.
 11

LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation.html

 1<!doctype html>
 2<html>
 3<head>
 4<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
 5<script>
 6function handleLoad(event) {
 7 TestPage.dispatchEventToFrontend("TestPageLoad");
 8
 9 runTest();
 10}
 11
 12function test() {
 13 let suite = InspectorTest.createAsyncSuite("DOMDebugger.EventWithNavigation");
 14
 15 suite.addTestCase({
 16 name: `DOMDebugger.EventWithNavigation.AddBreakpoint`,
 17 description: "Check that a breakpoint is preserved over navigation.",
 18 test(resolve, reject) {
 19 let paused = false;
 20
 21 let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 22 paused = true;
 23
 24 let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target);
 25 InspectorTest.expectEqual(targetData.pauseReason, WI.DebuggerManager.PauseReason.EventListener, "Pause reason should be EventListener.");
 26 InspectorTest.expectEqual(targetData.pauseData.eventName, "load", "Pause data eventName should be \"load\".");
 27
 28 WI.debuggerManager.resume()
 29 .catch((reason) => {
 30 InspectorTest.fail(reason);
 31 resolve();
 32 });
 33 });
 34
 35 InspectorTest.singleFireEventListener("TestPageLoad", (event) => {
 36 if (!paused) {
 37 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 38
 39 InspectorTest.fail("Should pause before \"load\" event handler is run");
 40 }
 41
 42 resolve();
 43 });
 44
 45 InspectorTest.log("Adding \"load\" Event Breakpoint...");
 46
 47 let breakpoint = new WI.EventBreakpoint("load");
 48
 49 WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded)
 50 .then((event) => {
 51 InspectorTest.assert(event.data.breakpoint.eventName, "load", "Breakpoint should be for expected event name.");
 52
 53 InspectorTest.log("Reloading WebInspector...");
 54 return InspectorTest.reloadPage();
 55 })
 56 .catch(reject);
 57
 58 WI.domDebuggerManager.addEventBreakpoint(breakpoint);
 59 },
 60 teardown(resolve, reject) {
 61 let breakpoints = WI.domDebuggerManager.eventBreakpoints;
 62 for (let breakpoint of breakpoints)
 63 WI.domDebuggerManager.removeEventBreakpoint(breakpoint);
 64
 65 resolve();
 66 },
 67 });
 68
 69 suite.runTestCasesAndFinish();
 70}
 71</script>
 72</head>
 73<body>
 74 <p>Tests for Event Listener breakpoints.</p>
 75 <div id="x"></div>
 76 <script>
 77 window.addEventListener("load", handleLoad);
 78 </script>
 79</body>
 80</html>

LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt

 1Tests for Event Listener breakpoints.
 2
 3
 4== Running test suite: DOMDebugger.Event
 5-- Running test case: DOMDebugger.Event.AddBreakpoint "click"
 6Adding "click" Event Breakpoint...
 7Firing "click" on body...
 8PASS: Should pause before event handler is run.
 9CALL STACK:
 100: [F] handleBody_click
 111: [F] bodyFire_click
 122: [P] Global Code
 13-- Running test teardown.
 14
 15-- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "click"
 16Adding "click" Event Breakpoint...
 17Disabling "click" Event Breakpoint...
 18Firing "click" on body...
 19PASS: Should not pause for disabled breakpoint.
 20-- Running test teardown.
 21
 22-- Running test case: DOMDebugger.Event.RemoveBreakpoint "click"
 23Adding "click" Event Breakpoint...
 24Removing "click" Event Breakpoint...
 25Firing "click" on body...
 26PASS: Should not pause for removed breakpoint.
 27-- Running test teardown.
 28
 29-- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "click"
 30Adding "click" Event Breakpoint...
 31Disabling "click" Event Breakpoint...
 32Removing "click" Event Breakpoint...
 33Firing "click" on body...
 34PASS: Should not pause for removed disabled breakpoint.
 35-- Running test teardown.
 36
 37-- Running test case: DOMDebugger.Event.AddBreakpoint "custom"
 38Adding "custom" Event Breakpoint...
 39Firing "custom" on body...
 40PASS: Should pause before event handler is run.
 41CALL STACK:
 420: [F] handleBody_custom
 431: [F] bodyFire_custom
 442: [P] Global Code
 45-- Running test teardown.
 46
 47-- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "custom"
 48Adding "custom" Event Breakpoint...
 49Disabling "custom" Event Breakpoint...
 50Firing "custom" on body...
 51PASS: Should not pause for disabled breakpoint.
 52-- Running test teardown.
 53
 54-- Running test case: DOMDebugger.Event.RemoveBreakpoint "custom"
 55Adding "custom" Event Breakpoint...
 56Removing "custom" Event Breakpoint...
 57Firing "custom" on body...
 58PASS: Should not pause for removed breakpoint.
 59-- Running test teardown.
 60
 61-- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "custom"
 62Adding "custom" Event Breakpoint...
 63Disabling "custom" Event Breakpoint...
 64Removing "custom" Event Breakpoint...
 65Firing "custom" on body...
 66PASS: Should not pause for removed disabled breakpoint.
 67-- Running test teardown.
 68
 69-- Running test case: DOMDebugger.Event.AddMultipleBreakpoints
 70Adding "click" Event Breakpoint...
 71Firing "click" on div#x...
 72PASS: Should pause before event handler is run.
 73CALL STACK:
 740: [F] handleX_click
 751: [F] xFire_click
 762: [P] Global Code
 77PASS: Should pause before event handler is run.
 78CALL STACK:
 790: [F] handleBody_click
 801: [F] xFire_click
 812: [P] Global Code
 82-- Running test teardown.
 83

LayoutTests/inspector/dom-debugger/event-breakpoints.html

 1<!doctype html>
 2<html>
 3<head>
 4<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
 5<script src="../debugger/resources/log-active-stack-trace.js"></script>
 6<script>
 7function handleBody_click(event) {
 8 TestPage.dispatchEventToFrontend("TestPageBody-click");
 9}
 10
 11function handleBody_custom(event) {
 12 TestPage.dispatchEventToFrontend("TestPageBody-custom");
 13}
 14
 15function handleX_click(event) {
 16 TestPage.dispatchEventToFrontend("TestPageX-click");
 17}
 18
 19function bodyFire_click() {
 20 document.body.click();
 21}
 22
 23function bodyFire_custom() {
 24 document.body.dispatchEvent(new Event("custom"));
 25}
 26
 27function xFire_click() {
 28 document.getElementById("x").click();
 29}
 30
 31function test() {
 32 let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event");
 33
 34 function teardown(resolve, reject) {
 35 let breakpoints = WI.domDebuggerManager.eventBreakpoints;
 36 for (let breakpoint of breakpoints)
 37 WI.domDebuggerManager.removeEventBreakpoint(breakpoint);
 38
 39 resolve();
 40 }
 41
 42 function awaitBodyEvent(eventName) {
 43 return function() {
 44 InspectorTest.log(`Firing "${eventName}" on body...`);
 45 return InspectorTest.evaluateInPage(`bodyFire_${eventName}()`);
 46 };
 47 }
 48
 49 function failOnPause(resolve, eventName, message) {
 50 let paused = false;
 51
 52 let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 53 paused = true;
 54
 55 let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target);
 56 InspectorTest.assert(targetData.pauseReason === WI.DebuggerManager.PauseReason.EventListener, "Pause reason should be EventListener.");
 57 InspectorTest.assert(targetData.pauseData.eventName === eventName, `Pause data eventName should be "${eventName}".`);
 58
 59 InspectorTest.fail(message);
 60 logActiveStackTrace();
 61
 62 WI.debuggerManager.resume()
 63 .catch((reason) => {
 64 InspectorTest.fail(reason);
 65 resolve();
 66 });
 67 });
 68
 69 InspectorTest.singleFireEventListener("TestPageBody-" + eventName, (event) => {
 70 if (!paused) {
 71 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 72
 73 InspectorTest.pass(message);
 74 }
 75
 76 resolve();
 77 });
 78 }
 79
 80 function addBreakpoint(eventName) {
 81 InspectorTest.log(`Adding "${eventName}" Event Breakpoint...`);
 82
 83 return new Promise((resolve, reject) => {
 84 let breakpoint = new WI.EventBreakpoint(eventName);
 85
 86 WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded)
 87 .then((event) => {
 88 InspectorTest.assert(event.data.breakpoint.eventName === eventName, "Breakpoint should be for expected event name.");
 89 InspectorTest.assert(!breakpoint.disabled, "Breakpoint should not be disabled initially.");
 90 resolve(breakpoint);
 91 });
 92
 93 WI.domDebuggerManager.addEventBreakpoint(breakpoint);
 94 });
 95 }
 96
 97 function removeBreakpoint(breakpoint) {
 98 InspectorTest.log(`Removing "${breakpoint.eventName}" Event Breakpoint...`);
 99
 100 return new Promise((resolve, reject) => {
 101 WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointRemoved)
 102 .then((event) => {
 103 InspectorTest.assert(event.data.breakpoint === breakpoint, "Removed Breakpoint should be expected object.");
 104 InspectorTest.assert(!WI.domDebuggerManager.eventBreakpoints.includes(breakpoint), "Breakpoint should not be in the list of breakpoints.");
 105 resolve(breakpoint);
 106 });
 107
 108 WI.domDebuggerManager.removeEventBreakpoint(breakpoint);
 109 });
 110 }
 111
 112 function disableBreakpoint(breakpoint) {
 113 InspectorTest.log(`Disabling "${breakpoint.eventName}" Event Breakpoint...`);
 114
 115 breakpoint.disabled = true;
 116 return breakpoint;
 117 }
 118
 119 function addTestCasesForEventName(eventName) {
 120 suite.addTestCase({
 121 name: `DOMDebugger.Event.AddBreakpoint "${eventName}"`,
 122 description: "Check that the debugger pauses for enabled breakpoints.",
 123 teardown,
 124 test(resolve, reject) {
 125 let paused = false;
 126
 127 let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 128 paused = true;
 129
 130 InspectorTest.pass("Should pause before event handler is run.");
 131 logActiveStackTrace();
 132
 133 WI.debuggerManager.resume();
 134 });
 135
 136 InspectorTest.singleFireEventListener(`TestPageBody-${eventName}`, (event) => {
 137 if (!paused) {
 138 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 139
 140 InspectorTest.fail("Should pause before event handler is run.");
 141 }
 142
 143 resolve();
 144 });
 145
 146 addBreakpoint(eventName)
 147 .then(awaitBodyEvent(eventName))
 148 .catch(reject);
 149 },
 150 });
 151
 152 suite.addTestCase({
 153 name: `DOMDebugger.Event.AddDisabledBreakpoint "${eventName}"`,
 154 description: "Check that debugger does the not pause for disabled breakpoints.",
 155 teardown,
 156 test(resolve, reject) {
 157 failOnPause(resolve, eventName, "Should not pause for disabled breakpoint.");
 158
 159 addBreakpoint(eventName)
 160 .then(disableBreakpoint)
 161 .then(awaitBodyEvent(eventName))
 162 .catch(reject);
 163 },
 164 });
 165
 166 suite.addTestCase({
 167 name: `DOMDebugger.Event.RemoveBreakpoint "${eventName}"`,
 168 description: "Check that debugger does not pause for removed breakpoint.",
 169 teardown,
 170 test(resolve, reject) {
 171 failOnPause(resolve, eventName, "Should not pause for removed breakpoint.");
 172
 173 addBreakpoint(eventName)
 174 .then(removeBreakpoint)
 175 .then(awaitBodyEvent(eventName))
 176 .catch(reject);
 177 },
 178 });
 179
 180 suite.addTestCase({
 181 name: `DOMDebugger.Event.RemoveDisabledBreakpoint "${eventName}"`,
 182 description: "Check that a disabled breakpoint can be removed.",
 183 teardown,
 184 test(resolve, reject) {
 185 failOnPause(resolve, eventName, "Should not pause for removed disabled breakpoint.");
 186
 187 addBreakpoint(eventName)
 188 .then(disableBreakpoint)
 189 .then(removeBreakpoint)
 190 .then(awaitBodyEvent(eventName))
 191 .catch(reject);
 192 },
 193 });
 194
 195 }
 196
 197 addTestCasesForEventName("click");
 198 addTestCasesForEventName("custom");
 199
 200 suite.addTestCase({
 201 name: `DOMDebugger.Event.AddMultipleBreakpoints`,
 202 description: "Check that a single breakpoint pauses for every event of that type.",
 203 teardown,
 204 test(resolve, reject) {
 205 let pauseCount = 0;
 206
 207 let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 208 ++pauseCount;
 209
 210 InspectorTest.pass("Should pause before event handler is run.");
 211 logActiveStackTrace();
 212
 213 WI.debuggerManager.resume()
 214 .catch((reason) => {
 215 InspectorTest.fail(reason);
 216 resolve();
 217 });
 218
 219 if (pauseCount >= 2) {
 220 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 221
 222 resolve();
 223 }
 224 });
 225
 226 addBreakpoint("click")
 227 .then(() => {
 228 InspectorTest.log("Firing \"click\" on div#x...");
 229 return InspectorTest.evaluateInPage(`xFire_click()`);
 230 })
 231 .catch(reject);
 232 },
 233 });
 234
 235 suite.runTestCasesAndFinish();
 236}
 237</script>
 238</head>
 239<body onload="runTest()">
 240 <p>Tests for Event Listener breakpoints.</p>
 241 <div id="x"></div>
 242 <script>
 243 document.body.addEventListener("click", handleBody_click);
 244 document.body.addEventListener("custom", handleBody_custom);
 245
 246 document.getElementById("x").addEventListener("click", handleX_click);
 247 </script>
 248</body>
 249</html>