Source/JavaScriptCore/ChangeLog

 12018-08-22 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: support breakpoints for timers and animation-frame events
 4 https://bugs.webkit.org/show_bug.cgi?id=188778
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * inspector/protocol/Debugger.json:
 9 Add `AnimationFrame` and `Timer` types to the list of pause reasons.
 10
 11 * inspector/protocol/DOMDebugger.json:
 12 Introduced `setEventBreakpoint` and `removeEventBreakpoint` to replace the more specific:
 13 - `setEventListenerBreakpoint`
 14 - `removeEventListenerBreakpoint`
 15 - `setInstrumentationBreakpoint`
 16 - `removeInstrumentationBreakpoint`
 17 Also created an `EventBreakpointType` to enumerate the available types of event breakpoints.
 18
1192018-08-20 Yusuke Suzuki <yusukesuzuki@slowstart.org>
220
321 [JSC] HeapUtil should care about pointer overflow

Source/WebCore/ChangeLog

 12018-08-22 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: support breakpoints for timers and animation-frame events
 4 https://bugs.webkit.org/show_bug.cgi?id=188778
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 The original implementation of "instrumentation" breakpoints relied upon the frontend
 9 sending somewhat arbitrary strings when enabling breakpoints for specific events. As an
 10 example, setting a breakpoint for `requestAnimationFrame` expects `"animationFrameFired"`
 11 as the string, which doesn't make much sense. This patch removes the usage of these strings
 12 and instead expects the agent to implement a method that matches what is happening.
 13
 14 Tests: inspector/dom-debugger/event-animation-frame-breakpoints.html
 15 inspector/dom-debugger/event-listener-breakpoints.html
 16 inspector/dom-debugger/event-timer-breakpoints.html
 17
 18 * inspector/InspectorInstrumentation.h:
 19 (WebCore::InspectorInstrumentation::willFireTimer):
 20 * inspector/InspectorInstrumentation.cpp:
 21 (WebCore::InspectorInstrumentation::didInstallTimerImpl):
 22 (WebCore::InspectorInstrumentation::didRemoveTimerImpl):
 23 (WebCore::InspectorInstrumentation::willFireTimerImpl):
 24 (WebCore::InspectorInstrumentation::didRequestAnimationFrameImpl):
 25 (WebCore::InspectorInstrumentation::didCancelAnimationFrameImpl):
 26 (WebCore::InspectorInstrumentation::willFireAnimationFrameImpl):
 27 (WebCore::InspectorInstrumentation::pauseOnNativeEventIfNeeded): Deleted.
 28
 29 * inspector/agents/InspectorDOMDebuggerAgent.h:
 30 * inspector/agents/InspectorDOMDebuggerAgent.cpp:
 31 (WebCore::InspectorDOMDebuggerAgent::setEventBreakpoint): Added.
 32 (WebCore::InspectorDOMDebuggerAgent::removeEventBreakpoint): Added.
 33 (WebCore::InspectorDOMDebuggerAgent::willHandleEvent):
 34 (WebCore::InspectorDOMDebuggerAgent::willFireTimer): Added.
 35 (WebCore::InspectorDOMDebuggerAgent::willFireAnimationFrame): Added.
 36 (WebCore::InspectorDOMDebuggerAgent::setEventListenerBreakpoint): Deleted.
 37 (WebCore::InspectorDOMDebuggerAgent::setInstrumentationBreakpoint): Deleted.
 38 (WebCore::InspectorDOMDebuggerAgent::setBreakpoint): Deleted.
 39 (WebCore::InspectorDOMDebuggerAgent::removeEventListenerBreakpoint): Deleted.
 40 (WebCore::InspectorDOMDebuggerAgent::removeInstrumentationBreakpoint): Deleted.
 41 (WebCore::InspectorDOMDebuggerAgent::removeBreakpoint): Deleted.
 42 (WebCore::InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded): Deleted.
 43 Unify the event listener and instrumentation breakpoint commands into a single method,
 44 `setEventBreakpoint`, that takes in both an `EventBreakpointType` and `eventName`.
 45
 46 * page/DOMTimer.cpp:
 47 (WebCore::DOMTimer::fired):
 48
1492018-08-21 Yusuke Suzuki <yusukesuzuki@slowstart.org>
250
351 Support "name" option for dedicated workers

Source/WebInspectorUI/ChangeLog

 12018-08-22 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: support breakpoints for timers and animation-frame events
 4 https://bugs.webkit.org/show_bug.cgi?id=188778
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Add a `type` to `WI.EventBreakpoint` that matches `DOMDebugger.EventBreakpointType`:
 9 - `AnimationFrame` for `requestAnimationFrame`
 10 - `Listener` for any named DOM Event
 11 - `Timer` for `setTimeout` and `setInterval`
 12
 13 Modified `WI.EventBreakpointPopover` to provide ways for selecting these other types, which
 14 is then passed to `WI.DOMDebuggerManager`, which now calls through to the newly added
 15 `DOMDebugger.removeEventBreakpoint` and `DOMDebugger.setEventBreakpoint` that sets
 16 breakpoints for all event types.
 17
 18 * Localizations/en.lproj/localizedStrings.js:
 19 * UserInterface/Images/EventBreakpointAnimationFrame.svg: Added.
 20 * UserInterface/Images/EventBreakpointListener.svg: Renamed from Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg.
 21 * UserInterface/Images/EventBreakpointTimer.svg: Added.
 22
 23 * UserInterface/Controllers/DOMDebuggerManager.js:
 24 (WI.DOMDebuggerManager.supportsEventBreakpoints): Added.
 25 (WI.DOMDebuggerManager.prototype.eventBreakpointForTypeAndEventName): Added.
 26 (WI.DOMDebuggerManager.prototype.addEventBreakpoint):
 27 (WI.DOMDebuggerManager.prototype.removeEventBreakpoint.breakpointRemoved): Added.
 28 (WI.DOMDebuggerManager.prototype.removeEventBreakpoint):
 29 (WI.DOMDebuggerManager.prototype._updateEventBreakpoint):
 30 (WI.DOMDebuggerManager.prototype.eventBreakpointForEventName): Deleted.
 31
 32 * UserInterface/Controllers/DOMTreeManager.js:
 33 (WI.DOMTreeManager.prototype.setBreakpointForEventListener):
 34
 35 * UserInterface/Controllers/DebuggerManager.js:
 36 (WI.DebuggerManager.prototype._pauseReasonFromPayload):
 37
 38 * UserInterface/Models/EventBreakpoint.js:
 39 (WI.EventBreakpoint):
 40 (WI.EventBreakpoint.fromPayload):
 41 (WI.EventBreakpoint.prototype.get type): Added.
 42 (WI.EventBreakpoint.prototype.get serializableInfo):
 43 (WI.EventBreakpoint.prototype.saveIdentityToCookie):
 44
 45 * UserInterface/Views/DebuggerSidebarPanel.js:
 46 (WI.DebuggerSidebarPanel.prototype._updatePauseReasonSection):
 47 (WI.DebuggerSidebarPanel.prototype.willDismissPopover):
 48
 49 * UserInterface/Views/EventBreakpointPopover.js:
 50 (WI.EventBreakpointPopover):
 51 (WI.EventBreakpointPopover.prototype.get breakpoint): Added.
 52 (WI.EventBreakpointPopover.prototype.show):
 53 (WI.EventBreakpointPopover.prototype.show.createOption): Added.
 54 (WI.EventBreakpointPopover.prototype.dismiss): Added.
 55 (WI.EventBreakpointPopover.prototype._presentOverTargetElement):
 56 (WI.EventBreakpointPopover.prototype._handleTypeSelectChange): Added.
 57 (WI.EventBreakpointPopover.prototype.get result): Deleted.
 58 (WI.EventBreakpointPopover.prototype.get value): Deleted.
 59 * UserInterface/Views/EventBreakpointPopover.css:
 60 (.popover .event-breakpoint-content > .event-type): Added.
 61 (.popover .event-breakpoint-content > input): Deleted.
 62
 63 * UserInterface/Views/EventBreakpointTreeElement.js:
 64 (WI.EventBreakpointTreeElement):
 65 * UserInterface/Views/EventBreakpointTreeElement.css:
 66 (.breakpoint.event.animation-frame:not(.breakpoint-paused-icon) .icon): Added.
 67 (.breakpoint.event.listener:not(.breakpoint-paused-icon) .icon): Added.
 68 (.breakpoint.event.timer:not(.breakpoint-paused-icon) .icon): Added.
 69 (.breakpoint.event:not(.breakpoint-paused-icon) .icon): Deleted.
 70
1712018-08-21 Matt Baker <mattbaker@apple.com>
272
373 Web Inspector: Remove TreeOutlineDataGridSynchronizer

Source/JavaScriptCore/inspector/protocol/DOMDebugger.json

88 "type": "string",
99 "enum": ["subtree-modified", "attribute-modified", "node-removed"],
1010 "description": "DOM breakpoint type."
 11 },
 12 {
 13 "id": "EventBreakpointType",
 14 "type": "string",
 15 "enum": ["animation-frame", "listener", "timer"],
 16 "description": "Event breakpoint type."
1117 }
1218 ],
1319 "commands": [

2834 ]
2935 },
3036 {
31  "name": "setEventListenerBreakpoint",
32  "description": "Sets breakpoint on particular DOM event.",
33  "parameters": [
34  { "name": "eventName", "type": "string", "description": "DOM Event name to stop on (any DOM event will do)." }
35  ]
36  },
37  {
38  "name": "removeEventListenerBreakpoint",
39  "description": "Removes breakpoint on particular DOM event.",
40  "parameters": [
41  { "name": "eventName", "type": "string", "description": "Event name." }
42  ]
43  },
44  {
45  "name": "setInstrumentationBreakpoint",
46  "description": "Sets breakpoint on particular native event.",
 37 "name": "setEventBreakpoint",
 38 "description": "Sets breakpoint on particular event of given type.",
4739 "parameters": [
48  { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." }
 40 { "name": "breakpointType", "$ref": "EventBreakpointType" },
 41 { "name": "eventName", "type": "string", "description": "The name of the event to stop on." }
4942 ]
5043 },
5144 {
52  "name": "removeInstrumentationBreakpoint",
53  "description": "Sets breakpoint on particular native event.",
 45 "name": "removeEventBreakpoint",
 46 "description": "Removes breakpoint on particular event of given type.",
5447 "parameters": [
55  { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." }
 48 { "name": "breakpointType", "$ref": "EventBreakpointType" },
 49 { "name": "eventName", "type": "string", "description": "The name of the event to stop on." }
5650 ]
5751 },
5852 {

Source/JavaScriptCore/inspector/protocol/Debugger.json

341341 "description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.",
342342 "parameters": [
343343 { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." },
344  { "name": "reason", "type": "string", "enum": ["XHR", "DOM", "EventListener", "exception", "assert", "CSPViolation", "DebuggerStatement", "Breakpoint", "PauseOnNextStatement", "other"], "description": "Pause reason." },
 344 { "name": "reason", "type": "string", "enum": ["XHR", "DOM", "AnimationFrame", "EventListener", "Timer", "exception", "assert", "CSPViolation", "DebuggerStatement", "Breakpoint", "PauseOnNextStatement", "other"], "description": "Pause reason." },
345345 { "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." },
346346 { "name": "asyncStackTrace", "$ref": "Console.StackTrace", "optional": true, "description": "Linked list of asynchronous StackTraces." }
347347 ]

Source/WebCore/inspector/InspectorInstrumentation.cpp

@@namespace WebCore {
7676
7777using namespace Inspector;
7878
79 static const char* const requestAnimationFrameEventName = "requestAnimationFrame";
80 static const char* const cancelAnimationFrameEventName = "cancelAnimationFrame";
81 static const char* const animationFrameFiredEventName = "animationFrameFired";
82 static const char* const setTimerEventName = "setTimer";
83 static const char* const clearTimerEventName = "clearTimer";
84 static const char* const timerFiredEventName = "timerFired";
85 
8679namespace {
8780static HashSet<InstrumentingAgents*>* s_instrumentingAgentsSet = nullptr;
8881}

@@void InspectorInstrumentation::willSendXMLHttpRequestImpl(InstrumentingAgents& i
294287
295288void InspectorInstrumentation::didInstallTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, Seconds timeout, bool singleShot, ScriptExecutionContext& context)
296289{
297  pauseOnNativeEventIfNeeded(instrumentingAgents, setTimerEventName, true);
298 
299290 if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent())
300291 debuggerAgent->didScheduleAsyncCall(context.execState(), InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId, singleShot);
301292

@@void InspectorInstrumentation::didInstallTimerImpl(InstrumentingAgents& instrume
305296
306297void InspectorInstrumentation::didRemoveTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, ScriptExecutionContext& context)
307298{
308  pauseOnNativeEventIfNeeded(instrumentingAgents, clearTimerEventName, true);
309 
310299 if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent())
311300 debuggerAgent->didCancelAsyncCall(InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId);
312301 if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent())

@@void InspectorInstrumentation::didEvaluateScriptImpl(const InspectorInstrumentat
443432 timelineAgent->didEvaluateScript(frame);
444433}
445434
446 InspectorInstrumentationCookie InspectorInstrumentation::willFireTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, ScriptExecutionContext& context)
 435InspectorInstrumentationCookie InspectorInstrumentation::willFireTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, bool oneShot, ScriptExecutionContext& context)
447436{
448  pauseOnNativeEventIfNeeded(instrumentingAgents, timerFiredEventName, false);
449 
450437 if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent())
451438 debuggerAgent->willDispatchAsyncCall(InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId);
452439
 440 if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent())
 441 domDebuggerAgent->willFireTimer(oneShot);
 442
453443 int timelineAgentId = 0;
454444 if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) {
455445 timelineAgent->willFireTimer(timerId, frameForScriptExecutionContext(context));

@@bool InspectorInstrumentation::timelineAgentEnabled(ScriptExecutionContext* scri
10441034 return instrumentingAgents && instrumentingAgents->inspectorTimelineAgent();
10451035}
10461036
1047 void InspectorInstrumentation::pauseOnNativeEventIfNeeded(InstrumentingAgents& instrumentingAgents, const String& eventName, bool synchronous)
1048 {
1049  if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent())
1050  domDebuggerAgent->pauseOnNativeEventIfNeeded(eventName, synchronous);
1051 }
1052 
10531037void InspectorInstrumentation::didRequestAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document)
10541038{
1055  pauseOnNativeEventIfNeeded(instrumentingAgents, requestAnimationFrameEventName, true);
1056 
10571039 if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent())
10581040 pageDebuggerAgent->didRequestAnimationFrame(callbackId, document);
10591041 if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent())

@@void InspectorInstrumentation::didRequestAnimationFrameImpl(InstrumentingAgents&
10621044
10631045void InspectorInstrumentation::didCancelAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document)
10641046{
1065  pauseOnNativeEventIfNeeded(instrumentingAgents, cancelAnimationFrameEventName, true);
1066 
10671047 if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent())
10681048 pageDebuggerAgent->didCancelAnimationFrame(callbackId);
10691049 if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent())

@@void InspectorInstrumentation::didCancelAnimationFrameImpl(InstrumentingAgents&
10721052
10731053InspectorInstrumentationCookie InspectorInstrumentation::willFireAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document)
10741054{
1075  pauseOnNativeEventIfNeeded(instrumentingAgents, animationFrameFiredEventName, false);
1076 
10771055 if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent())
10781056 pageDebuggerAgent->willFireAnimationFrame(callbackId);
10791057
 1058 if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent())
 1059 domDebuggerAgent->willFireAnimationFrame();
 1060
10801061 int timelineAgentId = 0;
10811062 if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) {
10821063 timelineAgent->willFireAnimationFrame(callbackId, document.frame());

Source/WebCore/inspector/InspectorInstrumentation.h

@@public:
157157 static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&);
158158 static InspectorInstrumentationCookie willEvaluateScript(Frame&, const String& url, int lineNumber);
159159 static void didEvaluateScript(const InspectorInstrumentationCookie&, Frame&);
160  static InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext&, int timerId);
 160 static InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext&, int timerId, bool oneShot);
161161 static void didFireTimer(const InspectorInstrumentationCookie&);
162162 static void didInvalidateLayout(Frame&);
163163 static InspectorInstrumentationCookie willLayout(Frame&);

@@private:
341341 static void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&);
342342 static InspectorInstrumentationCookie willEvaluateScriptImpl(InstrumentingAgents&, Frame&, const String& url, int lineNumber);
343343 static void didEvaluateScriptImpl(const InspectorInstrumentationCookie&, Frame&);
344  static InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents&, int timerId, ScriptExecutionContext&);
 344 static InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents&, int timerId, bool oneShot, ScriptExecutionContext&);
345345 static void didFireTimerImpl(const InspectorInstrumentationCookie&);
346346 static void didInvalidateLayoutImpl(InstrumentingAgents&, Frame&);
347347 static InspectorInstrumentationCookie willLayoutImpl(InstrumentingAgents&, Frame&);

@@private:
453453
454454 static InspectorTimelineAgent* retrieveTimelineAgent(const InspectorInstrumentationCookie&);
455455
456  static void pauseOnNativeEventIfNeeded(InstrumentingAgents&, const String& eventName, bool synchronous);
457 
458456 WEBCORE_EXPORT static int s_frontendCounter;
459457};
460458

@@inline void InspectorInstrumentation::didEvaluateScript(const InspectorInstrumen
807805 didEvaluateScriptImpl(cookie, frame);
808806}
809807
810 inline InspectorInstrumentationCookie InspectorInstrumentation::willFireTimer(ScriptExecutionContext& context, int timerId)
 808inline InspectorInstrumentationCookie InspectorInstrumentation::willFireTimer(ScriptExecutionContext& context, int timerId, bool oneShot)
811809{
812810 FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
813811 if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
814  return willFireTimerImpl(*instrumentingAgents, timerId, context);
 812 return willFireTimerImpl(*instrumentingAgents, timerId, oneShot, context);
815813 return InspectorInstrumentationCookie();
816814}
817815

Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp

@@enum DOMBreakpointType {
5252 DOMBreakpointTypesCount
5353};
5454
55 static const char eventNameCategoryType[] = "event-name:";
56 static const char instrumentationCategoryType[] = "instrumentation:";
 55static const char animationFrameCategoryType[] = "animation-frame";
 56static const char listenerCategoryType[] = "listener";
 57static const char timerCategoryType[] = "timer";
5758
5859const uint32_t inheritableDOMBreakpointTypesMask = (1 << SubtreeModified);
5960const int domBreakpointDerivedTypeShift = 16;

@@void InspectorDOMDebuggerAgent::discardBindings()
126127 m_xhrBreakpoints.clear();
127128}
128129
129 void InspectorDOMDebuggerAgent::setEventListenerBreakpoint(ErrorString& error, const String& eventName)
 130static String formatEventBreakpointString(const String& breakpointType, const String& eventName)
130131{
131  setBreakpoint(error, eventNameCategoryType + eventName);
 132 return makeString(breakpointType, ':', eventName);
132133}
133134
134 void InspectorDOMDebuggerAgent::setInstrumentationBreakpoint(ErrorString& error, const String& eventName)
 135void InspectorDOMDebuggerAgent::setEventBreakpoint(ErrorString& error, const String& breakpointType, const String& eventName)
135136{
136  setBreakpoint(error, instrumentationCategoryType + eventName);
137 }
 137 if (breakpointType.isEmpty()) {
 138 error = "Event breakpoint type is empty"_s;
 139 return;
 140 }
 141
 142 if (breakpointType != animationFrameCategoryType && breakpointType != listenerCategoryType && breakpointType != timerCategoryType) {
 143 error = makeString("Unknown event breakpoint type: "_s, breakpointType);
 144 return;
 145 }
138146
139 void InspectorDOMDebuggerAgent::setBreakpoint(ErrorString& error, const String& eventName)
140 {
141147 if (eventName.isEmpty()) {
142148 error = "Event name is empty"_s;
143149 return;
144150 }
145151
146  m_eventListenerBreakpoints.add(eventName);
 152 m_eventBreakpoints.add(formatEventBreakpointString(breakpointType, eventName));
147153}
148154
149 void InspectorDOMDebuggerAgent::removeEventListenerBreakpoint(ErrorString& error, const String& eventName)
 155void InspectorDOMDebuggerAgent::removeEventBreakpoint(ErrorString& error, const String& breakpointType, const String& eventName)
150156{
151  removeBreakpoint(error, eventNameCategoryType + eventName);
152 }
 157 if (breakpointType.isEmpty()) {
 158 error = "Event breakpoint type is empty"_s;
 159 return;
 160 }
153161
154 void InspectorDOMDebuggerAgent::removeInstrumentationBreakpoint(ErrorString& error, const String& eventName)
155 {
156  removeBreakpoint(error, instrumentationCategoryType + eventName);
157 }
 162 if (breakpointType != animationFrameCategoryType && breakpointType != listenerCategoryType && breakpointType != timerCategoryType) {
 163 error = makeString("Unknown event breakpoint type: "_s, breakpointType);
 164 return;
 165 }
158166
159 void InspectorDOMDebuggerAgent::removeBreakpoint(ErrorString& error, const String& eventName)
160 {
161167 if (eventName.isEmpty()) {
162168 error = "Event name is empty"_s;
163169 return;
164170 }
165171
166  m_eventListenerBreakpoints.remove(eventName);
 172 m_eventBreakpoints.remove(formatEventBreakpointString(breakpointType, eventName));
167173}
168174
169175void InspectorDOMDebuggerAgent::didInvalidateStyleAttr(Node& node)

@@void InspectorDOMDebuggerAgent::updateSubtreeBreakpoints(Node* node, uint32_t ro
366372
367373void InspectorDOMDebuggerAgent::willHandleEvent(const Event& event, const RegisteredEventListener& registeredEventListener)
368374{
369  bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventListenerBreakpoints.contains(eventNameCategoryType + event.type());
 375 bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(formatEventBreakpointString(listenerCategoryType, event.type()));
370376
371377 if (!shouldPause && m_domAgent)
372378 shouldPause = m_domAgent->hasBreakpointForEventListener(*event.currentTarget(), event.type(), registeredEventListener.callback(), registeredEventListener.useCapture());

@@void InspectorDOMDebuggerAgent::willHandleEvent(const Event& event, const Regist
385391 m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData));
386392}
387393
388 void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(const String& eventName, bool synchronous)
 394void InspectorDOMDebuggerAgent::willFireTimer(bool oneShot)
389395{
390  bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventListenerBreakpoints.contains(instrumentationCategoryType + eventName);
 396 String eventName = oneShot ? "setTimeout"_s : "setInterval"_s;
 397 bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(formatEventBreakpointString(timerCategoryType, eventName));
391398 if (!shouldPause)
392399 return;
393400
394401 Ref<JSON::Object> eventData = JSON::Object::create();
395402 eventData->setString("eventName"_s, eventName);
 403 m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::Timer, WTFMove(eventData));
 404}
396405
397  if (synchronous)
398  m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData));
399  else
400  m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData));
 406void InspectorDOMDebuggerAgent::willFireAnimationFrame()
 407{
 408 String eventName = "requestAnimationFrame"_s;
 409 bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(formatEventBreakpointString(animationFrameCategoryType, eventName));
 410 if (!shouldPause)
 411 return;
 412
 413 Ref<JSON::Object> eventData = JSON::Object::create();
 414 eventData->setString("eventName"_s, eventName);
 415 m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::AnimationFrame, WTFMove(eventData));
401416}
402417
403418void InspectorDOMDebuggerAgent::setXHRBreakpoint(ErrorString&, const String& url, const bool* optionalIsRegex)

Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.h

@@public:
5959 // DOMDebugger API
6060 void setXHRBreakpoint(ErrorString&, const String& url, const bool* optionalIsRegex) final;
6161 void removeXHRBreakpoint(ErrorString&, const String& url) final;
62  void setEventListenerBreakpoint(ErrorString&, const String& eventName) final;
63  void removeEventListenerBreakpoint(ErrorString&, const String& eventName) final;
64  void setInstrumentationBreakpoint(ErrorString&, const String& eventName) final;
65  void removeInstrumentationBreakpoint(ErrorString&, const String& eventName) final;
 62 void setEventBreakpoint(ErrorString&, const String& breakpointType, const String& eventName) final;
 63 void removeEventBreakpoint(ErrorString&, const String& breakpointType, const String& eventName) final;
6664 void setDOMBreakpoint(ErrorString&, int nodeId, const String& type) final;
6765 void removeDOMBreakpoint(ErrorString&, int nodeId, const String& type) final;
6866

@@public:
7674 void willSendXMLHttpRequest(const String& url);
7775 void frameDocumentUpdated(Frame&);
7876 void willHandleEvent(const Event&, const RegisteredEventListener&);
79  void pauseOnNativeEventIfNeeded(const String& eventName, bool synchronous);
 77 void willFireTimer(bool oneShot);
 78 void willFireAnimationFrame();
8079 void mainFrameDOMContentLoaded();
8180
8281 void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) final;

@@private:
9392 void updateSubtreeBreakpoints(Node*, uint32_t rootMask, bool set);
9493 bool hasBreakpoint(Node*, int type);
9594 void discardBindings();
96  void setBreakpoint(ErrorString&, const String& eventName);
97  void removeBreakpoint(ErrorString&, const String& eventName);
9895
9996 RefPtr<Inspector::DOMDebuggerBackendDispatcher> m_backendDispatcher;
10097 InspectorDOMAgent* m_domAgent { nullptr };
10198 Inspector::InspectorDebuggerAgent* m_debuggerAgent { nullptr };
10299
103100 HashMap<Node*, uint32_t> m_domBreakpoints;
104  HashSet<String> m_eventListenerBreakpoints;
 101 HashSet<String> m_eventBreakpoints;
105102
106103 enum class XHRBreakpointType { Text, RegularExpression };
107104

Source/WebCore/page/DOMTimer.cpp

@@void DOMTimer::fired()
321321 // Only the first execution of a multi-shot timer should get an affirmative user gesture indicator.
322322 m_userGestureTokenToForward = nullptr;
323323
324  InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId);
 324 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId, !repeatInterval());
325325
326326 // Simple case for non-one-shot timers.
327327 if (isActive()) {

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

@@localizedStrings["%s (%s, %s)"] = "%s (%s, %s)";
4141localizedStrings["%s (default)"] = "%s (default)";
4242localizedStrings["%s (hidden)"] = "%s (hidden)";
4343localizedStrings["%s Event Dispatched"] = "%s Event Dispatched";
 44localizedStrings["%s Fired"] = "%s Fired";
4445localizedStrings["%s Prototype"] = "%s Prototype";
4546localizedStrings["%s \u2013 %s"] = "%s \u2013 %s";
4647localizedStrings["%s \u2014 %s"] = "%s \u2014 %s";

@@localizedStrings["Boundary"] = "Boundary";
146147localizedStrings["Box Model"] = "Box Model";
147148localizedStrings["Box Shadow"] = "Box Shadow";
148149localizedStrings["Break on events with name:"] = "Break on events with name:";
149 localizedStrings["Break on listeners for event with name:"] = "Break on listeners for event with name:";
150150localizedStrings["Break on request with URL:"] = "Break on request with URL:";
151151localizedStrings["Break on…"] = "Break on…";
152152localizedStrings["Breakdown"] = "Breakdown";

@@localizedStrings["Custom"] = "Custom";
274274localizedStrings["DNS"] = "DNS";
275275localizedStrings["DOM Breakpoints"] = "DOM Breakpoints";
276276localizedStrings["DOM Content Loaded \u2014 %s"] = "DOM Content Loaded \u2014 %s";
 277localizedStrings["DOM Event"] = "DOM Event";
277278localizedStrings["Damping"] = "Damping";
278279localizedStrings["Dash Array"] = "Dash Array";
279280localizedStrings["Data"] = "Data";

@@localizedStrings["Event Breakpoints"] = "Event Breakpoints";
403404localizedStrings["Event Dispatched"] = "Event Dispatched";
404405localizedStrings["Event Listeners"] = "Event Listeners";
405406localizedStrings["Events"] = "Events";
 407localizedStrings["Example: “%s”"] = "Example: “%s”";
406408localizedStrings["Exception with thrown value: %s"] = "Exception with thrown value: %s";
407409localizedStrings["Expand All"] = "Expand All";
408410localizedStrings["Expand columns"] = "Expand columns";

Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
7878 }
7979 }
8080
 81 // Static
 82
 83 static supportsEventBreakpoints()
 84 {
 85 return DOMDebuggerAgent.setEventBreakpoint && DOMDebuggerAgent.removeEventBreakpoint;
 86 }
 87
8188 // Public
8289
8390 get supported()

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
193200 this._saveDOMBreakpoints();
194201 }
195202
196  eventBreakpointForEventName(eventName)
 203 eventBreakpointForTypeAndEventName(type, eventName)
197204 {
198  return this._eventBreakpoints.find((breakpoint) => breakpoint.eventName === eventName) || null;
 205 return this._eventBreakpoints.find((breakpoint) => breakpoint.type === type && breakpoint.eventName === eventName) || null;
199206 }
200207
201208 addEventBreakpoint(breakpoint)

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
204211 if (!breakpoint)
205212 return;
206213
207  if (this._eventBreakpoints.some((item) => item.eventName === breakpoint.eventName))
 214 if (this.eventBreakpointForTypeAndEventName(breakpoint.type, breakpoint.eventName))
208215 return;
209216
210217 this._eventBreakpoints.push(breakpoint);

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
232239 if (breakpoint.disabled)
233240 return;
234241
235  DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, (error) => {
 242 function breakpointRemoved(error) {
236243 if (error)
237244 console.error(error);
238  });
 245 }
 246
 247 // Compatibility (iOS 12): DOMDebuggerAgent.removeEventBreakpoint did not exist.
 248 if (!WI.DOMDebuggerManager.supportsEventBreakpoints()) {
 249 console.assert(breakpoint.type === WI.EventBreakpoint.Type.Listener);
 250 DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointRemoved);
 251 return;
 252 }
 253
 254 DOMDebuggerAgent.removeEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointRemoved);
239255 }
240256
241257 xhrBreakpointForURL(url)

@@WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object
415431 callback(error);
416432 }
417433
418  if (breakpoint.disabled)
419  DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
420  else
421  DOMDebuggerAgent.setEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
 434 if (breakpoint.disabled) {
 435 // Compatibility (iOS 12): DOMDebuggerAgent.removeEventBreakpoint did not exist.
 436 if (!WI.DOMDebuggerManager.supportsEventBreakpoints()) {
 437 console.assert(breakpoint.type === WI.EventBreakpoint.Type.Listener);
 438 DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
 439 return;
 440 }
 441
 442 DOMDebuggerAgent.removeEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointUpdated);
 443 } else {
 444 // Compatibility (iOS 12): DOMDebuggerAgent.setEventBreakpoint did not exist.
 445 if (!WI.DOMDebuggerManager.supportsEventBreakpoints()) {
 446 console.assert(breakpoint.type === WI.EventBreakpoint.Type.Listener);
 447 DOMDebuggerAgent.setEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
 448 return;
 449 }
 450
 451 DOMDebuggerAgent.setEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointUpdated);
 452 }
422453 }
423454
424455 _updateXHRBreakpoint(breakpoint, callback)

Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js

@@WI.DOMTreeManager = class DOMTreeManager extends WI.Object
556556
557557 setBreakpointForEventListener(eventListener)
558558 {
559  let breakpoint = new WI.EventBreakpoint(eventListener.type, {eventListener});
 559 let breakpoint = new WI.EventBreakpoint(WI.EventBreakpoint.Type.Listener, eventListener.type, {eventListener});
560560 this._breakpointsForEventListeners.set(eventListener.eventListenerId, breakpoint);
561561
562562 DOMAgent.setBreakpointForEventListener(eventListener.eventListenerId, (error) => {

Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js

@@WI.DebuggerManager = class DebuggerManager extends WI.Object
818818 {
819819 // FIXME: Handle other backend pause reasons.
820820 switch (payload) {
 821 case DebuggerAgent.PausedReason.AnimationFrame:
 822 return WI.DebuggerManager.PauseReason.AnimationFrame;
821823 case DebuggerAgent.PausedReason.Assert:
822824 return WI.DebuggerManager.PauseReason.Assertion;
823825 case DebuggerAgent.PausedReason.Breakpoint:

@@WI.DebuggerManager = class DebuggerManager extends WI.Object
834836 return WI.DebuggerManager.PauseReason.Exception;
835837 case DebuggerAgent.PausedReason.PauseOnNextStatement:
836838 return WI.DebuggerManager.PauseReason.PauseOnNextStatement;
 839 case DebuggerAgent.PausedReason.Timer:
 840 return WI.DebuggerManager.PauseReason.Timer;
837841 case DebuggerAgent.PausedReason.XHR:
838842 return WI.DebuggerManager.PauseReason.XHR;
839843 default:

@@WI.DebuggerManager.Event = {
12331237};
12341238
12351239WI.DebuggerManager.PauseReason = {
 1240 AnimationFrame: "animation-frame",
12361241 Assertion: "assertion",
12371242 Breakpoint: "breakpoint",
12381243 CSPViolation: "CSP-violation",

@@WI.DebuggerManager.PauseReason = {
12411246 EventListener: "event-listener",
12421247 Exception: "exception",
12431248 PauseOnNextStatement: "pause-on-next-statement",
 1249 Timer: "timer",
12441250 XHR: "xhr",
12451251 Other: "other",
12461252};

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/Images/EventBreakpointAnimationFrame.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.9 1 1 1.9 1 3 L 1 13 C 1 14.1 1.9 15 3 15 L 13 15 C 14.1 15 15 14.1 15 13 L 15 3 C 15 1.9 14.1 1 13 1 L 13 1 Z"/>
 5 <path fill="rgb(106, 136, 170)" d="M 13 1 L 3 1 C 1.9 1 1 1.9 1 3 L 1 13 C 1 14.1 1.9 15 3 15 L 13 15 C 14.1 15 15 14.1 15 13 L 15 3 C 15 1.9 14.1 1 13 1 M 13 2 C 13.552 2 14 2.449 14 3 L 14 13 C 14 13.552 13.552 14 13 14 L 3 14 C 2.449 14 2 13.552 2 13 L 2 3 C 2 2.449 2.449 2 3 2 L 13 2"/>
 6 <path fill="rgb(113, 146, 184)" d="M 8.1104 3 L 5.0004 3 L 4.0004 3 L 4.0004 4 L 4.0004 12 L 4.0004 13 L 5.0004 13 L 7.0004 13 L 8.0004 13 L 8.0004 12 L 8.0004 11.646 L 8.5584 12.533 L 8.8524 13 L 9.4044 13 L 11.7494 13 L 13.7134 13 L 12.5574 11.412 L 10.5494 8.650999 C 10.8754 8.459 11.1754 8.226 11.3874 7.924999 C 11.7944 7.351999 12.0004 6.702999 12.0004 6 C 12.0004 4.178 10.4734 3 8.1104 3 M 7.0004 7.632 L 7.0274 7.632 C 8.280399 7.632 9.0624 7.144 9.0624 6.167 C 9.0624 5.454 8.3484 5.097 7.2294 5.097 L 7.0004 5.097 L 7.0004 7.632 M 8.1104 4 C 9.7984 4 11.0004 4.678 11.0004 6 C 11.0004 6.493999 10.8574 6.943 10.5704 7.349 C 10.2854 7.754 9.5334 8.049 9.0314 8.264999 L 11.7494 12 L 9.4044 12 L 7.3434 8.729 L 7.0004 8.729 L 7.0004 12 L 5.0004 12 L 5.0004 4 L 8.1104 4"/>
 7 <path fill="white" d="M 7 7.6323 L 7.027 7.6323 C 8.281 7.6323 9.063001 7.1443 9.063001 6.1673 C 9.063001 5.4543 8.348001 5.0973 7.229001 5.0973 L 7 5.0973 L 7 7.6323 Z M 5 12.0003 L 5 4.0003 L 8.11 4.0003 C 9.799001 4.0003 11 4.6773 11 6.0003 C 11 6.4943 10.857 6.9433 10.57 7.3493 C 10.285 7.7543 9.533 8.0493 9.031 8.2643 L 11.749 12.0003 L 9.404 12.0003 L 7.344 8.7293 L 7 8.7293 L 7 12.0003 L 5 12.0003 Z"/>
 8</svg>

Source/WebInspectorUI/UserInterface/Images/EventBreakpointListener.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/Images/EventBreakpointTimer.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 6.980469 12.742188 C 6.429688 12.742188 5.980469 12.292969 5.980469 11.742188 C 5.980469 11.742188 5.980469 7.34375 5.980469 5.882812 C 5.140625 5.882812 4.136719 5.882812 4.136719 5.882812 C 3.582031 5.882812 3.136719 5.4375 3.136719 4.882812 L 3.136719 3.792969 C 3.136719 3.242188 3.582031 2.792969 4.136719 2.792969 L 11.488281 2.792969 C 12.042969 2.792969 12.488281 3.242188 12.488281 3.792969 L 12.488281 4.882812 C 12.488281 5.4375 12.042969 5.882812 11.488281 5.882812 C 11.488281 5.882812 10.484375 5.882812 9.640625 5.882812 C 9.640625 7.34375 9.640625 11.742188 9.640625 11.742188 C 9.640625 12.292969 9.195312 12.742188 8.640625 12.742188 L 6.980469 12.742188"/>
 7 <path fill="white" d="M 6.980469 11.742188 L 6.980469 4.882812 L 4.136719 4.882812 L 4.136719 3.792969 L 11.488281 3.792969 L 11.488281 4.882812 L 8.640625 4.882812 L 8.640625 11.742188 Z"/>
 8</svg>

Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js

2525
2626WI.EventBreakpoint = class EventBreakpoint extends WI.Object
2727{
28  constructor(eventName, {disabled, eventListener} = {})
 28 constructor(type, eventName, {disabled, eventListener} = {})
2929 {
3030 super();
3131
 32 console.assert(typeof type === "string");
 33 console.assert(Object.values(WI.EventBreakpoint.Type).includes(type));
3234 console.assert(typeof eventName === "string");
3335
 36 this._type = type;
3437 this._eventName = eventName;
3538
3639 this._disabled = disabled || false;

@@WI.EventBreakpoint = class EventBreakpoint extends WI.Object
4144
4245 static fromPayload(payload)
4346 {
44  return new WI.EventBreakpoint(payload.eventName, {
 47 return new WI.EventBreakpoint(payload.type, payload.eventName, {
4548 disabled: !!payload.disabled,
4649 });
4750 }
4851
4952 // Public
5053
 54 get type() { return this._type; }
5155 get eventName() { return this._eventName; }
5256 get eventListener() { return this._eventListener; }
5357

@@WI.EventBreakpoint = class EventBreakpoint extends WI.Object
6973 get serializableInfo()
7074 {
7175 let info = {
 76 type: this._type,
7277 eventName: this._eventName,
7378 };
7479 if (this._disabled)

@@WI.EventBreakpoint = class EventBreakpoint extends WI.Object
7984
8085 saveIdentityToCookie(cookie)
8186 {
 87 cookie[WI.EventBreakpoint.TypeCookieKey] = this._type;
8288 cookie[WI.EventBreakpoint.EventNameCookieKey] = this._eventName;
8389 }
8490};
8591
 92WI.EventBreakpoint.Type = {
 93 AnimationFrame: "animation-frame",
 94 Listener: "listener",
 95 Timer: "timer",
 96};
 97
 98WI.EventBreakpoint.TypeCookieKey = "event-breakpoint-type";
8699WI.EventBreakpoint.EventNameCookieKey = "event-breakpoint-event-name";
87100
88101WI.EventBreakpoint.Event = {

Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js

@@WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
951951 let {pauseReason, pauseData} = targetData;
952952
953953 switch (pauseReason) {
 954 case WI.DebuggerManager.PauseReason.AnimationFrame:
 955 console.assert(pauseData, "Expected data with an animation frame, but found none.");
 956 if (pauseData) {
 957 let eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.AnimationFrame, pauseData.eventName);
 958 console.assert(eventBreakpoint, "Expected AnimationFrame breakpoint for event name.", pauseData.eventName);
 959
 960 const suppressFiltering = true;
 961 this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering);
 962
 963 let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
 964 className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
 965 title: WI.UIString("%s Fired").format(pauseData.eventName),
 966 });
 967 this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
 968
 969 let eventBreakpointRow = new WI.DetailsSectionRow;
 970 eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
 971
 972 this._pauseReasonGroup.rows = [eventBreakpointRow];
 973 }
 974 return true;
 975
954976 case WI.DebuggerManager.PauseReason.Assertion:
955977 // FIXME: We should include the assertion condition string.
956978 console.assert(pauseData, "Expected data with an assertion, but found none.");

@@WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
10611083 if (pauseData.eventListenerId)
10621084 eventBreakpoint = WI.domTreeManager.breakpointForEventListenerId(pauseData.eventListenerId);
10631085 if (!eventBreakpoint)
1064  eventBreakpoint = WI.domDebuggerManager.eventBreakpointForEventName(pauseData.eventName);
 1086 eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.Listener, pauseData.eventName);
10651087 console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName);
10661088
1067  this._pauseReasonTreeOutline = this.createContentTreeOutline(true);
 1089 const suppressFiltering = true;
 1090 this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering);
10681091
10691092 let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
10701093 className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,

@@WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
11051128 this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
11061129 return true;
11071130
 1131 case WI.DebuggerManager.PauseReason.Timer:
 1132 console.assert(pauseData, "Expected data with a timer, but found none.");
 1133 if (pauseData) {
 1134 let eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.Timer, pauseData.eventName);
 1135 console.assert(eventBreakpoint, "Expected Timer breakpoint for event name.", pauseData.eventName);
 1136
 1137 const suppressFiltering = true;
 1138 this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering);
 1139
 1140 let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
 1141 className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
 1142 title: WI.UIString("%s Fired").format(pauseData.eventName),
 1143 });
 1144 this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
 1145
 1146 let eventBreakpointRow = new WI.DetailsSectionRow;
 1147 eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
 1148
 1149 this._pauseReasonGroup.rows = [eventBreakpointRow];
 1150 }
 1151 return true;
 1152
11081153 case WI.DebuggerManager.PauseReason.XHR:
11091154 console.assert(WI.domDebuggerManager.supported);
11101155 console.assert(pauseData, "Expected XHR breakpoint data, but found none.");

@@WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
12641309
12651310 willDismissPopover(popover)
12661311 {
1267  if (popover.result !== WI.InputPopover.Result.Committed)
1268  return;
1269 
12701312 if (popover instanceof WI.EventBreakpointPopover) {
1271  let eventName = popover.value;
1272  if (eventName)
1273  WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(eventName));
 1313 let breakpoint = popover.breakpoint;
 1314 if (breakpoint)
 1315 WI.domDebuggerManager.addEventBreakpoint(breakpoint);
12741316 return;
12751317 }
12761318
1277  if (popover instanceof WI.XHRBreakpointPopover) {
 1319 if (popover instanceof WI.XHRBreakpointPopover && popover.result === WI.InputPopover.Result.Committed) {
12781320 let url = popover.value;
12791321 if (url)
12801322 WI.domDebuggerManager.addXHRBreakpoint(new WI.XHRBreakpoint(popover.type, url));

Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css

2828 padding: 5px;
2929}
3030
31 .popover .event-breakpoint-content > input {
32  width: 100%;
 31.popover .event-breakpoint-content > .event-type {
 32 display: flex;
3333 margin-top: 4px;
34  padding: 4px 0 2px 0;
35  outline: none;
3634}

Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js

@@WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover
2929 {
3030 super(delegate);
3131
32  this._result = WI.InputPopover.Result.None;
33  this._value = null;
 32 this._breakpoint = null;
3433
35  this._codeMirror = null;
3634 this._targetElement = null;
3735 this._preferredEdges = null;
3836

@@WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover
4139
4240 // Public
4341
44  get result() { return this._result; }
45  get value() { return this._value; }
 42 get breakpoint() { return this._breakpoint; }
4643
4744 show(targetElement, preferredEdges)
4845 {

@@WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover
5653 label.classList.add("label");
5754 label.textContent = WI.UIString("Break on events with name:");
5855
59  this._inputElement = contentElement.appendChild(document.createElement("input"));
60  this._inputElement.placeholder = "click";
61  this._inputElement.spellcheck = false;
62  this._inputElement.addEventListener("keydown", (event) => {
 56 let typeContainer = contentElement.appendChild(document.createElement("div"));
 57 typeContainer.classList.add("event-type");
 58
 59 this._typeSelectElement = typeContainer.appendChild(document.createElement("select"));
 60 this._typeSelectElement.addEventListener("change", this._handleTypeSelectChange.bind(this));
 61 this._typeSelectElement.addEventListener("keydown", (event) => {
 62 if (isEnterKey(event))
 63 this.dismiss();
 64 });
 65
 66 let createOption = (text, value) => {
 67 let optionElement = this._typeSelectElement.appendChild(document.createElement("option"));
 68 optionElement.value = value;
 69 optionElement.textContent = text;
 70 };
 71
 72 createOption(WI.UIString("DOM Event"), WI.EventBreakpoint.Type.Listener);
 73
 74 if (WI.DOMDebuggerManager.supportsEventBreakpoints()) {
 75 createOption(WI.unlocalizedString("requestAnimationFrame"), "requestAnimationFrame");
 76 createOption(WI.unlocalizedString("setTimeout"), "setTimeout");
 77 createOption(WI.unlocalizedString("setInterval"), "setInterval");
 78 } else
 79 this._typeSelectElement.hidden = true;
 80
 81 this._domEventNameInputElement = typeContainer.appendChild(document.createElement("input"));
 82 this._domEventNameInputElement.placeholder = WI.UIString("Example: “%s”").format("click");
 83 this._domEventNameInputElement.spellcheck = false;
 84 this._domEventNameInputElement.addEventListener("keydown", (event) => {
6385 if (!isEnterKey(event))
6486 return;
6587
66  this._result = WI.InputPopover.Result.Committed;
67  this._value = event.target.value.trim();
68 
6988 this.dismiss();
7089 });
7190
7291 this.content = contentElement;
7392
7493 this._presentOverTargetElement();
 94
 95 this._typeSelectElement.value = WI.EventBreakpoint.Type.Listener;
 96 this._domEventNameInputElement.select();
 97 }
 98
 99 dismiss()
 100 {
 101 let type = this._typeSelectElement.value;
 102 let value = null;
 103
 104 if (type === WI.EventBreakpoint.Type.Listener)
 105 value = this._domEventNameInputElement.value;
 106 else {
 107 value = type;
 108
 109 if (value === "requestAnimationFrame")
 110 type = WI.EventBreakpoint.Type.AnimationFrame;
 111 else if (value === "setTimeout" || value === "setInterval")
 112 type = WI.EventBreakpoint.Type.Timer;
 113 }
 114
 115 if (type && value)
 116 this._breakpoint = new WI.EventBreakpoint(type, value);
 117
 118 super.dismiss();
75119 }
76120
77121 // Private

@@WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover
83127
84128 let targetFrame = WI.Rect.rectFromClientRect(this._targetElement.getBoundingClientRect());
85129 this.present(targetFrame, this._preferredEdges);
 130 }
 131
 132 _handleTypeSelectChange(event)
 133 {
 134 this._domEventNameInputElement.hidden = this._typeSelectElement.value !== WI.EventBreakpoint.Type.Listener;
86135
87  this._inputElement.select();
 136 this.update();
88137 }
89138};

Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css

2323 * THE POSSIBILITY OF SUCH DAMAGE.
2424 */
2525
26 .breakpoint.event:not(.breakpoint-paused-icon) .icon {
27  content: url(../Images/EventBreakpoint.svg);
 26.breakpoint.event.animation-frame:not(.breakpoint-paused-icon) .icon {
 27 content: url(../Images/EventBreakpointAnimationFrame.svg);
 28}
 29
 30.breakpoint.event.listener:not(.breakpoint-paused-icon) .icon {
 31 content: url(../Images/EventBreakpointListener.svg);
 32}
 33
 34.breakpoint.event.timer:not(.breakpoint-paused-icon) .icon {
 35 content: url(../Images/EventBreakpointTimer.svg);
2836}

Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js

@@WI.EventBreakpointTreeElement = class EventBreakpointTreeElement extends WI.Gene
2929 {
3030 console.assert(breakpoint instanceof WI.EventBreakpoint);
3131
32  let classNames = ["breakpoint", "event"];
 32 let classNames = ["breakpoint", "event", breakpoint.type];
3333 if (className)
3434 classNames.push(className);
3535

LayoutTests/ChangeLog

 12018-08-22 Devin Rousso <drousso@apple.com>
 2
 3 Web Inspector: support breakpoints for timers and animation-frame events
 4 https://bugs.webkit.org/show_bug.cgi?id=188778
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * inspector/dom-debugger/event-animation-frame-breakpoints-expected.txt: Added.
 9 * inspector/dom-debugger/event-animation-frame-breakpoints.html: Added.
 10
 11 * inspector/dom-debugger/event-breakpoint-with-navigation.html:
 12
 13 * inspector/dom-debugger/event-timer-breakpoints-expected.txt: Added.
 14 * inspector/dom-debugger/event-timer-breakpoints.html: Added.
 15
 16 * inspector/dom-debugger/event-listener-breakpoints-expected.txt: Renamed from LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt.
 17 * inspector/dom-debugger/event-listener-breakpoints.html: Renamed from LayoutTests/inspector/dom-debugger/event-breakpoints.html.
 18
 19 * inspector/dom-debugger/resources/event-breakpoint-utilities.js: Added.
 20 (TestPage.registerInitializer.window.teardown):
 21 (TestPage.registerInitializer.window.failOnPause):
 22 (TestPage.registerInitializer.window.addBreakpoint):
 23 (TestPage.registerInitializer.window.removeBreakpoint):
 24 (TestPage.registerInitializer.window.disableBreakpoint):
 25 (TestPage.registerInitializer.window.awaitEvent):
 26
1272018-08-21 Yusuke Suzuki <yusukesuzuki@slowstart.org>
228
329 Support "name" option for dedicated workers

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

 1Tests for Event AnimationFrame breakpoints.
 2
 3
 4== Running test suite: DOMDebugger.Event.AnimationFrame
 5-- Running test case: DOMDebugger.Event.AnimationFrame.AddBreakpoint "requestAnimationFrame"
 6Adding "requestAnimationFrame" Event Breakpoint...
 7Firing "requestAnimationFrame" on window...
 8PASS: Should pause before event handler is run.
 9CALL STACK:
 100: [F] handleWindow_requestAnimationFrame
 11ASYNC CALL STACK:
 121: --- requestAnimationFrame ---
 132: [F] windowFire_requestAnimationFrame
 143: [P] Global Code
 15-- Running test teardown.
 16
 17-- Running test case: DOMDebugger.Event.AnimationFrame.AddDisabledBreakpoint "requestAnimationFrame"
 18Adding "requestAnimationFrame" Event Breakpoint...
 19Disabling "requestAnimationFrame" Event Breakpoint...
 20Firing "requestAnimationFrame" on window...
 21PASS: Should not pause for disabled breakpoint.
 22-- Running test teardown.
 23
 24-- Running test case: DOMDebugger.Event.AnimationFrame.RemoveBreakpoint "requestAnimationFrame"
 25Adding "requestAnimationFrame" Event Breakpoint...
 26Removing "requestAnimationFrame" Event Breakpoint...
 27Firing "requestAnimationFrame" on window...
 28PASS: Should not pause for removed breakpoint.
 29-- Running test teardown.
 30
 31-- Running test case: DOMDebugger.Event.AnimationFrame.RemoveDisabledBreakpoint "requestAnimationFrame"
 32Adding "requestAnimationFrame" Event Breakpoint...
 33Disabling "requestAnimationFrame" Event Breakpoint...
 34Removing "requestAnimationFrame" Event Breakpoint...
 35Firing "requestAnimationFrame" on window...
 36PASS: Should not pause for removed disabled breakpoint.
 37-- Running test teardown.
 38

LayoutTests/inspector/dom-debugger/event-animation-frame-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 src="resources/event-breakpoint-utilities.js"></script>
 7<script>
 8
 9function handleWindow_requestAnimationFrame() {
 10 TestPage.dispatchEventToFrontend("TestPage-requestAnimationFrame");
 11}
 12
 13function windowFire_requestAnimationFrame() {
 14 requestAnimationFrame(handleWindow_requestAnimationFrame);
 15}
 16
 17function test() {
 18 let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event.AnimationFrame");
 19
 20 function addTestCasesForEventName(eventName) {
 21 suite.addTestCase({
 22 name: `DOMDebugger.Event.AnimationFrame.AddBreakpoint "${eventName}"`,
 23 description: "Check that the debugger pauses for enabled breakpoints.",
 24 teardown,
 25 test(resolve, reject) {
 26 let paused = false;
 27
 28 let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 29 paused = true;
 30
 31 InspectorTest.pass("Should pause before event handler is run.");
 32 logActiveStackTrace();
 33
 34 WI.debuggerManager.resume();
 35 });
 36
 37 InspectorTest.singleFireEventListener(`TestPage-${eventName}`, (event) => {
 38 if (!paused) {
 39 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 40
 41 InspectorTest.fail("Should pause before event handler is run.");
 42 }
 43
 44 resolve();
 45 });
 46
 47 addBreakpoint(WI.EventBreakpoint.Type.AnimationFrame, eventName)
 48 .then(awaitEvent("window", eventName))
 49 .catch(reject);
 50 },
 51 });
 52
 53 suite.addTestCase({
 54 name: `DOMDebugger.Event.AnimationFrame.AddDisabledBreakpoint "${eventName}"`,
 55 description: "Check that debugger does not pause for disabled breakpoints.",
 56 teardown,
 57 test(resolve, reject) {
 58 failOnPause(resolve, WI.DebuggerManager.PauseReason.AnimationFrame, eventName, "Should not pause for disabled breakpoint.");
 59
 60 addBreakpoint(WI.EventBreakpoint.Type.AnimationFrame, eventName)
 61 .then(disableBreakpoint)
 62 .then(awaitEvent("window", eventName))
 63 .catch(reject);
 64 },
 65 });
 66
 67 suite.addTestCase({
 68 name: `DOMDebugger.Event.AnimationFrame.RemoveBreakpoint "${eventName}"`,
 69 description: "Check that debugger does not pause for removed breakpoint.",
 70 teardown,
 71 test(resolve, reject) {
 72 failOnPause(resolve, WI.DebuggerManager.PauseReason.AnimationFrame, eventName, "Should not pause for removed breakpoint.");
 73
 74 addBreakpoint(WI.EventBreakpoint.Type.AnimationFrame, eventName)
 75 .then(removeBreakpoint)
 76 .then(awaitEvent("window", eventName))
 77 .catch(reject);
 78 },
 79 });
 80
 81 suite.addTestCase({
 82 name: `DOMDebugger.Event.AnimationFrame.RemoveDisabledBreakpoint "${eventName}"`,
 83 description: "Check that a disabled breakpoint can be removed.",
 84 teardown,
 85 test(resolve, reject) {
 86 failOnPause(resolve, WI.DebuggerManager.PauseReason.AnimationFrame, eventName, "Should not pause for removed disabled breakpoint.");
 87
 88 addBreakpoint(WI.EventBreakpoint.Type.AnimationFrame, eventName)
 89 .then(disableBreakpoint)
 90 .then(removeBreakpoint)
 91 .then(awaitEvent("window", eventName))
 92 .catch(reject);
 93 },
 94 });
 95 }
 96
 97 addTestCasesForEventName("requestAnimationFrame");
 98
 99 suite.runTestCasesAndFinish();
 100}
 101</script>
 102</head>
 103<body onload="runTest()">
 104 <p>Tests for Event AnimationFrame breakpoints.</p>
 105</body>
 106</html>

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

@@function test() {
4444
4545 InspectorTest.log("Adding \"load\" Event Breakpoint...");
4646
47  let breakpoint = new WI.EventBreakpoint("load");
 47 let breakpoint = new WI.EventBreakpoint(WI.EventBreakpoint.Type.Listener, "load");
4848
4949 WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded)
5050 .then((event) => {
51  InspectorTest.assert(event.data.breakpoint.eventName, "load", "Breakpoint should be for expected event name.");
 51 InspectorTest.assert(event.data.breakpoint.type === WI.EventBreakpoint.Type.Listener, "Breakpoint should be for expected type.");
 52 InspectorTest.assert(event.data.breakpoint.eventName === "load", "Breakpoint should be for expected event name.");
5253
5354 InspectorTest.log("Reloading WebInspector...");
5455 return InspectorTest.reloadPage();

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

1 Tests for Event Listener breakpoints.
2 
3 
4 == Running test suite: DOMDebugger.Event
5 -- Running test case: DOMDebugger.Event.AddBreakpoint "click"
6 Adding "click" Event Breakpoint...
7 Firing "click" on body...
8 PASS: Should pause before event handler is run.
9 CALL STACK:
10 0: [F] handleBody_click
11 1: [F] bodyFire_click
12 2: [P] Global Code
13 -- Running test teardown.
14 
15 -- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "click"
16 Adding "click" Event Breakpoint...
17 Disabling "click" Event Breakpoint...
18 Firing "click" on body...
19 PASS: Should not pause for disabled breakpoint.
20 -- Running test teardown.
21 
22 -- Running test case: DOMDebugger.Event.RemoveBreakpoint "click"
23 Adding "click" Event Breakpoint...
24 Removing "click" Event Breakpoint...
25 Firing "click" on body...
26 PASS: Should not pause for removed breakpoint.
27 -- Running test teardown.
28 
29 -- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "click"
30 Adding "click" Event Breakpoint...
31 Disabling "click" Event Breakpoint...
32 Removing "click" Event Breakpoint...
33 Firing "click" on body...
34 PASS: Should not pause for removed disabled breakpoint.
35 -- Running test teardown.
36 
37 -- Running test case: DOMDebugger.Event.AddBreakpoint "custom"
38 Adding "custom" Event Breakpoint...
39 Firing "custom" on body...
40 PASS: Should pause before event handler is run.
41 CALL STACK:
42 0: [F] handleBody_custom
43 1: [F] bodyFire_custom
44 2: [P] Global Code
45 -- Running test teardown.
46 
47 -- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "custom"
48 Adding "custom" Event Breakpoint...
49 Disabling "custom" Event Breakpoint...
50 Firing "custom" on body...
51 PASS: Should not pause for disabled breakpoint.
52 -- Running test teardown.
53 
54 -- Running test case: DOMDebugger.Event.RemoveBreakpoint "custom"
55 Adding "custom" Event Breakpoint...
56 Removing "custom" Event Breakpoint...
57 Firing "custom" on body...
58 PASS: Should not pause for removed breakpoint.
59 -- Running test teardown.
60 
61 -- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "custom"
62 Adding "custom" Event Breakpoint...
63 Disabling "custom" Event Breakpoint...
64 Removing "custom" Event Breakpoint...
65 Firing "custom" on body...
66 PASS: Should not pause for removed disabled breakpoint.
67 -- Running test teardown.
68 
69 -- Running test case: DOMDebugger.Event.AddMultipleBreakpoints
70 Adding "click" Event Breakpoint...
71 Firing "click" on div#x...
72 PASS: Should pause before event handler is run.
73 CALL STACK:
74 0: [F] handleX_click
75 1: [F] xFire_click
76 2: [P] Global Code
77 PASS: Should pause before event handler is run.
78 CALL STACK:
79 0: [F] handleBody_click
80 1: [F] xFire_click
81 2: [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>
7 function handleBody_click(event) {
8  TestPage.dispatchEventToFrontend("TestPageBody-click");
9 }
10 
11 function handleBody_custom(event) {
12  TestPage.dispatchEventToFrontend("TestPageBody-custom");
13 }
14 
15 function handleX_click(event) {
16  TestPage.dispatchEventToFrontend("TestPageX-click");
17 }
18 
19 function bodyFire_click() {
20  document.body.click();
21 }
22 
23 function bodyFire_custom() {
24  document.body.dispatchEvent(new Event("custom"));
25 }
26 
27 function xFire_click() {
28  document.getElementById("x").click();
29 }
30 
31 function 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>

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

 1Tests for Event Listener breakpoints.
 2
 3
 4== Running test suite: DOMDebugger.Event.Listener
 5-- Running test case: DOMDebugger.Event.Listener.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.Listener.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.Listener.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.Listener.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.Listener.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.Listener.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.Listener.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.Listener.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.Listener.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-listener-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 src="resources/event-breakpoint-utilities.js"></script>
 7<script>
 8function handleBody_click(event) {
 9 TestPage.dispatchEventToFrontend("TestPage-click");
 10}
 11
 12function handleBody_custom(event) {
 13 TestPage.dispatchEventToFrontend("TestPage-custom");
 14}
 15
 16function handleX_click(event) {
 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.Listener");
 33
 34 function addTestCasesForEventName(eventName) {
 35 suite.addTestCase({
 36 name: `DOMDebugger.Event.Listener.AddBreakpoint "${eventName}"`,
 37 description: "Check that the debugger pauses for enabled breakpoints.",
 38 teardown,
 39 test(resolve, reject) {
 40 let paused = false;
 41
 42 let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 43 paused = true;
 44
 45 InspectorTest.pass("Should pause before event handler is run.");
 46 logActiveStackTrace();
 47
 48 WI.debuggerManager.resume();
 49 });
 50
 51 InspectorTest.singleFireEventListener(`TestPage-${eventName}`, (event) => {
 52 if (!paused) {
 53 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 54
 55 InspectorTest.fail("Should pause before event handler is run.");
 56 }
 57
 58 resolve();
 59 });
 60
 61 addBreakpoint(WI.EventBreakpoint.Type.Listener, eventName)
 62 .then(awaitEvent("body", eventName))
 63 .catch(reject);
 64 },
 65 });
 66
 67 suite.addTestCase({
 68 name: `DOMDebugger.Event.Listener.AddDisabledBreakpoint "${eventName}"`,
 69 description: "Check that debugger does not pause for disabled breakpoints.",
 70 teardown,
 71 test(resolve, reject) {
 72 failOnPause(resolve, WI.DebuggerManager.PauseReason.EventListener, eventName, "Should not pause for disabled breakpoint.");
 73
 74 addBreakpoint(WI.EventBreakpoint.Type.Listener, eventName)
 75 .then(disableBreakpoint)
 76 .then(awaitEvent("body", eventName))
 77 .catch(reject);
 78 },
 79 });
 80
 81 suite.addTestCase({
 82 name: `DOMDebugger.Event.Listener.RemoveBreakpoint "${eventName}"`,
 83 description: "Check that debugger does not pause for removed breakpoint.",
 84 teardown,
 85 test(resolve, reject) {
 86 failOnPause(resolve, WI.DebuggerManager.PauseReason.EventListener, eventName, "Should not pause for removed breakpoint.");
 87
 88 addBreakpoint(WI.EventBreakpoint.Type.Listener, eventName)
 89 .then(removeBreakpoint)
 90 .then(awaitEvent("body", eventName))
 91 .catch(reject);
 92 },
 93 });
 94
 95 suite.addTestCase({
 96 name: `DOMDebugger.Event.Listener.RemoveDisabledBreakpoint "${eventName}"`,
 97 description: "Check that a disabled breakpoint can be removed.",
 98 teardown,
 99 test(resolve, reject) {
 100 failOnPause(resolve, WI.DebuggerManager.PauseReason.EventListener, eventName, "Should not pause for removed disabled breakpoint.");
 101
 102 addBreakpoint(WI.EventBreakpoint.Type.Listener, eventName)
 103 .then(disableBreakpoint)
 104 .then(removeBreakpoint)
 105 .then(awaitEvent("body", eventName))
 106 .catch(reject);
 107 },
 108 });
 109 }
 110
 111 addTestCasesForEventName("click");
 112 addTestCasesForEventName("custom");
 113
 114 suite.addTestCase({
 115 name: `DOMDebugger.Event.Listener.AddMultipleBreakpoints`,
 116 description: "Check that a single breakpoint pauses for every event of that type.",
 117 teardown,
 118 test(resolve, reject) {
 119 let pauseCount = 0;
 120
 121 let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 122 ++pauseCount;
 123
 124 InspectorTest.pass("Should pause before event handler is run.");
 125 logActiveStackTrace();
 126
 127 WI.debuggerManager.resume()
 128 .catch((reason) => {
 129 InspectorTest.fail(reason);
 130 resolve();
 131 });
 132
 133 if (pauseCount >= 2) {
 134 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 135
 136 resolve();
 137 }
 138 });
 139
 140 addBreakpoint(WI.EventBreakpoint.Type.Listener, "click")
 141 .then(() => {
 142 InspectorTest.log("Firing \"click\" on div#x...");
 143 return InspectorTest.evaluateInPage(`xFire_click()`);
 144 })
 145 .catch(reject);
 146 },
 147 });
 148
 149 suite.runTestCasesAndFinish();
 150}
 151</script>
 152</head>
 153<body onload="runTest()">
 154 <p>Tests for Event Listener breakpoints.</p>
 155 <div id="x"></div>
 156 <script>
 157 document.body.addEventListener("click", handleBody_click);
 158 document.body.addEventListener("custom", handleBody_custom);
 159
 160 document.getElementById("x").addEventListener("click", handleX_click);
 161 </script>
 162</body>
 163</html>

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

 1Tests for Event Timer breakpoints.
 2
 3
 4== Running test suite: DOMDebugger.Event.Timer
 5-- Running test case: DOMDebugger.Event.Timer.AddBreakpoint "setTimeout"
 6Adding "setTimeout" Event Breakpoint...
 7Firing "setTimeout" on window...
 8PASS: Should pause before event handler is run.
 9CALL STACK:
 100: [F] handleWindow_setTimeout
 11ASYNC CALL STACK:
 121: --- setTimeout ---
 132: [F] windowFire_setTimeout
 143: [P] Global Code
 15-- Running test teardown.
 16
 17-- Running test case: DOMDebugger.Event.Timer.AddDisabledBreakpoint "setTimeout"
 18Adding "setTimeout" Event Breakpoint...
 19Disabling "setTimeout" Event Breakpoint...
 20Firing "setTimeout" on window...
 21PASS: Should not pause for disabled breakpoint.
 22-- Running test teardown.
 23
 24-- Running test case: DOMDebugger.Event.Timer.RemoveBreakpoint "setTimeout"
 25Adding "setTimeout" Event Breakpoint...
 26Removing "setTimeout" Event Breakpoint...
 27Firing "setTimeout" on window...
 28PASS: Should not pause for removed breakpoint.
 29-- Running test teardown.
 30
 31-- Running test case: DOMDebugger.Event.Timer.RemoveDisabledBreakpoint "setTimeout"
 32Adding "setTimeout" Event Breakpoint...
 33Disabling "setTimeout" Event Breakpoint...
 34Removing "setTimeout" Event Breakpoint...
 35Firing "setTimeout" on window...
 36PASS: Should not pause for removed disabled breakpoint.
 37-- Running test teardown.
 38
 39-- Running test case: DOMDebugger.Event.Timer.AddBreakpoint "setInterval"
 40Adding "setInterval" Event Breakpoint...
 41Firing "setInterval" on window...
 42PASS: Should pause before event handler is run.
 43CALL STACK:
 440: [F] handleWindow_setInterval
 45ASYNC CALL STACK:
 461: --- setInterval ---
 472: [F] windowFire_setInterval
 483: [P] Global Code
 49-- Running test teardown.
 50
 51-- Running test case: DOMDebugger.Event.Timer.AddDisabledBreakpoint "setInterval"
 52Adding "setInterval" Event Breakpoint...
 53Disabling "setInterval" Event Breakpoint...
 54Firing "setInterval" on window...
 55PASS: Should not pause for disabled breakpoint.
 56-- Running test teardown.
 57
 58-- Running test case: DOMDebugger.Event.Timer.RemoveBreakpoint "setInterval"
 59Adding "setInterval" Event Breakpoint...
 60Removing "setInterval" Event Breakpoint...
 61Firing "setInterval" on window...
 62PASS: Should not pause for removed breakpoint.
 63-- Running test teardown.
 64
 65-- Running test case: DOMDebugger.Event.Timer.RemoveDisabledBreakpoint "setInterval"
 66Adding "setInterval" Event Breakpoint...
 67Disabling "setInterval" Event Breakpoint...
 68Removing "setInterval" Event Breakpoint...
 69Firing "setInterval" on window...
 70PASS: Should not pause for removed disabled breakpoint.
 71-- Running test teardown.
 72
 73-- Running test case: DOMDebugger.Event.Listener.RepeatFireBreakpoint
 74Adding "setInterval" Event Breakpoint...
 75Firing "setInterval" on window...
 76PASS: Should pause before event handler is run.
 77CALL STACK:
 780: [F] handleRepeat
 79ASYNC CALL STACK:
 801: --- setInterval ---
 812: [F] repeatSetInterval
 823: [P] Global Code
 83PASS: Should pause before event handler is run.
 84CALL STACK:
 850: [F] handleRepeat
 86ASYNC CALL STACK:
 871: --- setInterval ---
 882: [F] repeatSetInterval
 893: [P] Global Code
 90-- Running test teardown.
 91

LayoutTests/inspector/dom-debugger/event-timer-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 src="resources/event-breakpoint-utilities.js"></script>
 7<script>
 8
 9let intervalID = NaN;
 10
 11function handleWindow_setTimeout() {
 12 TestPage.dispatchEventToFrontend("TestPage-setTimeout");
 13}
 14
 15function handleWindow_setInterval() {
 16 TestPage.dispatchEventToFrontend("TestPage-setInterval");
 17
 18 repeatClearInterval();
 19}
 20
 21function handleRepeat() {
 22}
 23
 24function windowFire_setTimeout() {
 25 setTimeout(handleWindow_setTimeout, 100);
 26}
 27
 28function windowFire_setInterval() {
 29 intervalID = setInterval(handleWindow_setInterval, 100);
 30}
 31
 32function repeatSetInterval() {
 33 intervalID = setInterval(handleRepeat, 100);
 34}
 35
 36function repeatClearInterval() {
 37 clearInterval(intervalID);
 38 intervalID = NaN;
 39}
 40
 41function test() {
 42 let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event.Timer");
 43
 44 function addTestCasesForEventName(eventName) {
 45 suite.addTestCase({
 46 name: `DOMDebugger.Event.Timer.AddBreakpoint "${eventName}"`,
 47 description: "Check that the debugger pauses for enabled breakpoints.",
 48 teardown,
 49 test(resolve, reject) {
 50 let paused = false;
 51
 52 let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 53 paused = true;
 54
 55 InspectorTest.pass("Should pause before event handler is run.");
 56 logActiveStackTrace();
 57
 58 WI.debuggerManager.resume();
 59 });
 60
 61 InspectorTest.singleFireEventListener(`TestPage-${eventName}`, (event) => {
 62 if (!paused) {
 63 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 64
 65 InspectorTest.fail("Should pause before event handler is run.");
 66 }
 67
 68 resolve();
 69 });
 70
 71 addBreakpoint(WI.EventBreakpoint.Type.Timer, eventName)
 72 .then(awaitEvent("window", eventName))
 73 .catch(reject);
 74 },
 75 });
 76
 77 suite.addTestCase({
 78 name: `DOMDebugger.Event.Timer.AddDisabledBreakpoint "${eventName}"`,
 79 description: "Check that debugger does not pause for disabled breakpoints.",
 80 teardown,
 81 test(resolve, reject) {
 82 failOnPause(resolve, WI.DebuggerManager.PauseReason.Timer, eventName, "Should not pause for disabled breakpoint.");
 83
 84 addBreakpoint(WI.EventBreakpoint.Type.Timer, eventName)
 85 .then(disableBreakpoint)
 86 .then(awaitEvent("window", eventName))
 87 .catch(reject);
 88 },
 89 });
 90
 91 suite.addTestCase({
 92 name: `DOMDebugger.Event.Timer.RemoveBreakpoint "${eventName}"`,
 93 description: "Check that debugger does not pause for removed breakpoint.",
 94 teardown,
 95 test(resolve, reject) {
 96 failOnPause(resolve, WI.DebuggerManager.PauseReason.Timer, eventName, "Should not pause for removed breakpoint.");
 97
 98 addBreakpoint(WI.EventBreakpoint.Type.Timer, eventName)
 99 .then(removeBreakpoint)
 100 .then(awaitEvent("window", eventName))
 101 .catch(reject);
 102 },
 103 });
 104
 105 suite.addTestCase({
 106 name: `DOMDebugger.Event.Timer.RemoveDisabledBreakpoint "${eventName}"`,
 107 description: "Check that a disabled breakpoint can be removed.",
 108 teardown,
 109 test(resolve, reject) {
 110 failOnPause(resolve, WI.DebuggerManager.PauseReason.Timer, eventName, "Should not pause for removed disabled breakpoint.");
 111
 112 addBreakpoint(WI.EventBreakpoint.Type.Timer, eventName)
 113 .then(disableBreakpoint)
 114 .then(removeBreakpoint)
 115 .then(awaitEvent("window", eventName))
 116 .catch(reject);
 117 },
 118 });
 119 }
 120
 121 addTestCasesForEventName("setTimeout");
 122 addTestCasesForEventName("setInterval");
 123
 124 suite.addTestCase({
 125 name: `DOMDebugger.Event.Listener.RepeatFireBreakpoint`,
 126 description: "Check that a single breakpoint pauses multiple times for the same interval.",
 127 teardown,
 128 test(resolve, reject) {
 129 let pauseCount = 0;
 130
 131 let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 132 ++pauseCount;
 133
 134 InspectorTest.pass("Should pause before event handler is run.");
 135 logActiveStackTrace();
 136
 137 WI.debuggerManager.resume()
 138 .catch((reason) => {
 139 InspectorTest.fail(reason);
 140 resolve();
 141 });
 142
 143 if (pauseCount >= 2) {
 144 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 145
 146 InspectorTest.evaluateInPage(`repeatClearInterval()`)
 147 .then(resolve)
 148 .catch((reason) => {
 149 InspectorTest.fail(reason);
 150 resolve();
 151 });
 152 }
 153 });
 154
 155 addBreakpoint(WI.EventBreakpoint.Type.Timer, "setInterval")
 156 .then(() => {
 157 InspectorTest.log("Firing \"setInterval\" on window...");
 158 return InspectorTest.evaluateInPage(`repeatSetInterval()`);
 159 })
 160 .catch(reject);
 161 },
 162 });
 163
 164 suite.runTestCasesAndFinish();
 165}
 166</script>
 167</head>
 168<body onload="runTest()">
 169 <p>Tests for Event Timer breakpoints.</p>
 170</body>
 171</html>

LayoutTests/inspector/dom-debugger/resources/event-breakpoint-utilities.js

 1TestPage.registerInitializer(() => {
 2 window.teardown = function(resolve, reject) {
 3 let breakpoints = WI.domDebuggerManager.eventBreakpoints;
 4 for (let breakpoint of breakpoints)
 5 WI.domDebuggerManager.removeEventBreakpoint(breakpoint);
 6
 7 resolve();
 8 };
 9
 10 window.failOnPause = function(resolve, pauseReason, eventName, message) {
 11 let paused = false;
 12
 13 let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
 14 paused = true;
 15
 16 let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target);
 17 InspectorTest.assert(targetData.pauseReason === pauseReason, `Pause reason should be "${pauseReason}".`);
 18 InspectorTest.assert(targetData.pauseData.eventName === eventName, `Pause data eventName should be "${eventName}".`);
 19
 20 InspectorTest.fail(message);
 21 logActiveStackTrace();
 22
 23 WI.debuggerManager.resume()
 24 .catch((reason) => {
 25 InspectorTest.fail(reason);
 26 resolve();
 27 });
 28 });
 29
 30 InspectorTest.singleFireEventListener("TestPage-" + eventName, (event) => {
 31 if (!paused) {
 32 WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);
 33
 34 InspectorTest.pass(message);
 35 }
 36
 37 resolve();
 38 });
 39 };
 40
 41 window.addBreakpoint = function(type, eventName) {
 42 InspectorTest.log(`Adding "${eventName}" Event Breakpoint...`);
 43
 44 return new Promise((resolve, reject) => {
 45 let breakpoint = new WI.EventBreakpoint(type, eventName);
 46
 47 WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded)
 48 .then((event) => {
 49 InspectorTest.assert(event.data.breakpoint.type === type, `Breakpoint should be for expected type "${type}".`);
 50 InspectorTest.assert(event.data.breakpoint.eventName === eventName, `Breakpoint should be for expected event name "${eventName}".`);
 51 InspectorTest.assert(!breakpoint.disabled, "Breakpoint should not be disabled initially.");
 52 resolve(breakpoint);
 53 });
 54
 55 WI.domDebuggerManager.addEventBreakpoint(breakpoint);
 56 });
 57 };
 58
 59 window.removeBreakpoint = function(breakpoint) {
 60 InspectorTest.log(`Removing "${breakpoint.eventName}" Event Breakpoint...`);
 61
 62 return new Promise((resolve, reject) => {
 63 WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointRemoved)
 64 .then((event) => {
 65 InspectorTest.assert(event.data.breakpoint === breakpoint, "Removed Breakpoint should be expected object.");
 66 InspectorTest.assert(!WI.domDebuggerManager.eventBreakpoints.includes(breakpoint), "Breakpoint should not be in the list of breakpoints.");
 67 resolve(breakpoint);
 68 });
 69
 70 WI.domDebuggerManager.removeEventBreakpoint(breakpoint);
 71 });
 72 };
 73
 74 window.disableBreakpoint = function(breakpoint) {
 75 InspectorTest.log(`Disabling "${breakpoint.eventName}" Event Breakpoint...`);
 76
 77 breakpoint.disabled = true;
 78 return breakpoint;
 79 };
 80
 81 window.awaitEvent = function(context, eventName) {
 82 return function() {
 83 InspectorTest.log(`Firing "${eventName}" on ${context}...`);
 84 return InspectorTest.evaluateInPage(`${context}Fire_${eventName}()`);
 85 };
 86 };
 87});