Title: [287802] trunk/Source/WebCore
Revision
287802
Author
[email protected]
Date
2022-01-07 18:13:46 -0800 (Fri, 07 Jan 2022)

Log Message

Don't dispatch "focusin" / "focusout" events if there are no listeners
https://bugs.webkit.org/show_bug.cgi?id=234928

Patch by Alexey Shvayka <[email protected]> on 2022-01-07
Reviewed by Geoff Garen.

This patch avoids creating and dispatching "focusin" / "focusout" events if it's
guaranteed there are no registered listeners for them. These events are rather new
and not widely popular: according to Chrome stats, only 17% page loads use them [1],
which is even less than `document.all`.

Together with r287787, creation of four FocusEvent instances is now avoided when
focus is changed, advancing attached microbenchmark by 6%.

[1] https://chromestatus.com/metrics/feature/timeline/popularity/433

No new tests, no behavior change.

* dom/Document.cpp:
(WebCore::Document::setFocusedElement):
(WebCore::Document::addListenerTypeIfNeeded):
* dom/Document.h:
* dom/Element.cpp:
(WebCore::Element::dispatchFocusInEventIfNeeded):
(WebCore::Element::dispatchFocusOutEventIfNeeded):
(WebCore::Element::dispatchFocusInEvent): Deleted.
(WebCore::Element::dispatchFocusOutEvent): Deleted.
* dom/Element.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (287801 => 287802)


--- trunk/Source/WebCore/ChangeLog	2022-01-08 01:57:04 UTC (rev 287801)
+++ trunk/Source/WebCore/ChangeLog	2022-01-08 02:13:46 UTC (rev 287802)
@@ -1,5 +1,35 @@
 2022-01-07  Alexey Shvayka  <[email protected]>
 
+        Don't dispatch "focusin" / "focusout" events if there are no listeners
+        https://bugs.webkit.org/show_bug.cgi?id=234928
+
+        Reviewed by Geoff Garen.
+
+        This patch avoids creating and dispatching "focusin" / "focusout" events if it's
+        guaranteed there are no registered listeners for them. These events are rather new
+        and not widely popular: according to Chrome stats, only 17% page loads use them [1],
+        which is even less than `document.all`.
+
+        Together with r287787, creation of four FocusEvent instances is now avoided when
+        focus is changed, advancing attached microbenchmark by 6%.
+
+        [1] https://chromestatus.com/metrics/feature/timeline/popularity/433
+
+        No new tests, no behavior change.
+
+        * dom/Document.cpp:
+        (WebCore::Document::setFocusedElement):
+        (WebCore::Document::addListenerTypeIfNeeded):
+        * dom/Document.h:
+        * dom/Element.cpp:
+        (WebCore::Element::dispatchFocusInEventIfNeeded):
+        (WebCore::Element::dispatchFocusOutEventIfNeeded):
+        (WebCore::Element::dispatchFocusInEvent): Deleted.
+        (WebCore::Element::dispatchFocusOutEvent): Deleted.
+        * dom/Element.h:
+
+2022-01-07  Alexey Shvayka  <[email protected]>
+
         Remove obsolete DOM Level 2 "DOMFocusIn" / "DOMFocusOut" events
         https://bugs.webkit.org/show_bug.cgi?id=234978
 

Modified: trunk/Source/WebCore/dom/Document.cpp (287801 => 287802)


--- trunk/Source/WebCore/dom/Document.cpp	2022-01-08 01:57:04 UTC (rev 287801)
+++ trunk/Source/WebCore/dom/Document.cpp	2022-01-08 02:13:46 UTC (rev 287802)
@@ -4658,7 +4658,7 @@
                 newFocusedElement = nullptr;
             }
 
-            oldFocusedElement->dispatchFocusOutEvent(newFocusedElement.copyRef()); // DOM level 3 bubbling blur event.
+            oldFocusedElement->dispatchFocusOutEventIfNeeded(newFocusedElement.copyRef()); // DOM level 3 bubbling blur event.
 
             if (m_focusedElement) {
                 // handler shifted focus
@@ -4723,7 +4723,7 @@
             return false;
         }
 
-        m_focusedElement->dispatchFocusInEvent(oldFocusedElement.copyRef()); // DOM level 3 bubbling focus event.
+        m_focusedElement->dispatchFocusInEventIfNeeded(oldFocusedElement.copyRef()); // DOM level 3 bubbling focus event.
 
         if (m_focusedElement != newFocusedElement) {
             // handler shifted focus
@@ -5285,6 +5285,10 @@
         addListenerType(FORCEUP_LISTENER);
     else if (eventType == eventNames().resizeEvent)
         addListenerType(RESIZE_LISTENER);
+    else if (eventType == eventNames().focusinEvent)
+        addListenerType(FOCUSIN_LISTENER);
+    else if (eventType == eventNames().focusoutEvent)
+        addListenerType(FOCUSOUT_LISTENER);
 }
 
 HTMLFrameOwnerElement* Document::ownerElement() const

Modified: trunk/Source/WebCore/dom/Document.h (287801 => 287802)


--- trunk/Source/WebCore/dom/Document.h	2022-01-08 01:57:04 UTC (rev 287801)
+++ trunk/Source/WebCore/dom/Document.h	2022-01-08 02:13:46 UTC (rev 287802)
@@ -906,7 +906,9 @@
         FORCECHANGED_LISTENER                = 1 << 14,
         FORCEDOWN_LISTENER                   = 1 << 15,
         FORCEUP_LISTENER                     = 1 << 16,
-        RESIZE_LISTENER                      = 1 << 17
+        RESIZE_LISTENER                      = 1 << 17,
+        FOCUSIN_LISTENER                     = 1 << 18,
+        FOCUSOUT_LISTENER                    = 1 << 19,
     };
 
     bool hasListenerType(ListenerType listenerType) const { return (m_listenerTypes & listenerType); }

Modified: trunk/Source/WebCore/dom/Element.cpp (287801 => 287802)


--- trunk/Source/WebCore/dom/Element.cpp	2022-01-08 01:57:04 UTC (rev 287801)
+++ trunk/Source/WebCore/dom/Element.cpp	2022-01-08 02:13:46 UTC (rev 287802)
@@ -3182,14 +3182,18 @@
     focus();
 }
 
-void Element::dispatchFocusInEvent(RefPtr<Element>&& oldFocusedElement)
+void Element::dispatchFocusInEventIfNeeded(RefPtr<Element>&& oldFocusedElement)
 {
+    if (!document().hasListenerType(Document::FOCUSIN_LISTENER))
+        return;
     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed() || !isInWebProcess());
     dispatchScopedEvent(FocusEvent::create(eventNames().focusinEvent, Event::CanBubble::Yes, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(oldFocusedElement)));
 }
 
-void Element::dispatchFocusOutEvent(RefPtr<Element>&& newFocusedElement)
+void Element::dispatchFocusOutEventIfNeeded(RefPtr<Element>&& newFocusedElement)
 {
+    if (!document().hasListenerType(Document::FOCUSOUT_LISTENER))
+        return;
     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed() || !isInWebProcess());
     dispatchScopedEvent(FocusEvent::create(eventNames().focusoutEvent, Event::CanBubble::Yes, Event::IsCancelable::No, document().windowProxy(), 0, WTFMove(newFocusedElement)));
 }

Modified: trunk/Source/WebCore/dom/Element.h (287801 => 287802)


--- trunk/Source/WebCore/dom/Element.h	2022-01-08 01:57:04 UTC (rev 287801)
+++ trunk/Source/WebCore/dom/Element.h	2022-01-08 02:13:46 UTC (rev 287802)
@@ -571,8 +571,8 @@
     bool dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions = SendNoEvents, SimulatedClickVisualOptions = ShowPressedLook);
 
     // FIXME: Consider changing signature to accept Element* because all callers perform copyRef().
-    void dispatchFocusInEvent(RefPtr<Element>&& oldFocusedElement);
-    void dispatchFocusOutEvent(RefPtr<Element>&& newFocusedElement);
+    void dispatchFocusInEventIfNeeded(RefPtr<Element>&& oldFocusedElement);
+    void dispatchFocusOutEventIfNeeded(RefPtr<Element>&& newFocusedElement);
     virtual void dispatchFocusEvent(RefPtr<Element>&& oldFocusedElement, FocusDirection);
     virtual void dispatchBlurEvent(RefPtr<Element>&& newFocusedElement);
     void dispatchWebKitImageReadyEventForTesting();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to