Changeset 235248 in webkit


Ignore:
Timestamp:
Aug 23, 2018 2:36:40 PM (6 years ago)
Author:
Devin Rousso
Message:

Web Inspector: support breakpoints for timers and animation-frame events
https://bugs.webkit.org/show_bug.cgi?id=188778

Reviewed by Brian Burg.

Source/JavaScriptCore:

  • 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.

  • inspector/scripts/codegen/generate_cpp_protocol_types_header.py:

(CppProtocolTypesHeaderGenerator.generate_output):
(CppProtocolTypesHeaderGenerator._generate_forward_declarations_for_binding_traits):
(CppProtocolTypesHeaderGenerator._generate_declarations_for_enum_conversion_methods):
(CppProtocolTypesHeaderGenerator._generate_hash_declarations): Added.
Generate DefaultHash for all enum class used by inspector protocols.

  • inspector/scripts/tests/generic/expected/commands-with-async-attribute.json-result:
  • inspector/scripts/tests/generic/expected/commands-with-optional-call-return-parameters.json-result:
  • inspector/scripts/tests/generic/expected/enum-values.json-result:
  • inspector/scripts/tests/generic/expected/type-declaration-array-type.json-result:
  • inspector/scripts/tests/generic/expected/type-declaration-enum-type.json-result:
  • inspector/scripts/tests/generic/expected/type-declaration-object-type.json-result:
  • inspector/scripts/tests/generic/expected/type-requiring-runtime-casts.json-result:

Source/WebCore:

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):

Source/WebInspectorUI:

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.

LayoutTests:

  • 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):

Location:
trunk
Files:
8 added
1 deleted
30 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

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

    r234974 r235248  
    4545            InspectorTest.log("Adding \"load\" Event Breakpoint...");
    4646
    47             let breakpoint = new WI.EventBreakpoint("load");
     47            let breakpoint = new WI.EventBreakpoint(WI.EventBreakpoint.Type.Listener, "load");
    4848
    4949            WI.domDebuggerManager.awaitEvent(WI.DOMDebuggerManager.Event.EventBreakpointAdded)
    5050            .then((event) => {
    51                 InspectorTest.assert(event.data.breakpoint.eventName, "load", "Breakpoint should be for expected event name.");
     51                InspectorTest.assert(event.data.breakpoint.type === WI.EventBreakpoint.Type.Listener, "Breakpoint should be for expected type.");
     52                InspectorTest.assert(event.data.breakpoint.eventName === "load", "Breakpoint should be for expected event name.");
    5253
    5354                InspectorTest.log("Reloading WebInspector...");
  • trunk/LayoutTests/inspector/dom-debugger/event-listener-breakpoints-expected.txt

    r235247 r235248  
    22
    33
    4 == Running test suite: DOMDebugger.Event
    5 -- Running test case: DOMDebugger.Event.AddBreakpoint "click"
     4== Running test suite: DOMDebugger.Event.Listener
     5-- Running test case: DOMDebugger.Event.Listener.AddBreakpoint "click"
    66Adding "click" Event Breakpoint...
    77Firing "click" on body...
     
    99CALL STACK:
    10100: [F] handleBody_click
    11 1: [F] bodyFire_click
     111: [F] trigger_click
    12122: [P] Global Code
    1313-- Running test teardown.
    1414
    15 -- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "click"
     15-- Running test case: DOMDebugger.Event.Listener.AddDisabledBreakpoint "click"
    1616Adding "click" Event Breakpoint...
    1717Disabling "click" Event Breakpoint...
     
    2020-- Running test teardown.
    2121
    22 -- Running test case: DOMDebugger.Event.RemoveBreakpoint "click"
     22-- Running test case: DOMDebugger.Event.Listener.RemoveBreakpoint "click"
    2323Adding "click" Event Breakpoint...
    2424Removing "click" Event Breakpoint...
     
    2727-- Running test teardown.
    2828
    29 -- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "click"
     29-- Running test case: DOMDebugger.Event.Listener.RemoveDisabledBreakpoint "click"
    3030Adding "click" Event Breakpoint...
    3131Disabling "click" Event Breakpoint...
     
    3535-- Running test teardown.
    3636
    37 -- Running test case: DOMDebugger.Event.AddBreakpoint "custom"
     37-- Running test case: DOMDebugger.Event.Listener.AddBreakpoint "custom"
    3838Adding "custom" Event Breakpoint...
    3939Firing "custom" on body...
     
    4141CALL STACK:
    42420: [F] handleBody_custom
    43 1: [F] bodyFire_custom
     431: [F] trigger_custom
    44442: [P] Global Code
    4545-- Running test teardown.
    4646
    47 -- Running test case: DOMDebugger.Event.AddDisabledBreakpoint "custom"
     47-- Running test case: DOMDebugger.Event.Listener.AddDisabledBreakpoint "custom"
    4848Adding "custom" Event Breakpoint...
    4949Disabling "custom" Event Breakpoint...
     
    5252-- Running test teardown.
    5353
    54 -- Running test case: DOMDebugger.Event.RemoveBreakpoint "custom"
     54-- Running test case: DOMDebugger.Event.Listener.RemoveBreakpoint "custom"
    5555Adding "custom" Event Breakpoint...
    5656Removing "custom" Event Breakpoint...
     
    5959-- Running test teardown.
    6060
    61 -- Running test case: DOMDebugger.Event.RemoveDisabledBreakpoint "custom"
     61-- Running test case: DOMDebugger.Event.Listener.RemoveDisabledBreakpoint "custom"
    6262Adding "custom" Event Breakpoint...
    6363Disabling "custom" Event Breakpoint...
     
    6767-- Running test teardown.
    6868
    69 -- Running test case: DOMDebugger.Event.AddMultipleBreakpoints
     69-- Running test case: DOMDebugger.Event.Listener.AddMultipleBreakpoints
    7070Adding "click" Event Breakpoint...
    7171Firing "click" on div#x...
     
    7373CALL STACK:
    74740: [F] handleX_click
    75 1: [F] xFire_click
     751: [F] clickX
    76762: [P] Global Code
    7777PASS: Should pause before event handler is run.
    7878CALL STACK:
    79790: [F] handleBody_click
    80 1: [F] xFire_click
     801: [F] clickX
    81812: [P] Global Code
    8282-- Running test teardown.
  • trunk/Source/JavaScriptCore/ChangeLog

    r235238 r235248  
     12018-08-23  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: support breakpoints for timers and animation-frame events
     4        https://bugs.webkit.org/show_bug.cgi?id=188778
     5
     6        Reviewed by Brian Burg.
     7
     8        * inspector/protocol/Debugger.json:
     9        Add `AnimationFrame` and `Timer` types to the list of pause reasons.
     10
     11        * inspector/protocol/DOMDebugger.json:
     12        Introduced `setEventBreakpoint` and `removeEventBreakpoint` to replace the more specific:
     13         - `setEventListenerBreakpoint`
     14         - `removeEventListenerBreakpoint`
     15         - `setInstrumentationBreakpoint`
     16         - `removeInstrumentationBreakpoint`
     17        Also created an `EventBreakpointType` to enumerate the available types of event breakpoints.
     18
     19        * inspector/scripts/codegen/generate_cpp_protocol_types_header.py:
     20        (CppProtocolTypesHeaderGenerator.generate_output):
     21        (CppProtocolTypesHeaderGenerator._generate_forward_declarations_for_binding_traits):
     22        (CppProtocolTypesHeaderGenerator._generate_declarations_for_enum_conversion_methods):
     23        (CppProtocolTypesHeaderGenerator._generate_hash_declarations): Added.
     24        Generate `DefaultHash` for all `enum class` used by inspector protocols.
     25
     26        * inspector/scripts/tests/generic/expected/commands-with-async-attribute.json-result:
     27        * inspector/scripts/tests/generic/expected/commands-with-optional-call-return-parameters.json-result:
     28        * inspector/scripts/tests/generic/expected/enum-values.json-result:
     29        * inspector/scripts/tests/generic/expected/type-declaration-array-type.json-result:
     30        * inspector/scripts/tests/generic/expected/type-declaration-enum-type.json-result:
     31        * inspector/scripts/tests/generic/expected/type-declaration-object-type.json-result:
     32        * inspector/scripts/tests/generic/expected/type-requiring-runtime-casts.json-result:
     33
    1342018-08-23  Michael Saboff  <msaboff@apple.com>
    235
  • trunk/Source/JavaScriptCore/inspector/protocol/DOMDebugger.json

    r224634 r235248  
    99            "enum": ["subtree-modified", "attribute-modified", "node-removed"],
    1010            "description": "DOM breakpoint type."
     11        },
     12        {
     13            "id": "EventBreakpointType",
     14            "type": "string",
     15            "enum": ["animation-frame", "listener", "timer"],
     16            "description": "Event breakpoint type."
    1117        }
    1218    ],
     
    2935        },
    3036        {
    31             "name": "setEventListenerBreakpoint",
    32             "description": "Sets breakpoint on particular DOM event.",
     37            "name": "setEventBreakpoint",
     38            "description": "Sets breakpoint on particular event of given type.",
    3339            "parameters": [
    34                 { "name": "eventName", "type": "string", "description": "DOM Event name to stop on (any DOM event will do)." }
     40                { "name": "breakpointType", "$ref": "EventBreakpointType" },
     41                { "name": "eventName", "type": "string", "description": "The name of the event to stop on." }
    3542            ]
    3643        },
    3744        {
    38             "name": "removeEventListenerBreakpoint",
    39             "description": "Removes breakpoint on particular DOM event.",
     45            "name": "removeEventBreakpoint",
     46            "description": "Removes breakpoint on particular event of given type.",
    4047            "parameters": [
    41                 { "name": "eventName", "type": "string", "description": "Event name." }
    42             ]
    43         },
    44         {
    45             "name": "setInstrumentationBreakpoint",
    46             "description": "Sets breakpoint on particular native event.",
    47             "parameters": [
    48                 { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." }
    49             ]
    50         },
    51         {
    52             "name": "removeInstrumentationBreakpoint",
    53             "description": "Sets breakpoint on particular native event.",
    54             "parameters": [
    55                 { "name": "eventName", "type": "string", "description": "Instrumentation name to stop on." }
     48                { "name": "breakpointType", "$ref": "EventBreakpointType" },
     49                { "name": "eventName", "type": "string", "description": "The name of the event to stop on." }
    5650            ]
    5751        },
  • trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json

    r233655 r235248  
    342342            "parameters": [
    343343                { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." },
    344                 { "name": "reason", "type": "string", "enum": ["XHR", "DOM", "EventListener", "exception", "assert", "CSPViolation", "DebuggerStatement", "Breakpoint", "PauseOnNextStatement", "other"], "description": "Pause reason." },
     344                { "name": "reason", "type": "string", "enum": ["XHR", "DOM", "AnimationFrame", "EventListener", "Timer", "exception", "assert", "CSPViolation", "DebuggerStatement", "Breakpoint", "PauseOnNextStatement", "other"], "description": "Pause reason." },
    345345                { "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." },
    346346                { "name": "asyncStackTrace", "$ref": "Console.StackTrace", "optional": true, "description": "Linked list of asynchronous StackTraces." }
  • trunk/Source/JavaScriptCore/inspector/scripts/codegen/generate_cpp_protocol_types_header.py

    r233122 r235248  
    6565        builder_sections = map(self._generate_builders_for_domain, domains)
    6666        sections.extend(filter(lambda section: len(section) > 0, builder_sections))
    67         sections.append(self._generate_forward_declarations_for_binding_traits())
    68         sections.extend(self._generate_declarations_for_enum_conversion_methods())
     67        sections.append(self._generate_forward_declarations_for_binding_traits(domains))
     68        sections.extend(self._generate_declarations_for_enum_conversion_methods(domains))
    6969        sections.append('} // namespace Protocol')
    7070        sections.append(Template(CppTemplates.HeaderPostlude).substitute(None, **header_args))
     71        sections.extend(self._generate_hash_declarations(domains))
    7172        return "\n\n".join(sections)
    7273
     
    338339        return '\n'.join(lines)
    339340
    340     def _generate_forward_declarations_for_binding_traits(self):
     341    def _generate_forward_declarations_for_binding_traits(self, domains):
    341342        # A list of (builder_type, needs_runtime_cast)
    342343        type_arguments = []
    343344
    344         for domain in self.domains_to_generate():
     345        for domain in domains:
    345346            type_declarations = self.type_declarations_for_domain(domain)
    346347            declarations_to_generate = filter(lambda decl: self.type_needs_shape_assertions(decl.type), type_declarations)
     
    370371        return '\n'.join(lines)
    371372
    372     def _generate_declarations_for_enum_conversion_methods(self):
     373    def _generate_declarations_for_enum_conversion_methods(self, domains):
    373374        sections = []
    374375        sections.append('\n'.join([
     
    390391            return isinstance(type_member.type, EnumType) and type_member.type.is_anonymous
    391392
    392         for domain in self.domains_to_generate():
     393        for domain in domains:
    393394            type_declarations = self.type_declarations_for_domain(domain)
    394395            declaration_types = [decl.type for decl in type_declarations]
     
    425426
    426427        return ['\n\n'.join(sections)]
     428
     429    def _generate_hash_declarations(self, domains):
     430        lines = []
     431
     432        for domain in domains:
     433            type_declarations = self.type_declarations_for_domain(domain)
     434            declaration_types = [decl.type for decl in type_declarations]
     435            enum_types = filter(lambda _type: isinstance(_type, EnumType), declaration_types)
     436
     437            if len(enum_types) == 0:
     438                continue
     439
     440            if len(lines) == 0:
     441                lines.append('namespace WTF {')
     442                lines.append('')
     443                lines.append('template<typename T> struct DefaultHash;')
     444
     445            lines.append('')
     446            lines.append("// Hash declarations in the '%s' Domain" % domain.domain_name)
     447
     448            for enum_type in enum_types:
     449                lines.append('template<>')
     450                lines.append('struct DefaultHash<Inspector::Protocol::%s::%s> {' % (domain.domain_name, enum_type.raw_name()))
     451                lines.append('    typedef IntHash<Inspector::Protocol::%s::%s> Hash;' % (domain.domain_name, enum_type.raw_name()))
     452                lines.append('};')
     453
     454        if len(lines) == 0:
     455            return []
     456
     457        lines.append('')
     458        lines.append('} // namespace WTF')
     459        return ['\n'.join(lines)]
  • trunk/Source/JavaScriptCore/inspector/scripts/tests/generic/expected/commands-with-async-attribute.json-result

    r233122 r235248  
    721721
    722722} // namespace Inspector
     723
     724namespace WTF {
     725
     726template<typename T> struct DefaultHash;
     727
     728// Hash declarations in the 'Database' Domain
     729template<>
     730struct DefaultHash<Inspector::Protocol::Database::PrimaryColors> {
     731    typedef IntHash<Inspector::Protocol::Database::PrimaryColors> Hash;
     732};
     733
     734} // namespace WTF
    723735### End File: TestProtocolObjects.h
    724736
  • trunk/Source/JavaScriptCore/inspector/scripts/tests/generic/expected/commands-with-optional-call-return-parameters.json-result

    r233122 r235248  
    636636
    637637} // namespace Inspector
     638
     639namespace WTF {
     640
     641template<typename T> struct DefaultHash;
     642
     643// Hash declarations in the 'Database' Domain
     644template<>
     645struct DefaultHash<Inspector::Protocol::Database::PrimaryColors> {
     646    typedef IntHash<Inspector::Protocol::Database::PrimaryColors> Hash;
     647};
     648
     649} // namespace WTF
    638650### End File: TestProtocolObjects.h
    639651
  • trunk/Source/JavaScriptCore/inspector/scripts/tests/generic/expected/enum-values.json-result

    r233122 r235248  
    484484
    485485} // namespace Inspector
     486
     487namespace WTF {
     488
     489template<typename T> struct DefaultHash;
     490
     491// Hash declarations in the 'TypeDomain' Domain
     492template<>
     493struct DefaultHash<Inspector::Protocol::TypeDomain::TypeDomainEnum> {
     494    typedef IntHash<Inspector::Protocol::TypeDomain::TypeDomainEnum> Hash;
     495};
     496
     497} // namespace WTF
    486498### End File: TestProtocolObjects.h
    487499
  • trunk/Source/JavaScriptCore/inspector/scripts/tests/generic/expected/type-declaration-array-type.json-result

    r233122 r235248  
    376376
    377377} // namespace Inspector
     378
     379namespace WTF {
     380
     381template<typename T> struct DefaultHash;
     382
     383// Hash declarations in the 'Debugger' Domain
     384template<>
     385struct DefaultHash<Inspector::Protocol::Debugger::Reason> {
     386    typedef IntHash<Inspector::Protocol::Debugger::Reason> Hash;
     387};
     388
     389} // namespace WTF
    378390### End File: TestProtocolObjects.h
    379391
  • trunk/Source/JavaScriptCore/inspector/scripts/tests/generic/expected/type-declaration-enum-type.json-result

    r233122 r235248  
    375375
    376376} // namespace Inspector
     377
     378namespace WTF {
     379
     380template<typename T> struct DefaultHash;
     381
     382// Hash declarations in the 'Runtime' Domain
     383template<>
     384struct DefaultHash<Inspector::Protocol::Runtime::FarmAnimals> {
     385    typedef IntHash<Inspector::Protocol::Runtime::FarmAnimals> Hash;
     386};
     387template<>
     388struct DefaultHash<Inspector::Protocol::Runtime::TwoLeggedAnimals> {
     389    typedef IntHash<Inspector::Protocol::Runtime::TwoLeggedAnimals> Hash;
     390};
     391
     392} // namespace WTF
    377393### End File: TestProtocolObjects.h
    378394
  • trunk/Source/JavaScriptCore/inspector/scripts/tests/generic/expected/type-declaration-object-type.json-result

    r233122 r235248  
    898898
    899899} // namespace Inspector
     900
     901namespace WTF {
     902
     903template<typename T> struct DefaultHash;
     904
     905// Hash declarations in the 'Database' Domain
     906template<>
     907struct DefaultHash<Inspector::Protocol::Database::MouseButton> {
     908    typedef IntHash<Inspector::Protocol::Database::MouseButton> Hash;
     909};
     910
     911} // namespace WTF
    900912### End File: TestProtocolObjects.h
    901913
  • trunk/Source/JavaScriptCore/inspector/scripts/tests/generic/expected/type-requiring-runtime-casts.json-result

    r233122 r235248  
    589589
    590590} // namespace Inspector
     591
     592namespace WTF {
     593
     594template<typename T> struct DefaultHash;
     595
     596// Hash declarations in the 'Test' Domain
     597template<>
     598struct DefaultHash<Inspector::Protocol::Test::UncastedAnimals> {
     599    typedef IntHash<Inspector::Protocol::Test::UncastedAnimals> Hash;
     600};
     601template<>
     602struct DefaultHash<Inspector::Protocol::Test::CastedAnimals> {
     603    typedef IntHash<Inspector::Protocol::Test::CastedAnimals> Hash;
     604};
     605
     606} // namespace WTF
    591607### End File: TestProtocolObjects.h
    592608
  • trunk/Source/WebCore/ChangeLog

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

    r235103 r235248  
    7777using namespace Inspector;
    7878
    79 static const char* const requestAnimationFrameEventName = "requestAnimationFrame";
    80 static const char* const cancelAnimationFrameEventName = "cancelAnimationFrame";
    81 static const char* const animationFrameFiredEventName = "animationFrameFired";
    82 static const char* const setTimerEventName = "setTimer";
    83 static const char* const clearTimerEventName = "clearTimer";
    84 static const char* const timerFiredEventName = "timerFired";
    85 
    8679namespace {
    8780static HashSet<InstrumentingAgents*>* s_instrumentingAgentsSet = nullptr;
     
    295288void InspectorInstrumentation::didInstallTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, Seconds timeout, bool singleShot, ScriptExecutionContext& context)
    296289{
    297     pauseOnNativeEventIfNeeded(instrumentingAgents, setTimerEventName, true);
    298 
    299290    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent())
    300291        debuggerAgent->didScheduleAsyncCall(context.execState(), InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId, singleShot);
     
    306297void InspectorInstrumentation::didRemoveTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, ScriptExecutionContext& context)
    307298{
    308     pauseOnNativeEventIfNeeded(instrumentingAgents, clearTimerEventName, true);
    309 
    310299    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent())
    311300        debuggerAgent->didCancelAsyncCall(InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId);
     
    444433}
    445434
    446 InspectorInstrumentationCookie InspectorInstrumentation::willFireTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, ScriptExecutionContext& context)
    447 {
    448     pauseOnNativeEventIfNeeded(instrumentingAgents, timerFiredEventName, false);
    449 
     435InspectorInstrumentationCookie InspectorInstrumentation::willFireTimerImpl(InstrumentingAgents& instrumentingAgents, int timerId, bool oneShot, ScriptExecutionContext& context)
     436{
    450437    if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent())
    451438        debuggerAgent->willDispatchAsyncCall(InspectorDebuggerAgent::AsyncCallType::DOMTimer, timerId);
     439
     440    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent())
     441        domDebuggerAgent->willFireTimer(oneShot);
    452442
    453443    int timelineAgentId = 0;
     
    10451035}
    10461036
    1047 void InspectorInstrumentation::pauseOnNativeEventIfNeeded(InstrumentingAgents& instrumentingAgents, const String& eventName, bool synchronous)
    1048 {
    1049     if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent())
    1050         domDebuggerAgent->pauseOnNativeEventIfNeeded(eventName, synchronous);
    1051 }
    1052 
    10531037void InspectorInstrumentation::didRequestAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document)
    10541038{
    1055     pauseOnNativeEventIfNeeded(instrumentingAgents, requestAnimationFrameEventName, true);
    1056 
    10571039    if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent())
    10581040        pageDebuggerAgent->didRequestAnimationFrame(callbackId, document);
     
    10631045void InspectorInstrumentation::didCancelAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document)
    10641046{
    1065     pauseOnNativeEventIfNeeded(instrumentingAgents, cancelAnimationFrameEventName, true);
    1066 
    10671047    if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent())
    10681048        pageDebuggerAgent->didCancelAnimationFrame(callbackId);
     
    10731053InspectorInstrumentationCookie InspectorInstrumentation::willFireAnimationFrameImpl(InstrumentingAgents& instrumentingAgents, int callbackId, Document& document)
    10741054{
    1075     pauseOnNativeEventIfNeeded(instrumentingAgents, animationFrameFiredEventName, false);
    1076 
    10771055    if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent())
    10781056        pageDebuggerAgent->willFireAnimationFrame(callbackId);
     1057
     1058    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent())
     1059        domDebuggerAgent->willFireAnimationFrame();
    10791060
    10801061    int timelineAgentId = 0;
  • trunk/Source/WebCore/inspector/InspectorInstrumentation.h

    r235103 r235248  
    158158    static InspectorInstrumentationCookie willEvaluateScript(Frame&, const String& url, int lineNumber);
    159159    static void didEvaluateScript(const InspectorInstrumentationCookie&, Frame&);
    160     static InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext&, int timerId);
     160    static InspectorInstrumentationCookie willFireTimer(ScriptExecutionContext&, int timerId, bool oneShot);
    161161    static void didFireTimer(const InspectorInstrumentationCookie&);
    162162    static void didInvalidateLayout(Frame&);
     
    342342    static InspectorInstrumentationCookie willEvaluateScriptImpl(InstrumentingAgents&, Frame&, const String& url, int lineNumber);
    343343    static void didEvaluateScriptImpl(const InspectorInstrumentationCookie&, Frame&);
    344     static InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents&, int timerId, ScriptExecutionContext&);
     344    static InspectorInstrumentationCookie willFireTimerImpl(InstrumentingAgents&, int timerId, bool oneShot, ScriptExecutionContext&);
    345345    static void didFireTimerImpl(const InspectorInstrumentationCookie&);
    346346    static void didInvalidateLayoutImpl(InstrumentingAgents&, Frame&);
     
    454454    static InspectorTimelineAgent* retrieveTimelineAgent(const InspectorInstrumentationCookie&);
    455455
    456     static void pauseOnNativeEventIfNeeded(InstrumentingAgents&, const String& eventName, bool synchronous);
    457 
    458456    WEBCORE_EXPORT static int s_frontendCounter;
    459457};
     
    808806}
    809807
    810 inline InspectorInstrumentationCookie InspectorInstrumentation::willFireTimer(ScriptExecutionContext& context, int timerId)
     808inline InspectorInstrumentationCookie InspectorInstrumentation::willFireTimer(ScriptExecutionContext& context, int timerId, bool oneShot)
    811809{
    812810    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
    813811    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
    814         return willFireTimerImpl(*instrumentingAgents, timerId, context);
     812        return willFireTimerImpl(*instrumentingAgents, timerId, oneShot, context);
    815813    return InspectorInstrumentationCookie();
    816814}
  • trunk/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp

    r235103 r235248  
    5353};
    5454
    55 static const char eventNameCategoryType[] = "event-name:";
    56 static const char instrumentationCategoryType[] = "instrumentation:";
    57 
    5855const uint32_t inheritableDOMBreakpointTypesMask = (1 << SubtreeModified);
    5956const int domBreakpointDerivedTypeShift = 16;
     
    127124}
    128125
    129 void InspectorDOMDebuggerAgent::setEventListenerBreakpoint(ErrorString& error, const String& eventName)
    130 {
    131     setBreakpoint(error, eventNameCategoryType + eventName);
    132 }
    133 
    134 void InspectorDOMDebuggerAgent::setInstrumentationBreakpoint(ErrorString& error, const String& eventName)
    135 {
    136     setBreakpoint(error, instrumentationCategoryType + eventName);
    137 }
    138 
    139 void InspectorDOMDebuggerAgent::setBreakpoint(ErrorString& error, const String& eventName)
    140 {
     126void InspectorDOMDebuggerAgent::setEventBreakpoint(ErrorString& error, const String& breakpointTypeString, const String& eventName)
     127{
     128    if (breakpointTypeString.isEmpty()) {
     129        error = "Event breakpoint type is empty"_s;
     130        return;
     131    }
     132
     133    auto breakpointType = Inspector::Protocol::InspectorHelpers::parseEnumValueFromString<Inspector::Protocol::DOMDebugger::EventBreakpointType>(breakpointTypeString);
     134    if (!breakpointType) {
     135        error = makeString("Unknown event breakpoint type: "_s, breakpointTypeString);
     136        return;
     137    }
     138
    141139    if (eventName.isEmpty()) {
    142140        error = "Event name is empty"_s;
     
    144142    }
    145143
    146     m_eventListenerBreakpoints.add(eventName);
    147 }
    148 
    149 void InspectorDOMDebuggerAgent::removeEventListenerBreakpoint(ErrorString& error, const String& eventName)
    150 {
    151     removeBreakpoint(error, eventNameCategoryType + eventName);
    152 }
    153 
    154 void InspectorDOMDebuggerAgent::removeInstrumentationBreakpoint(ErrorString& error, const String& eventName)
    155 {
    156     removeBreakpoint(error, instrumentationCategoryType + eventName);
    157 }
    158 
    159 void InspectorDOMDebuggerAgent::removeBreakpoint(ErrorString& error, const String& eventName)
    160 {
     144    m_eventBreakpoints.add(std::make_pair(*breakpointType, eventName));
     145}
     146
     147void InspectorDOMDebuggerAgent::removeEventBreakpoint(ErrorString& error, const String& breakpointTypeString, const String& eventName)
     148{
     149    if (breakpointTypeString.isEmpty()) {
     150        error = "Event breakpoint type is empty"_s;
     151        return;
     152    }
     153
     154    auto breakpointType = Inspector::Protocol::InspectorHelpers::parseEnumValueFromString<Inspector::Protocol::DOMDebugger::EventBreakpointType>(breakpointTypeString);
     155    if (!breakpointType) {
     156        error = makeString("Unknown event breakpoint type: "_s, breakpointTypeString);
     157        return;
     158    }
     159
    161160    if (eventName.isEmpty()) {
    162161        error = "Event name is empty"_s;
     
    164163    }
    165164
    166     m_eventListenerBreakpoints.remove(eventName);
     165    m_eventBreakpoints.remove(std::make_pair(*breakpointType, eventName));
    167166}
    168167
     
    367366void InspectorDOMDebuggerAgent::willHandleEvent(const Event& event, const RegisteredEventListener& registeredEventListener)
    368367{
    369     bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventListenerBreakpoints.contains(eventNameCategoryType + event.type());
     368    bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(std::make_pair(Inspector::Protocol::DOMDebugger::EventBreakpointType::Listener, event.type()));
    370369
    371370    if (!shouldPause && m_domAgent)
     
    386385}
    387386
    388 void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(const String& eventName, bool synchronous)
    389 {
    390     bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventListenerBreakpoints.contains(instrumentationCategoryType + eventName);
     387void InspectorDOMDebuggerAgent::willFireTimer(bool oneShot)
     388{
     389    String eventName = oneShot ? "setTimeout"_s : "setInterval"_s;
     390    bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(std::make_pair(Inspector::Protocol::DOMDebugger::EventBreakpointType::Timer, eventName));
    391391    if (!shouldPause)
    392392        return;
     
    394394    Ref<JSON::Object> eventData = JSON::Object::create();
    395395    eventData->setString("eventName"_s, eventName);
    396 
    397     if (synchronous)
    398         m_debuggerAgent->breakProgram(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData));
    399     else
    400         m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData));
     396    m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::Timer, WTFMove(eventData));
     397}
     398
     399void InspectorDOMDebuggerAgent::willFireAnimationFrame()
     400{
     401    String eventName = "requestAnimationFrame"_s;
     402    bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(std::make_pair(Inspector::Protocol::DOMDebugger::EventBreakpointType::AnimationFrame, eventName));
     403    if (!shouldPause)
     404        return;
     405
     406    Ref<JSON::Object> eventData = JSON::Object::create();
     407    eventData->setString("eventName"_s, eventName);
     408    m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::AnimationFrame, WTFMove(eventData));
    401409}
    402410
  • trunk/Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.h

    r235103 r235248  
    6060    void setXHRBreakpoint(ErrorString&, const String& url, const bool* optionalIsRegex) final;
    6161    void removeXHRBreakpoint(ErrorString&, const String& url) final;
    62     void setEventListenerBreakpoint(ErrorString&, const String& eventName) final;
    63     void removeEventListenerBreakpoint(ErrorString&, const String& eventName) final;
    64     void setInstrumentationBreakpoint(ErrorString&, const String& eventName) final;
    65     void removeInstrumentationBreakpoint(ErrorString&, const String& eventName) final;
     62    void setEventBreakpoint(ErrorString&, const String& breakpointType, const String& eventName) final;
     63    void removeEventBreakpoint(ErrorString&, const String& breakpointType, const String& eventName) final;
    6664    void setDOMBreakpoint(ErrorString&, int nodeId, const String& type) final;
    6765    void removeDOMBreakpoint(ErrorString&, int nodeId, const String& type) final;
     
    7775    void frameDocumentUpdated(Frame&);
    7876    void willHandleEvent(const Event&, const RegisteredEventListener&);
    79     void pauseOnNativeEventIfNeeded(const String& eventName, bool synchronous);
     77    void willFireTimer(bool oneShot);
     78    void willFireAnimationFrame();
    8079    void mainFrameDOMContentLoaded();
    8180
     
    9493    bool hasBreakpoint(Node*, int type);
    9594    void discardBindings();
    96     void setBreakpoint(ErrorString&, const String& eventName);
    97     void removeBreakpoint(ErrorString&, const String& eventName);
    9895
    9996    RefPtr<Inspector::DOMDebuggerBackendDispatcher> m_backendDispatcher;
     
    10299
    103100    HashMap<Node*, uint32_t> m_domBreakpoints;
    104     HashSet<String> m_eventListenerBreakpoints;
     101
     102    using EventBreakpointType = Inspector::Protocol::DOMDebugger::EventBreakpointType;
     103    HashSet<std::pair<EventBreakpointType, String>,
     104        WTF::PairHash<EventBreakpointType, String>,
     105        WTF::PairHashTraits<WTF::StrongEnumHashTraits<EventBreakpointType>, WTF::HashTraits<String>>
     106    > m_eventBreakpoints;
    105107
    106108    enum class XHRBreakpointType { Text, RegularExpression };
  • trunk/Source/WebCore/page/DOMTimer.cpp

    r229209 r235248  
    322322    m_userGestureTokenToForward = nullptr;
    323323
    324     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId);
     324    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId, !repeatInterval());
    325325
    326326    // Simple case for non-one-shot timers.
  • trunk/Source/WebInspectorUI/ChangeLog

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

    r235103 r235248  
    4242localizedStrings["%s (hidden)"] = "%s (hidden)";
    4343localizedStrings["%s Event Dispatched"] = "%s Event Dispatched";
     44localizedStrings["%s Fired"] = "%s Fired";
    4445localizedStrings["%s Prototype"] = "%s Prototype";
    4546localizedStrings["%s \u2013 %s"] = "%s \u2013 %s";
     
    147148localizedStrings["Box Shadow"] = "Box Shadow";
    148149localizedStrings["Break on events with name:"] = "Break on events with name:";
    149 localizedStrings["Break on listeners for event with name:"] = "Break on listeners for event with name:";
    150150localizedStrings["Break on request with URL:"] = "Break on request with URL:";
    151151localizedStrings["Break on…"] = "Break on…";
     
    275275localizedStrings["DOM Breakpoints"] = "DOM Breakpoints";
    276276localizedStrings["DOM Content Loaded \u2014 %s"] = "DOM Content Loaded \u2014 %s";
     277localizedStrings["DOM Event"] = "DOM Event";
    277278localizedStrings["Damping"] = "Damping";
    278279localizedStrings["Dash Array"] = "Dash Array";
     
    404405localizedStrings["Event Listeners"] = "Event Listeners";
    405406localizedStrings["Events"] = "Events";
     407localizedStrings["Example: “%s”"] = "Example: “%s”";
    406408localizedStrings["Exception with thrown value: %s"] = "Exception with thrown value: %s";
    407409localizedStrings["Expand All"] = "Expand All";
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMDebuggerManager.js

    r235103 r235248  
    7979    }
    8080
     81    // Static
     82
     83    static supportsEventBreakpoints()
     84    {
     85        return DOMDebuggerAgent.setEventBreakpoint && DOMDebuggerAgent.removeEventBreakpoint;
     86    }
     87
    8188    // Public
    8289
     
    194201    }
    195202
    196     eventBreakpointForEventName(eventName)
    197     {
    198         return this._eventBreakpoints.find((breakpoint) => breakpoint.eventName === eventName) || null;
     203    eventBreakpointForTypeAndEventName(type, eventName)
     204    {
     205        return this._eventBreakpoints.find((breakpoint) => breakpoint.type === type && breakpoint.eventName === eventName) || null;
    199206    }
    200207
     
    205212            return;
    206213
    207         if (this._eventBreakpoints.some((item) => item.eventName === breakpoint.eventName))
     214        if (this.eventBreakpointForTypeAndEventName(breakpoint.type, breakpoint.eventName))
    208215            return;
    209216
     
    233240            return;
    234241
    235         DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, (error) => {
     242        function breakpointRemoved(error) {
    236243            if (error)
    237244                console.error(error);
    238         });
     245        }
     246
     247        // Compatibility (iOS 12): DOMDebuggerAgent.removeEventBreakpoint did not exist.
     248        if (!WI.DOMDebuggerManager.supportsEventBreakpoints()) {
     249            console.assert(breakpoint.type === WI.EventBreakpoint.Type.Listener);
     250            DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointRemoved);
     251            return;
     252        }
     253
     254        DOMDebuggerAgent.removeEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointRemoved);
    239255    }
    240256
     
    416432        }
    417433
     434        // Compatibility (iOS 12): DOMDebuggerAgent.removeEventBreakpoint did not exist.
     435        if (!WI.DOMDebuggerManager.supportsEventBreakpoints()) {
     436            console.assert(breakpoint.type === WI.EventBreakpoint.Type.Listener);
     437            if (breakpoint.disabled)
     438                DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
     439            else
     440                DOMDebuggerAgent.setEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
     441            return;
     442        }
     443
    418444        if (breakpoint.disabled)
    419             DOMDebuggerAgent.removeEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
     445            DOMDebuggerAgent.removeEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointUpdated);
    420446        else
    421             DOMDebuggerAgent.setEventListenerBreakpoint(breakpoint.eventName, breakpointUpdated);
     447            DOMDebuggerAgent.setEventBreakpoint(breakpoint.type, breakpoint.eventName, breakpointUpdated);
    422448    }
    423449
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/DOMTreeManager.js

    r235103 r235248  
    557557    setBreakpointForEventListener(eventListener)
    558558    {
    559         let breakpoint = new WI.EventBreakpoint(eventListener.type, {eventListener});
     559        let breakpoint = new WI.EventBreakpoint(WI.EventBreakpoint.Type.Listener, eventListener.type, {eventListener});
    560560        this._breakpointsForEventListeners.set(eventListener.eventListenerId, breakpoint);
    561561
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js

    r234974 r235248  
    819819        // FIXME: Handle other backend pause reasons.
    820820        switch (payload) {
     821        case DebuggerAgent.PausedReason.AnimationFrame:
     822            return WI.DebuggerManager.PauseReason.AnimationFrame;
    821823        case DebuggerAgent.PausedReason.Assert:
    822824            return WI.DebuggerManager.PauseReason.Assertion;
     
    835837        case DebuggerAgent.PausedReason.PauseOnNextStatement:
    836838            return WI.DebuggerManager.PauseReason.PauseOnNextStatement;
     839        case DebuggerAgent.PausedReason.Timer:
     840            return WI.DebuggerManager.PauseReason.Timer;
    837841        case DebuggerAgent.PausedReason.XHR:
    838842            return WI.DebuggerManager.PauseReason.XHR;
     
    12341238
    12351239WI.DebuggerManager.PauseReason = {
     1240    AnimationFrame: "animation-frame",
    12361241    Assertion: "assertion",
    12371242    Breakpoint: "breakpoint",
     
    12421247    Exception: "exception",
    12431248    PauseOnNextStatement: "pause-on-next-statement",
     1249    Timer: "timer",
    12441250    XHR: "xhr",
    12451251    Other: "other",
  • trunk/Source/WebInspectorUI/UserInterface/Models/EventBreakpoint.js

    r235103 r235248  
    2626WI.EventBreakpoint = class EventBreakpoint extends WI.Object
    2727{
    28     constructor(eventName, {disabled, eventListener} = {})
     28    constructor(type, eventName, {disabled, eventListener} = {})
    2929    {
    3030        super();
    3131
     32        console.assert(typeof type === "string");
     33        console.assert(Object.values(WI.EventBreakpoint.Type).includes(type));
    3234        console.assert(typeof eventName === "string");
    3335
     36        this._type = type;
    3437        this._eventName = eventName;
    3538
     
    4245    static fromPayload(payload)
    4346    {
    44         return new WI.EventBreakpoint(payload.eventName, {
     47        return new WI.EventBreakpoint(payload.type, payload.eventName, {
    4548            disabled: !!payload.disabled,
    4649        });
     
    4952    // Public
    5053
     54    get type() { return this._type; }
    5155    get eventName() { return this._eventName; }
    5256    get eventListener() { return this._eventListener; }
     
    7074    {
    7175        let info = {
     76            type: this._type,
    7277            eventName: this._eventName,
    7378        };
     
    8085    saveIdentityToCookie(cookie)
    8186    {
     87        cookie[WI.EventBreakpoint.TypeCookieKey] = this._type;
    8288        cookie[WI.EventBreakpoint.EventNameCookieKey] = this._eventName;
    8389    }
    8490};
    8591
     92WI.EventBreakpoint.Type = {
     93    AnimationFrame: "animation-frame",
     94    Listener: "listener",
     95    Timer: "timer",
     96};
     97
     98WI.EventBreakpoint.TypeCookieKey = "event-breakpoint-type";
    8699WI.EventBreakpoint.EventNameCookieKey = "event-breakpoint-event-name";
    87100
  • trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js

    r235183 r235248  
    952952
    953953        switch (pauseReason) {
     954        case WI.DebuggerManager.PauseReason.AnimationFrame:
     955            console.assert(pauseData, "Expected data with an animation frame, but found none.");
     956            if (!pauseData)
     957                return false;
     958
     959            var eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.AnimationFrame, pauseData.eventName);
     960            console.assert(eventBreakpoint, "Expected AnimationFrame breakpoint for event name.", pauseData.eventName);
     961            if (!eventBreakpoint)
     962                return false;
     963
     964            var suppressFiltering = true;
     965            this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering);
     966
     967            var eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
     968                className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
     969                title: WI.UIString("%s Fired").format(pauseData.eventName),
     970            });
     971            this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
     972
     973            var eventBreakpointRow = new WI.DetailsSectionRow;
     974            eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
     975
     976            this._pauseReasonGroup.rows = [eventBreakpointRow];
     977            return true;
     978
    954979        case WI.DebuggerManager.PauseReason.Assertion:
    955980            // FIXME: We should include the assertion condition string.
     
    10571082        case WI.DebuggerManager.PauseReason.EventListener:
    10581083            console.assert(pauseData, "Expected data with an event listener, but found none.");
    1059             if (pauseData) {
    1060                 let eventBreakpoint = null;
    1061                 if (pauseData.eventListenerId)
    1062                     eventBreakpoint = WI.domTreeManager.breakpointForEventListenerId(pauseData.eventListenerId);
    1063                 if (!eventBreakpoint)
    1064                     eventBreakpoint = WI.domDebuggerManager.eventBreakpointForEventName(pauseData.eventName);
    1065                 console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName);
    1066 
    1067                 this._pauseReasonTreeOutline = this.createContentTreeOutline(true);
    1068 
    1069                 let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
    1070                     className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
    1071                     title: WI.UIString("“%s“ Event Fired").format(pauseData.eventName),
    1072                 });
    1073                 this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
    1074 
    1075                 let eventBreakpointRow = new WI.DetailsSectionRow;
    1076                 eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
    1077 
    1078                 let rows = [eventBreakpointRow];
    1079 
    1080                 let eventListener = eventBreakpoint.eventListener;
    1081                 if (eventListener) {
    1082                     console.assert(eventListener.eventListenerId === pauseData.eventListenerId);
    1083 
    1084                     let ownerElementRow = new WI.DetailsSectionSimpleRow(WI.UIString("Element"), WI.linkifyNodeReference(eventListener.node));
    1085                     rows.push(ownerElementRow);
    1086                 }
    1087 
    1088                 this._pauseReasonGroup.rows = rows;
     1084            if (!pauseData)
     1085                return false;
     1086
     1087            var eventBreakpoint = null;
     1088            if (pauseData.eventListenerId)
     1089                eventBreakpoint = WI.domTreeManager.breakpointForEventListenerId(pauseData.eventListenerId);
     1090            if (!eventBreakpoint)
     1091                eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.Listener, pauseData.eventName);
     1092
     1093            console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName);
     1094            if (!eventBreakpoint)
     1095                return false;
     1096
     1097            var suppressFiltering = true;
     1098            this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering);
     1099
     1100            var eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
     1101                className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
     1102                title: WI.UIString("“%s“ Event Fired").format(pauseData.eventName),
     1103            });
     1104            this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
     1105
     1106            var eventBreakpointRow = new WI.DetailsSectionRow;
     1107            eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
     1108
     1109            var rows = [eventBreakpointRow];
     1110
     1111            var eventListener = eventBreakpoint.eventListener;
     1112            if (eventListener) {
     1113                console.assert(eventListener.eventListenerId === pauseData.eventListenerId);
     1114
     1115                let ownerElementRow = new WI.DetailsSectionSimpleRow(WI.UIString("Element"), WI.linkifyNodeReference(eventListener.node));
     1116                rows.push(ownerElementRow);
    10891117            }
     1118
     1119            this._pauseReasonGroup.rows = rows;
    10901120            return true;
    10911121
     
    11041134            this._pauseReasonTextRow.text = WI.UIString("Immediate Pause Requested");
    11051135            this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
     1136            return true;
     1137
     1138        case WI.DebuggerManager.PauseReason.Timer:
     1139            console.assert(pauseData, "Expected data with a timer, but found none.");
     1140            if (!pauseData)
     1141                return false;
     1142
     1143            var eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.Timer, pauseData.eventName);
     1144            console.assert(eventBreakpoint, "Expected Timer breakpoint for event name.", pauseData.eventName);
     1145            if (!eventBreakpoint)
     1146                return false;
     1147
     1148            var suppressFiltering = true;
     1149            this._pauseReasonTreeOutline = this.createContentTreeOutline(suppressFiltering);
     1150
     1151            var eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
     1152                className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
     1153                title: WI.UIString("%s Fired").format(pauseData.eventName),
     1154            });
     1155            this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
     1156
     1157            var eventBreakpointRow = new WI.DetailsSectionRow;
     1158            eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
     1159
     1160            this._pauseReasonGroup.rows = [eventBreakpointRow];
    11061161            return true;
    11071162
     
    12651320    willDismissPopover(popover)
    12661321    {
    1267         if (popover.result !== WI.InputPopover.Result.Committed)
    1268             return;
    1269 
    12701322        if (popover instanceof WI.EventBreakpointPopover) {
    1271             let eventName = popover.value;
    1272             if (eventName)
    1273                 WI.domDebuggerManager.addEventBreakpoint(new WI.EventBreakpoint(eventName));
    1274             return;
    1275         }
    1276 
    1277         if (popover instanceof WI.XHRBreakpointPopover) {
     1323            let breakpoint = popover.breakpoint;
     1324            if (breakpoint)
     1325                WI.domDebuggerManager.addEventBreakpoint(breakpoint);
     1326            return;
     1327        }
     1328
     1329        if (popover instanceof WI.XHRBreakpointPopover && popover.result === WI.InputPopover.Result.Committed) {
    12781330            let url = popover.value;
    12791331            if (url)
  • trunk/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.css

    r234974 r235248  
    2929}
    3030
    31 .popover .event-breakpoint-content > input {
    32     width: 100%;
     31.popover .event-breakpoint-content > .event-type {
     32    display: flex;
    3333    margin-top: 4px;
    34     padding: 4px 0 2px 0;
    35     outline: none;
    3634}
  • trunk/Source/WebInspectorUI/UserInterface/Views/EventBreakpointPopover.js

    r234974 r235248  
    3030        super(delegate);
    3131
    32         this._result = WI.InputPopover.Result.None;
    33         this._value = null;
     32        this._breakpoint = null;
    3433
    35         this._codeMirror = null;
    3634        this._targetElement = null;
    3735        this._preferredEdges = null;
     
    4240    // Public
    4341
    44     get result() { return this._result; }
    45     get value() { return this._value; }
     42    get breakpoint() { return this._breakpoint; }
    4643
    4744    show(targetElement, preferredEdges)
     
    5754        label.textContent = WI.UIString("Break on events with name:");
    5855
    59         this._inputElement = contentElement.appendChild(document.createElement("input"));
    60         this._inputElement.placeholder = "click";
    61         this._inputElement.spellcheck = false;
    62         this._inputElement.addEventListener("keydown", (event) => {
     56        let typeContainer = contentElement.appendChild(document.createElement("div"));
     57        typeContainer.classList.add("event-type");
     58
     59        this._typeSelectElement = typeContainer.appendChild(document.createElement("select"));
     60        this._typeSelectElement.addEventListener("change", this._handleTypeSelectChange.bind(this));
     61        this._typeSelectElement.addEventListener("keydown", (event) => {
     62            if (isEnterKey(event))
     63                this.dismiss();
     64        });
     65
     66        let createOption = (text, value) => {
     67            let optionElement = this._typeSelectElement.appendChild(document.createElement("option"));
     68            optionElement.value = value;
     69            optionElement.textContent = text;
     70        };
     71
     72        createOption(WI.UIString("DOM Event"), WI.EventBreakpoint.Type.Listener);
     73
     74        if (WI.DOMDebuggerManager.supportsEventBreakpoints()) {
     75            createOption(WI.unlocalizedString("requestAnimationFrame"), "requestAnimationFrame");
     76            createOption(WI.unlocalizedString("setTimeout"), "setTimeout");
     77            createOption(WI.unlocalizedString("setInterval"), "setInterval");
     78        } else
     79            this._typeSelectElement.hidden = true;
     80
     81        this._domEventNameInputElement = typeContainer.appendChild(document.createElement("input"));
     82        this._domEventNameInputElement.placeholder = WI.UIString("Example: “%s”").format("click");
     83        this._domEventNameInputElement.spellcheck = false;
     84        this._domEventNameInputElement.addEventListener("keydown", (event) => {
    6385            if (!isEnterKey(event))
    6486                return;
    65 
    66             this._result = WI.InputPopover.Result.Committed;
    67             this._value = event.target.value.trim();
    6887
    6988            this.dismiss();
     
    7392
    7493        this._presentOverTargetElement();
     94
     95        this._typeSelectElement.value = WI.EventBreakpoint.Type.Listener;
     96        this._domEventNameInputElement.select();
     97    }
     98
     99    dismiss()
     100    {
     101        let type = this._typeSelectElement.value;
     102        let value = null;
     103
     104        if (type === WI.EventBreakpoint.Type.Listener)
     105            value = this._domEventNameInputElement.value;
     106        else {
     107            value = type;
     108
     109            if (value === "requestAnimationFrame")
     110                type = WI.EventBreakpoint.Type.AnimationFrame;
     111            else if (value === "setTimeout" || value === "setInterval")
     112                type = WI.EventBreakpoint.Type.Timer;
     113        }
     114
     115        if (type && value)
     116            this._breakpoint = new WI.EventBreakpoint(type, value);
     117
     118        super.dismiss();
    75119    }
    76120
     
    84128        let targetFrame = WI.Rect.rectFromClientRect(this._targetElement.getBoundingClientRect());
    85129        this.present(targetFrame, this._preferredEdges);
     130    }
    86131
    87         this._inputElement.select();
     132    _handleTypeSelectChange(event)
     133    {
     134        this._domEventNameInputElement.hidden = this._typeSelectElement.value !== WI.EventBreakpoint.Type.Listener;
     135
     136        this.update();
    88137    }
    89138};
  • trunk/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.css

    r234974 r235248  
    2424 */
    2525
    26 .breakpoint.event:not(.breakpoint-paused-icon) .icon {
    27     content: url(../Images/EventBreakpoint.svg);
     26.breakpoint.event.breakpoint-for-animation-frame:not(.breakpoint-paused-icon) .icon {
     27    content: url(../Images/EventBreakpointAnimationFrame.svg);
    2828}
     29
     30.breakpoint.event.breakpoint-for-listener:not(.breakpoint-paused-icon) .icon {
     31    content: url(../Images/EventBreakpointListener.svg);
     32}
     33
     34.breakpoint.event.breakpoint-for-timer:not(.breakpoint-paused-icon) .icon {
     35    content: url(../Images/EventBreakpointTimer.svg);
     36}
  • trunk/Source/WebInspectorUI/UserInterface/Views/EventBreakpointTreeElement.js

    r235103 r235248  
    3030        console.assert(breakpoint instanceof WI.EventBreakpoint);
    3131
    32         let classNames = ["breakpoint", "event"];
     32        let classNames = ["breakpoint", "event", `breakpoint-for-${breakpoint.type}`];
    3333        if (className)
    3434            classNames.push(className);
Note: See TracChangeset for help on using the changeset viewer.