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 {