Title: [252263] trunk
Revision
252263
Author
cdu...@apple.com
Date
2019-11-08 14:10:58 -0800 (Fri, 08 Nov 2019)

Log Message

Make DeferredPromise behave nicely with regards to the back/forward cache
https://bugs.webkit.org/show_bug.cgi?id=203976

Reviewed by Ryosuke Niwa.

Source/_javascript_Core:

Add template parameter to JSC::Strong to indicate that the destructor should grab the JS lock.
Normally, the callers are in charge of grabbing the lock but this is not always feasible.
In particular, in this patch, I capture a JSC::Strong in a lambda. If the document gets destroyed
before the lambda has run, the lambda will get destroyed and it will destroy the captured JSC::Strong
as a result.

* heap/Handle.h:
* heap/Strong.h:
(JSC::Strong::clear):
* heap/StrongInlines.h:
(JSC::shouldStrongDestructorGrabLock>::Strong):
(JSC::shouldStrongDestructorGrabLock>::set):

Source/WebCore:

Previously, DeferredPromise would ignore requests to fulfill the promise if
reject/resolve/settle got called while the promise's script execution context
is suspended in the back/forward cache. This is really never the right thing to
do though because this means the promise will never be fulfilled if the user
ever goes back to this page.

To address the issue, DeferredPromise now schedules a task on the event loop if
it gets fulfilled while its script execution context is suspended. As a result,
the promise will properly get fulfilled if the document ever comes out of the
back/forward cache and developers using DeferredPromise do not have to worry
about suspension.

Now that DeferredPromise properly deals with suspended documents, this patch also
reverts changes I made recently in code using DeferredPromise. I had made them
queue a task on the event loop before fulfilling the promise, which did not match
their specification and is no longer needed.

Note that capturing the Strong<> in the lambda is correct here because we want
the resolution value to survive until either:
1. The task is processed by the event loop and the promise is resolved.
2. The back/forward cache entry containing this document is destroyed

Note that we do not leak here because when the back/forward cache's CachedFrame
gets destroyed, it will call Document::prepareForDestruction(), which will call
WindowEventLoop::stop() and destroys all pending tasks associated with this
document. This will therefore destroy the Strong captured in the task.

No new tests, covered by existing back/forward cache tests.

* Modules/cache/DOMCacheStorage.cpp:
(WebCore::DOMCacheStorage::doSequentialMatch):
(WebCore::DOMCacheStorage::match):
(WebCore::DOMCacheStorage::has):
(WebCore::DOMCacheStorage::open):
(WebCore::DOMCacheStorage::doOpen):
(WebCore::DOMCacheStorage::remove):
(WebCore::DOMCacheStorage::doRemove):
(WebCore::DOMCacheStorage::keys):
* Modules/cache/DOMCacheStorage.h:
* Modules/fetch/FetchBodyOwner.cpp:
(WebCore::FetchBodyOwner::blobLoadingSucceeded):
(WebCore::FetchBodyOwner::blobLoadingFailed):
(WebCore::FetchBodyOwner::blobChunk):
* Modules/fetch/FetchBodyOwner.h:
* Modules/mediastream/UserMediaRequest.cpp:
(WebCore::UserMediaRequest::allow):
(WebCore::UserMediaRequest::deny):
* WebCore.xcodeproj/project.pbxproj:
* bindings/IDLTypes.h:
* bindings/js/JSDOMGuardedObject.h:
* bindings/js/JSDOMPromiseDeferred.cpp:
(WebCore::DeferredPromise::callFunction):
(WebCore::DeferredPromise::whenSettled):
(WebCore::DeferredPromise::reject):
* bindings/js/JSDOMPromiseDeferred.h:
(WebCore::DeferredPromise::resolve):
(WebCore::DeferredPromise::resolveWithNewlyCreated):
(WebCore::DeferredPromise::resolveCallbackValueWithNewlyCreated):
(WebCore::DeferredPromise::reject):
(WebCore::DeferredPromise::resolveWithCallback):
(WebCore::DeferredPromise::rejectWithCallback):
(WebCore::DeferredPromise::shouldIgnoreRequestToFulfill const):
* css/FontFaceSet.cpp:
(WebCore::FontFaceSet::didFirstLayout):
(WebCore::FontFaceSet::completedLoading):
(WebCore::FontFaceSet::faceFinished):
* dom/ActiveDOMCallback.cpp:
(WebCore::ActiveDOMCallback::activeDOMObjectsAreSuspended const):
(WebCore::ActiveDOMCallback::activeDOMObjectAreStopped const):
* dom/ActiveDOMCallback.h:
* dom/Element.h:
* dom/ScriptExecutionContext.h:
* page/DOMWindow.h:
* page/RemoteDOMWindow.h:

LayoutTests:

Rebaseline test where ordering has changed slightly due to not queueing a task anymore before
resolving the promise. This restores pre-r251746 behavior.

* fast/mediastream/MediaDevices-getUserMedia-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (252262 => 252263)


--- trunk/LayoutTests/ChangeLog	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/LayoutTests/ChangeLog	2019-11-08 22:10:58 UTC (rev 252263)
@@ -1,3 +1,15 @@
+2019-11-08  Chris Dumez  <cdu...@apple.com>
+
+        Make DeferredPromise behave nicely with regards to the back/forward cache
+        https://bugs.webkit.org/show_bug.cgi?id=203976
+
+        Reviewed by Ryosuke Niwa.
+
+        Rebaseline test where ordering has changed slightly due to not queueing a task anymore before
+        resolving the promise. This restores pre-r251746 behavior.
+
+        * fast/mediastream/MediaDevices-getUserMedia-expected.txt:
+
 2019-11-08  Truitt Savell  <tsav...@apple.com>
 
         Update expectations for 3 fast/events/ios/key-events-comprehensive tests

Modified: trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt (252262 => 252263)


--- trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt	2019-11-08 22:10:58 UTC (rev 252263)
@@ -6,9 +6,9 @@
 PASS typeof navigator.mediaDevices.webkitGetUserMedia is 'undefined'
 
 PASS navigator.mediaDevices.getUserMedia({audio:true}).then(gotStream1); did not throw exception.
-PASS navigator.mediaDevices.getUserMedia.apply(undefined) rejected with error: TypeError: Can only call MediaDevices.getUserMedia on instances of MediaDevices
 PASS navigator.mediaDevices.getUserMedia() rejected with error: TypeError: Type error
 PASS navigator.mediaDevices.getUserMedia({}) rejected with error: TypeError: Type error
+PASS navigator.mediaDevices.getUserMedia.apply(undefined) rejected with error: TypeError: Can only call MediaDevices.getUserMedia on instances of MediaDevices
 PASS Stream 1 generated.
 PASS stream.getAudioTracks().length is 1
 PASS stream.getVideoTracks().length is 0

Modified: trunk/Source/_javascript_Core/ChangeLog (252262 => 252263)


--- trunk/Source/_javascript_Core/ChangeLog	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-11-08 22:10:58 UTC (rev 252263)
@@ -1,3 +1,23 @@
+2019-11-08  Chris Dumez  <cdu...@apple.com>
+
+        Make DeferredPromise behave nicely with regards to the back/forward cache
+        https://bugs.webkit.org/show_bug.cgi?id=203976
+
+        Reviewed by Ryosuke Niwa.
+
+        Add template parameter to JSC::Strong to indicate that the destructor should grab the JS lock.
+        Normally, the callers are in charge of grabbing the lock but this is not always feasible.
+        In particular, in this patch, I capture a JSC::Strong in a lambda. If the document gets destroyed
+        before the lambda has run, the lambda will get destroyed and it will destroy the captured JSC::Strong
+        as a result.
+
+        * heap/Handle.h:
+        * heap/Strong.h:
+        (JSC::Strong::clear):
+        * heap/StrongInlines.h:
+        (JSC::shouldStrongDestructorGrabLock>::Strong):
+        (JSC::shouldStrongDestructorGrabLock>::set):
+
 2019-11-08  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Use LinkTimeConstants and make some properties lazy

Modified: trunk/Source/_javascript_Core/heap/Handle.h (252262 => 252263)


--- trunk/Source/_javascript_Core/heap/Handle.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/_javascript_Core/heap/Handle.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -37,6 +37,8 @@
     lifetime is guaranteed by something else.
 */
 
+enum class ShouldStrongDestructorGrabLock : bool { No, Yes };
+
 template <class T> class Handle;
 
 // Creating a JSValue Handle is invalid
@@ -44,7 +46,7 @@
 
 class HandleBase {
     template <typename T> friend class Weak;
-    template <typename T> friend class Strong;
+    template <typename T, ShouldStrongDestructorGrabLock shouldStrongDestructorGrabLock> friend class Strong;
     friend class HandleSet;
     friend struct JSCallbackObjectData;
 

Modified: trunk/Source/_javascript_Core/heap/Strong.h (252262 => 252263)


--- trunk/Source/_javascript_Core/heap/Strong.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/_javascript_Core/heap/Strong.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -28,6 +28,7 @@
 #include <wtf/Assertions.h>
 #include "Handle.h"
 #include "HandleSet.h"
+#include "JSLock.h"
 
 namespace JSC {
 
@@ -34,10 +35,10 @@
 class VM;
 
 // A strongly referenced handle that prevents the object it points to from being garbage collected.
-template <typename T> class Strong : public Handle<T> {
+template <typename T, ShouldStrongDestructorGrabLock shouldStrongDestructorGrabLock = ShouldStrongDestructorGrabLock::No> class Strong : public Handle<T> {
     using Handle<T>::slot;
     using Handle<T>::setSlot;
-    template <typename U> friend class Strong;
+    template <typename U, ShouldStrongDestructorGrabLock> friend class Strong;
 
 public:
     typedef typename Handle<T>::ExternalType ExternalType;
@@ -120,8 +121,16 @@
     {
         if (!slot())
             return;
-        HandleSet::heapFor(slot())->deallocate(slot());
-        setSlot(0);
+
+        auto* heap = HandleSet::heapFor(slot());
+        if (shouldStrongDestructorGrabLock == ShouldStrongDestructorGrabLock::Yes) {
+            JSLockHolder holder(heap->vm());
+            heap->deallocate(slot());
+            setSlot(0);
+        } else {
+            heap->deallocate(slot());
+            setSlot(0);
+        }
     }
 
 private:

Modified: trunk/Source/_javascript_Core/heap/StrongInlines.h (252262 => 252263)


--- trunk/Source/_javascript_Core/heap/StrongInlines.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/_javascript_Core/heap/StrongInlines.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -30,22 +30,22 @@
 
 namespace JSC {
 
-template <typename T>
-inline Strong<T>::Strong(VM& vm, ExternalType value)
+template <typename T, ShouldStrongDestructorGrabLock shouldStrongDestructorGrabLock>
+inline Strong<T, shouldStrongDestructorGrabLock>::Strong(VM& vm, ExternalType value)
     : Handle<T>(vm.heap.handleSet()->allocate())
 {
     set(value);
 }
 
-template <typename T>
-inline Strong<T>::Strong(VM& vm, Handle<T> handle)
+template <typename T, ShouldStrongDestructorGrabLock shouldStrongDestructorGrabLock>
+inline Strong<T, shouldStrongDestructorGrabLock>::Strong(VM& vm, Handle<T> handle)
     : Handle<T>(vm.heap.handleSet()->allocate())
 {
     set(handle.get());
 }
 
-template <typename T>
-inline void Strong<T>::set(VM& vm, ExternalType value)
+template <typename T, ShouldStrongDestructorGrabLock shouldStrongDestructorGrabLock>
+inline void Strong<T, shouldStrongDestructorGrabLock>::set(VM& vm, ExternalType value)
 {
     if (!slot())
         setSlot(vm.heap.handleSet()->allocate());

Modified: trunk/Source/WebCore/ChangeLog (252262 => 252263)


--- trunk/Source/WebCore/ChangeLog	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/ChangeLog	2019-11-08 22:10:58 UTC (rev 252263)
@@ -1,3 +1,85 @@
+2019-11-08  Chris Dumez  <cdu...@apple.com>
+
+        Make DeferredPromise behave nicely with regards to the back/forward cache
+        https://bugs.webkit.org/show_bug.cgi?id=203976
+
+        Reviewed by Ryosuke Niwa.
+
+        Previously, DeferredPromise would ignore requests to fulfill the promise if
+        reject/resolve/settle got called while the promise's script execution context
+        is suspended in the back/forward cache. This is really never the right thing to
+        do though because this means the promise will never be fulfilled if the user
+        ever goes back to this page.
+
+        To address the issue, DeferredPromise now schedules a task on the event loop if
+        it gets fulfilled while its script execution context is suspended. As a result,
+        the promise will properly get fulfilled if the document ever comes out of the
+        back/forward cache and developers using DeferredPromise do not have to worry
+        about suspension.
+
+        Now that DeferredPromise properly deals with suspended documents, this patch also
+        reverts changes I made recently in code using DeferredPromise. I had made them
+        queue a task on the event loop before fulfilling the promise, which did not match
+        their specification and is no longer needed.
+
+        Note that capturing the Strong<> in the lambda is correct here because we want
+        the resolution value to survive until either:
+        1. The task is processed by the event loop and the promise is resolved.
+        2. The back/forward cache entry containing this document is destroyed
+
+        Note that we do not leak here because when the back/forward cache's CachedFrame
+        gets destroyed, it will call Document::prepareForDestruction(), which will call
+        WindowEventLoop::stop() and destroys all pending tasks associated with this
+        document. This will therefore destroy the Strong captured in the task.
+
+        No new tests, covered by existing back/forward cache tests.
+
+        * Modules/cache/DOMCacheStorage.cpp:
+        (WebCore::DOMCacheStorage::doSequentialMatch):
+        (WebCore::DOMCacheStorage::match):
+        (WebCore::DOMCacheStorage::has):
+        (WebCore::DOMCacheStorage::open):
+        (WebCore::DOMCacheStorage::doOpen):
+        (WebCore::DOMCacheStorage::remove):
+        (WebCore::DOMCacheStorage::doRemove):
+        (WebCore::DOMCacheStorage::keys):
+        * Modules/cache/DOMCacheStorage.h:
+        * Modules/fetch/FetchBodyOwner.cpp:
+        (WebCore::FetchBodyOwner::blobLoadingSucceeded):
+        (WebCore::FetchBodyOwner::blobLoadingFailed):
+        (WebCore::FetchBodyOwner::blobChunk):
+        * Modules/fetch/FetchBodyOwner.h:
+        * Modules/mediastream/UserMediaRequest.cpp:
+        (WebCore::UserMediaRequest::allow):
+        (WebCore::UserMediaRequest::deny):
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/IDLTypes.h:
+        * bindings/js/JSDOMGuardedObject.h:
+        * bindings/js/JSDOMPromiseDeferred.cpp:
+        (WebCore::DeferredPromise::callFunction):
+        (WebCore::DeferredPromise::whenSettled):
+        (WebCore::DeferredPromise::reject):
+        * bindings/js/JSDOMPromiseDeferred.h:
+        (WebCore::DeferredPromise::resolve):
+        (WebCore::DeferredPromise::resolveWithNewlyCreated):
+        (WebCore::DeferredPromise::resolveCallbackValueWithNewlyCreated):
+        (WebCore::DeferredPromise::reject):
+        (WebCore::DeferredPromise::resolveWithCallback):
+        (WebCore::DeferredPromise::rejectWithCallback):
+        (WebCore::DeferredPromise::shouldIgnoreRequestToFulfill const):
+        * css/FontFaceSet.cpp:
+        (WebCore::FontFaceSet::didFirstLayout):
+        (WebCore::FontFaceSet::completedLoading):
+        (WebCore::FontFaceSet::faceFinished):
+        * dom/ActiveDOMCallback.cpp:
+        (WebCore::ActiveDOMCallback::activeDOMObjectsAreSuspended const):
+        (WebCore::ActiveDOMCallback::activeDOMObjectAreStopped const):
+        * dom/ActiveDOMCallback.h:
+        * dom/Element.h:
+        * dom/ScriptExecutionContext.h:
+        * page/DOMWindow.h:
+        * page/RemoteDOMWindow.h:
+
 2019-11-08  Antti Koivisto  <an...@apple.com>
 
         StyleResolver state should store user agent appearance style as RenderStyle

Modified: trunk/Source/WebCore/Modules/cache/DOMCacheStorage.cpp (252262 => 252263)


--- trunk/Source/WebCore/Modules/cache/DOMCacheStorage.cpp	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/Modules/cache/DOMCacheStorage.cpp	2019-11-08 22:10:58 UTC (rev 252263)
@@ -87,18 +87,16 @@
 
 void DOMCacheStorage::doSequentialMatch(DOMCache::RequestInfo&& info, CacheQueryOptions&& options, Ref<DeferredPromise>&& promise)
 {
-    startSequentialMatch(WTF::map(m_caches, copyCache), WTFMove(info), WTFMove(options), [this, pendingActivity = makePendingActivity(*this), promise = WTFMove(promise)](auto&& result) mutable {
-        enqueueTask([promise = WTFMove(promise), result = WTFMove(result)]() mutable {
-            if (result.hasException()) {
-                promise->reject(result.releaseException());
-                return;
-            }
-            if (!result.returnValue()) {
-                promise->resolve();
-                return;
-            }
-            promise->resolve<IDLInterface<FetchResponse>>(*result.returnValue());
-        });
+    startSequentialMatch(WTF::map(m_caches, copyCache), WTFMove(info), WTFMove(options), [pendingActivity = makePendingActivity(*this), promise = WTFMove(promise)](auto&& result) mutable {
+        if (result.hasException()) {
+            promise->reject(result.releaseException());
+            return;
+        }
+        if (!result.returnValue()) {
+            promise->resolve();
+            return;
+        }
+        promise->resolve<IDLInterface<FetchResponse>>(*result.returnValue());
     });
 }
 
@@ -106,9 +104,7 @@
 {
     retrieveCaches([this, info = WTFMove(info), options = WTFMove(options), promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
         if (exception) {
-            enqueueTask([promise = WTFMove(promise), exception = WTFMove(exception.value())]() mutable {
-                promise->reject(WTFMove(exception));
-            });
+            promise->reject(WTFMove(*exception));
             return;
         }
 
@@ -118,9 +114,7 @@
                 m_caches[position]->match(WTFMove(info), WTFMove(options), WTFMove(promise));
                 return;
             }
-            enqueueTask([promise = WTFMove(promise)]() mutable {
-                promise->resolve();
-            });
+            promise->resolve();
             return;
         }
 
@@ -131,13 +125,11 @@
 void DOMCacheStorage::has(const String& name, DOMPromiseDeferred<IDLBoolean>&& promise)
 {
     retrieveCaches([this, name, promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
-        enqueueTask([this, name, promise = WTFMove(promise), exception = WTFMove(exception)]() mutable {
-            if (exception) {
-                promise.reject(WTFMove(exception.value()));
-                return;
-            }
-            promise.resolve(m_caches.findMatching([&](auto& item) { return item->name() == name; }) != notFound);
-        });
+        if (exception) {
+            promise.reject(WTFMove(exception.value()));
+            return;
+        }
+        promise.resolve(m_caches.findMatching([&](auto& item) { return item->name() == name; }) != notFound);
     });
 }
 
@@ -188,9 +180,7 @@
 {
     retrieveCaches([this, name, promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
         if (exception) {
-            enqueueTask([promise = WTFMove(promise), exception = WTFMove(exception.value())]() mutable {
-                promise.reject(WTFMove(exception));
-            });
+            promise.reject(WTFMove(*exception));
             return;
         }
         doOpen(name, WTFMove(promise));
@@ -201,26 +191,20 @@
 {
     auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
     if (position != notFound) {
-        enqueueTask([this, promise = WTFMove(promise), cache = m_caches[position].copyRef()]() mutable {
-            promise.resolve(DOMCache::create(*scriptExecutionContext(), String { cache->name() }, cache->identifier(), m_connection.copyRef()));
-        });
+        promise.resolve(DOMCache::create(*scriptExecutionContext(), String { m_caches[position]->name() }, m_caches[position]->identifier(), m_connection.copyRef()));
         return;
     }
 
     m_connection->open(*origin(), name, [this, name, promise = WTFMove(promise), pendingActivity = makePendingActivity(*this)](const CacheIdentifierOrError& result) mutable {
-        if (!result.has_value()) {
-            enqueueTask([this, promise = WTFMove(promise), error = result.error()]() mutable {
-                promise.reject(DOMCacheEngine::convertToExceptionAndLog(scriptExecutionContext(), error));
-            });
-        } else {
+        if (!result.has_value())
+            promise.reject(DOMCacheEngine::convertToExceptionAndLog(scriptExecutionContext(), result.error()));
+        else {
             if (result.value().hadStorageError)
                 logConsolePersistencyError(scriptExecutionContext(), name);
 
-            enqueueTask([this, name, promise = WTFMove(promise), identifier = result.value().identifier]() mutable {
-                auto cache = DOMCache::create(*scriptExecutionContext(), String { name }, identifier, m_connection.copyRef());
-                promise.resolve(cache);
-                m_caches.append(WTFMove(cache));
-            });
+            auto cache = DOMCache::create(*scriptExecutionContext(), String { name }, result.value().identifier, m_connection.copyRef());
+            promise.resolve(cache);
+            m_caches.append(WTFMove(cache));
         }
     });
 }
@@ -229,9 +213,7 @@
 {
     retrieveCaches([this, name, promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
         if (exception) {
-            enqueueTask([promise = WTFMove(promise), exception = WTFMove(exception.value())]() mutable {
-                promise.reject(WTFMove(exception));
-            });
+            promise.reject(WTFMove(*exception));
             return;
         }
         doRemove(name, WTFMove(promise));
@@ -242,22 +224,18 @@
 {
     auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
     if (position == notFound) {
-        enqueueTask([promise = WTFMove(promise)]() mutable {
-            promise.resolve(false);
-        });
+        promise.resolve(false);
         return;
     }
 
     m_connection->remove(m_caches[position]->identifier(), [this, name, promise = WTFMove(promise), pendingActivity = makePendingActivity(*this)](const CacheIdentifierOrError& result) mutable {
-        enqueueTask([this, name, promise = WTFMove(promise), result]() mutable {
-            if (!result.has_value())
-                promise.reject(DOMCacheEngine::convertToExceptionAndLog(scriptExecutionContext(), result.error()));
-            else {
-                if (result.value().hadStorageError)
-                    logConsolePersistencyError(scriptExecutionContext(), name);
-                promise.resolve(!!result.value().identifier);
-            }
-        });
+        if (!result.has_value())
+            promise.reject(DOMCacheEngine::convertToExceptionAndLog(scriptExecutionContext(), result.error()));
+        else {
+            if (result.value().hadStorageError)
+                logConsolePersistencyError(scriptExecutionContext(), name);
+            promise.resolve(!!result.value().identifier);
+        }
     });
 }
 
@@ -264,16 +242,14 @@
 void DOMCacheStorage::keys(KeysPromise&& promise)
 {
     retrieveCaches([this, promise = WTFMove(promise)](Optional<Exception>&& exception) mutable {
-        enqueueTask([this, promise = WTFMove(promise), exception = WTFMove(exception)]() mutable {
-            if (exception) {
-                promise.reject(WTFMove(exception.value()));
-                return;
-            }
+        if (exception) {
+            promise.reject(WTFMove(exception.value()));
+            return;
+        }
 
-            promise.resolve(WTF::map(m_caches, [] (const auto& cache) {
-                return cache->name();
-            }));
-        });
+        promise.resolve(WTF::map(m_caches, [] (const auto& cache) {
+            return cache->name();
+        }));
     });
 }
 
@@ -287,14 +263,4 @@
     return "CacheStorage";
 }
 
-void DOMCacheStorage::enqueueTask(Function<void()>&& task)
-{
-    auto* context = scriptExecutionContext();
-    if (!context)
-        return;
-    context->eventLoop().queueTask(TaskSource::DOMManipulation, *context, [protectedThis = makeRef(*this), pendingActivity = makePendingActivity(*this), task = WTFMove(task)] {
-        task();
-    });
-}
-
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/cache/DOMCacheStorage.h (252262 => 252263)


--- trunk/Source/WebCore/Modules/cache/DOMCacheStorage.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/Modules/cache/DOMCacheStorage.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -59,8 +59,6 @@
     Ref<DOMCache> findCacheOrCreate(DOMCacheEngine::CacheInfo&&);
     Optional<ClientOrigin> origin() const;
 
-    void enqueueTask(Function<void()>&&);
-
     Vector<Ref<DOMCache>> m_caches;
     uint64_t m_updateCounter { 0 };
     Ref<CacheStorageConnection> m_connection;

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp (252262 => 252263)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2019-11-08 22:10:58 UTC (rev 252263)
@@ -39,17 +39,6 @@
 
 namespace WebCore {
 
-void FetchBodyOwner::runNetworkTaskWhenPossible(Function<void()>&& task)
-{
-    auto* context = scriptExecutionContext();
-    if (!context || !scriptExecutionContext()->activeDOMObjectsAreSuspended())
-        return task();
-
-    context->eventLoop().queueTask(TaskSource::Networking, *context, [pendingActivity = makePendingActivity(*this), task = WTFMove(task)] {
-        task();
-    });
-}
-
 FetchBodyOwner::FetchBodyOwner(ScriptExecutionContext& context, Optional<FetchBody>&& body, Ref<FetchHeaders>&& headers)
     : ActiveDOMObject(&context)
     , m_body(WTFMove(body))
@@ -281,15 +270,13 @@
 void FetchBodyOwner::blobLoadingSucceeded()
 {
     ASSERT(!isBodyNull());
-    runNetworkTaskWhenPossible([this]() mutable {
 #if ENABLE(STREAMS_API)
-        if (m_readableStreamSource) {
-            m_readableStreamSource->close();
-            m_readableStreamSource = nullptr;
-        }
+    if (m_readableStreamSource) {
+        m_readableStreamSource->close();
+        m_readableStreamSource = nullptr;
+    }
 #endif
-        m_body->loadingSucceeded();
-    });
+    m_body->loadingSucceeded();
     finishBlobLoading();
 }
 
@@ -296,16 +283,14 @@
 void FetchBodyOwner::blobLoadingFailed()
 {
     ASSERT(!isBodyNull());
-    runNetworkTaskWhenPossible([this]() mutable {
 #if ENABLE(STREAMS_API)
-        if (m_readableStreamSource) {
-            if (!m_readableStreamSource->isCancelling())
-                m_readableStreamSource->error(Exception { TypeError, "Blob loading failed"_s});
-            m_readableStreamSource = nullptr;
-        } else
+    if (m_readableStreamSource) {
+        if (!m_readableStreamSource->isCancelling())
+            m_readableStreamSource->error(Exception { TypeError, "Blob loading failed"_s});
+        m_readableStreamSource = nullptr;
+    } else
 #endif
-            m_body->loadingFailed(Exception { TypeError, "Blob loading failed"_s});
-    });
+        m_body->loadingFailed(Exception { TypeError, "Blob loading failed"_s});
     finishBlobLoading();
 }
 
@@ -314,10 +299,8 @@
     ASSERT(data);
 #if ENABLE(STREAMS_API)
     ASSERT(m_readableStreamSource);
-    runNetworkTaskWhenPossible([this, arrayBuffer = ArrayBuffer::tryCreate(data, size)]() mutable {
-        if (!m_readableStreamSource->enqueue(WTFMove(arrayBuffer)))
-            stop();
-    });
+    if (!m_readableStreamSource->enqueue(ArrayBuffer::tryCreate(data, size)))
+        stop();
 #else
     UNUSED_PARAM(data);
     UNUSED_PARAM(size);

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h (252262 => 252263)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -125,8 +125,6 @@
     Ref<FetchHeaders> m_headers;
 
 private:
-    void runNetworkTaskWhenPossible(Function<void()>&&);
-
     Optional<BlobLoader> m_blobLoader;
     bool m_isBodyOpaque { false };
 

Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp (252262 => 252263)


--- trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp	2019-11-08 22:10:58 UTC (rev 252263)
@@ -230,53 +230,48 @@
 void UserMediaRequest::allow(CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt, CompletionHandler<void()>&& completionHandler)
 {
     RELEASE_LOG(MediaStream, "UserMediaRequest::allow %s %s", audioDevice ? audioDevice.persistentId().utf8().data() : "", videoDevice ? videoDevice.persistentId().utf8().data() : "");
-    auto* document = this->document();
-    if (!document)
-        return completionHandler();
 
-    document->eventLoop().queueTask(TaskSource::UserInteraction, *document, [this, protectedThis = makeRef(*this), audioDevice = WTFMove(audioDevice), videoDevice = WTFMove(videoDevice), deviceIdentifierHashSalt = WTFMove(deviceIdentifierHashSalt), completionHandler = WTFMove(completionHandler)]() mutable {
-        auto callback = [this, protector = makePendingActivity(*this), completionHandler = WTFMove(completionHandler)](RefPtr<MediaStreamPrivate>&& privateStream) mutable {
-            auto scopeExit = makeScopeExit([completionHandler = WTFMove(completionHandler)]() mutable {
-                completionHandler();
-            });
-            if (isContextStopped())
-                return;
+    auto callback = [this, protector = makePendingActivity(*this), completionHandler = WTFMove(completionHandler)](RefPtr<MediaStreamPrivate>&& privateStream) mutable {
+        auto scopeExit = makeScopeExit([completionHandler = WTFMove(completionHandler)]() mutable {
+            completionHandler();
+        });
+        if (isContextStopped())
+            return;
 
-            if (!privateStream) {
-                RELEASE_LOG(MediaStream, "UserMediaRequest::allow failed to create media stream!");
-                deny(MediaAccessDenialReason::HardwareError);
-                return;
-            }
+        if (!privateStream) {
+            RELEASE_LOG(MediaStream, "UserMediaRequest::allow failed to create media stream!");
+            deny(MediaAccessDenialReason::HardwareError);
+            return;
+        }
 
-            auto& document = downcast<Document>(*m_scriptExecutionContext);
-            privateStream->monitorOrientation(document.orientationNotifier());
+        auto& document = downcast<Document>(*m_scriptExecutionContext);
+        privateStream->monitorOrientation(document.orientationNotifier());
 
-            auto stream = MediaStream::create(document, privateStream.releaseNonNull());
-            stream->startProducingData();
+        auto stream = MediaStream::create(document, privateStream.releaseNonNull());
+        stream->startProducingData();
 
-            if (!isMediaStreamCorrectlyStarted(stream)) {
-                deny(MediaAccessDenialReason::HardwareError);
-                return;
-            }
+        if (!isMediaStreamCorrectlyStarted(stream)) {
+            deny(MediaAccessDenialReason::HardwareError);
+            return;
+        }
 
-            ASSERT(document.isCapturing());
-            stream->document()->setHasCaptureMediaStreamTrack();
-            m_promise->resolve(WTFMove(stream));
-        };
+        ASSERT(document.isCapturing());
+        stream->document()->setHasCaptureMediaStreamTrack();
+        m_promise->resolve(WTFMove(stream));
+    };
 
-        auto& document = downcast<Document>(*scriptExecutionContext());
-        document.setDeviceIDHashSalt(deviceIdentifierHashSalt);
+    auto& document = downcast<Document>(*scriptExecutionContext());
+    document.setDeviceIDHashSalt(deviceIdentifierHashSalt);
 
-        RealtimeMediaSourceCenter::singleton().createMediaStream(document.logger(), WTFMove(callback), WTFMove(deviceIdentifierHashSalt), WTFMove(audioDevice), WTFMove(videoDevice), m_request);
+    RealtimeMediaSourceCenter::singleton().createMediaStream(document.logger(), WTFMove(callback), WTFMove(deviceIdentifierHashSalt), WTFMove(audioDevice), WTFMove(videoDevice), m_request);
 
-        if (!m_scriptExecutionContext)
-            return;
+    if (!m_scriptExecutionContext)
+        return;
 
 #if ENABLE(WEB_RTC)
-        if (auto* page = document.page())
-            page->rtcController().disableICECandidateFilteringForDocument(document);
+    if (auto* page = document.page())
+        page->rtcController().disableICECandidateFilteringForDocument(document);
 #endif
-    });
 }
 
 void UserMediaRequest::deny(MediaAccessDenialReason reason, const String& message)
@@ -324,12 +319,10 @@
         break;
     }
 
-    document()->eventLoop().queueTask(TaskSource::UserInteraction, *document(), [this, protectedThis = makeRef(*this), code, message]() mutable {
-        if (!message.isEmpty())
-            m_promise->reject(code, message);
-        else
-            m_promise->reject(code);
-    });
+    if (!message.isEmpty())
+        m_promise->reject(code, message);
+    else
+        m_promise->reject(code);
 }
 
 void UserMediaRequest::stop()

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (252262 => 252263)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-11-08 22:10:58 UTC (rev 252263)
@@ -1250,6 +1250,7 @@
 		46EF142C1F97B7D800C2A524 /* ServiceWorkerClients.h in Headers */ = {isa = PBXBuildFile; fileRef = 46EF14221F97B7BA00C2A524 /* ServiceWorkerClients.h */; };
 		46EF142D1F97B7D800C2A524 /* ServiceWorkerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 46EF14241F97B7BA00C2A524 /* ServiceWorkerClient.h */; };
 		46EFAF121E5FB9F100E7F34B /* LowPowerModeNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 46EFAF101E5FB9E100E7F34B /* LowPowerModeNotifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		46F02A1A23737F8300106A64 /* AbstractEventLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B0ABCA123679AB300B45085 /* AbstractEventLoop.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		46FCB6181A70820E00C5A21E /* DiagnosticLoggingKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = CD37B37515C1A7E1006DC898 /* DiagnosticLoggingKeys.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		490707E71219C04300D90E51 /* ANGLEWebKitBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 490707E51219C04300D90E51 /* ANGLEWebKitBridge.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		49291E4B134172C800E753DE /* ImageRenderingMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 49291E4A134172C800E753DE /* ImageRenderingMode.h */; };
@@ -28743,6 +28744,7 @@
 				7CD0E2B81F80A4820016A4CE /* AbortController.h in Headers */,
 				7CD0E2BF1F80A56E0016A4CE /* AbortSignal.h in Headers */,
 				46B95195207D633400A7D2DD /* AbstractDOMWindow.h in Headers */,
+				46F02A1A23737F8300106A64 /* AbstractEventLoop.h in Headers */,
 				46B95196207D633A00A7D2DD /* AbstractFrame.h in Headers */,
 				F48223131E386E240066FC79 /* AbstractPasteboard.h in Headers */,
 				41E1B1D10FF5986900576B3B /* AbstractWorker.h in Headers */,

Modified: trunk/Source/WebCore/bindings/IDLTypes.h (252262 => 252263)


--- trunk/Source/WebCore/bindings/IDLTypes.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/bindings/IDLTypes.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -43,7 +43,6 @@
 class DataView;
 class JSValue;
 class JSObject;
-template<typename> class Strong;
 }
 
 namespace WebCore {

Modified: trunk/Source/WebCore/bindings/js/JSDOMGuardedObject.h (252262 => 252263)


--- trunk/Source/WebCore/bindings/js/JSDOMGuardedObject.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/bindings/js/JSDOMGuardedObject.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -51,7 +51,7 @@
     DOMGuardedObject(JSDOMGlobalObject&, JSC::JSCell&);
 
     void contextDestroyed() override;
-    bool isEmpty() { return !m_guarded; }
+    bool isEmpty() const { return !m_guarded; }
 
     JSC::Weak<JSC::JSCell> m_guarded;
     JSC::Weak<JSDOMGlobalObject> m_globalObject;

Modified: trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp (252262 => 252263)


--- trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp	2019-11-08 22:10:58 UTC (rev 252263)
@@ -33,6 +33,7 @@
 #include <_javascript_Core/Exception.h>
 #include <_javascript_Core/JSONObject.h>
 #include <_javascript_Core/JSPromiseConstructor.h>
+#include <_javascript_Core/Strong.h>
 
 namespace WebCore {
 using namespace JSC;
@@ -45,9 +46,18 @@
 
 void DeferredPromise::callFunction(JSGlobalObject& lexicalGlobalObject, ResolveMode mode, JSValue resolution)
 {
-    if (!canInvokeCallback())
+    if (shouldIgnoreRequestToFulfill())
         return;
 
+    if (activeDOMObjectsAreSuspended()) {
+        JSC::Strong<JSC::Unknown, ShouldStrongDestructorGrabLock::Yes> strongResolution(lexicalGlobalObject.vm(), resolution);
+        scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, *scriptExecutionContext(), [this, protectedThis = makeRef(*this), mode, strongResolution = WTFMove(strongResolution)]() mutable {
+            if (!shouldIgnoreRequestToFulfill())
+                callFunction(*globalObject(), mode, strongResolution.get());
+        });
+        return;
+    }
+
     // FIXME: We could have error since any JS call can throw stack-overflow errors.
     // https://bugs.webkit.org/show_bug.cgi?id=203402
     switch (mode) {
@@ -65,15 +75,22 @@
 
 void DeferredPromise::whenSettled(Function<void()>&& callback)
 {
-    if (isSuspended())
+    if (shouldIgnoreRequestToFulfill())
         return;
 
+    if (activeDOMObjectsAreSuspended()) {
+        scriptExecutionContext()->eventLoop().queueTask(TaskSource::Networking, *scriptExecutionContext(), [this, protectedThis = makeRef(*this), callback = WTFMove(callback)]() mutable {
+            whenSettled(WTFMove(callback));
+        });
+        return;
+    }
+
     DOMPromise::whenPromiseIsSettled(globalObject(), deferred(), WTFMove(callback));
 }
 
 void DeferredPromise::reject()
 {
-    if (isSuspended())
+    if (shouldIgnoreRequestToFulfill())
         return;
 
     ASSERT(deferred());
@@ -85,7 +102,7 @@
 
 void DeferredPromise::reject(std::nullptr_t)
 {
-    if (isSuspended())
+    if (shouldIgnoreRequestToFulfill())
         return;
 
     ASSERT(deferred());
@@ -97,7 +114,7 @@
 
 void DeferredPromise::reject(Exception exception)
 {
-    if (isSuspended())
+    if (shouldIgnoreRequestToFulfill())
         return;
 
     ASSERT(deferred());
@@ -129,7 +146,7 @@
 
 void DeferredPromise::reject(ExceptionCode ec, const String& message)
 {
-    if (isSuspended())
+    if (shouldIgnoreRequestToFulfill())
         return;
 
     ASSERT(deferred());
@@ -162,7 +179,7 @@
 
 void DeferredPromise::reject(const JSC::PrivateName& privateName)
 {
-    if (isSuspended())
+    if (shouldIgnoreRequestToFulfill())
         return;
 
     ASSERT(deferred());

Modified: trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h (252262 => 252263)


--- trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -25,9 +25,11 @@
 
 #pragma once
 
+#include "AbstractEventLoop.h"
 #include "ExceptionOr.h"
 #include "JSDOMConvert.h"
 #include "JSDOMGuardedObject.h"
+#include "ScriptExecutionContext.h"
 #include <_javascript_Core/CatchScope.h>
 #include <_javascript_Core/JSPromise.h>
 
@@ -58,8 +60,9 @@
     template<class IDLType>
     void resolve(typename IDLType::ParameterType value)
     {
-        if (isSuspended())
+        if (shouldIgnoreRequestToFulfill())
             return;
+
         ASSERT(deferred());
         ASSERT(globalObject());
         JSC::JSGlobalObject* lexicalGlobalObject = globalObject();
@@ -69,8 +72,9 @@
 
     void resolve()
     {
-        if (isSuspended())
+        if (shouldIgnoreRequestToFulfill())
             return;
+
         ASSERT(deferred());
         ASSERT(globalObject());
         JSC::JSGlobalObject* lexicalGlobalObject = globalObject();
@@ -81,8 +85,9 @@
     template<class IDLType>
     void resolveWithNewlyCreated(typename IDLType::ParameterType value)
     {
-        if (isSuspended())
+        if (shouldIgnoreRequestToFulfill())
             return;
+
         ASSERT(deferred());
         ASSERT(globalObject());
         JSC::JSGlobalObject* lexicalGlobalObject = globalObject();
@@ -93,8 +98,9 @@
     template<class IDLType>
     void resolveCallbackValueWithNewlyCreated(const Function<typename IDLType::InnerParameterType(ScriptExecutionContext&)>& createValue)
     {
-        if (isSuspended())
+        if (shouldIgnoreRequestToFulfill())
             return;
+
         ASSERT(deferred());
         ASSERT(globalObject());
         auto* lexicalGlobalObject = globalObject();
@@ -105,8 +111,9 @@
     template<class IDLType>
     void reject(typename IDLType::ParameterType value)
     {
-        if (isSuspended())
+        if (shouldIgnoreRequestToFulfill())
             return;
+
         ASSERT(deferred());
         ASSERT(globalObject());
         JSC::JSGlobalObject* lexicalGlobalObject = globalObject();
@@ -123,8 +130,9 @@
     template<typename Callback>
     void resolveWithCallback(Callback callback)
     {
-        if (isSuspended())
+        if (shouldIgnoreRequestToFulfill())
             return;
+
         ASSERT(deferred());
         ASSERT(globalObject());
         JSC::JSGlobalObject* lexicalGlobalObject = globalObject();
@@ -135,8 +143,9 @@
     template<typename Callback>
     void rejectWithCallback(Callback callback)
     {
-        if (isSuspended())
+        if (shouldIgnoreRequestToFulfill())
             return;
+
         ASSERT(deferred());
         ASSERT(globalObject());
         JSC::JSGlobalObject* lexicalGlobalObject = globalObject();
@@ -155,6 +164,8 @@
     {
     }
 
+    bool shouldIgnoreRequestToFulfill() const { return isEmpty() || activeDOMObjectAreStopped(); }
+
     JSC::JSPromise* deferred() const { return guarded(); }
 
     enum class ResolveMode { Resolve, Reject };

Modified: trunk/Source/WebCore/css/FontFaceSet.cpp (252262 => 252263)


--- trunk/Source/WebCore/css/FontFaceSet.cpp	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/css/FontFaceSet.cpp	2019-11-08 22:10:58 UTC (rev 252263)
@@ -199,22 +199,14 @@
 void FontFaceSet::didFirstLayout()
 {
     m_isFirstLayoutDone = true;
-    if (!m_backing->hasActiveFontFaces() && !m_readyPromise->isFulfilled()) {
-        queueTaskKeepingObjectAlive(*this, TaskSource::FontLoading, [this] {
-            if (!m_readyPromise->isFulfilled())
-                m_readyPromise->resolve(*this);
-        });
-    }
+    if (!m_backing->hasActiveFontFaces() && !m_readyPromise->isFulfilled())
+        m_readyPromise->resolve(*this);
 }
 
 void FontFaceSet::completedLoading()
 {
-    if (m_isFirstLayoutDone && !m_readyPromise->isFulfilled()) {
-        queueTaskKeepingObjectAlive(*this, TaskSource::FontLoading, [this] {
-            if (!m_readyPromise->isFulfilled())
-                m_readyPromise->resolve(*this);
-        });
-    }
+    if (m_isFirstLayoutDone && !m_readyPromise->isFulfilled())
+        m_readyPromise->resolve(*this);
 }
 
 void FontFaceSet::faceFinished(CSSFontFace& face, CSSFontFace::Status newStatus)
@@ -226,22 +218,20 @@
     if (pendingPromises.isEmpty())
         return;
 
-    queueTaskKeepingObjectAlive(*this, TaskSource::FontLoading, [pendingPromises = WTFMove(pendingPromises), newStatus] {
-        for (auto& pendingPromise : pendingPromises) {
-            if (pendingPromise->hasReachedTerminalState)
-                continue;
-            if (newStatus == CSSFontFace::Status::Success) {
-                if (pendingPromise->hasOneRef()) {
-                    pendingPromise->promise->resolve(pendingPromise->faces);
-                    pendingPromise->hasReachedTerminalState = true;
-                }
-            } else {
-                ASSERT(newStatus == CSSFontFace::Status::Failure);
-                pendingPromise->promise->reject(NetworkError);
+    for (auto& pendingPromise : pendingPromises) {
+        if (pendingPromise->hasReachedTerminalState)
+            continue;
+        if (newStatus == CSSFontFace::Status::Success) {
+            if (pendingPromise->hasOneRef()) {
+                pendingPromise->promise->resolve(pendingPromise->faces);
                 pendingPromise->hasReachedTerminalState = true;
             }
+        } else {
+            ASSERT(newStatus == CSSFontFace::Status::Failure);
+            pendingPromise->promise->reject(NetworkError);
+            pendingPromise->hasReachedTerminalState = true;
         }
-    });
+    }
 }
 
 FontFaceSet& FontFaceSet::readyPromiseResolve()

Modified: trunk/Source/WebCore/dom/ActiveDOMCallback.cpp (252262 => 252263)


--- trunk/Source/WebCore/dom/ActiveDOMCallback.cpp	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/dom/ActiveDOMCallback.cpp	2019-11-08 22:10:58 UTC (rev 252263)
@@ -48,4 +48,16 @@
     return context && !context->activeDOMObjectsAreSuspended() && !context->activeDOMObjectsAreStopped();
 }
 
+bool ActiveDOMCallback::activeDOMObjectsAreSuspended() const
+{
+    auto* context = scriptExecutionContext();
+    return context && context->activeDOMObjectsAreSuspended();
+}
+
+bool ActiveDOMCallback::activeDOMObjectAreStopped() const
+{
+    auto* context = scriptExecutionContext();
+    return !context || context->activeDOMObjectsAreStopped();
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/ActiveDOMCallback.h (252262 => 252263)


--- trunk/Source/WebCore/dom/ActiveDOMCallback.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/dom/ActiveDOMCallback.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -51,6 +51,9 @@
     virtual ~ActiveDOMCallback();
 
     WEBCORE_EXPORT bool canInvokeCallback() const;
+
+    WEBCORE_EXPORT bool activeDOMObjectsAreSuspended() const;
+    WEBCORE_EXPORT bool activeDOMObjectAreStopped() const;
     
     virtual void visitJSFunction(JSC::SlotVisitor&) { }
 };

Modified: trunk/Source/WebCore/dom/Element.h (252262 => 252263)


--- trunk/Source/WebCore/dom/Element.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/dom/Element.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -34,6 +34,7 @@
 #include "ShadowRootMode.h"
 #include "SimulatedClickOptions.h"
 #include "StyleChange.h"
+#include <_javascript_Core/Strong.h>
 
 namespace WebCore {
 

Modified: trunk/Source/WebCore/dom/ScriptExecutionContext.h (252262 => 252263)


--- trunk/Source/WebCore/dom/ScriptExecutionContext.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/dom/ScriptExecutionContext.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -44,7 +44,6 @@
 class Exception;
 class JSPromise;
 class VM;
-template<typename> class Strong;
 }
 
 namespace Inspector {

Modified: trunk/Source/WebCore/page/DOMWindow.h (252262 => 252263)


--- trunk/Source/WebCore/page/DOMWindow.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/page/DOMWindow.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -37,6 +37,7 @@
 #include "ScrollTypes.h"
 #include "Supplementable.h"
 #include <_javascript_Core/HandleTypes.h>
+#include <_javascript_Core/Strong.h>
 #include <wtf/Function.h>
 #include <wtf/HashSet.h>
 #include <wtf/WeakPtr.h>
@@ -45,7 +46,6 @@
 class CallFrame;
 class JSObject;
 class JSValue;
-template<typename> class Strong;
 }
 
 namespace WebCore {

Modified: trunk/Source/WebCore/page/RemoteDOMWindow.h (252262 => 252263)


--- trunk/Source/WebCore/page/RemoteDOMWindow.h	2019-11-08 21:43:04 UTC (rev 252262)
+++ trunk/Source/WebCore/page/RemoteDOMWindow.h	2019-11-08 22:10:58 UTC (rev 252263)
@@ -27,6 +27,7 @@
 
 #include "AbstractDOMWindow.h"
 #include "RemoteFrame.h"
+#include <_javascript_Core/Strong.h>
 #include <wtf/IsoMalloc.h>
 #include <wtf/TypeCasts.h>
 
@@ -35,7 +36,6 @@
 class JSGlobalObject;
 class JSObject;
 class JSValue;
-template<typename> class Strong;
 }
 
 namespace WebCore {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to