Title: [260576] trunk
Revision
260576
Author
[email protected]
Date
2020-04-23 10:15:45 -0700 (Thu, 23 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 Geoff 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 (260575 => 260576)


--- trunk/LayoutTests/ChangeLog	2020-04-23 17:07:56 UTC (rev 260575)
+++ trunk/LayoutTests/ChangeLog	2020-04-23 17:15:45 UTC (rev 260576)
@@ -1,3 +1,15 @@
+2020-04-23  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 Geoff Garen.
+
+        Unskip test now that it is no longer flaky.
+
+        * platform/mac-wk2/TestExpectations:
+
 2020-04-23  Diego Pino Garcia  <[email protected]>
 
         [WPE] Gardening, update expectations after r259705

Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (260575 => 260576)


--- trunk/LayoutTests/platform/mac-wk2/TestExpectations	2020-04-23 17:07:56 UTC (rev 260575)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations	2020-04-23 17:15:45 UTC (rev 260576)
@@ -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 (260575 => 260576)


--- trunk/Source/WebCore/ChangeLog	2020-04-23 17:07:56 UTC (rev 260575)
+++ trunk/Source/WebCore/ChangeLog	2020-04-23 17:15:45 UTC (rev 260576)
@@ -1,3 +1,40 @@
+2020-04-23  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 Geoff 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-23  Andres Gonzalez  <[email protected]>
 
         Correction for patch 397001.

Modified: trunk/Source/WebCore/Modules/notifications/Notification.cpp (260575 => 260576)


--- trunk/Source/WebCore/Modules/notifications/Notification.cpp	2020-04-23 17:07:56 UTC (rev 260575)
+++ trunk/Source/WebCore/Modules/notifications/Notification.cpp	2020-04-23 17:15:45 UTC (rev 260576)
@@ -53,6 +53,7 @@
 {
     auto notification = adoptRef(*new Notification(context, title, options));
     notification->suspendIfNeeded();
+    notification->showSoon();
     return notification;
 }
 
@@ -64,7 +65,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);
@@ -71,13 +71,18 @@
         if (iconURL.isValid())
             m_icon = iconURL;
     }
-
-    m_showNotificationTimer.startOneShot(0_s);
-    m_showNotificationTimer.suspendIfNeeded();
 }
 
 Notification::~Notification() = default;
 
+
+void Notification::showSoon()
+{
+    queueTaskKeepingObjectAlive(*this, TaskSource::UserInteraction, [this] {
+        show();
+    });
+}
+
 void Notification::show()
 {
     // prevent double-showing
@@ -94,10 +99,8 @@
         dispatchErrorEvent();
         return;
     }
-    if (client.show(this)) {
+    if (client.show(this))
         m_state = Showing;
-        setPendingActivity(*this);
-    }
 }
 
 void Notification::close()
@@ -143,28 +146,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 +163,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 +202,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 (260575 => 260576)


--- trunk/Source/WebCore/Modules/notifications/Notification.h	2020-04-23 17:07:56 UTC (rev 260575)
+++ trunk/Source/WebCore/Modules/notifications/Notification.h	2020-04-23 17:15:45 UTC (rev 260576)
@@ -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,18 @@
     Document* document() const;
     EventTargetInterface eventTargetInterface() const final { return NotificationEventTargetInterfaceType; }
 
-    void queueTask(Function<void()>&&);
+    void showSoon();
 
     // 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 +117,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