WebKit Bugzilla
Attachment 347824 Details for
Bug 188778
: Web Inspector: support breakpoints for timers and animation-frame events
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188778-20180822115639.patch (text/plain), 107.01 KB, created by
Devin Rousso
on 2018-08-22 11:56:40 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Devin Rousso
Created:
2018-08-22 11:56:40 PDT
Size:
107.01 KB
patch
obsolete
>diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index bfd244a910d77ecd691743d966905e3c3987281a..0c966bfbf78819e520ed034b9f3f941bf06033fb 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,21 @@ >+2018-08-22 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: support breakpoints for timers and animation-frame events >+ https://bugs.webkit.org/show_bug.cgi?id=188778 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * inspector/protocol/Debugger.json: >+ Add `AnimationFrame` and `Timer` types to the list of pause reasons. >+ >+ * inspector/protocol/DOMDebugger.json: >+ Introduced `setEventBreakpoint` and `removeEventBreakpoint` to replace the more specific: >+ - `setEventListenerBreakpoint` >+ - `removeEventListenerBreakpoint` >+ - `setInstrumentationBreakpoint` >+ - `removeInstrumentationBreakpoint` >+ Also created an `EventBreakpointType` to enumerate the available types of event breakpoints. >+ > 2018-08-20 Yusuke Suzuki <yusukesuzuki@slowstart.org> > > [JSC] HeapUtil should care about pointer overflow >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 4feca02ea4dd363679892ca31bb6589ea26b49bd..6563175b05d6e48e89fd87c7a370eaea41155e8e 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,51 @@ >+2018-08-22 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: support breakpoints for timers and animation-frame events >+ https://bugs.webkit.org/show_bug.cgi?id=188778 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ The original implementation of "instrumentation" breakpoints relied upon the frontend >+ sending somewhat arbitrary strings when enabling breakpoints for specific events. As an >+ example, setting a breakpoint for `requestAnimationFrame` expects `"animationFrameFired"` >+ as the string, which doesn't make much sense. This patch removes the usage of these strings >+ and instead expects the agent to implement a method that matches what is happening. >+ >+ Tests: inspector/dom-debugger/event-animation-frame-breakpoints.html >+ inspector/dom-debugger/event-listener-breakpoints.html >+ inspector/dom-debugger/event-timer-breakpoints.html >+ >+ * inspector/InspectorInstrumentation.h: >+ (WebCore::InspectorInstrumentation::willFireTimer): >+ * inspector/InspectorInstrumentation.cpp: >+ (WebCore::InspectorInstrumentation::didInstallTimerImpl): >+ (WebCore::InspectorInstrumentation::didRemoveTimerImpl): >+ (WebCore::InspectorInstrumentation::willFireTimerImpl): >+ (WebCore::InspectorInstrumentation::didRequestAnimationFrameImpl): >+ (WebCore::InspectorInstrumentation::didCancelAnimationFrameImpl): >+ (WebCore::InspectorInstrumentation::willFireAnimationFrameImpl): >+ (WebCore::InspectorInstrumentation::pauseOnNativeEventIfNeeded): Deleted. >+ >+ * inspector/agents/InspectorDOMDebuggerAgent.h: >+ * inspector/agents/InspectorDOMDebuggerAgent.cpp: >+ (WebCore::InspectorDOMDebuggerAgent::setEventBreakpoint): Added. >+ (WebCore::InspectorDOMDebuggerAgent::removeEventBreakpoint): Added. >+ (WebCore::InspectorDOMDebuggerAgent::willHandleEvent): >+ (WebCore::InspectorDOMDebuggerAgent::willFireTimer): Added. >+ (WebCore::InspectorDOMDebuggerAgent::willFireAnimationFrame): Added. >+ (WebCore::InspectorDOMDebuggerAgent::setEventListenerBreakpoint): Deleted. >+ (WebCore::InspectorDOMDebuggerAgent::setInstrumentationBreakpoint): Deleted. >+ (WebCore::InspectorDOMDebuggerAgent::setBreakpoint): Deleted. >+ (WebCore::InspectorDOMDebuggerAgent::removeEventListenerBreakpoint): Deleted. >+ (WebCore::InspectorDOMDebuggerAgent::removeInstrumentationBreakpoint): Deleted. >+ (WebCore::InspectorDOMDebuggerAgent::removeBreakpoint): Deleted. >+ (WebCore::InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded): Deleted. >+ Unify the event listener and instrumentation breakpoint commands into a single method, >+ `setEventBreakpoint`, that takes in both an `EventBreakpointType` and `eventName`. >+ >+ * page/DOMTimer.cpp: >+ (WebCore::DOMTimer::fired): >+ > 2018-08-21 Yusuke Suzuki <yusukesuzuki@slowstart.org> > > Support "name" option for dedicated workers >diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index dd6b865b5b6a7275b52d2cab410b6e4acb6b6327..96e632e40b371b6a98af19a06fdec59b725b7ef2 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,73 @@ >+2018-08-22 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: support breakpoints for timers and animation-frame events >+ https://bugs.webkit.org/show_bug.cgi?id=188778 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add a `type` to `WI.EventBreakpoint` that matches `DOMDebugger.EventBreakpointType`: >+ - `AnimationFrame` for `requestAnimationFrame` >+ - `Listener` for any named DOM Event >+ - `Timer` for `setTimeout` and `setInterval` >+ >+ Modified `WI.EventBreakpointPopover` to provide ways for selecting these other types, which >+ is then passed to `WI.DOMDebuggerManager`, which now calls through to the newly added >+ `DOMDebugger.removeEventBreakpoint` and `DOMDebugger.setEventBreakpoint` that sets >+ breakpoints for all event types. >+ >+ * Localizations/en.lproj/localizedStrings.js: >+ * UserInterface/Images/EventBreakpointAnimationFrame.svg: Added. >+ * UserInterface/Images/EventBreakpointListener.svg: Renamed from Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg. >+ * UserInterface/Images/EventBreakpointTimer.svg: Added. >+ >+ * UserInterface/Controllers/DOMDebuggerManager.js: >+ (WI.DOMDebuggerManager.supportsEventBreakpoints): Added. >+ (WI.DOMDebuggerManager.prototype.eventBreakpointForTypeAndEventName): Added. >+ (WI.DOMDebuggerManager.prototype.addEventBreakpoint): >+ (WI.DOMDebuggerManager.prototype.removeEventBreakpoint.breakpointRemoved): Added. >+ (WI.DOMDebuggerManager.prototype.removeEventBreakpoint): >+ (WI.DOMDebuggerManager.prototype._updateEventBreakpoint): >+ (WI.DOMDebuggerManager.prototype.eventBreakpointForEventName): Deleted. >+ >+ * UserInterface/Controllers/DOMTreeManager.js: >+ (WI.DOMTreeManager.prototype.setBreakpointForEventListener): >+ >+ * UserInterface/Controllers/DebuggerManager.js: >+ (WI.DebuggerManager.prototype._pauseReasonFromPayload): >+ >+ * UserInterface/Models/EventBreakpoint.js: >+ (WI.EventBreakpoint): >+ (WI.EventBreakpoint.fromPayload): >+ (WI.EventBreakpoint.prototype.get type): Added. >+ (WI.EventBreakpoint.prototype.get serializableInfo): >+ (WI.EventBreakpoint.prototype.saveIdentityToCookie): >+ >+ * UserInterface/Views/DebuggerSidebarPanel.js: >+ (WI.DebuggerSidebarPanel.prototype._updatePauseReasonSection): >+ (WI.DebuggerSidebarPanel.prototype.willDismissPopover): >+ >+ * UserInterface/Views/EventBreakpointPopover.js: >+ (WI.EventBreakpointPopover): >+ (WI.EventBreakpointPopover.prototype.get breakpoint): Added. >+ (WI.EventBreakpointPopover.prototype.show): >+ (WI.EventBreakpointPopover.prototype.show.createOption): Added. >+ (WI.EventBreakpointPopover.prototype.dismiss): Added. >+ (WI.EventBreakpointPopover.prototype._presentOverTargetElement): >+ (WI.EventBreakpointPopover.prototype._handleTypeSelectChange): Added. >+ (WI.EventBreakpointPopover.prototype.get result): Deleted. >+ (WI.EventBreakpointPopover.prototype.get value): Deleted. >+ * UserInterface/Views/EventBreakpointPopover.css: >+ (.popover .event-breakpoint-content > .event-type): Added. >+ (.popover .event-breakpoint-content > input): Deleted. >+ >+ * UserInterface/Views/EventBreakpointTreeElement.js: >+ (WI.EventBreakpointTreeElement): >+ * UserInterface/Views/EventBreakpointTreeElement.css: >+ (.breakpoint.event.animation-frame:not(.breakpoint-paused-icon) .icon): Added. >+ (.breakpoint.event.listener:not(.breakpoint-paused-icon) .icon): Added. >+ (.breakpoint.event.timer:not(.breakpoint-paused-icon) .icon): Added. >+ (.breakpoint.event:not(.breakpoint-paused-icon) .icon): Deleted. >+ > 2018-08-21 Matt Baker <mattbaker@apple.com> > > Web Inspector: Remove TreeOutlineDataGridSynchronizer >diff --git a/Source/JavaScriptCore/inspector/protocol/DOMDebugger.json b/Source/JavaScriptCore/inspector/protocol/DOMDebugger.json >index 04c176160019f4898082619acd93e5ce8c1815da..b4204d18d057149f3d1bb2460ec9c3711114d801 100644 >--- a/Source/JavaScriptCore/inspector/protocol/DOMDebugger.json >+++ b/Source/JavaScriptCore/inspector/protocol/DOMDebugger.json >@@ -8,6 +8,12 @@ > "type": "string", > "enum": ["subtree-modified", "attribute-modified", "node-removed"], > "description": "DOM breakpoint type." >+ }, >+ { >+ "id": "EventBreakpointType", >+ "type": "string", >+ "enum": ["animation-frame", "listener", "timer"], >+ "description": "Event breakpoint type." > } > ], > "commands": [ >@@ -28,31 +34,19 @@ > ] > }, > { >- "name": "setEventListenerBreakpoint", >- "description": "Sets breakpoint on particular DOM event.", >- "parameters": [ >- { "name": "eventName", "type": "string", "description": "DOM Event name to stop on (any DOM event will do)." } >- ] >- }, >- { >- "name": "removeEventListenerBreakpoint", >- "description": "Removes breakpoint on particular DOM event.", >- "parameters": [ >- { "name": "eventName", "type": "string", "description": "Event name." } >- ] >- }, >- { >- "name": "setInstrumentationBreakpoint", >- "description": "Sets breakpoint on particular native event.", >+ "name": "setEventBreakpoint", >+ "description": "Sets breakpoint on particular event of given type.", > "parameters": [ >- { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." } >+ { "name": "breakpointType", "$ref": "EventBreakpointType" }, >+ { "name": "eventName", "type": "string", "description": "The name of the event to stop on." } > ] > }, > { >- "name": "removeInstrumentationBreakpoint", >- "description": "Sets breakpoint on particular native event.", >+ "name": "removeEventBreakpoint", >+ "description": "Removes breakpoint on particular event of given type.", > "parameters": [ >- { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." } >+ { "name": "breakpointType", "$ref": "EventBreakpointType" }, >+ { "name": "eventName", "type": "string", "description": "The name of the event to stop on." } > ] > }, > { >diff --git a/Source/JavaScriptCore/inspector/protocol/Debugger.json b/Source/JavaScriptCore/inspector/protocol/Debugger.json >index 045b91ffebbd08885485a883aae44d1f174d67b3..3143141247813d2f0c47863e3dd159a8fed54c5e 100644 >--- a/Source/JavaScriptCore/inspector/protocol/Debugger.json >+++ b/Source/JavaScriptCore/inspector/protocol/Debugger.json >@@ -341,7 +341,7 @@ > "description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria.", > "parameters": [ > { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." }, >- { "name": "reason", "type": "string", "enum": ["XHR", "DOM", "EventListener", "exception", "assert", "CSPViolation", "DebuggerStatement", "Breakpoint", "PauseOnNextStatement", "other"], "description": "Pause reason." }, >+ { "name": "reason", "type": "string", "enum": ["XHR", "DOM", "AnimationFrame", "EventListener", "Timer", "exception", "assert", "CSPViolation", "DebuggerStatement", "Breakpoint", "PauseOnNextStatement", "other"], "description": "Pause reason." }, > { "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." }, > { "name": "asyncStackTrace", "$ref": "Console.StackTrace", "optional": true, "description": "Linked list of asynchronous StackTraces." } > ] >diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp >index 41b7877161fa1bd8da5851d74da73b0fbefa32bf..7f7f126e0471dc4e820c96df4a8648e20972f865 100644 >--- a/Source/WebCore/inspector/InspectorInstrumentation.cpp >+++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp >@@ -76,13 +76,6 @@ namespace WebCore { > > using namespace Inspector; > >-static const char* const requestAnimationFrameEventName = "requestAnimationFrame"; >-static const char* const cancelAnimationFrameEventName = "cancelAnimationFrame"; >-static const char* const animationFrameFiredEventName = "animationFrameFired"; >-static const char* const setTimerEventName = "setTimer"; >-static const char* const clearTimerEventName = "clearTimer"; >-static const char* const timerFiredEventName = "timerFired"; >- > namespace { > static HashSet<InstrumentingAgents*>* s_instrumentingAgentsSet = nullptr; > } >@@ -294,8 +287,6 @@ void InspectorInstrumentation::willSendXMLHttpRequestImpl(InstrumentingAgents& i > > void InspectorInstrumentation::didInstallTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, Seconds timeout, bool singleShot, ScriptExecutionContext& context) > { >- pauseOnNativeEventIfNeeded(instrumentingAgents, setTimerEventName, true); >- > if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent()) > debuggerAgent->didScheduleAsyncCall(context.execState(), InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId, singleShot); > >@@ -305,8 +296,6 @@ void InspectorInstrumentation::didInstallTimerImpl(InstrumentingAgents& instrume > > void InspectorInstrumentation::didRemoveTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, ScriptExecutionContext& context) > { >- pauseOnNativeEventIfNeeded(instrumentingAgents, clearTimerEventName, true); >- > if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent()) > debuggerAgent->didCancelAsyncCall(InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId); > if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) >@@ -443,13 +432,14 @@ void InspectorInstrumentation::didEvaluateScriptImpl(const InspectorInstrumentat > timelineAgent->didEvaluateScript(frame); > } > >-InspectorInstrumentationCookie InspectorInstrumentation::willFireTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, ScriptExecutionContext& context) >+InspectorInstrumentationCookie InspectorInstrumentation::willFireTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, bool oneShot, ScriptExecutionContext& context) > { >- pauseOnNativeEventIfNeeded(instrumentingAgents, timerFiredEventName, false); >- > if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent()) > debuggerAgent->willDispatchAsyncCall(InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId); > >+ if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent()) >+ domDebuggerAgent->willFireTimer(oneShot); >+ > int timelineAgentId = 0; > if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) { > timelineAgent->willFireTimer(timerId, frameForScriptExecutionContext(context)); >@@ -1044,16 +1034,8 @@ bool InspectorInstrumentation::timelineAgentEnabled(ScriptExecutionContext* scri > return instrumentingAgents && instrumentingAgents->inspectorTimelineAgent(); > } > >-void InspectorInstrumentation::pauseOnNativeEventIfNeeded(InstrumentingAgents& instrumentingAgents, const String& eventName, bool synchronous) >-{ >- if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent()) >- domDebuggerAgent->pauseOnNativeEventIfNeeded(eventName, synchronous); >-} >- > void InspectorInstrumentation::didRequestAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document) > { >- pauseOnNativeEventIfNeeded(instrumentingAgents, requestAnimationFrameEventName, true); >- > if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent()) > pageDebuggerAgent->didRequestAnimationFrame(callbackId, document); > if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) >@@ -1062,8 +1044,6 @@ void InspectorInstrumentation::didRequestAnimationFrameImpl(InstrumentingAgents& > > void InspectorInstrumentation::didCancelAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document) > { >- pauseOnNativeEventIfNeeded(instrumentingAgents, cancelAnimationFrameEventName, true); >- > if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent()) > pageDebuggerAgent->didCancelAnimationFrame(callbackId); > if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) >@@ -1072,11 +1052,12 @@ void InspectorInstrumentation::didCancelAnimationFrameImpl(InstrumentingAgents& > > InspectorInstrumentationCookie InspectorInstrumentation::willFireAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document) > { >- pauseOnNativeEventIfNeeded(instrumentingAgents, animationFrameFiredEventName, false); >- > if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent()) > pageDebuggerAgent->willFireAnimationFrame(callbackId); > >+ if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent()) >+ domDebuggerAgent->willFireAnimationFrame(); >+ > int timelineAgentId = 0; > if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) { > timelineAgent->willFireAnimationFrame(callbackId, document.frame()); >diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h >index 622fc5602070a4481c72ab65ed5b6e6c71be0d46..dde2122cced00a8e320cf44098fad06657647970 100644 >--- a/Source/WebCore/inspector/InspectorInstrumentation.h >+++ b/Source/WebCore/inspector/InspectorInstrumentation.h >@@ -157,7 +157,7 @@ public: > static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&); > static InspectorInstrumentationCookie willEvaluateScript(Frame&, const String& url, int lineNumber); > static void didEvaluateScript(const InspectorInstrumentationCookie&, Frame&); >- static InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext&, int timerId); >+ static InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext&, int timerId, bool oneShot); > static void didFireTimer(const InspectorInstrumentationCookie&); > static void didInvalidateLayout(Frame&); > static InspectorInstrumentationCookie willLayout(Frame&); >@@ -341,7 +341,7 @@ private: > static void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&); > static InspectorInstrumentationCookie willEvaluateScriptImpl(InstrumentingAgents&, Frame&, const String& url, int lineNumber); > static void didEvaluateScriptImpl(const InspectorInstrumentationCookie&, Frame&); >- static InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents&, int timerId, ScriptExecutionContext&); >+ static InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents&, int timerId, bool oneShot, ScriptExecutionContext&); > static void didFireTimerImpl(const InspectorInstrumentationCookie&); > static void didInvalidateLayoutImpl(InstrumentingAgents&, Frame&); > static InspectorInstrumentationCookie willLayoutImpl(InstrumentingAgents&, Frame&); >@@ -453,8 +453,6 @@ private: > > static InspectorTimelineAgent* retrieveTimelineAgent(const InspectorInstrumentationCookie&); > >- static void pauseOnNativeEventIfNeeded(InstrumentingAgents&, const String& eventName, bool synchronous); >- > WEBCORE_EXPORT static int s_frontendCounter; > }; > >@@ -807,11 +805,11 @@ inline void InspectorInstrumentation::didEvaluateScript(const InspectorInstrumen > didEvaluateScriptImpl(cookie, frame); > } > >-inline InspectorInstrumentationCookie InspectorInstrumentation::willFireTimer(ScriptExecutionContext& context, int timerId) >+inline InspectorInstrumentationCookie InspectorInstrumentation::willFireTimer(ScriptExecutionContext& context, int timerId, bool oneShot) > { > FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie()); > if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context)) >- return willFireTimerImpl(*instrumentingAgents, timerId, context); >+ return willFireTimerImpl(*instrumentingAgents, timerId, oneShot, context); > return InspectorInstrumentationCookie(); > } > >diff --git a/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp >index 8a5098ab6fae7bd7d8a0b761f4c72a901f7e8402..09b98421c860ef96ea671c516ab3d35c7703d230 100644 >--- a/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp >+++ b/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp >@@ -52,8 +52,9 @@ enum DOMBreakpointType { > DOMBreakpointTypesCount > }; > >-static const char eventNameCategoryType[] = "event-name:"; >-static const char instrumentationCategoryType[] = "instrumentation:"; >+static const char animationFrameCategoryType[] = "animation-frame"; >+static const char listenerCategoryType[] = "listener"; >+static const char timerCategoryType[] = "timer"; > > const uint32_t inheritableDOMBreakpointTypesMask = (1 << SubtreeModified); > const int domBreakpointDerivedTypeShift = 16; >@@ -126,44 +127,49 @@ void InspectorDOMDebuggerAgent::discardBindings() > m_xhrBreakpoints.clear(); > } > >-void InspectorDOMDebuggerAgent::setEventListenerBreakpoint(ErrorString& error, const String& eventName) >+static String formatEventBreakpointString(const String& breakpointType, const String& eventName) > { >- setBreakpoint(error, eventNameCategoryType + eventName); >+ return makeString(breakpointType, ':', eventName); > } > >-void InspectorDOMDebuggerAgent::setInstrumentationBreakpoint(ErrorString& error, const String& eventName) >+void InspectorDOMDebuggerAgent::setEventBreakpoint(ErrorString& error, const String& breakpointType, const String& eventName) > { >- setBreakpoint(error, instrumentationCategoryType + eventName); >-} >+ if (breakpointType.isEmpty()) { >+ error = "Event breakpoint type is empty"_s; >+ return; >+ } >+ >+ if (breakpointType != animationFrameCategoryType && breakpointType != listenerCategoryType && breakpointType != timerCategoryType) { >+ error = makeString("Unknown event breakpoint type: "_s, breakpointType); >+ return; >+ } > >-void InspectorDOMDebuggerAgent::setBreakpoint(ErrorString& error, const String& eventName) >-{ > if (eventName.isEmpty()) { > error = "Event name is empty"_s; > return; > } > >- m_eventListenerBreakpoints.add(eventName); >+ m_eventBreakpoints.add(formatEventBreakpointString(breakpointType, eventName)); > } > >-void InspectorDOMDebuggerAgent::removeEventListenerBreakpoint(ErrorString& error, const String& eventName) >+void InspectorDOMDebuggerAgent::removeEventBreakpoint(ErrorString& error, const String& breakpointType, const String& eventName) > { >- removeBreakpoint(error, eventNameCategoryType + eventName); >-} >+ if (breakpointType.isEmpty()) { >+ error = "Event breakpoint type is empty"_s; >+ return; >+ } > >-void InspectorDOMDebuggerAgent::removeInstrumentationBreakpoint(ErrorString& error, const String& eventName) >-{ >- removeBreakpoint(error, instrumentationCategoryType + eventName); >-} >+ if (breakpointType != animationFrameCategoryType && breakpointType != listenerCategoryType && breakpointType != timerCategoryType) { >+ error = makeString("Unknown event breakpoint type: "_s, breakpointType); >+ return; >+ } > >-void InspectorDOMDebuggerAgent::removeBreakpoint(ErrorString& error, const String& eventName) >-{ > if (eventName.isEmpty()) { > error = "Event name is empty"_s; > return; > } > >- m_eventListenerBreakpoints.remove(eventName); >+ m_eventBreakpoints.remove(formatEventBreakpointString(breakpointType, eventName)); > } > > void InspectorDOMDebuggerAgent::didInvalidateStyleAttr(Node& node) >@@ -366,7 +372,7 @@ void InspectorDOMDebuggerAgent::updateSubtreeBreakpoints(Node* node, uint32_t ro > > void InspectorDOMDebuggerAgent::willHandleEvent(const Event& event, const RegisteredEventListener& registeredEventListener) > { >- bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventListenerBreakpoints.contains(eventNameCategoryType + event.type()); >+ bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(formatEventBreakpointString(listenerCategoryType, event.type())); > > if (!shouldPause && m_domAgent) > shouldPause = m_domAgent->hasBreakpointForEventListener(*event.currentTarget(), event.type(), registeredEventListener.callback(), registeredEventListener.useCapture()); >@@ -385,19 +391,28 @@ void InspectorDOMDebuggerAgent::willHandleEvent(const Event& event, const Regist > m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData)); > } > >-void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(const String& eventName, bool synchronous) >+void InspectorDOMDebuggerAgent::willFireTimer(bool oneShot) > { >- bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventListenerBreakpoints.contains(instrumentationCategoryType + eventName); >+ String eventName = oneShot ? "setTimeout"_s : "setInterval"_s; >+ bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(formatEventBreakpointString(timerCategoryType, eventName)); > if (!shouldPause) > return; > > Ref<JSON::Object> eventData = JSON::Object::create(); > eventData->setString("eventName"_s, eventName); >+ m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::Timer, WTFMove(eventData)); >+} > >- if (synchronous) >- m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData)); >- else >- m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData)); >+void InspectorDOMDebuggerAgent::willFireAnimationFrame() >+{ >+ String eventName = "requestAnimationFrame"_s; >+ bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(formatEventBreakpointString(animationFrameCategoryType, eventName)); >+ if (!shouldPause) >+ return; >+ >+ Ref<JSON::Object> eventData = JSON::Object::create(); >+ eventData->setString("eventName"_s, eventName); >+ m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::AnimationFrame, WTFMove(eventData)); > } > > void InspectorDOMDebuggerAgent::setXHRBreakpoint(ErrorString&, const String& url, const bool* optionalIsRegex) >diff --git a/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.h b/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.h >index 0b306313a697c66045fd2fe3d42d599881fbeae2..a3a96a267c7381b50e289bdf048abdc813b86d8a 100644 >--- a/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.h >+++ b/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.h >@@ -59,10 +59,8 @@ public: > // DOMDebugger API > void setXHRBreakpoint(ErrorString&, const String& url, const bool* optionalIsRegex) final; > void removeXHRBreakpoint(ErrorString&, const String& url) final; >- void setEventListenerBreakpoint(ErrorString&, const String& eventName) final; >- void removeEventListenerBreakpoint(ErrorString&, const String& eventName) final; >- void setInstrumentationBreakpoint(ErrorString&, const String& eventName) final; >- void removeInstrumentationBreakpoint(ErrorString&, const String& eventName) final; >+ void setEventBreakpoint(ErrorString&, const String& breakpointType, const String& eventName) final; >+ void removeEventBreakpoint(ErrorString&, const String& breakpointType, const String& eventName) final; > void setDOMBreakpoint(ErrorString&, int nodeId, const String& type) final; > void removeDOMBreakpoint(ErrorString&, int nodeId, const String& type) final; > >@@ -76,7 +74,8 @@ public: > void willSendXMLHttpRequest(const String& url); > void frameDocumentUpdated(Frame&); > void willHandleEvent(const Event&, const RegisteredEventListener&); >- void pauseOnNativeEventIfNeeded(const String& eventName, bool synchronous); >+ void willFireTimer(bool oneShot); >+ void willFireAnimationFrame(); > void mainFrameDOMContentLoaded(); > > void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) final; >@@ -93,15 +92,13 @@ private: > void updateSubtreeBreakpoints(Node*, uint32_t rootMask, bool set); > bool hasBreakpoint(Node*, int type); > void discardBindings(); >- void setBreakpoint(ErrorString&, const String& eventName); >- void removeBreakpoint(ErrorString&, const String& eventName); > > RefPtr<Inspector::DOMDebuggerBackendDispatcher> m_backendDispatcher; > InspectorDOMAgent* m_domAgent { nullptr }; > Inspector::InspectorDebuggerAgent* m_debuggerAgent { nullptr }; > > HashMap<Node*, uint32_t> m_domBreakpoints; >- HashSet<String> m_eventListenerBreakpoints; >+ HashSet<String> m_eventBreakpoints; > > enum class XHRBreakpointType { Text, RegularExpression }; > >diff --git a/Source/WebCore/page/DOMTimer.cpp b/Source/WebCore/page/DOMTimer.cpp >index 021ce79f083d7e23cc0a660e765c3b2f64689fe6..fd79a1bf78443f8db7d2283d598b82fe63ef75ec 100644 >--- a/Source/WebCore/page/DOMTimer.cpp >+++ b/Source/WebCore/page/DOMTimer.cpp >@@ -321,7 +321,7 @@ void DOMTimer::fired() > // Only the first execution of a multi-shot timer should get an affirmative user gesture indicator. > m_userGestureTokenToForward = nullptr; > >- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId); >+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId, !repeatInterval()); > > // Simple case for non-one-shot timers. > if (isActive()) { >diff --git a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >index fa9c15d97585e92f69bc2841dc450211833b486c..024b3f2cdae9ef7b91deeca3ab6eb9b6437714ef 100644 >--- a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >+++ b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >@@ -41,6 +41,7 @@ localizedStrings["%s (%s, %s)"] = "%s (%s, %s)"; > localizedStrings["%s (default)"] = "%s (default)"; > localizedStrings["%s (hidden)"] = "%s (hidden)"; > localizedStrings["%s Event Dispatched"] = "%s Event Dispatched"; >+localizedStrings["%s Fired"] = "%s Fired"; > localizedStrings["%s Prototype"] = "%s Prototype"; > localizedStrings["%s \u2013 %s"] = "%s \u2013 %s"; > localizedStrings["%s \u2014 %s"] = "%s \u2014 %s"; >@@ -146,7 +147,6 @@ localizedStrings["Boundary"] = "Boundary"; > localizedStrings["Box Model"] = "Box Model"; > localizedStrings["Box Shadow"] = "Box Shadow"; > localizedStrings["Break on events with name:"] = "Break on events with name:"; >-localizedStrings["Break on listeners for event with name:"] = "Break on listeners for event with name:"; > localizedStrings["Break on request with URL:"] = "Break on request with URL:"; > localizedStrings["Break onâ¦"] = "Break onâ¦"; > localizedStrings["Breakdown"] = "Breakdown"; >@@ -274,6 +274,7 @@ localizedStrings["Custom"] = "Custom"; > localizedStrings["DNS"] = "DNS"; > localizedStrings["DOM Breakpoints"] = "DOM Breakpoints"; > localizedStrings["DOM Content Loaded \u2014 %s"] = "DOM Content Loaded \u2014 %s"; >+localizedStrings["DOM Event"] = "DOM Event"; > localizedStrings["Damping"] = "Damping"; > localizedStrings["Dash Array"] = "Dash Array"; > localizedStrings["Data"] = "Data"; >@@ -403,6 +404,7 @@ localizedStrings["Event Breakpoints"] = "Event Breakpoints"; > localizedStrings["Event Dispatched"] = "Event Dispatched"; > localizedStrings["Event Listeners"] = "Event Listeners"; > localizedStrings["Events"] = "Events"; >+localizedStrings["Example: â%sâ"] = "Example: â%sâ"; > localizedStrings["Exception with thrown value: %s"] = "Exception with thrown value: %s"; > localizedStrings["Expand All"] = "Expand All"; > localizedStrings["Expand columns"] = "Expand columns"; >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js b/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js >index cbabcab72f7be001eb4c57d4d78f476e68f102da..917f81484d5d734120105925d60be951fa8a40a6 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js >@@ -78,6 +78,13 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > } > } > >+ // Static >+ >+ static supportsEventBreakpoints() >+ { >+ return DOMDebuggerAgent.setEventBreakpoint && DOMDebuggerAgent.removeEventBreakpoint; >+ } >+ > // Public > > get supported() >@@ -193,9 +200,9 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > this._saveDOMBreakpoints(); > } > >- eventBreakpointForEventName(eventName) >+ eventBreakpointForTypeAndEventName(type, eventName) > { >- return this._eventBreakpoints.find((breakpoint) => breakpoint.eventName === eventName) || null; >+ return this._eventBreakpoints.find((breakpoint) => breakpoint.type === type && breakpoint.eventName === eventName) || null; > } > > addEventBreakpoint(breakpoint) >@@ -204,7 +211,7 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > if (!breakpoint) > return; > >- if (this._eventBreakpoints.some((item) => item.eventName === breakpoint.eventName)) >+ if (this.eventBreakpointForTypeAndEventName(breakpoint.type, breakpoint.eventName)) > return; > > this._eventBreakpoints.push(breakpoint); >@@ -232,10 +239,19 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > if (breakpoint.disabled) > return; > >- DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, (error) => { >+ function breakpointRemoved(error) { > if (error) > console.error(error); >- }); >+ } >+ >+ // Compatibility (iOS 12): DOMDebuggerAgent.removeEventBreakpoint did not exist. >+ if (!WI.DOMDebuggerManager.supportsEventBreakpoints()) { >+ console.assert(breakpoint.type === WI.EventBreakpoint.Type.Listener); >+ DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointRemoved); >+ return; >+ } >+ >+ DOMDebuggerAgent.removeEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointRemoved); > } > > xhrBreakpointForURL(url) >@@ -415,10 +431,25 @@ WI.DOMDebuggerManager = class DOMDebuggerManager extends WI.Object > callback(error); > } > >- if (breakpoint.disabled) >- DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated); >- else >- DOMDebuggerAgent.setEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated); >+ if (breakpoint.disabled) { >+ // Compatibility (iOS 12): DOMDebuggerAgent.removeEventBreakpoint did not exist. >+ if (!WI.DOMDebuggerManager.supportsEventBreakpoints()) { >+ console.assert(breakpoint.type === WI.EventBreakpoint.Type.Listener); >+ DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated); >+ return; >+ } >+ >+ DOMDebuggerAgent.removeEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointUpdated); >+ } else { >+ // Compatibility (iOS 12): DOMDebuggerAgent.setEventBreakpoint did not exist. >+ if (!WI.DOMDebuggerManager.supportsEventBreakpoints()) { >+ console.assert(breakpoint.type === WI.EventBreakpoint.Type.Listener); >+ DOMDebuggerAgent.setEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated); >+ return; >+ } >+ >+ DOMDebuggerAgent.setEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointUpdated); >+ } > } > > _updateXHRBreakpoint(breakpoint, callback) >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js b/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js >index 7c6280c202c6d49bdf9dd0415fcddbb6ed8d8dee..c4c8599c15c9f9c669478199247ead8a014b61d2 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js >@@ -556,7 +556,7 @@ WI.DOMTreeManager = class DOMTreeManager extends WI.Object > > setBreakpointForEventListener(eventListener) > { >- let breakpoint = new WI.EventBreakpoint(eventListener.type, {eventListener}); >+ let breakpoint = new WI.EventBreakpoint(WI.EventBreakpoint.Type.Listener, eventListener.type, {eventListener}); > this._breakpointsForEventListeners.set(eventListener.eventListenerId, breakpoint); > > DOMAgent.setBreakpointForEventListener(eventListener.eventListenerId, (error) => { >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js b/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >index 60eef5b1a1a25474f82c9d01d784fd2fa36bebf0..a37affd662c20cf6126cf2a33f61453cab8ba1fc 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js >@@ -818,6 +818,8 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object > { > // FIXME: Handle other backend pause reasons. > switch (payload) { >+ case DebuggerAgent.PausedReason.AnimationFrame: >+ return WI.DebuggerManager.PauseReason.AnimationFrame; > case DebuggerAgent.PausedReason.Assert: > return WI.DebuggerManager.PauseReason.Assertion; > case DebuggerAgent.PausedReason.Breakpoint: >@@ -834,6 +836,8 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object > return WI.DebuggerManager.PauseReason.Exception; > case DebuggerAgent.PausedReason.PauseOnNextStatement: > return WI.DebuggerManager.PauseReason.PauseOnNextStatement; >+ case DebuggerAgent.PausedReason.Timer: >+ return WI.DebuggerManager.PauseReason.Timer; > case DebuggerAgent.PausedReason.XHR: > return WI.DebuggerManager.PauseReason.XHR; > default: >@@ -1233,6 +1237,7 @@ WI.DebuggerManager.Event = { > }; > > WI.DebuggerManager.PauseReason = { >+ AnimationFrame: "animation-frame", > Assertion: "assertion", > Breakpoint: "breakpoint", > CSPViolation: "CSP-violation", >@@ -1241,6 +1246,7 @@ WI.DebuggerManager.PauseReason = { > EventListener: "event-listener", > Exception: "exception", > PauseOnNextStatement: "pause-on-next-statement", >+ Timer: "timer", > XHR: "xhr", > Other: "other", > }; >diff --git a/Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg b/Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg >deleted file mode 100644 >index 15dacd648fad15184e7ee1e44a7a7b03c61f748c..0000000000000000000000000000000000000000 >--- a/Source/WebInspectorUI/UserInterface/Images/EventBreakpoint.svg >+++ /dev/null >@@ -1,8 +0,0 @@ >-<?xml version="1.0" encoding="utf-8"?> >-<!-- Copyright © 2018 Apple Inc. All rights reserved. --> >-<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16"> >- <path fill="rgb(148, 183, 219)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 Z"/> >- <path fill="rgb(106, 136, 170)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 M 13 2 C 13.550781 2 14 2.449219 14 3 L 14 13 C 14 13.550781 13.550781 14 13 14 L 3 14 C 2.449219 14 2 13.550781 2 13 L 2 3 C 2 2.449219 2.449219 2 3 2 L 13 2"/> >- <path fill="rgb(113, 146, 184)" d="M 5.503906 12.742188 C 4.949219 12.742188 4.503906 12.292969 4.503906 11.742188 L 4.503906 3.792969 C 4.503906 3.242188 4.949219 2.792969 5.503906 2.792969 L 10.472656 2.792969 C 11.023438 2.792969 11.472656 3.242188 11.472656 3.792969 L 11.472656 4.882812 C 11.472656 5.4375 11.023438 5.882812 10.472656 5.882812 C 10.472656 5.882812 9.132812 5.882812 8.15625 5.882812 C 8.15625 5.992188 8.15625 5.996094 8.15625 6.101562 C 8.957031 6.101562 9.875 6.101562 9.875 6.101562 C 10.425781 6.101562 10.875 6.550781 10.875 7.101562 L 10.875 8.164062 C 10.875 8.71875 10.425781 9.164062 9.875 9.164062 C 9.875 9.164062 8.957031 9.164062 8.15625 9.164062 C 8.15625 9.382812 8.15625 9.398438 8.15625 9.613281 C 9.191406 9.613281 10.722656 9.613281 10.722656 9.613281 C 11.277344 9.613281 11.722656 10.0625 11.722656 10.613281 L 11.722656 11.742188 C 11.722656 12.292969 11.277344 12.742188 10.722656 12.742188 L 5.503906 12.742188"/> >- <path fill="white" d="M 5.503906 11.742188 L 5.503906 3.792969 L 10.46875 3.792969 L 10.46875 4.882812 L 7.15625 4.882812 L 7.15625 7.101562 L 9.875 7.101562 L 9.875 8.164062 L 7.15625 8.164062 L 7.15625 10.613281 L 10.722656 10.613281 L 10.722656 11.742188 Z"/> >-</svg> >diff --git a/Source/WebInspectorUI/UserInterface/Images/EventBreakpointAnimationFrame.svg b/Source/WebInspectorUI/UserInterface/Images/EventBreakpointAnimationFrame.svg >new file mode 100644 >index 0000000000000000000000000000000000000000..02e106bd5c49bf32f77f5df4b1f676366a3cdcd6 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Images/EventBreakpointAnimationFrame.svg >@@ -0,0 +1,8 @@ >+<?xml version="1.0" encoding="utf-8"?> >+<!-- Copyright © 2018 Apple Inc. All rights reserved. --> >+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16"> >+ <path fill="rgb(148, 183, 219)" d="M 13 1 L 3 1 C 1.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"/> >+ <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"/> >+ <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"/> >+ <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"/> >+</svg> >diff --git a/Source/WebInspectorUI/UserInterface/Images/EventBreakpointListener.svg b/Source/WebInspectorUI/UserInterface/Images/EventBreakpointListener.svg >new file mode 100644 >index 0000000000000000000000000000000000000000..15dacd648fad15184e7ee1e44a7a7b03c61f748c >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Images/EventBreakpointListener.svg >@@ -0,0 +1,8 @@ >+<?xml version="1.0" encoding="utf-8"?> >+<!-- Copyright © 2018 Apple Inc. All rights reserved. --> >+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16"> >+ <path fill="rgb(148, 183, 219)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 Z"/> >+ <path fill="rgb(106, 136, 170)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 M 13 2 C 13.550781 2 14 2.449219 14 3 L 14 13 C 14 13.550781 13.550781 14 13 14 L 3 14 C 2.449219 14 2 13.550781 2 13 L 2 3 C 2 2.449219 2.449219 2 3 2 L 13 2"/> >+ <path fill="rgb(113, 146, 184)" d="M 5.503906 12.742188 C 4.949219 12.742188 4.503906 12.292969 4.503906 11.742188 L 4.503906 3.792969 C 4.503906 3.242188 4.949219 2.792969 5.503906 2.792969 L 10.472656 2.792969 C 11.023438 2.792969 11.472656 3.242188 11.472656 3.792969 L 11.472656 4.882812 C 11.472656 5.4375 11.023438 5.882812 10.472656 5.882812 C 10.472656 5.882812 9.132812 5.882812 8.15625 5.882812 C 8.15625 5.992188 8.15625 5.996094 8.15625 6.101562 C 8.957031 6.101562 9.875 6.101562 9.875 6.101562 C 10.425781 6.101562 10.875 6.550781 10.875 7.101562 L 10.875 8.164062 C 10.875 8.71875 10.425781 9.164062 9.875 9.164062 C 9.875 9.164062 8.957031 9.164062 8.15625 9.164062 C 8.15625 9.382812 8.15625 9.398438 8.15625 9.613281 C 9.191406 9.613281 10.722656 9.613281 10.722656 9.613281 C 11.277344 9.613281 11.722656 10.0625 11.722656 10.613281 L 11.722656 11.742188 C 11.722656 12.292969 11.277344 12.742188 10.722656 12.742188 L 5.503906 12.742188"/> >+ <path fill="white" d="M 5.503906 11.742188 L 5.503906 3.792969 L 10.46875 3.792969 L 10.46875 4.882812 L 7.15625 4.882812 L 7.15625 7.101562 L 9.875 7.101562 L 9.875 8.164062 L 7.15625 8.164062 L 7.15625 10.613281 L 10.722656 10.613281 L 10.722656 11.742188 Z"/> >+</svg> >diff --git a/Source/WebInspectorUI/UserInterface/Images/EventBreakpointTimer.svg b/Source/WebInspectorUI/UserInterface/Images/EventBreakpointTimer.svg >new file mode 100644 >index 0000000000000000000000000000000000000000..f94ac63d03c2c63ca1f05e6f7e59535c10349d87 >--- /dev/null >+++ b/Source/WebInspectorUI/UserInterface/Images/EventBreakpointTimer.svg >@@ -0,0 +1,8 @@ >+<?xml version="1.0" encoding="utf-8"?> >+<!-- Copyright © 2018 Apple Inc. All rights reserved. --> >+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16"> >+ <path fill="rgb(148, 183, 219)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 Z"/> >+ <path fill="rgb(106, 136, 170)" d="M 13 1 L 3 1 C 1.898438 1 1 1.898438 1 3 L 1 13 C 1 14.101562 1.898438 15 3 15 L 13 15 C 14.101562 15 15 14.101562 15 13 L 15 3 C 15 1.898438 14.101562 1 13 1 M 13 2 C 13.550781 2 14 2.449219 14 3 L 14 13 C 14 13.550781 13.550781 14 13 14 L 3 14 C 2.449219 14 2 13.550781 2 13 L 2 3 C 2 2.449219 2.449219 2 3 2 L 13 2"/> >+ <path fill="rgb(113, 146, 184)" d="M 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"/> >+ <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"/> >+</svg> >diff --git a/Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js b/Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js >index 7dd7f36705f866bb9c048821bf75c9b9722ae827..1bdc3f3b19e5935d680c9259f93d016ba7fa2fb3 100644 >--- a/Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js >+++ b/Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js >@@ -25,12 +25,15 @@ > > WI.EventBreakpoint = class EventBreakpoint extends WI.Object > { >- constructor(eventName, {disabled, eventListener} = {}) >+ constructor(type, eventName, {disabled, eventListener} = {}) > { > super(); > >+ console.assert(typeof type === "string"); >+ console.assert(Object.values(WI.EventBreakpoint.Type).includes(type)); > console.assert(typeof eventName === "string"); > >+ this._type = type; > this._eventName = eventName; > > this._disabled = disabled || false; >@@ -41,13 +44,14 @@ WI.EventBreakpoint = class EventBreakpoint extends WI.Object > > static fromPayload(payload) > { >- return new WI.EventBreakpoint(payload.eventName, { >+ return new WI.EventBreakpoint(payload.type, payload.eventName, { > disabled: !!payload.disabled, > }); > } > > // Public > >+ get type() { return this._type; } > get eventName() { return this._eventName; } > get eventListener() { return this._eventListener; } > >@@ -69,6 +73,7 @@ WI.EventBreakpoint = class EventBreakpoint extends WI.Object > get serializableInfo() > { > let info = { >+ type: this._type, > eventName: this._eventName, > }; > if (this._disabled) >@@ -79,10 +84,18 @@ WI.EventBreakpoint = class EventBreakpoint extends WI.Object > > saveIdentityToCookie(cookie) > { >+ cookie[WI.EventBreakpoint.TypeCookieKey] = this._type; > cookie[WI.EventBreakpoint.EventNameCookieKey] = this._eventName; > } > }; > >+WI.EventBreakpoint.Type = { >+ AnimationFrame: "animation-frame", >+ Listener: "listener", >+ Timer: "timer", >+}; >+ >+WI.EventBreakpoint.TypeCookieKey = "event-breakpoint-type"; > WI.EventBreakpoint.EventNameCookieKey = "event-breakpoint-event-name"; > > WI.EventBreakpoint.Event = { >diff --git a/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js b/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js >index 4e23315880b16df1eed2390a671986e64e51bb86..cbb167812cd01d4c5cad8e9dec8fc4c6973e36a4 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js >+++ b/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js >@@ -951,6 +951,28 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba > let {pauseReason, pauseData} = targetData; > > switch (pauseReason) { >+ case WI.DebuggerManager.PauseReason.AnimationFrame: >+ console.assert(pauseData, "Expected data with an animation frame, but found none."); >+ if (pauseData) { >+ let eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.AnimationFrame, pauseData.eventName); >+ console.assert(eventBreakpoint, "Expected AnimationFrame breakpoint for event name.", pauseData.eventName); >+ >+ const suppressFiltering = true; >+ this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering); >+ >+ let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, { >+ className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName, >+ title: WI.UIString("%s Fired").format(pauseData.eventName), >+ }); >+ this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement); >+ >+ let eventBreakpointRow = new WI.DetailsSectionRow; >+ eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element); >+ >+ this._pauseReasonGroup.rows = [eventBreakpointRow]; >+ } >+ return true; >+ > case WI.DebuggerManager.PauseReason.Assertion: > // FIXME: We should include the assertion condition string. > console.assert(pauseData, "Expected data with an assertion, but found none."); >@@ -1061,10 +1083,11 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba > if (pauseData.eventListenerId) > eventBreakpoint = WI.domTreeManager.breakpointForEventListenerId(pauseData.eventListenerId); > if (!eventBreakpoint) >- eventBreakpoint = WI.domDebuggerManager.eventBreakpointForEventName(pauseData.eventName); >+ eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.Listener, pauseData.eventName); > console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName); > >- this._pauseReasonTreeOutline = this.createContentTreeOutline(true); >+ const suppressFiltering = true; >+ this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering); > > let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, { > className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName, >@@ -1105,6 +1128,28 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba > this._pauseReasonGroup.rows = [this._pauseReasonTextRow]; > return true; > >+ case WI.DebuggerManager.PauseReason.Timer: >+ console.assert(pauseData, "Expected data with a timer, but found none."); >+ if (pauseData) { >+ let eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.Timer, pauseData.eventName); >+ console.assert(eventBreakpoint, "Expected Timer breakpoint for event name.", pauseData.eventName); >+ >+ const suppressFiltering = true; >+ this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering); >+ >+ let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, { >+ className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName, >+ title: WI.UIString("%s Fired").format(pauseData.eventName), >+ }); >+ this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement); >+ >+ let eventBreakpointRow = new WI.DetailsSectionRow; >+ eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element); >+ >+ this._pauseReasonGroup.rows = [eventBreakpointRow]; >+ } >+ return true; >+ > case WI.DebuggerManager.PauseReason.XHR: > console.assert(WI.domDebuggerManager.supported); > console.assert(pauseData, "Expected XHR breakpoint data, but found none."); >@@ -1264,17 +1309,14 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba > > willDismissPopover(popover) > { >- if (popover.result !== WI.InputPopover.Result.Committed) >- return; >- > if (popover instanceof WI.EventBreakpointPopover) { >- let eventName = popover.value; >- if (eventName) >- WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(eventName)); >+ let breakpoint = popover.breakpoint; >+ if (breakpoint) >+ WI.domDebuggerManager.addEventBreakpoint(breakpoint); > return; > } > >- if (popover instanceof WI.XHRBreakpointPopover) { >+ if (popover instanceof WI.XHRBreakpointPopover && popover.result === WI.InputPopover.Result.Committed) { > let url = popover.value; > if (url) > WI.domDebuggerManager.addXHRBreakpoint(new WI.XHRBreakpoint(popover.type, url)); >diff --git a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css >index 37a06c6ade0f4a5b06ec075af9919abaa372b05c..4a42ece745c919e2420b74f4a08e49db8d84e360 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css >+++ b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css >@@ -28,9 +28,7 @@ > padding: 5px; > } > >-.popover .event-breakpoint-content > input { >- width: 100%; >+.popover .event-breakpoint-content > .event-type { >+ display: flex; > margin-top: 4px; >- padding: 4px 0 2px 0; >- outline: none; > } >diff --git a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js >index 5f75b513d3d6b1f4c0dea9b29699dbdbe189e069..ad7a92a077bcab059c738d60eeeca65dc93f9e04 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js >+++ b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js >@@ -29,10 +29,8 @@ WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover > { > super(delegate); > >- this._result = WI.InputPopover.Result.None; >- this._value = null; >+ this._breakpoint = null; > >- this._codeMirror = null; > this._targetElement = null; > this._preferredEdges = null; > >@@ -41,8 +39,7 @@ WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover > > // Public > >- get result() { return this._result; } >- get value() { return this._value; } >+ get breakpoint() { return this._breakpoint; } > > show(targetElement, preferredEdges) > { >@@ -56,22 +53,69 @@ WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover > label.classList.add("label"); > label.textContent = WI.UIString("Break on events with name:"); > >- this._inputElement = contentElement.appendChild(document.createElement("input")); >- this._inputElement.placeholder = "click"; >- this._inputElement.spellcheck = false; >- this._inputElement.addEventListener("keydown", (event) => { >+ let typeContainer = contentElement.appendChild(document.createElement("div")); >+ typeContainer.classList.add("event-type"); >+ >+ this._typeSelectElement = typeContainer.appendChild(document.createElement("select")); >+ this._typeSelectElement.addEventListener("change", this._handleTypeSelectChange.bind(this)); >+ this._typeSelectElement.addEventListener("keydown", (event) => { >+ if (isEnterKey(event)) >+ this.dismiss(); >+ }); >+ >+ let createOption = (text, value) => { >+ let optionElement = this._typeSelectElement.appendChild(document.createElement("option")); >+ optionElement.value = value; >+ optionElement.textContent = text; >+ }; >+ >+ createOption(WI.UIString("DOM Event"), WI.EventBreakpoint.Type.Listener); >+ >+ if (WI.DOMDebuggerManager.supportsEventBreakpoints()) { >+ createOption(WI.unlocalizedString("requestAnimationFrame"), "requestAnimationFrame"); >+ createOption(WI.unlocalizedString("setTimeout"), "setTimeout"); >+ createOption(WI.unlocalizedString("setInterval"), "setInterval"); >+ } else >+ this._typeSelectElement.hidden = true; >+ >+ this._domEventNameInputElement = typeContainer.appendChild(document.createElement("input")); >+ this._domEventNameInputElement.placeholder = WI.UIString("Example: â%sâ").format("click"); >+ this._domEventNameInputElement.spellcheck = false; >+ this._domEventNameInputElement.addEventListener("keydown", (event) => { > if (!isEnterKey(event)) > return; > >- this._result = WI.InputPopover.Result.Committed; >- this._value = event.target.value.trim(); >- > this.dismiss(); > }); > > this.content = contentElement; > > this._presentOverTargetElement(); >+ >+ this._typeSelectElement.value = WI.EventBreakpoint.Type.Listener; >+ this._domEventNameInputElement.select(); >+ } >+ >+ dismiss() >+ { >+ let type = this._typeSelectElement.value; >+ let value = null; >+ >+ if (type === WI.EventBreakpoint.Type.Listener) >+ value = this._domEventNameInputElement.value; >+ else { >+ value = type; >+ >+ if (value === "requestAnimationFrame") >+ type = WI.EventBreakpoint.Type.AnimationFrame; >+ else if (value === "setTimeout" || value === "setInterval") >+ type = WI.EventBreakpoint.Type.Timer; >+ } >+ >+ if (type && value) >+ this._breakpoint = new WI.EventBreakpoint(type, value); >+ >+ super.dismiss(); > } > > // Private >@@ -83,7 +127,12 @@ WI.EventBreakpointPopover = class EventBreakpointPopover extends WI.Popover > > let targetFrame = WI.Rect.rectFromClientRect(this._targetElement.getBoundingClientRect()); > this.present(targetFrame, this._preferredEdges); >+ } >+ >+ _handleTypeSelectChange(event) >+ { >+ this._domEventNameInputElement.hidden = this._typeSelectElement.value !== WI.EventBreakpoint.Type.Listener; > >- this._inputElement.select(); >+ this.update(); > } > }; >diff --git a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css >index 622f025034b6ff102292223a9f710fa2ed076e9c..d84b00b193ac236d8a1b09bd21c16556667a381c 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css >+++ b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css >@@ -23,6 +23,14 @@ > * THE POSSIBILITY OF SUCH DAMAGE. > */ > >-.breakpoint.event:not(.breakpoint-paused-icon) .icon { >- content: url(../Images/EventBreakpoint.svg); >+.breakpoint.event.animation-frame:not(.breakpoint-paused-icon) .icon { >+ content: url(../Images/EventBreakpointAnimationFrame.svg); >+} >+ >+.breakpoint.event.listener:not(.breakpoint-paused-icon) .icon { >+ content: url(../Images/EventBreakpointListener.svg); >+} >+ >+.breakpoint.event.timer:not(.breakpoint-paused-icon) .icon { >+ content: url(../Images/EventBreakpointTimer.svg); > } >diff --git a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js >index 6964b79c9c64033c6dd3743c64d3640ef1331cd8..dab6fcac95ee8afdaa3240d515b1fb28ab13fea2 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js >+++ b/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js >@@ -29,7 +29,7 @@ WI.EventBreakpointTreeElement = class EventBreakpointTreeElement extends WI.Gene > { > console.assert(breakpoint instanceof WI.EventBreakpoint); > >- let classNames = ["breakpoint", "event"]; >+ let classNames = ["breakpoint", "event", breakpoint.type]; > if (className) > classNames.push(className); > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index a7209be7bd36334d62e3d2b40d6082a9a593b53e..15b03e8a78a913c2c95a6c189d8965033fbb8714 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,29 @@ >+2018-08-22 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: support breakpoints for timers and animation-frame events >+ https://bugs.webkit.org/show_bug.cgi?id=188778 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * inspector/dom-debugger/event-animation-frame-breakpoints-expected.txt: Added. >+ * inspector/dom-debugger/event-animation-frame-breakpoints.html: Added. >+ >+ * inspector/dom-debugger/event-breakpoint-with-navigation.html: >+ >+ * inspector/dom-debugger/event-timer-breakpoints-expected.txt: Added. >+ * inspector/dom-debugger/event-timer-breakpoints.html: Added. >+ >+ * inspector/dom-debugger/event-listener-breakpoints-expected.txt: Renamed from LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt. >+ * inspector/dom-debugger/event-listener-breakpoints.html: Renamed from LayoutTests/inspector/dom-debugger/event-breakpoints.html. >+ >+ * inspector/dom-debugger/resources/event-breakpoint-utilities.js: Added. >+ (TestPage.registerInitializer.window.teardown): >+ (TestPage.registerInitializer.window.failOnPause): >+ (TestPage.registerInitializer.window.addBreakpoint): >+ (TestPage.registerInitializer.window.removeBreakpoint): >+ (TestPage.registerInitializer.window.disableBreakpoint): >+ (TestPage.registerInitializer.window.awaitEvent): >+ > 2018-08-21 Yusuke Suzuki <yusukesuzuki@slowstart.org> > > Support "name" option for dedicated workers >diff --git a/LayoutTests/inspector/dom-debugger/event-animation-frame-breakpoints-expected.txt b/LayoutTests/inspector/dom-debugger/event-animation-frame-breakpoints-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..b4c4f2017a1d29fc7a5c4ad92c9b46e34a83c3cb >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-animation-frame-breakpoints-expected.txt >@@ -0,0 +1,38 @@ >+Tests for Event AnimationFrame breakpoints. >+ >+ >+== Running test suite: DOMDebugger.Event.AnimationFrame >+-- Running test case: DOMDebugger.Event.AnimationFrame.AddBreakpoint "requestAnimationFrame" >+Adding "requestAnimationFrame" Event Breakpoint... >+Firing "requestAnimationFrame" on window... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleWindow_requestAnimationFrame >+ASYNC CALL STACK: >+1: --- requestAnimationFrame --- >+2: [F] windowFire_requestAnimationFrame >+3: [P] Global Code >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.AnimationFrame.AddDisabledBreakpoint "requestAnimationFrame" >+Adding "requestAnimationFrame" Event Breakpoint... >+Disabling "requestAnimationFrame" Event Breakpoint... >+Firing "requestAnimationFrame" on window... >+PASS: Should not pause for disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.AnimationFrame.RemoveBreakpoint "requestAnimationFrame" >+Adding "requestAnimationFrame" Event Breakpoint... >+Removing "requestAnimationFrame" Event Breakpoint... >+Firing "requestAnimationFrame" on window... >+PASS: Should not pause for removed breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.AnimationFrame.RemoveDisabledBreakpoint "requestAnimationFrame" >+Adding "requestAnimationFrame" Event Breakpoint... >+Disabling "requestAnimationFrame" Event Breakpoint... >+Removing "requestAnimationFrame" Event Breakpoint... >+Firing "requestAnimationFrame" on window... >+PASS: Should not pause for removed disabled breakpoint. >+-- Running test teardown. >+ >diff --git a/LayoutTests/inspector/dom-debugger/event-animation-frame-breakpoints.html b/LayoutTests/inspector/dom-debugger/event-animation-frame-breakpoints.html >new file mode 100644 >index 0000000000000000000000000000000000000000..1fd7f38eab2989c7167d86c882316d0bc6a9a7c3 >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-animation-frame-breakpoints.html >@@ -0,0 +1,106 @@ >+<!doctype html> >+<html> >+<head> >+<script src="../../http/tests/inspector/resources/inspector-test.js"></script> >+<script src="../debugger/resources/log-active-stack-trace.js"></script> >+<script src="resources/event-breakpoint-utilities.js"></script> >+<script> >+ >+function handleWindow_requestAnimationFrame() { >+ TestPage.dispatchEventToFrontend("TestPage-requestAnimationFrame"); >+} >+ >+function windowFire_requestAnimationFrame() { >+ requestAnimationFrame(handleWindow_requestAnimationFrame); >+} >+ >+function test() { >+ let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event.AnimationFrame"); >+ >+ function addTestCasesForEventName(eventName) { >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.AnimationFrame.AddBreakpoint "${eventName}"`, >+ description: "Check that the debugger pauses for enabled breakpoints.", >+ teardown, >+ test(resolve, reject) { >+ let paused = false; >+ >+ let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ paused = true; >+ >+ InspectorTest.pass("Should pause before event handler is run."); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume(); >+ }); >+ >+ InspectorTest.singleFireEventListener(`TestPage-${eventName}`, (event) => { >+ if (!paused) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ InspectorTest.fail("Should pause before event handler is run."); >+ } >+ >+ resolve(); >+ }); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.AnimationFrame, eventName) >+ .then(awaitEvent("window", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.AnimationFrame.AddDisabledBreakpoint "${eventName}"`, >+ description: "Check that debugger does not pause for disabled breakpoints.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.AnimationFrame, eventName, "Should not pause for disabled breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.AnimationFrame, eventName) >+ .then(disableBreakpoint) >+ .then(awaitEvent("window", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.AnimationFrame.RemoveBreakpoint "${eventName}"`, >+ description: "Check that debugger does not pause for removed breakpoint.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.AnimationFrame, eventName, "Should not pause for removed breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.AnimationFrame, eventName) >+ .then(removeBreakpoint) >+ .then(awaitEvent("window", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.AnimationFrame.RemoveDisabledBreakpoint "${eventName}"`, >+ description: "Check that a disabled breakpoint can be removed.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.AnimationFrame, eventName, "Should not pause for removed disabled breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.AnimationFrame, eventName) >+ .then(disableBreakpoint) >+ .then(removeBreakpoint) >+ .then(awaitEvent("window", eventName)) >+ .catch(reject); >+ }, >+ }); >+ } >+ >+ addTestCasesForEventName("requestAnimationFrame"); >+ >+ suite.runTestCasesAndFinish(); >+} >+</script> >+</head> >+<body onload="runTest()"> >+ <p>Tests for Event AnimationFrame breakpoints.</p> >+</body> >+</html> >diff --git a/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation.html b/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation.html >index 586f59d2f5f3725fa67f329530479a0eb4fc69c3..e70bb655bc515c17c470dd23221947e4833a557f 100644 >--- a/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation.html >+++ b/LayoutTests/inspector/dom-debugger/event-breakpoint-with-navigation.html >@@ -44,11 +44,12 @@ function test() { > > InspectorTest.log("Adding \"load\" Event Breakpoint..."); > >- let breakpoint = new WI.EventBreakpoint("load"); >+ let breakpoint = new WI.EventBreakpoint(WI.EventBreakpoint.Type.Listener, "load"); > > WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded) > .then((event) => { >- InspectorTest.assert(event.data.breakpoint.eventName, "load", "Breakpoint should be for expected event name."); >+ InspectorTest.assert(event.data.breakpoint.type === WI.EventBreakpoint.Type.Listener, "Breakpoint should be for expected type."); >+ InspectorTest.assert(event.data.breakpoint.eventName === "load", "Breakpoint should be for expected event name."); > > InspectorTest.log("Reloading WebInspector..."); > return InspectorTest.reloadPage(); >diff --git a/LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt b/LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt >deleted file mode 100644 >index 5114e695b393ced23d65bfe120e43248c25af92a..0000000000000000000000000000000000000000 >--- a/LayoutTests/inspector/dom-debugger/event-breakpoints-expected.txt >+++ /dev/null >@@ -1,83 +0,0 @@ >-Tests for Event Listener breakpoints. >- >- >-== Running test suite: DOMDebugger.Event >--- Running test case: DOMDebugger.Event.AddBreakpoint "click" >-Adding "click" Event Breakpoint... >-Firing "click" on body... >-PASS: Should pause before event handler is run. >-CALL STACK: >-0: [F] handleBody_click >-1: [F] bodyFire_click >-2: [P] Global Code >--- Running test teardown. >- >--- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "click" >-Adding "click" Event Breakpoint... >-Disabling "click" Event Breakpoint... >-Firing "click" on body... >-PASS: Should not pause for disabled breakpoint. >--- Running test teardown. >- >--- Running test case: DOMDebugger.Event.RemoveBreakpoint "click" >-Adding "click" Event Breakpoint... >-Removing "click" Event Breakpoint... >-Firing "click" on body... >-PASS: Should not pause for removed breakpoint. >--- Running test teardown. >- >--- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "click" >-Adding "click" Event Breakpoint... >-Disabling "click" Event Breakpoint... >-Removing "click" Event Breakpoint... >-Firing "click" on body... >-PASS: Should not pause for removed disabled breakpoint. >--- Running test teardown. >- >--- Running test case: DOMDebugger.Event.AddBreakpoint "custom" >-Adding "custom" Event Breakpoint... >-Firing "custom" on body... >-PASS: Should pause before event handler is run. >-CALL STACK: >-0: [F] handleBody_custom >-1: [F] bodyFire_custom >-2: [P] Global Code >--- Running test teardown. >- >--- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "custom" >-Adding "custom" Event Breakpoint... >-Disabling "custom" Event Breakpoint... >-Firing "custom" on body... >-PASS: Should not pause for disabled breakpoint. >--- Running test teardown. >- >--- Running test case: DOMDebugger.Event.RemoveBreakpoint "custom" >-Adding "custom" Event Breakpoint... >-Removing "custom" Event Breakpoint... >-Firing "custom" on body... >-PASS: Should not pause for removed breakpoint. >--- Running test teardown. >- >--- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "custom" >-Adding "custom" Event Breakpoint... >-Disabling "custom" Event Breakpoint... >-Removing "custom" Event Breakpoint... >-Firing "custom" on body... >-PASS: Should not pause for removed disabled breakpoint. >--- Running test teardown. >- >--- Running test case: DOMDebugger.Event.AddMultipleBreakpoints >-Adding "click" Event Breakpoint... >-Firing "click" on div#x... >-PASS: Should pause before event handler is run. >-CALL STACK: >-0: [F] handleX_click >-1: [F] xFire_click >-2: [P] Global Code >-PASS: Should pause before event handler is run. >-CALL STACK: >-0: [F] handleBody_click >-1: [F] xFire_click >-2: [P] Global Code >--- Running test teardown. >- >diff --git a/LayoutTests/inspector/dom-debugger/event-breakpoints.html b/LayoutTests/inspector/dom-debugger/event-breakpoints.html >deleted file mode 100644 >index 29fb9b9752545cbb1ff7ce2ec353979b2b48e6fe..0000000000000000000000000000000000000000 >--- a/LayoutTests/inspector/dom-debugger/event-breakpoints.html >+++ /dev/null >@@ -1,249 +0,0 @@ >-<!doctype html> >-<html> >-<head> >-<script src="../../http/tests/inspector/resources/inspector-test.js"></script> >-<script src="../debugger/resources/log-active-stack-trace.js"></script> >-<script> >-function handleBody_click(event) { >- TestPage.dispatchEventToFrontend("TestPageBody-click"); >-} >- >-function handleBody_custom(event) { >- TestPage.dispatchEventToFrontend("TestPageBody-custom"); >-} >- >-function handleX_click(event) { >- TestPage.dispatchEventToFrontend("TestPageX-click"); >-} >- >-function bodyFire_click() { >- document.body.click(); >-} >- >-function bodyFire_custom() { >- document.body.dispatchEvent(new Event("custom")); >-} >- >-function xFire_click() { >- document.getElementById("x").click(); >-} >- >-function test() { >- let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event"); >- >- function teardown(resolve, reject) { >- let breakpoints = WI.domDebuggerManager.eventBreakpoints; >- for (let breakpoint of breakpoints) >- WI.domDebuggerManager.removeEventBreakpoint(breakpoint); >- >- resolve(); >- } >- >- function awaitBodyEvent(eventName) { >- return function() { >- InspectorTest.log(`Firing "${eventName}" on body...`); >- return InspectorTest.evaluateInPage(`bodyFire_${eventName}()`); >- }; >- } >- >- function failOnPause(resolve, eventName, message) { >- let paused = false; >- >- let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >- paused = true; >- >- let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target); >- InspectorTest.assert(targetData.pauseReason === WI.DebuggerManager.PauseReason.EventListener, "Pause reason should be EventListener."); >- InspectorTest.assert(targetData.pauseData.eventName === eventName, `Pause data eventName should be "${eventName}".`); >- >- InspectorTest.fail(message); >- logActiveStackTrace(); >- >- WI.debuggerManager.resume() >- .catch((reason) => { >- InspectorTest.fail(reason); >- resolve(); >- }); >- }); >- >- InspectorTest.singleFireEventListener("TestPageBody-" + eventName, (event) => { >- if (!paused) { >- WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >- >- InspectorTest.pass(message); >- } >- >- resolve(); >- }); >- } >- >- function addBreakpoint(eventName) { >- InspectorTest.log(`Adding "${eventName}" Event Breakpoint...`); >- >- return new Promise((resolve, reject) => { >- let breakpoint = new WI.EventBreakpoint(eventName); >- >- WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded) >- .then((event) => { >- InspectorTest.assert(event.data.breakpoint.eventName === eventName, "Breakpoint should be for expected event name."); >- InspectorTest.assert(!breakpoint.disabled, "Breakpoint should not be disabled initially."); >- resolve(breakpoint); >- }); >- >- WI.domDebuggerManager.addEventBreakpoint(breakpoint); >- }); >- } >- >- function removeBreakpoint(breakpoint) { >- InspectorTest.log(`Removing "${breakpoint.eventName}" Event Breakpoint...`); >- >- return new Promise((resolve, reject) => { >- WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointRemoved) >- .then((event) => { >- InspectorTest.assert(event.data.breakpoint === breakpoint, "Removed Breakpoint should be expected object."); >- InspectorTest.assert(!WI.domDebuggerManager.eventBreakpoints.includes(breakpoint), "Breakpoint should not be in the list of breakpoints."); >- resolve(breakpoint); >- }); >- >- WI.domDebuggerManager.removeEventBreakpoint(breakpoint); >- }); >- } >- >- function disableBreakpoint(breakpoint) { >- InspectorTest.log(`Disabling "${breakpoint.eventName}" Event Breakpoint...`); >- >- breakpoint.disabled = true; >- return breakpoint; >- } >- >- function addTestCasesForEventName(eventName) { >- suite.addTestCase({ >- name: `DOMDebugger.Event.AddBreakpoint "${eventName}"`, >- description: "Check that the debugger pauses for enabled breakpoints.", >- teardown, >- test(resolve, reject) { >- let paused = false; >- >- let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >- paused = true; >- >- InspectorTest.pass("Should pause before event handler is run."); >- logActiveStackTrace(); >- >- WI.debuggerManager.resume(); >- }); >- >- InspectorTest.singleFireEventListener(`TestPageBody-${eventName}`, (event) => { >- if (!paused) { >- WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >- >- InspectorTest.fail("Should pause before event handler is run."); >- } >- >- resolve(); >- }); >- >- addBreakpoint(eventName) >- .then(awaitBodyEvent(eventName)) >- .catch(reject); >- }, >- }); >- >- suite.addTestCase({ >- name: `DOMDebugger.Event.AddDisabledBreakpoint "${eventName}"`, >- description: "Check that debugger does the not pause for disabled breakpoints.", >- teardown, >- test(resolve, reject) { >- failOnPause(resolve, eventName, "Should not pause for disabled breakpoint."); >- >- addBreakpoint(eventName) >- .then(disableBreakpoint) >- .then(awaitBodyEvent(eventName)) >- .catch(reject); >- }, >- }); >- >- suite.addTestCase({ >- name: `DOMDebugger.Event.RemoveBreakpoint "${eventName}"`, >- description: "Check that debugger does not pause for removed breakpoint.", >- teardown, >- test(resolve, reject) { >- failOnPause(resolve, eventName, "Should not pause for removed breakpoint."); >- >- addBreakpoint(eventName) >- .then(removeBreakpoint) >- .then(awaitBodyEvent(eventName)) >- .catch(reject); >- }, >- }); >- >- suite.addTestCase({ >- name: `DOMDebugger.Event.RemoveDisabledBreakpoint "${eventName}"`, >- description: "Check that a disabled breakpoint can be removed.", >- teardown, >- test(resolve, reject) { >- failOnPause(resolve, eventName, "Should not pause for removed disabled breakpoint."); >- >- addBreakpoint(eventName) >- .then(disableBreakpoint) >- .then(removeBreakpoint) >- .then(awaitBodyEvent(eventName)) >- .catch(reject); >- }, >- }); >- >- } >- >- addTestCasesForEventName("click"); >- addTestCasesForEventName("custom"); >- >- suite.addTestCase({ >- name: `DOMDebugger.Event.AddMultipleBreakpoints`, >- description: "Check that a single breakpoint pauses for every event of that type.", >- teardown, >- test(resolve, reject) { >- let pauseCount = 0; >- >- let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => { >- ++pauseCount; >- >- InspectorTest.pass("Should pause before event handler is run."); >- logActiveStackTrace(); >- >- WI.debuggerManager.resume() >- .catch((reason) => { >- InspectorTest.fail(reason); >- resolve(); >- }); >- >- if (pauseCount >= 2) { >- WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >- >- resolve(); >- } >- }); >- >- addBreakpoint("click") >- .then(() => { >- InspectorTest.log("Firing \"click\" on div#x..."); >- return InspectorTest.evaluateInPage(`xFire_click()`); >- }) >- .catch(reject); >- }, >- }); >- >- suite.runTestCasesAndFinish(); >-} >-</script> >-</head> >-<body onload="runTest()"> >- <p>Tests for Event Listener breakpoints.</p> >- <div id="x"></div> >- <script> >- document.body.addEventListener("click", handleBody_click); >- document.body.addEventListener("custom", handleBody_custom); >- >- document.getElementById("x").addEventListener("click", handleX_click); >- </script> >-</body> >-</html> >diff --git a/LayoutTests/inspector/dom-debugger/event-listener-breakpoints-expected.txt b/LayoutTests/inspector/dom-debugger/event-listener-breakpoints-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..1391e7ff15a3551d6b6b273c0d69caa889bdb6e2 >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-listener-breakpoints-expected.txt >@@ -0,0 +1,83 @@ >+Tests for Event Listener breakpoints. >+ >+ >+== Running test suite: DOMDebugger.Event.Listener >+-- Running test case: DOMDebugger.Event.Listener.AddBreakpoint "click" >+Adding "click" Event Breakpoint... >+Firing "click" on body... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleBody_click >+1: [F] bodyFire_click >+2: [P] Global Code >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.AddDisabledBreakpoint "click" >+Adding "click" Event Breakpoint... >+Disabling "click" Event Breakpoint... >+Firing "click" on body... >+PASS: Should not pause for disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.RemoveBreakpoint "click" >+Adding "click" Event Breakpoint... >+Removing "click" Event Breakpoint... >+Firing "click" on body... >+PASS: Should not pause for removed breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.RemoveDisabledBreakpoint "click" >+Adding "click" Event Breakpoint... >+Disabling "click" Event Breakpoint... >+Removing "click" Event Breakpoint... >+Firing "click" on body... >+PASS: Should not pause for removed disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.AddBreakpoint "custom" >+Adding "custom" Event Breakpoint... >+Firing "custom" on body... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleBody_custom >+1: [F] bodyFire_custom >+2: [P] Global Code >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.AddDisabledBreakpoint "custom" >+Adding "custom" Event Breakpoint... >+Disabling "custom" Event Breakpoint... >+Firing "custom" on body... >+PASS: Should not pause for disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.RemoveBreakpoint "custom" >+Adding "custom" Event Breakpoint... >+Removing "custom" Event Breakpoint... >+Firing "custom" on body... >+PASS: Should not pause for removed breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.RemoveDisabledBreakpoint "custom" >+Adding "custom" Event Breakpoint... >+Disabling "custom" Event Breakpoint... >+Removing "custom" Event Breakpoint... >+Firing "custom" on body... >+PASS: Should not pause for removed disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.AddMultipleBreakpoints >+Adding "click" Event Breakpoint... >+Firing "click" on div#x... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleX_click >+1: [F] xFire_click >+2: [P] Global Code >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleBody_click >+1: [F] xFire_click >+2: [P] Global Code >+-- Running test teardown. >+ >diff --git a/LayoutTests/inspector/dom-debugger/event-listener-breakpoints.html b/LayoutTests/inspector/dom-debugger/event-listener-breakpoints.html >new file mode 100644 >index 0000000000000000000000000000000000000000..e6c599ba7f910c28a22d051f33aa1feb0a1ea9d7 >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-listener-breakpoints.html >@@ -0,0 +1,163 @@ >+<!doctype html> >+<html> >+<head> >+<script src="../../http/tests/inspector/resources/inspector-test.js"></script> >+<script src="../debugger/resources/log-active-stack-trace.js"></script> >+<script src="resources/event-breakpoint-utilities.js"></script> >+<script> >+function handleBody_click(event) { >+ TestPage.dispatchEventToFrontend("TestPage-click"); >+} >+ >+function handleBody_custom(event) { >+ TestPage.dispatchEventToFrontend("TestPage-custom"); >+} >+ >+function handleX_click(event) { >+} >+ >+function bodyFire_click() { >+ document.body.click(); >+} >+ >+function bodyFire_custom() { >+ document.body.dispatchEvent(new Event("custom")); >+} >+ >+function xFire_click() { >+ document.getElementById("x").click(); >+} >+ >+function test() { >+ let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event.Listener"); >+ >+ function addTestCasesForEventName(eventName) { >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Listener.AddBreakpoint "${eventName}"`, >+ description: "Check that the debugger pauses for enabled breakpoints.", >+ teardown, >+ test(resolve, reject) { >+ let paused = false; >+ >+ let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ paused = true; >+ >+ InspectorTest.pass("Should pause before event handler is run."); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume(); >+ }); >+ >+ InspectorTest.singleFireEventListener(`TestPage-${eventName}`, (event) => { >+ if (!paused) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ InspectorTest.fail("Should pause before event handler is run."); >+ } >+ >+ resolve(); >+ }); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Listener, eventName) >+ .then(awaitEvent("body", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Listener.AddDisabledBreakpoint "${eventName}"`, >+ description: "Check that debugger does not pause for disabled breakpoints.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.EventListener, eventName, "Should not pause for disabled breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Listener, eventName) >+ .then(disableBreakpoint) >+ .then(awaitEvent("body", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Listener.RemoveBreakpoint "${eventName}"`, >+ description: "Check that debugger does not pause for removed breakpoint.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.EventListener, eventName, "Should not pause for removed breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Listener, eventName) >+ .then(removeBreakpoint) >+ .then(awaitEvent("body", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Listener.RemoveDisabledBreakpoint "${eventName}"`, >+ description: "Check that a disabled breakpoint can be removed.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.EventListener, eventName, "Should not pause for removed disabled breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Listener, eventName) >+ .then(disableBreakpoint) >+ .then(removeBreakpoint) >+ .then(awaitEvent("body", eventName)) >+ .catch(reject); >+ }, >+ }); >+ } >+ >+ addTestCasesForEventName("click"); >+ addTestCasesForEventName("custom"); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Listener.AddMultipleBreakpoints`, >+ description: "Check that a single breakpoint pauses for every event of that type.", >+ teardown, >+ test(resolve, reject) { >+ let pauseCount = 0; >+ >+ let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ ++pauseCount; >+ >+ InspectorTest.pass("Should pause before event handler is run."); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume() >+ .catch((reason) => { >+ InspectorTest.fail(reason); >+ resolve(); >+ }); >+ >+ if (pauseCount >= 2) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ resolve(); >+ } >+ }); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Listener, "click") >+ .then(() => { >+ InspectorTest.log("Firing \"click\" on div#x..."); >+ return InspectorTest.evaluateInPage(`xFire_click()`); >+ }) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.runTestCasesAndFinish(); >+} >+</script> >+</head> >+<body onload="runTest()"> >+ <p>Tests for Event Listener breakpoints.</p> >+ <div id="x"></div> >+ <script> >+ document.body.addEventListener("click", handleBody_click); >+ document.body.addEventListener("custom", handleBody_custom); >+ >+ document.getElementById("x").addEventListener("click", handleX_click); >+ </script> >+</body> >+</html> >diff --git a/LayoutTests/inspector/dom-debugger/event-timer-breakpoints-expected.txt b/LayoutTests/inspector/dom-debugger/event-timer-breakpoints-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..54c9653072c0a0fed5cceae98777cee1334ac8c5 >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-timer-breakpoints-expected.txt >@@ -0,0 +1,91 @@ >+Tests for Event Timer breakpoints. >+ >+ >+== Running test suite: DOMDebugger.Event.Timer >+-- Running test case: DOMDebugger.Event.Timer.AddBreakpoint "setTimeout" >+Adding "setTimeout" Event Breakpoint... >+Firing "setTimeout" on window... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleWindow_setTimeout >+ASYNC CALL STACK: >+1: --- setTimeout --- >+2: [F] windowFire_setTimeout >+3: [P] Global Code >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Timer.AddDisabledBreakpoint "setTimeout" >+Adding "setTimeout" Event Breakpoint... >+Disabling "setTimeout" Event Breakpoint... >+Firing "setTimeout" on window... >+PASS: Should not pause for disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Timer.RemoveBreakpoint "setTimeout" >+Adding "setTimeout" Event Breakpoint... >+Removing "setTimeout" Event Breakpoint... >+Firing "setTimeout" on window... >+PASS: Should not pause for removed breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Timer.RemoveDisabledBreakpoint "setTimeout" >+Adding "setTimeout" Event Breakpoint... >+Disabling "setTimeout" Event Breakpoint... >+Removing "setTimeout" Event Breakpoint... >+Firing "setTimeout" on window... >+PASS: Should not pause for removed disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Timer.AddBreakpoint "setInterval" >+Adding "setInterval" Event Breakpoint... >+Firing "setInterval" on window... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleWindow_setInterval >+ASYNC CALL STACK: >+1: --- setInterval --- >+2: [F] windowFire_setInterval >+3: [P] Global Code >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Timer.AddDisabledBreakpoint "setInterval" >+Adding "setInterval" Event Breakpoint... >+Disabling "setInterval" Event Breakpoint... >+Firing "setInterval" on window... >+PASS: Should not pause for disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Timer.RemoveBreakpoint "setInterval" >+Adding "setInterval" Event Breakpoint... >+Removing "setInterval" Event Breakpoint... >+Firing "setInterval" on window... >+PASS: Should not pause for removed breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Timer.RemoveDisabledBreakpoint "setInterval" >+Adding "setInterval" Event Breakpoint... >+Disabling "setInterval" Event Breakpoint... >+Removing "setInterval" Event Breakpoint... >+Firing "setInterval" on window... >+PASS: Should not pause for removed disabled breakpoint. >+-- Running test teardown. >+ >+-- Running test case: DOMDebugger.Event.Listener.RepeatFireBreakpoint >+Adding "setInterval" Event Breakpoint... >+Firing "setInterval" on window... >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleRepeat >+ASYNC CALL STACK: >+1: --- setInterval --- >+2: [F] repeatSetInterval >+3: [P] Global Code >+PASS: Should pause before event handler is run. >+CALL STACK: >+0: [F] handleRepeat >+ASYNC CALL STACK: >+1: --- setInterval --- >+2: [F] repeatSetInterval >+3: [P] Global Code >+-- Running test teardown. >+ >diff --git a/LayoutTests/inspector/dom-debugger/event-timer-breakpoints.html b/LayoutTests/inspector/dom-debugger/event-timer-breakpoints.html >new file mode 100644 >index 0000000000000000000000000000000000000000..acc3f90ba4bc920624d015d0ff01324dc4c4aaab >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/event-timer-breakpoints.html >@@ -0,0 +1,171 @@ >+<!doctype html> >+<html> >+<head> >+<script src="../../http/tests/inspector/resources/inspector-test.js"></script> >+<script src="../debugger/resources/log-active-stack-trace.js"></script> >+<script src="resources/event-breakpoint-utilities.js"></script> >+<script> >+ >+let intervalID = NaN; >+ >+function handleWindow_setTimeout() { >+ TestPage.dispatchEventToFrontend("TestPage-setTimeout"); >+} >+ >+function handleWindow_setInterval() { >+ TestPage.dispatchEventToFrontend("TestPage-setInterval"); >+ >+ repeatClearInterval(); >+} >+ >+function handleRepeat() { >+} >+ >+function windowFire_setTimeout() { >+ setTimeout(handleWindow_setTimeout, 100); >+} >+ >+function windowFire_setInterval() { >+ intervalID = setInterval(handleWindow_setInterval, 100); >+} >+ >+function repeatSetInterval() { >+ intervalID = setInterval(handleRepeat, 100); >+} >+ >+function repeatClearInterval() { >+ clearInterval(intervalID); >+ intervalID = NaN; >+} >+ >+function test() { >+ let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event.Timer"); >+ >+ function addTestCasesForEventName(eventName) { >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Timer.AddBreakpoint "${eventName}"`, >+ description: "Check that the debugger pauses for enabled breakpoints.", >+ teardown, >+ test(resolve, reject) { >+ let paused = false; >+ >+ let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ paused = true; >+ >+ InspectorTest.pass("Should pause before event handler is run."); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume(); >+ }); >+ >+ InspectorTest.singleFireEventListener(`TestPage-${eventName}`, (event) => { >+ if (!paused) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ InspectorTest.fail("Should pause before event handler is run."); >+ } >+ >+ resolve(); >+ }); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Timer, eventName) >+ .then(awaitEvent("window", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Timer.AddDisabledBreakpoint "${eventName}"`, >+ description: "Check that debugger does not pause for disabled breakpoints.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.Timer, eventName, "Should not pause for disabled breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Timer, eventName) >+ .then(disableBreakpoint) >+ .then(awaitEvent("window", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Timer.RemoveBreakpoint "${eventName}"`, >+ description: "Check that debugger does not pause for removed breakpoint.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.Timer, eventName, "Should not pause for removed breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Timer, eventName) >+ .then(removeBreakpoint) >+ .then(awaitEvent("window", eventName)) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Timer.RemoveDisabledBreakpoint "${eventName}"`, >+ description: "Check that a disabled breakpoint can be removed.", >+ teardown, >+ test(resolve, reject) { >+ failOnPause(resolve, WI.DebuggerManager.PauseReason.Timer, eventName, "Should not pause for removed disabled breakpoint."); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Timer, eventName) >+ .then(disableBreakpoint) >+ .then(removeBreakpoint) >+ .then(awaitEvent("window", eventName)) >+ .catch(reject); >+ }, >+ }); >+ } >+ >+ addTestCasesForEventName("setTimeout"); >+ addTestCasesForEventName("setInterval"); >+ >+ suite.addTestCase({ >+ name: `DOMDebugger.Event.Listener.RepeatFireBreakpoint`, >+ description: "Check that a single breakpoint pauses multiple times for the same interval.", >+ teardown, >+ test(resolve, reject) { >+ let pauseCount = 0; >+ >+ let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ ++pauseCount; >+ >+ InspectorTest.pass("Should pause before event handler is run."); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume() >+ .catch((reason) => { >+ InspectorTest.fail(reason); >+ resolve(); >+ }); >+ >+ if (pauseCount >= 2) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ InspectorTest.evaluateInPage(`repeatClearInterval()`) >+ .then(resolve) >+ .catch((reason) => { >+ InspectorTest.fail(reason); >+ resolve(); >+ }); >+ } >+ }); >+ >+ addBreakpoint(WI.EventBreakpoint.Type.Timer, "setInterval") >+ .then(() => { >+ InspectorTest.log("Firing \"setInterval\" on window..."); >+ return InspectorTest.evaluateInPage(`repeatSetInterval()`); >+ }) >+ .catch(reject); >+ }, >+ }); >+ >+ suite.runTestCasesAndFinish(); >+} >+</script> >+</head> >+<body onload="runTest()"> >+ <p>Tests for Event Timer breakpoints.</p> >+</body> >+</html> >diff --git a/LayoutTests/inspector/dom-debugger/resources/event-breakpoint-utilities.js b/LayoutTests/inspector/dom-debugger/resources/event-breakpoint-utilities.js >new file mode 100644 >index 0000000000000000000000000000000000000000..7974c8de7cf1302d0d8fc616e717af684798ed25 >--- /dev/null >+++ b/LayoutTests/inspector/dom-debugger/resources/event-breakpoint-utilities.js >@@ -0,0 +1,87 @@ >+TestPage.registerInitializer(() => { >+ window.teardown = function(resolve, reject) { >+ let breakpoints = WI.domDebuggerManager.eventBreakpoints; >+ for (let breakpoint of breakpoints) >+ WI.domDebuggerManager.removeEventBreakpoint(breakpoint); >+ >+ resolve(); >+ }; >+ >+ window.failOnPause = function(resolve, pauseReason, eventName, message) { >+ let paused = false; >+ >+ let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => { >+ paused = true; >+ >+ let targetData = WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target); >+ InspectorTest.assert(targetData.pauseReason === pauseReason, `Pause reason should be "${pauseReason}".`); >+ InspectorTest.assert(targetData.pauseData.eventName === eventName, `Pause data eventName should be "${eventName}".`); >+ >+ InspectorTest.fail(message); >+ logActiveStackTrace(); >+ >+ WI.debuggerManager.resume() >+ .catch((reason) => { >+ InspectorTest.fail(reason); >+ resolve(); >+ }); >+ }); >+ >+ InspectorTest.singleFireEventListener("TestPage-" + eventName, (event) => { >+ if (!paused) { >+ WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener); >+ >+ InspectorTest.pass(message); >+ } >+ >+ resolve(); >+ }); >+ }; >+ >+ window.addBreakpoint = function(type, eventName) { >+ InspectorTest.log(`Adding "${eventName}" Event Breakpoint...`); >+ >+ return new Promise((resolve, reject) => { >+ let breakpoint = new WI.EventBreakpoint(type, eventName); >+ >+ WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded) >+ .then((event) => { >+ InspectorTest.assert(event.data.breakpoint.type === type, `Breakpoint should be for expected type "${type}".`); >+ InspectorTest.assert(event.data.breakpoint.eventName === eventName, `Breakpoint should be for expected event name "${eventName}".`); >+ InspectorTest.assert(!breakpoint.disabled, "Breakpoint should not be disabled initially."); >+ resolve(breakpoint); >+ }); >+ >+ WI.domDebuggerManager.addEventBreakpoint(breakpoint); >+ }); >+ }; >+ >+ window.removeBreakpoint = function(breakpoint) { >+ InspectorTest.log(`Removing "${breakpoint.eventName}" Event Breakpoint...`); >+ >+ return new Promise((resolve, reject) => { >+ WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointRemoved) >+ .then((event) => { >+ InspectorTest.assert(event.data.breakpoint === breakpoint, "Removed Breakpoint should be expected object."); >+ InspectorTest.assert(!WI.domDebuggerManager.eventBreakpoints.includes(breakpoint), "Breakpoint should not be in the list of breakpoints."); >+ resolve(breakpoint); >+ }); >+ >+ WI.domDebuggerManager.removeEventBreakpoint(breakpoint); >+ }); >+ }; >+ >+ window.disableBreakpoint = function(breakpoint) { >+ InspectorTest.log(`Disabling "${breakpoint.eventName}" Event Breakpoint...`); >+ >+ breakpoint.disabled = true; >+ return breakpoint; >+ }; >+ >+ window.awaitEvent = function(context, eventName) { >+ return function() { >+ InspectorTest.log(`Firing "${eventName}" on ${context}...`); >+ return InspectorTest.evaluateInPage(`${context}Fire_${eventName}()`); >+ }; >+ }; >+});
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188778
:
347612
|
347620
|
347622
|
347702
|
347716
|
347755
|
347768
|
347824
|
347907
|
347933
|
347940