Title: [260535] trunk
Revision
260535
Author
[email protected]
Date
2020-04-22 15:45:00 -0700 (Wed, 22 Apr 2020)

Log Message

[ Mac wk2 ] imported/w3c/web-platform-tests/notifications/event-onclose.html is flaky failing.
https://bugs.webkit.org/show_bug.cgi?id=209483
<rdar://problem/60830377>

Reviewed by Geoffrey Garen.

Source/WebCore:

Align garbage collection of Notification JS wrapper with the specification:
- https://notifications.spec.whatwg.org/#garbage-collection [1]

In particular, the following changes were made:
1. Instead of using the legacy setPendingActivity() / unsetPendingActivity(), override
   ActiveDOMObject::virtualHasPendingActivity() to implement the behavior documented
   in the specification.
2. Keep the wrapper alive as long as the notification is showing and as long as there
   are relevant event listeners, as per [1]. Previously, we failed to check for event
   listeners, which was suboptimal.
3. Update the constructor to queue a task on the event loop in order to show the
   notification asynchronously, instead of relying on a SuspendableTimer for this
   purpose. Previously, the JS wrapper could get collected between construction and
   the notification getting shown, which was leading to the test flakiness.

No new tests, unskipped existing test.

* Modules/notifications/Notification.cpp:
(WebCore::Notification::Notification):
(WebCore::Notification::show):
(WebCore::Notification::finalize):
(WebCore::Notification::dispatchShowEvent):
(WebCore::Notification::dispatchClickEvent):
(WebCore::Notification::dispatchCloseEvent):
(WebCore::Notification::dispatchErrorEvent):
(WebCore::Notification::eventListenersDidChange):
(WebCore::Notification::virtualHasPendingActivity const):
* Modules/notifications/Notification.h:

LayoutTests:

Unskip test now that it is no longer flaky.

* platform/mac-wk2/TestExpectations:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (260534 => 260535)


--- trunk/LayoutTests/ChangeLog	2020-04-22 22:16:31 UTC (rev 260534)
+++ trunk/LayoutTests/ChangeLog	2020-04-22 22:45:00 UTC (rev 260535)
@@ -1,3 +1,15 @@
+2020-04-22  Chris Dumez  <[email protected]>
+
+        [ Mac wk2 ] imported/w3c/web-platform-tests/notifications/event-onclose.html is flaky failing.
+        https://bugs.webkit.org/show_bug.cgi?id=209483
+        <rdar://problem/60830377>
+
+        Reviewed by Geoffrey Garen.
+
+        Unskip test now that it is no longer flaky.
+
+        * platform/mac-wk2/TestExpectations:
+
 2020-04-22  Myles C. Maxfield  <[email protected]>
 
         Update dom/events/Event-dispatch-redispatch.html from upstream WPT

Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (260534 => 260535)


--- trunk/LayoutTests/platform/mac-wk2/TestExpectations	2020-04-22 22:16:31 UTC (rev 260534)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations	2020-04-22 22:45:00 UTC (rev 260535)
@@ -1028,8 +1028,6 @@
 
 webkit.org/b/209295 [ Debug ] imported/w3c/web-platform-tests/service-workers/service-worker/respond-with-body-accessed-response.https.html  [ Pass Failure ]
 
-webkit.org/b/209483 imported/w3c/web-platform-tests/notifications/event-onclose.html [ Pass Failure ]
-
 webkit.org/b/209503 [ Debug ] http/tests/referrer-policy-anchor/origin/cross-origin-http.https.html [ Pass Crash ]
 
 webkit.org/b/209564 svg/as-image/svg-image-with-data-uri-background.html [ Pass ImageOnlyFailure ]

Modified: trunk/Source/WebCore/ChangeLog (260534 => 260535)


--- trunk/Source/WebCore/ChangeLog	2020-04-22 22:16:31 UTC (rev 260534)
+++ trunk/Source/WebCore/ChangeLog	2020-04-22 22:45:00 UTC (rev 260535)
@@ -1,3 +1,40 @@
+2020-04-22  Chris Dumez  <[email protected]>
+
+        [ Mac wk2 ] imported/w3c/web-platform-tests/notifications/event-onclose.html is flaky failing.
+        https://bugs.webkit.org/show_bug.cgi?id=209483
+        <rdar://problem/60830377>
+
+        Reviewed by Geoffrey Garen.
+
+        Align garbage collection of Notification JS wrapper with the specification:
+        - https://notifications.spec.whatwg.org/#garbage-collection [1]
+
+        In particular, the following changes were made:
+        1. Instead of using the legacy setPendingActivity() / unsetPendingActivity(), override
+           ActiveDOMObject::virtualHasPendingActivity() to implement the behavior documented
+           in the specification.
+        2. Keep the wrapper alive as long as the notification is showing and as long as there
+           are relevant event listeners, as per [1]. Previously, we failed to check for event
+           listeners, which was suboptimal.
+        3. Update the constructor to queue a task on the event loop in order to show the
+           notification asynchronously, instead of relying on a SuspendableTimer for this
+           purpose. Previously, the JS wrapper could get collected between construction and
+           the notification getting shown, which was leading to the test flakiness.
+
+        No new tests, unskipped existing test.
+
+        * Modules/notifications/Notification.cpp:
+        (WebCore::Notification::Notification):
+        (WebCore::Notification::show):
+        (WebCore::Notification::finalize):
+        (WebCore::Notification::dispatchShowEvent):
+        (WebCore::Notification::dispatchClickEvent):
+        (WebCore::Notification::dispatchCloseEvent):
+        (WebCore::Notification::dispatchErrorEvent):
+        (WebCore::Notification::eventListenersDidChange):
+        (WebCore::Notification::virtualHasPendingActivity const):
+        * Modules/notifications/Notification.h:
+
 2020-04-22  Don Olmstead  <[email protected]>
 
         [CMake] Add WebKit::WebCoreTestSupport target

Modified: trunk/Source/WebCore/Modules/notifications/Notification.cpp (260534 => 260535)


--- trunk/Source/WebCore/Modules/notifications/Notification.cpp	2020-04-22 22:16:31 UTC (rev 260534)
+++ trunk/Source/WebCore/Modules/notifications/Notification.cpp	2020-04-22 22:45:00 UTC (rev 260535)
@@ -64,7 +64,6 @@
     , m_body(options.body)
     , m_tag(options.tag)
     , m_state(Idle)
-    , m_showNotificationTimer(&document, *this, &Notification::show)
 {
     if (!options.icon.isEmpty()) {
         auto iconURL = document.completeURL(options.icon);
@@ -72,8 +71,9 @@
             m_icon = iconURL;
     }
 
-    m_showNotificationTimer.startOneShot(0_s);
-    m_showNotificationTimer.suspendIfNeeded();
+    queueTaskKeepingObjectAlive(*this, TaskSource::UserInteraction, [this] {
+        show();
+    });
 }
 
 Notification::~Notification() = default;
@@ -94,10 +94,8 @@
         dispatchErrorEvent();
         return;
     }
-    if (client.show(this)) {
+    if (client.show(this))
         m_state = Showing;
-        setPendingActivity(*this);
-    }
 }
 
 void Notification::close()
@@ -143,28 +141,16 @@
     if (m_state == Closed)
         return;
     m_state = Closed;
-    unsetPendingActivity(*this);
 }
 
-void Notification::queueTask(Function<void()>&& task)
-{
-    auto* document = this->document();
-    if (!document)
-        return;
-
-    document->eventLoop().queueTask(TaskSource::UserInteraction, WTFMove(task));
-}
-
 void Notification::dispatchShowEvent()
 {
-    queueTask([this, pendingActivity = makePendingActivity(*this)] {
-        dispatchEvent(Event::create(eventNames().showEvent, Event::CanBubble::No, Event::IsCancelable::No));
-    });
+    queueTaskToDispatchEvent(*this, TaskSource::UserInteraction, Event::create(eventNames().showEvent, Event::CanBubble::No, Event::IsCancelable::No));
 }
 
 void Notification::dispatchClickEvent()
 {
-    queueTask([this, pendingActivity = makePendingActivity(*this)] {
+    queueTaskKeepingObjectAlive(*this, TaskSource::UserInteraction, [this] {
         WindowFocusAllowedIndicator windowFocusAllowed;
         dispatchEvent(Event::create(eventNames().clickEvent, Event::CanBubble::No, Event::IsCancelable::No));
     });
@@ -172,17 +158,13 @@
 
 void Notification::dispatchCloseEvent()
 {
-    queueTask([this, pendingActivity = makePendingActivity(*this)] {
-        dispatchEvent(Event::create(eventNames().closeEvent, Event::CanBubble::No, Event::IsCancelable::No));
-    });
+    queueTaskToDispatchEvent(*this, TaskSource::UserInteraction, Event::create(eventNames().closeEvent, Event::CanBubble::No, Event::IsCancelable::No));
     finalize();
 }
 
 void Notification::dispatchErrorEvent()
 {
-    queueTask([this, pendingActivity = makePendingActivity(*this)] {
-        dispatchEvent(Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No));
-    });
+    queueTaskToDispatchEvent(*this, TaskSource::UserInteraction, Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No));
 }
 
 auto Notification::permission(Document& document) -> Permission
@@ -215,6 +197,22 @@
     NotificationController::from(page)->client().requestPermission(&document, WTFMove(callback));
 }
 
+void Notification::eventListenersDidChange()
+{
+    m_hasRelevantEventListener = hasEventListeners(eventNames().clickEvent)
+        || hasEventListeners(eventNames().closeEvent)
+        || hasEventListeners(eventNames().errorEvent)
+        || hasEventListeners(eventNames().showEvent);
+}
+
+// A Notification object must not be garbage collected while the list of notifications contains its corresponding
+// notification and it has an event listener whose type is click, show, close, or error.
+// See https://notifications.spec.whatwg.org/#garbage-collection
+bool Notification::virtualHasPendingActivity() const
+{
+    return m_state == Showing && m_hasRelevantEventListener;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(NOTIFICATIONS)

Modified: trunk/Source/WebCore/Modules/notifications/Notification.h (260534 => 260535)


--- trunk/Source/WebCore/Modules/notifications/Notification.h	2020-04-22 22:16:31 UTC (rev 260534)
+++ trunk/Source/WebCore/Modules/notifications/Notification.h	2020-04-22 22:45:00 UTC (rev 260535)
@@ -37,7 +37,6 @@
 #include "EventTarget.h"
 #include "NotificationDirection.h"
 #include "NotificationPermission.h"
-#include "SuspendableTimer.h"
 #include <wtf/URL.h>
 #include "WritingMode.h"
 
@@ -96,15 +95,16 @@
     Document* document() const;
     EventTargetInterface eventTargetInterface() const final { return NotificationEventTargetInterfaceType; }
 
-    void queueTask(Function<void()>&&);
-
     // ActiveDOMObject
     const char* activeDOMObjectName() const final;
     void suspend(ReasonForSuspension);
     void stop() final;
+    bool virtualHasPendingActivity() const final;
 
+    // EventTarget
     void refEventTarget() final { ref(); }
     void derefEventTarget() final { deref(); }
+    void eventListenersDidChange() final;
 
     String m_title;
     Direction m_direction;
@@ -115,8 +115,7 @@
 
     enum State { Idle, Showing, Closed };
     State m_state { Idle };
-
-    SuspendableTimer m_showNotificationTimer;
+    bool m_hasRelevantEventListener { false };
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to