Title: [205257] trunk/Source
Revision
205257
Author
[email protected]
Date
2016-08-31 11:36:46 -0700 (Wed, 31 Aug 2016)

Log Message

Avoid using strong reference in JSDOMPromise’s DeferredWrapper
https://bugs.webkit.org/show_bug.cgi?id=161426
<rdar://problem/28091123>

Reviewed by Geoffrey Garen.

Replace JSC::Strong in DeferredWrapper by JSC::Weak, and make the global object own JSPromiseDeferred.

DeferredWrapper adds itself to JSDOMGlobalObject's newly added HashSet when it's created and clears itself
from the HashSet inside its destructor as well as when the promise is resolved or rejected.
This is so that JSDOMGlobalObject's visitChildren can visit every live DeferredWrapper.

Because this operation is rather expense, this patch turns DeferredWrapper into a RefCounted object to avoid
HashMap churns. Most of code changes in this patch is due to this type change, and the fact lambda cannot
capture Ref<DeferredWrapper> since its copy constructor doesn't exist.

We also create a write barrier from the global object to JSPromiseDeferred so that they won't be collected
during an eden collection when it happens before JSDOMGlobalObject's visitChildren is invoked.

Note that it's possible for the entire DOM wrapper world of the promise to go away before the promise is
resolved or rejected by a ref-counted C++ object. In this case, m_deferred and m_globalObject become dead.
Various member resolve* and reject functions of DeferredWrapper have been modified to check this condition.

Because JSDOMGlobalObject can be finalized before DeferredWrapper is finalized. DeferredWrapper's destructor,
which calls DeferredWrapper::clear, should only remove itself from m_globalObject when m_globalObject is alive.

Finally, this patch makes DeferredWrapper inherit from ActiveDOMCallback so that it won't try to execute scripts
when the active DOM objects have been suspended; e.g. after a page navigation.

No new tests since there should be no author/user visible behavioral change.

* Modules/applepay/ApplePaySession.cpp:
(WebCore::ApplePaySession::canMakePaymentsWithActiveCard):
* Modules/applepay/ApplePaySession.h:
* Modules/fetch/DOMWindowFetch.cpp:
(WebCore::DOMWindowFetch::fetch):
* Modules/fetch/DOMWindowFetch.h:
* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::arrayBuffer):
(WebCore::FetchBody::blob):
(WebCore::FetchBody::json):
(WebCore::FetchBody::text):
(WebCore::FetchBody::consume):
(WebCore::FetchBody::consumeArrayBuffer):
(WebCore::FetchBody::consumeArrayBufferView):
(WebCore::FetchBody::consumeText):
(WebCore::FetchBody::consumeBlob):
(WebCore::FetchBody::loadingFailed):
(WebCore::FetchBody::loadingSucceeded):
* Modules/fetch/FetchBody.h:
(WebCore::FetchBody::formData):
(WebCore::FetchBody::cleanConsumePromise):
(WebCore::FetchBody): Use RefPtr<DeferredWrapper> instead of Optional<DeferredWrapper> now that DeferredWrapper
is ref counted. Perhaps we could use Optional<Ref<DeferredWrapper>> here but that seemed rather verbose.
* Modules/fetch/FetchBodyConsumer.cpp:
(WebCore::FetchBodyConsumer::resolveWithData):
(WebCore::FetchBodyConsumer::resolve):
* Modules/fetch/FetchBodyConsumer.h:
* Modules/fetch/FetchBodyOwner.cpp:
(WebCore::FetchBodyOwner::arrayBuffer):
(WebCore::FetchBodyOwner::blob):
(WebCore::FetchBodyOwner::formData):
(WebCore::FetchBodyOwner::json):
(WebCore::FetchBodyOwner::text):
* Modules/fetch/FetchBodyOwner.h:
* Modules/fetch/FetchResponse.cpp:
(WebCore::FetchResponse::consume):
(WebCore::FetchResponse::finishConsumingStream):
* Modules/fetch/FetchResponse.h:
* Modules/fetch/WorkerGlobalScopeFetch.cpp:
(WebCore::WorkerGlobalScopeFetch::fetch):
* Modules/fetch/WorkerGlobalScopeFetch.h:
* Modules/mediastream/UserMediaPermissionCheck.h:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::JSDOMGlobalObject::~JSDOMGlobalObject): Added.
(WebCore::JSDOMGlobalObject::visitChildren): Added visits to each JSPromiseDeferred owned by this global object.
* bindings/js/JSDOMGlobalObject.h:
(WebCore::JSDOMGlobalObject::deferredWrappers): Added. This map is only used by JSDOMGlobalObject's visitChildren.
* bindings/js/JSDOMPromise.cpp:
(WebCore::DeferredWrapper::DeferredWrapper):
(WebCore::DeferredWrapper::~DeferredWrapper): Calls clear. When the global object has already been finalized,
m_globalObject is dead. In that case, there is no need to remove itself from the global object. When m_deferred
has been cleared, either clear() has already been called (1) or the callback is dead (2). Since (2) happens only
when the global object itself is dead (as its visitChildren would have visited m_deferred otherwise), again, there
is no need to remove itself from global object.
(WebCore::DeferredWrapper::clear): Added. Clears m_deferred and removes itself from JSDOMGlobalObject.
(WebCore::DeferredWrapper::contextDestroyed): ScriptExecutionContext has been destroyed. We must call clear().
(WebCore::DeferredWrapper::callFunction): Check canInvokeCallback in ActiveDOMCallback.
(WebCore::DeferredWrapper::reject): Exit early when isSuspended() is true. See below.
(WebCore::rejectPromiseWithExceptionIfAny):
(WebCore::fulfillPromiseWithJSON):
(WebCore::fulfillPromiseWithArrayBuffer):
* bindings/js/JSDOMPromise.h:
(WebCore::DeferredWrapper::create): Added.
(WebCore::DeferredWrapper::isSuspended): Added. Returns true iff the DOM wrapper world has gone away or active DOM
objects have been suspended.
(WebCore::DeferredWrapper::globalObject): Made this inline.
(WebCore::DeferredWrapper::visitAggregate): Added. Called by JSDOMGlobalObject::visitChildren.
(WebCore::DOMPromise::resolve):
(WebCore::DOMPromise::reject):
(WebCore::DeferredWrapper::resolveWithValue): Exit early when isSuspended() is true.
(WebCore::DeferredWrapper::resolveWithNewlyCreated): Ditto.
(WebCore::DeferredWrapper::rejectWithValue): Ditto.
(WebCore::DeferredWrapper::resolve): Ditto.
(WebCore::DeferredWrapper::reject): Ditto.
* bindings/js/JSFontFaceCustom.cpp:
(WebCore::JSFontFace::loaded):
* bindings/js/JSFontFaceSetCustom.cpp:
(WebCore::JSFontFaceSet::ready):
* bindings/js/JSMediaDevicesCustom.cpp:
(WebCore::JSMediaDevices::getUserMedia):
* bindings/js/JSReadableStreamSourceCustom.cpp:
(WebCore::JSReadableStreamSource::start):
* bindings/js/JSWebKitSubtleCryptoCustom.cpp:
(WebCore::JSWebKitSubtleCrypto::encrypt):
(WebCore::JSWebKitSubtleCrypto::decrypt):
(WebCore::JSWebKitSubtleCrypto::sign):
(WebCore::JSWebKitSubtleCrypto::verify):
(WebCore::JSWebKitSubtleCrypto::digest):
(WebCore::JSWebKitSubtleCrypto::generateKey):
(WebCore::JSWebKitSubtleCrypto::importKey):
(WebCore::JSWebKitSubtleCrypto::exportKey):
(WebCore::JSWebKitSubtleCrypto::wrapKey):
(WebCore::JSWebKitSubtleCrypto::unwrapKey):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateReturnParameters):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (205256 => 205257)


--- trunk/Source/WebCore/ChangeLog	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/ChangeLog	2016-08-31 18:36:46 UTC (rev 205257)
@@ -1,3 +1,133 @@
+2016-08-30  Ryosuke Niwa  <[email protected]>
+
+        Avoid using strong reference in JSDOMPromise’s DeferredWrapper
+        https://bugs.webkit.org/show_bug.cgi?id=161426
+        <rdar://problem/28091123>
+
+        Reviewed by Geoffrey Garen.
+
+        Replace JSC::Strong in DeferredWrapper by JSC::Weak, and make the global object own JSPromiseDeferred.
+
+        DeferredWrapper adds itself to JSDOMGlobalObject's newly added HashSet when it's created and clears itself
+        from the HashSet inside its destructor as well as when the promise is resolved or rejected.
+        This is so that JSDOMGlobalObject's visitChildren can visit every live DeferredWrapper.
+
+        Because this operation is rather expense, this patch turns DeferredWrapper into a RefCounted object to avoid
+        HashMap churns. Most of code changes in this patch is due to this type change, and the fact lambda cannot
+        capture Ref<DeferredWrapper> since its copy constructor doesn't exist.
+
+        We also create a write barrier from the global object to JSPromiseDeferred so that they won't be collected
+        during an eden collection when it happens before JSDOMGlobalObject's visitChildren is invoked.
+
+        Note that it's possible for the entire DOM wrapper world of the promise to go away before the promise is
+        resolved or rejected by a ref-counted C++ object. In this case, m_deferred and m_globalObject become dead.
+        Various member resolve* and reject functions of DeferredWrapper have been modified to check this condition.
+
+        Because JSDOMGlobalObject can be finalized before DeferredWrapper is finalized. DeferredWrapper's destructor,
+        which calls DeferredWrapper::clear, should only remove itself from m_globalObject when m_globalObject is alive.
+
+        Finally, this patch makes DeferredWrapper inherit from ActiveDOMCallback so that it won't try to execute scripts
+        when the active DOM objects have been suspended; e.g. after a page navigation.
+
+        No new tests since there should be no author/user visible behavioral change.
+
+        * Modules/applepay/ApplePaySession.cpp:
+        (WebCore::ApplePaySession::canMakePaymentsWithActiveCard):
+        * Modules/applepay/ApplePaySession.h:
+        * Modules/fetch/DOMWindowFetch.cpp:
+        (WebCore::DOMWindowFetch::fetch):
+        * Modules/fetch/DOMWindowFetch.h:
+        * Modules/fetch/FetchBody.cpp:
+        (WebCore::FetchBody::arrayBuffer):
+        (WebCore::FetchBody::blob):
+        (WebCore::FetchBody::json):
+        (WebCore::FetchBody::text):
+        (WebCore::FetchBody::consume):
+        (WebCore::FetchBody::consumeArrayBuffer):
+        (WebCore::FetchBody::consumeArrayBufferView):
+        (WebCore::FetchBody::consumeText):
+        (WebCore::FetchBody::consumeBlob):
+        (WebCore::FetchBody::loadingFailed):
+        (WebCore::FetchBody::loadingSucceeded):
+        * Modules/fetch/FetchBody.h:
+        (WebCore::FetchBody::formData):
+        (WebCore::FetchBody::cleanConsumePromise):
+        (WebCore::FetchBody): Use RefPtr<DeferredWrapper> instead of Optional<DeferredWrapper> now that DeferredWrapper
+        is ref counted. Perhaps we could use Optional<Ref<DeferredWrapper>> here but that seemed rather verbose.
+        * Modules/fetch/FetchBodyConsumer.cpp:
+        (WebCore::FetchBodyConsumer::resolveWithData):
+        (WebCore::FetchBodyConsumer::resolve):
+        * Modules/fetch/FetchBodyConsumer.h:
+        * Modules/fetch/FetchBodyOwner.cpp:
+        (WebCore::FetchBodyOwner::arrayBuffer):
+        (WebCore::FetchBodyOwner::blob):
+        (WebCore::FetchBodyOwner::formData):
+        (WebCore::FetchBodyOwner::json):
+        (WebCore::FetchBodyOwner::text):
+        * Modules/fetch/FetchBodyOwner.h:
+        * Modules/fetch/FetchResponse.cpp:
+        (WebCore::FetchResponse::consume):
+        (WebCore::FetchResponse::finishConsumingStream):
+        * Modules/fetch/FetchResponse.h:
+        * Modules/fetch/WorkerGlobalScopeFetch.cpp:
+        (WebCore::WorkerGlobalScopeFetch::fetch):
+        * Modules/fetch/WorkerGlobalScopeFetch.h:
+        * Modules/mediastream/UserMediaPermissionCheck.h:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::~JSDOMGlobalObject): Added.
+        (WebCore::JSDOMGlobalObject::visitChildren): Added visits to each JSPromiseDeferred owned by this global object.
+        * bindings/js/JSDOMGlobalObject.h:
+        (WebCore::JSDOMGlobalObject::deferredWrappers): Added. This map is only used by JSDOMGlobalObject's visitChildren.
+        * bindings/js/JSDOMPromise.cpp:
+        (WebCore::DeferredWrapper::DeferredWrapper):
+        (WebCore::DeferredWrapper::~DeferredWrapper): Calls clear. When the global object has already been finalized,
+        m_globalObject is dead. In that case, there is no need to remove itself from the global object. When m_deferred
+        has been cleared, either clear() has already been called (1) or the callback is dead (2). Since (2) happens only
+        when the global object itself is dead (as its visitChildren would have visited m_deferred otherwise), again, there
+        is no need to remove itself from global object.
+        (WebCore::DeferredWrapper::clear): Added. Clears m_deferred and removes itself from JSDOMGlobalObject.
+        (WebCore::DeferredWrapper::contextDestroyed): ScriptExecutionContext has been destroyed. We must call clear().
+        (WebCore::DeferredWrapper::callFunction): Check canInvokeCallback in ActiveDOMCallback.
+        (WebCore::DeferredWrapper::reject): Exit early when isSuspended() is true. See below.
+        (WebCore::rejectPromiseWithExceptionIfAny):
+        (WebCore::fulfillPromiseWithJSON):
+        (WebCore::fulfillPromiseWithArrayBuffer):
+        * bindings/js/JSDOMPromise.h:
+        (WebCore::DeferredWrapper::create): Added.
+        (WebCore::DeferredWrapper::isSuspended): Added. Returns true iff the DOM wrapper world has gone away or active DOM
+        objects have been suspended.
+        (WebCore::DeferredWrapper::globalObject): Made this inline.
+        (WebCore::DeferredWrapper::visitAggregate): Added. Called by JSDOMGlobalObject::visitChildren.
+        (WebCore::DOMPromise::resolve):
+        (WebCore::DOMPromise::reject):
+        (WebCore::DeferredWrapper::resolveWithValue): Exit early when isSuspended() is true.
+        (WebCore::DeferredWrapper::resolveWithNewlyCreated): Ditto.
+        (WebCore::DeferredWrapper::rejectWithValue): Ditto.
+        (WebCore::DeferredWrapper::resolve): Ditto.
+        (WebCore::DeferredWrapper::reject): Ditto.
+        * bindings/js/JSFontFaceCustom.cpp:
+        (WebCore::JSFontFace::loaded):
+        * bindings/js/JSFontFaceSetCustom.cpp:
+        (WebCore::JSFontFaceSet::ready):
+        * bindings/js/JSMediaDevicesCustom.cpp:
+        (WebCore::JSMediaDevices::getUserMedia):
+        * bindings/js/JSReadableStreamSourceCustom.cpp:
+        (WebCore::JSReadableStreamSource::start):
+        * bindings/js/JSWebKitSubtleCryptoCustom.cpp:
+        (WebCore::JSWebKitSubtleCrypto::encrypt):
+        (WebCore::JSWebKitSubtleCrypto::decrypt):
+        (WebCore::JSWebKitSubtleCrypto::sign):
+        (WebCore::JSWebKitSubtleCrypto::verify):
+        (WebCore::JSWebKitSubtleCrypto::digest):
+        (WebCore::JSWebKitSubtleCrypto::generateKey):
+        (WebCore::JSWebKitSubtleCrypto::importKey):
+        (WebCore::JSWebKitSubtleCrypto::exportKey):
+        (WebCore::JSWebKitSubtleCrypto::wrapKey):
+        (WebCore::JSWebKitSubtleCrypto::unwrapKey):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateReturnParameters):
+
 2016-08-31  Youenn Fablet  <[email protected]>
 
         [Fetch API] Request construction failure should not set "bodyUsed"

Modified: trunk/Source/WebCore/Modules/applepay/ApplePaySession.cpp (205256 => 205257)


--- trunk/Source/WebCore/Modules/applepay/ApplePaySession.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/applepay/ApplePaySession.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -733,7 +733,7 @@
     return paymentCoordinator.canMakePayments();
 }
 
-void ApplePaySession::canMakePaymentsWithActiveCard(ScriptExecutionContext& scriptExecutionContext, const String& merchantIdentifier, DeferredWrapper&& promise, ExceptionCode& ec)
+void ApplePaySession::canMakePaymentsWithActiveCard(ScriptExecutionContext& scriptExecutionContext, const String& merchantIdentifier, Ref<DeferredWrapper>&& passedPromise, ExceptionCode& ec)
 {
     auto& document = downcast<Document>(scriptExecutionContext);
     DOMWindow& window = *document.domWindow();
@@ -745,12 +745,13 @@
         return;
     }
 
+    RefPtr<DeferredWrapper> promise(WTFMove(passedPromise));
     if (!shouldDiscloseApplePayCapability(document)) {
         auto& paymentCoordinator = document.frame()->mainFrame().paymentCoordinator();
         bool canMakePayments = paymentCoordinator.canMakePayments();
 
         RunLoop::main().dispatch([promise, canMakePayments]() mutable {
-            promise.resolve(canMakePayments);
+            promise->resolve(canMakePayments);
         });
         return;
     }
@@ -758,7 +759,7 @@
     auto& paymentCoordinator = document.frame()->mainFrame().paymentCoordinator();
 
     paymentCoordinator.canMakePaymentsWithActiveCard(merchantIdentifier, document.domain(), [promise](bool canMakePayments) mutable {
-        promise.resolve(canMakePayments);
+        promise->resolve(canMakePayments);
     });
 }
 

Modified: trunk/Source/WebCore/Modules/applepay/ApplePaySession.h (205256 => 205257)


--- trunk/Source/WebCore/Modules/applepay/ApplePaySession.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/applepay/ApplePaySession.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -63,7 +63,7 @@
 
     static bool supportsVersion(ScriptExecutionContext&, unsigned version, ExceptionCode&);
     static bool canMakePayments(ScriptExecutionContext&, ExceptionCode&);
-    static void canMakePaymentsWithActiveCard(ScriptExecutionContext&, const String& merchantIdentifier, DeferredWrapper&&, ExceptionCode&);
+    static void canMakePaymentsWithActiveCard(ScriptExecutionContext&, const String& merchantIdentifier, Ref<DeferredWrapper>&&, ExceptionCode&);
 
     void begin(ExceptionCode&);
     void abort(ExceptionCode&);

Modified: trunk/Source/WebCore/Modules/fetch/DOMWindowFetch.cpp (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/DOMWindowFetch.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/DOMWindowFetch.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -37,7 +37,7 @@
 
 namespace WebCore {
 
-void DOMWindowFetch::fetch(DOMWindow& window, FetchRequest& request, DeferredWrapper&& promise)
+void DOMWindowFetch::fetch(DOMWindow& window, FetchRequest& request, DOMPromise<FetchResponse>&& promise)
 {
     if (!window.scriptExecutionContext())
         return;

Modified: trunk/Source/WebCore/Modules/fetch/DOMWindowFetch.h (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/DOMWindowFetch.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/DOMWindowFetch.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -30,6 +30,7 @@
 
 #if ENABLE(FETCH_API)
 
+#include "JSDOMPromise.h"
 #include <wtf/Forward.h>
 
 namespace WebCore {
@@ -38,10 +39,11 @@
 class DeferredWrapper;
 class Dictionary;
 class FetchRequest;
+class FetchResponse;
 
 class DOMWindowFetch {
 public:
-    static void fetch(DOMWindow&, FetchRequest&, DeferredWrapper&&);
+    static void fetch(DOMWindow&, FetchRequest&, DOMPromise<FetchResponse>&&);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.cpp (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/FetchBody.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -124,7 +124,7 @@
         headers.fastSet(HTTPHeaderName::ContentType, m_contentType);
 }
 
-void FetchBody::arrayBuffer(FetchBodyOwner& owner, DeferredWrapper&& promise)
+void FetchBody::arrayBuffer(FetchBodyOwner& owner, Ref<DeferredWrapper>&& promise)
 {
     ASSERT(m_type != Type::None);
     m_consumer.setType(FetchBodyConsumer::Type::ArrayBuffer);
@@ -131,7 +131,7 @@
     consume(owner, WTFMove(promise));
 }
 
-void FetchBody::blob(FetchBodyOwner& owner, DeferredWrapper&& promise)
+void FetchBody::blob(FetchBodyOwner& owner, Ref<DeferredWrapper>&& promise)
 {
     ASSERT(m_type != Type::None);
     m_consumer.setType(FetchBodyConsumer::Type::Blob);
@@ -139,12 +139,12 @@
     consume(owner, WTFMove(promise));
 }
 
-void FetchBody::json(FetchBodyOwner& owner, DeferredWrapper&& promise)
+void FetchBody::json(FetchBodyOwner& owner, Ref<DeferredWrapper>&& promise)
 {
     ASSERT(m_type != Type::None);
 
     if (m_type == Type::Text) {
-        fulfillPromiseWithJSON(promise, m_text);
+        fulfillPromiseWithJSON(WTFMove(promise), m_text);
         return;
     }
     m_consumer.setType(FetchBodyConsumer::Type::JSON);
@@ -151,12 +151,12 @@
     consume(owner, WTFMove(promise));
 }
 
-void FetchBody::text(FetchBodyOwner& owner, DeferredWrapper&& promise)
+void FetchBody::text(FetchBodyOwner& owner, Ref<DeferredWrapper>&& promise)
 {
     ASSERT(m_type != Type::None);
 
     if (m_type == Type::Text) {
-        promise.resolve(m_text);
+        promise->resolve(m_text);
         return;
     }
     m_consumer.setType(FetchBodyConsumer::Type::Text);
@@ -163,7 +163,7 @@
     consume(owner, WTFMove(promise));
 }
 
-void FetchBody::consume(FetchBodyOwner& owner, DeferredWrapper&& promise)
+void FetchBody::consume(FetchBodyOwner& owner, Ref<DeferredWrapper>&& promise)
 {
     // This should be handled by FetchBodyOwner
     ASSERT(m_type != Type::None);
@@ -172,13 +172,13 @@
 
     switch (m_type) {
     case Type::ArrayBuffer:
-        consumeArrayBuffer(promise);
+        consumeArrayBuffer(WTFMove(promise));
         return;
     case Type::ArrayBufferView:
-        consumeArrayBufferView(promise);
+        consumeArrayBufferView(WTFMove(promise));
         return;
     case Type::Text:
-        consumeText(promise);
+        consumeText(WTFMove(promise));
         return;
     case Type::Blob:
         consumeBlob(owner, WTFMove(promise));
@@ -187,11 +187,11 @@
         m_consumePromise = WTFMove(promise);
         return;
     case Type::Loaded:
-        m_consumer.resolve(promise);
+        m_consumer.resolve(WTFMove(promise));
         return;
     case Type::FormData:
         // FIXME: Support consuming FormData.
-        promise.reject(0);
+        promise->reject(0);
         return;
     default:
         ASSERT_NOT_REACHED();
@@ -246,28 +246,28 @@
 }
 #endif
 
-void FetchBody::consumeArrayBuffer(DeferredWrapper& promise)
+void FetchBody::consumeArrayBuffer(Ref<DeferredWrapper>&& promise)
 {
     ASSERT(m_data);
-    m_consumer.resolveWithData(promise, static_cast<const uint8_t*>(m_data->data()), m_data->byteLength());
+    m_consumer.resolveWithData(WTFMove(promise), static_cast<const uint8_t*>(m_data->data()), m_data->byteLength());
     m_data = nullptr;
 }
 
-void FetchBody::consumeArrayBufferView(DeferredWrapper& promise)
+void FetchBody::consumeArrayBufferView(Ref<DeferredWrapper>&& promise)
 {
     ASSERT(m_dataView);
-    m_consumer.resolveWithData(promise, static_cast<const uint8_t*>(m_dataView->baseAddress()), m_dataView->byteLength());
+    m_consumer.resolveWithData(WTFMove(promise), static_cast<const uint8_t*>(m_dataView->baseAddress()), m_dataView->byteLength());
     m_dataView = nullptr;
 }
 
-void FetchBody::consumeText(DeferredWrapper& promise)
+void FetchBody::consumeText(Ref<DeferredWrapper>&& promise)
 {
     Vector<uint8_t> data = ""
-    m_consumer.resolveWithData(promise, data.data(), data.size());
+    m_consumer.resolveWithData(WTFMove(promise), data.data(), data.size());
     m_text = { };
 }
 
-void FetchBody::consumeBlob(FetchBodyOwner& owner, DeferredWrapper&& promise)
+void FetchBody::consumeBlob(FetchBodyOwner& owner, Ref<DeferredWrapper>&& promise)
 {
     ASSERT(m_blob);
 
@@ -290,7 +290,7 @@
 {
     if (m_consumePromise) {
         m_consumePromise->reject(0);
-        m_consumePromise = Nullopt;
+        m_consumePromise = nullptr;
     }
 }
 
@@ -297,10 +297,8 @@
 void FetchBody::loadingSucceeded()
 {
     m_type = m_consumer.hasData() ? Type::Loaded : Type::None;
-    if (m_consumePromise) {
-        m_consumer.resolve(*m_consumePromise);
-        m_consumePromise = Nullopt;
-    }
+    if (m_consumePromise)
+        m_consumer.resolve(m_consumePromise.releaseNonNull());
 }
 
 RefPtr<FormData> FetchBody::bodyForInternalRequest(ScriptExecutionContext& context) const

Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.h (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/FetchBody.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -52,11 +52,11 @@
 
 class FetchBody {
 public:
-    void arrayBuffer(FetchBodyOwner&, DeferredWrapper&&);
-    void blob(FetchBodyOwner&, DeferredWrapper&&);
-    void json(FetchBodyOwner&, DeferredWrapper&&);
-    void text(FetchBodyOwner&, DeferredWrapper&&);
-    void formData(FetchBodyOwner&, DeferredWrapper&& promise) { promise.reject(0); }
+    void arrayBuffer(FetchBodyOwner&, Ref<DeferredWrapper>&&);
+    void blob(FetchBodyOwner&, Ref<DeferredWrapper>&&);
+    void json(FetchBodyOwner&, Ref<DeferredWrapper>&&);
+    void text(FetchBodyOwner&, Ref<DeferredWrapper>&&);
+    void formData(FetchBodyOwner&, Ref<DeferredWrapper>&& promise) { promise.get().reject(0); }
 
 #if ENABLE(STREAMS_API)
     void consumeAsStream(FetchBodyOwner&, FetchResponseSource&);
@@ -83,7 +83,7 @@
 
     FetchBodyConsumer& consumer() { return m_consumer; }
 
-    void cleanConsumePromise() { m_consumePromise = Nullopt; }
+    void cleanConsumePromise() { m_consumePromise = nullptr; }
 
 private:
     FetchBody(Ref<Blob>&&);
@@ -93,13 +93,13 @@
     FetchBody(String&&);
     FetchBody(Type type) : m_type(type) { }
 
-    void consume(FetchBodyOwner&, DeferredWrapper&&);
+    void consume(FetchBodyOwner&, Ref<DeferredWrapper>&&);
 
     Vector<uint8_t> extractFromText() const;
-    void consumeArrayBuffer(DeferredWrapper&);
-    void consumeArrayBufferView(DeferredWrapper&);
-    void consumeText(DeferredWrapper&);
-    void consumeBlob(FetchBodyOwner&, DeferredWrapper&&);
+    void consumeArrayBuffer(Ref<DeferredWrapper>&&);
+    void consumeArrayBufferView(Ref<DeferredWrapper>&&);
+    void consumeText(Ref<DeferredWrapper>&&);
+    void consumeBlob(FetchBodyOwner&, Ref<DeferredWrapper>&&);
 
     Type m_type { Type::None };
     String m_contentType;
@@ -112,7 +112,7 @@
     String m_text;
 
     FetchBodyConsumer m_consumer { FetchBodyConsumer::Type::None };
-    Optional<DeferredWrapper> m_consumePromise;
+    RefPtr<DeferredWrapper> m_consumePromise;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -59,20 +59,20 @@
     return decoder->decodeAndFlush(reinterpret_cast<const char*>(data), length);
 }
 
-void FetchBodyConsumer::resolveWithData(DeferredWrapper& promise, const unsigned char* data, unsigned length)
+void FetchBodyConsumer::resolveWithData(Ref<DeferredWrapper>&& promise, const unsigned char* data, unsigned length)
 {
     switch (m_type) {
     case Type::ArrayBuffer:
-        fulfillPromiseWithArrayBuffer(promise, data, length);
+        fulfillPromiseWithArrayBuffer(WTFMove(promise), data, length);
         return;
     case Type::Blob:
-        promise.resolveWithNewlyCreated(blobFromData(data, length, m_contentType));
+        promise->resolveWithNewlyCreated(blobFromData(data, length, m_contentType));
         return;
     case Type::JSON:
-        fulfillPromiseWithJSON(promise, textFromUTF8(data, length));
+        fulfillPromiseWithJSON(WTFMove(promise), textFromUTF8(data, length));
         return;
     case Type::Text:
-        promise.resolve(textFromUTF8(data, length));
+        promise->resolve(textFromUTF8(data, length));
         return;
     case Type::None:
         ASSERT_NOT_REACHED();
@@ -80,21 +80,21 @@
     }
 }
 
-void FetchBodyConsumer::resolve(DeferredWrapper& promise)
+void FetchBodyConsumer::resolve(Ref<DeferredWrapper>&& promise)
 {
     ASSERT(m_type != Type::None);
     switch (m_type) {
     case Type::ArrayBuffer:
-        fulfillPromiseWithArrayBuffer(promise, takeAsArrayBuffer().get());
+        fulfillPromiseWithArrayBuffer(WTFMove(promise), takeAsArrayBuffer().get());
         return;
     case Type::Blob:
-        promise.resolveWithNewlyCreated(takeAsBlob());
+        promise->resolveWithNewlyCreated(takeAsBlob());
         return;
     case Type::JSON:
-        fulfillPromiseWithJSON(promise, takeAsText());
+        fulfillPromiseWithJSON(WTFMove(promise), takeAsText());
         return;
     case Type::Text:
-        promise.resolve(takeAsText());
+        promise->resolve(takeAsText());
         return;
     case Type::None:
         ASSERT_NOT_REACHED();

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.h (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -57,8 +57,8 @@
 
     void clean() { m_buffer = nullptr; }
 
-    void resolve(DeferredWrapper&);
-    void resolveWithData(DeferredWrapper&, const unsigned char*, unsigned);
+    void resolve(Ref<DeferredWrapper>&&);
+    void resolveWithData(Ref<DeferredWrapper>&&, const unsigned char*, unsigned);
 
     bool hasData() const { return !!m_buffer; }
 

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -71,14 +71,14 @@
     return false;
 }
 
-void FetchBodyOwner::arrayBuffer(DeferredWrapper&& promise)
+void FetchBodyOwner::arrayBuffer(Ref<DeferredWrapper>&& promise)
 {
     if (m_body.isEmpty()) {
-        fulfillPromiseWithArrayBuffer(promise, nullptr, 0);
+        fulfillPromiseWithArrayBuffer(WTFMove(promise), nullptr, 0);
         return;
     }
     if (isDisturbedOrLocked()) {
-        promise.reject(TypeError);
+        promise->reject(TypeError);
         return;
     }
     m_isDisturbed = true;
@@ -85,14 +85,14 @@
     m_body.arrayBuffer(*this, WTFMove(promise));
 }
 
-void FetchBodyOwner::blob(DeferredWrapper&& promise)
+void FetchBodyOwner::blob(Ref<DeferredWrapper>&& promise)
 {
     if (m_body.isEmpty()) {
-        promise.resolve(Blob::create(Vector<uint8_t>(), Blob::normalizedContentType(extractMIMETypeFromMediaType(m_body.contentType()))));
+        promise->resolve(Blob::create(Vector<uint8_t>(), Blob::normalizedContentType(extractMIMETypeFromMediaType(m_body.contentType()))));
         return;
     }
     if (isDisturbedOrLocked()) {
-        promise.reject(TypeError);
+        promise->reject(TypeError);
         return;
     }
     m_isDisturbed = true;
@@ -99,14 +99,14 @@
     m_body.blob(*this, WTFMove(promise));
 }
 
-void FetchBodyOwner::formData(DeferredWrapper&& promise)
+void FetchBodyOwner::formData(Ref<DeferredWrapper>&& promise)
 {
     if (m_body.isEmpty()) {
-        promise.reject(0);
+        promise->reject(0);
         return;
     }
     if (isDisturbedOrLocked()) {
-        promise.reject(TypeError);
+        promise->reject(TypeError);
         return;
     }
     m_isDisturbed = true;
@@ -113,14 +113,14 @@
     m_body.formData(*this, WTFMove(promise));
 }
 
-void FetchBodyOwner::json(DeferredWrapper&& promise)
+void FetchBodyOwner::json(Ref<DeferredWrapper>&& promise)
 {
     if (m_body.isEmpty()) {
-        promise.reject(SYNTAX_ERR);
+        promise->reject(SYNTAX_ERR);
         return;
     }
     if (isDisturbedOrLocked()) {
-        promise.reject(TypeError);
+        promise->reject(TypeError);
         return;
     }
     m_isDisturbed = true;
@@ -127,14 +127,14 @@
     m_body.json(*this, WTFMove(promise));
 }
 
-void FetchBodyOwner::text(DeferredWrapper&& promise)
+void FetchBodyOwner::text(Ref<DeferredWrapper>&& promise)
 {
     if (m_body.isEmpty()) {
-        promise.resolve(String());
+        promise->resolve(String());
         return;
     }
     if (isDisturbedOrLocked()) {
-        promise.reject(TypeError);
+        promise->reject(TypeError);
         return;
     }
     m_isDisturbed = true;

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -46,11 +46,11 @@
     // Exposed Body API
     bool isDisturbed() const { return m_isDisturbed; };
 
-    void arrayBuffer(DeferredWrapper&&);
-    void blob(DeferredWrapper&&);
-    void formData(DeferredWrapper&&);
-    void json(DeferredWrapper&&);
-    void text(DeferredWrapper&&);
+    void arrayBuffer(Ref<DeferredWrapper>&&);
+    void blob(Ref<DeferredWrapper>&&);
+    void formData(Ref<DeferredWrapper>&&);
+    void json(Ref<DeferredWrapper>&&);
+    void text(Ref<DeferredWrapper>&&);
 
     bool isDisturbedOrLocked() const;
 

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -206,7 +206,7 @@
         m_loader->stop();
 }
 
-void FetchResponse::consume(unsigned type, DeferredWrapper&& wrapper)
+void FetchResponse::consume(unsigned type, Ref<DeferredWrapper>&& wrapper)
 {
     ASSERT(type <= static_cast<unsigned>(FetchBodyConsumer::Type::Text));
 
@@ -241,9 +241,9 @@
     m_consumer.append(chunk->data(), chunk->byteLength());
 }
 
-void FetchResponse::finishConsumingStream(DeferredWrapper&& promise)
+void FetchResponse::finishConsumingStream(Ref<DeferredWrapper>&& promise)
 {
-    m_consumer.resolve(promise);
+    m_consumer.resolve(WTFMove(promise));
 }
 
 void FetchResponse::consumeBodyAsStream()

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.h (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -60,11 +60,11 @@
     using FetchPromise = DOMPromise<FetchResponse>;
     static void fetch(ScriptExecutionContext&, FetchRequest&, FetchPromise&&);
 
-    void consume(unsigned, DeferredWrapper&&);
+    void consume(unsigned, Ref<DeferredWrapper>&&);
 #if ENABLE(STREAMS_API)
     void startConsumingStream(unsigned);
     void consumeChunk(Ref<JSC::Uint8Array>&&);
-    void finishConsumingStream(DeferredWrapper&&);
+    void finishConsumingStream(Ref<DeferredWrapper>&&);
 #endif
 
     void setStatus(int, const String&, ExceptionCode&);

Modified: trunk/Source/WebCore/Modules/fetch/WorkerGlobalScopeFetch.cpp (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/WorkerGlobalScopeFetch.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/WorkerGlobalScopeFetch.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -36,7 +36,7 @@
 
 namespace WebCore {
 
-void WorkerGlobalScopeFetch::fetch(WorkerGlobalScope& scope, FetchRequest& request, DeferredWrapper&& promise)
+void WorkerGlobalScopeFetch::fetch(WorkerGlobalScope& scope, FetchRequest& request, Ref<DeferredWrapper>&& promise)
 {
     if (!scope.scriptExecutionContext())
         return;

Modified: trunk/Source/WebCore/Modules/fetch/WorkerGlobalScopeFetch.h (205256 => 205257)


--- trunk/Source/WebCore/Modules/fetch/WorkerGlobalScopeFetch.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/fetch/WorkerGlobalScopeFetch.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -41,7 +41,7 @@
 
 class WorkerGlobalScopeFetch {
 public:
-    static void fetch(WorkerGlobalScope&, FetchRequest&, DeferredWrapper&&);
+    static void fetch(WorkerGlobalScope&, FetchRequest&, Ref<DeferredWrapper>&&);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/mediastream/UserMediaPermissionCheck.h (205256 => 205257)


--- trunk/Source/WebCore/Modules/mediastream/UserMediaPermissionCheck.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/Modules/mediastream/UserMediaPermissionCheck.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -30,7 +30,6 @@
 #if ENABLE(MEDIA_STREAM)
 
 #include "ActiveDOMObject.h"
-#include "MediaDevices.h"
 #include <wtf/RefCounted.h>
 #include <wtf/text/WTFString.h>
 

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (205256 => 205257)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2016-08-31 18:36:46 UTC (rev 205257)
@@ -4941,7 +4941,7 @@
 		B5B7A17017C10AA800E4AA0A /* ElementData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5B7A16F17C1080600E4AA0A /* ElementData.cpp */; };
 		B5B7A17117C10AC000E4AA0A /* ElementData.h in Headers */ = {isa = PBXBuildFile; fileRef = B5B7A16E17C1048000E4AA0A /* ElementData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		B5D31DFA11CF610B009F22B4 /* ActiveDOMCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5D31DF811CF610B009F22B4 /* ActiveDOMCallback.cpp */; };
-		B5D31DFB11CF610B009F22B4 /* ActiveDOMCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D31DF911CF610B009F22B4 /* ActiveDOMCallback.h */; };
+		B5D31DFB11CF610B009F22B4 /* ActiveDOMCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D31DF911CF610B009F22B4 /* ActiveDOMCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		B6566270120B1227006EA85C /* JSIDBTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = B656626E120B1227006EA85C /* JSIDBTransaction.h */; };
 		B658FFA11522EF3A00DD5595 /* JSRadioNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B658FF9F1522EF3A00DD5595 /* JSRadioNodeList.cpp */; };
 		B658FFA21522EF3A00DD5595 /* JSRadioNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = B658FFA01522EF3A00DD5595 /* JSRadioNodeList.h */; };

Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -28,6 +28,7 @@
 #include "JSDOMGlobalObject.h"
 
 #include "Document.h"
+#include "JSDOMPromise.h"
 #include "JSDOMWindow.h"
 #include "JSEventListener.h"
 #include "JSMediaStream.h"
@@ -61,6 +62,10 @@
 {
 }
 
+JSDOMGlobalObject::~JSDOMGlobalObject()
+{
+}
+
 void JSDOMGlobalObject::destroy(JSCell* cell)
 {
     static_cast<JSDOMGlobalObject*>(cell)->JSDOMGlobalObject::~JSDOMGlobalObject();
@@ -167,6 +172,9 @@
     for (auto& constructor : thisObject->constructors().values())
         visitor.append(&constructor);
 
+    for (auto& deferredWrapper : thisObject->deferredWrappers())
+        deferredWrapper->visitAggregate(visitor);
+
     thisObject->m_builtinInternalFunctions.visit(visitor);
 }
 

Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -34,6 +34,7 @@
 
 namespace WebCore {
 
+    class DeferredWrapper;
     class Document;
     class Event;
     class DOMWrapperWorld;
@@ -41,6 +42,7 @@
 
     typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::Structure>> JSDOMStructureMap;
     typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::JSObject>> JSDOMConstructorMap;
+    typedef HashSet<DeferredWrapper*> DeferredWrapperSet;
 
     class WEBCORE_EXPORT JSDOMGlobalObject : public JSC::JSGlobalObject {
         typedef JSC::JSGlobalObject Base;
@@ -56,6 +58,8 @@
         JSDOMStructureMap& structures() { return m_structures; }
         JSDOMConstructorMap& constructors() { return m_constructors; }
 
+        DeferredWrapperSet& deferredWrappers() { return m_deferredWrappers; }
+
         ScriptExecutionContext* scriptExecutionContext() const;
 
         // Make binding code generation easier.
@@ -75,6 +79,8 @@
         static const JSC::ClassInfo s_info;
 
     public:
+        ~JSDOMGlobalObject();
+
         static const JSC::ClassInfo* info() { return &s_info; }
 
         static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSValue prototype)
@@ -85,6 +91,7 @@
     protected:
         JSDOMStructureMap m_structures;
         JSDOMConstructorMap m_constructors;
+        DeferredWrapperSet m_deferredWrappers;
 
         Event* m_currentEvent;
         Ref<DOMWrapperWorld> m_world;

Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -35,18 +35,33 @@
 
 namespace WebCore {
 
-DeferredWrapper::DeferredWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, JSPromiseDeferred* promiseDeferred)
-    : m_globalObject(exec->vm(), globalObject)
-    , m_deferred(exec->vm(), promiseDeferred)
+DeferredWrapper::DeferredWrapper(ExecState*, JSDOMGlobalObject* globalObject, JSPromiseDeferred* promiseDeferred)
+    : ActiveDOMCallback(globalObject->scriptExecutionContext())
+    , m_deferred(promiseDeferred)
+    , m_globalObject(globalObject)
 {
+    globalObject->vm().heap.writeBarrier(globalObject, promiseDeferred);
+    m_globalObject->deferredWrappers().add(this);
 }
 
-JSDOMGlobalObject& DeferredWrapper::globalObject() const
+DeferredWrapper::~DeferredWrapper()
 {
-    ASSERT(m_globalObject);
-    return *m_globalObject.get();
+    clear();
 }
 
+void DeferredWrapper::clear()
+{
+    ASSERT(!m_deferred || m_globalObject);
+    if (m_deferred && m_globalObject)
+        m_globalObject->deferredWrappers().remove(this);
+    m_deferred.clear();
+}
+
+void DeferredWrapper::contextDestroyed()
+{
+    clear();
+}
+
 JSC::JSValue DeferredWrapper::promise() const
 {
     ASSERT(m_deferred);
@@ -55,6 +70,9 @@
 
 void DeferredWrapper::callFunction(ExecState& exec, JSValue function, JSValue resolution)
 {
+    if (!canInvokeCallback())
+        return;
+
     CallData callData;
     CallType callType = getCallData(function, callData);
     ASSERT(callType != CallType::None);
@@ -64,12 +82,14 @@
 
     call(&exec, function, callType, callData, jsUndefined(), arguments);
 
-    m_globalObject.clear();
-    m_deferred.clear();
+    clear();
 }
 
 void DeferredWrapper::reject(ExceptionCode ec, const String& message)
 {
+    if (isSuspended())
+        return;
+
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* state = m_globalObject->globalExec();
@@ -85,7 +105,7 @@
     JSValue error = state.exception()->value();
     state.clearException();
 
-    DeferredWrapper(&state, &globalObject, &promiseDeferred).reject(error);
+    DeferredWrapper::create(&state, &globalObject, &promiseDeferred)->reject(error);
 }
 
 static inline JSC::JSValue parseAsJSON(JSC::ExecState* state, const String& data)
@@ -94,27 +114,27 @@
     return JSC::JSONParse(state, data);
 }
 
-void fulfillPromiseWithJSON(DeferredWrapper& promise, const String& data)
+void fulfillPromiseWithJSON(Ref<DeferredWrapper>&& promise, const String& data)
 {
-    JSC::JSValue value = parseAsJSON(promise.globalObject().globalExec(), data);
+    JSC::JSValue value = parseAsJSON(promise->globalObject()->globalExec(), data);
     if (!value)
-        promise.reject(SYNTAX_ERR);
+        promise->reject(SYNTAX_ERR);
     else
-        promise.resolve(value);
+        promise->resolve(value);
 }
 
-void fulfillPromiseWithArrayBuffer(DeferredWrapper& promise, ArrayBuffer* arrayBuffer)
+void fulfillPromiseWithArrayBuffer(Ref<DeferredWrapper>&& promise, ArrayBuffer* arrayBuffer)
 {
     if (!arrayBuffer) {
-        promise.reject<JSValue>(createOutOfMemoryError(promise.globalObject().globalExec()));
+        promise->reject<JSValue>(createOutOfMemoryError(promise->globalObject()->globalExec()));
         return;
     }
-    promise.resolve(arrayBuffer);
+    promise->resolve(arrayBuffer);
 }
 
-void fulfillPromiseWithArrayBuffer(DeferredWrapper& promise, const void* data, size_t length)
+void fulfillPromiseWithArrayBuffer(Ref<DeferredWrapper>&& promise, const void* data, size_t length)
 {
-    fulfillPromiseWithArrayBuffer(promise, ArrayBuffer::tryCreate(data, length).get());
+    fulfillPromiseWithArrayBuffer(WTFMove(promise), ArrayBuffer::tryCreate(data, length).get());
 }
 
 }

Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.h (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSDOMPromise.h	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.h	2016-08-31 18:36:46 UTC (rev 205257)
@@ -26,6 +26,7 @@
 #ifndef JSDOMPromise_h
 #define JSDOMPromise_h
 
+#include "ActiveDOMCallback.h"
 #include "JSDOMBinding.h"
 #include <heap/StrongInlines.h>
 #include <runtime/JSPromiseDeferred.h>
@@ -95,10 +96,15 @@
     static constexpr bool passByConstRef = false;
 };
 
-class DeferredWrapper {
+class DeferredWrapper : public RefCounted<DeferredWrapper>, public ActiveDOMCallback {
 public:
-    DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*, JSC::JSPromiseDeferred*);
+    static Ref<DeferredWrapper> create(JSC::ExecState* state, JSDOMGlobalObject* globalObject, JSC::JSPromiseDeferred* deferred)
+    {
+        return adoptRef(*new DeferredWrapper(state, globalObject, deferred));
+    }
 
+    ~DeferredWrapper();
+
     template<class ResolveResultType> typename std::enable_if<PromiseResultInspector<ResolveResultType>::passByValue, void>::type
     resolve(ResolveResultType result) { resolveWithValue(result); }
     template<class ResolveResultType> typename std::enable_if<PromiseResultInspector<ResolveResultType>::passByRef, void>::type
@@ -121,10 +127,19 @@
 
     void reject(ExceptionCode, const String& = { });
 
-    JSDOMGlobalObject& globalObject() const;
     JSC::JSValue promise() const;
 
+    bool isSuspended() { return !m_deferred || !canInvokeCallback(); } // The wrapper world has gone away or active DOM objects have been suspended.
+    JSDOMGlobalObject* globalObject() { return m_globalObject.get(); }
+
+    void visitAggregate(JSC::SlotVisitor& visitor) { visitor.appendUnbarrieredWeak(&m_deferred); }
+
 private:
+    DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*, JSC::JSPromiseDeferred*);
+
+    void clear();
+    void contextDestroyed() override;
+
     void callFunction(JSC::ExecState&, JSC::JSValue function, JSC::JSValue resolution);
     void resolve(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->resolve(), resolution); }
     void reject(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->reject(), resolution); }
@@ -132,13 +147,13 @@
     template<class RejectResultType> void rejectWithValue(RejectResultType&&);
     template<class ResolveResultType> void resolveWithValue(ResolveResultType&&);
 
-    JSC::Strong<JSDOMGlobalObject> m_globalObject;
-    JSC::Strong<JSC::JSPromiseDeferred> m_deferred;
+    JSC::Weak<JSC::JSPromiseDeferred> m_deferred;
+    JSC::Weak<JSDOMGlobalObject> m_globalObject;
 };
 
-void fulfillPromiseWithJSON(DeferredWrapper&, const String&);
-void fulfillPromiseWithArrayBuffer(DeferredWrapper&, ArrayBuffer*);
-void fulfillPromiseWithArrayBuffer(DeferredWrapper&, const void*, size_t);
+void fulfillPromiseWithJSON(Ref<DeferredWrapper>&&, const String&);
+void fulfillPromiseWithArrayBuffer(Ref<DeferredWrapper>&&, ArrayBuffer*);
+void fulfillPromiseWithArrayBuffer(Ref<DeferredWrapper>&&, const void*, size_t);
 void rejectPromiseWithExceptionIfAny(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromiseDeferred&);
 
 inline JSC::JSValue callPromiseFunction(JSC::ExecState& state, JSC::EncodedJSValue promiseFunction(JSC::ExecState*, JSC::JSPromiseDeferred*))
@@ -156,26 +171,31 @@
 template <typename Value>
 class DOMPromise {
 public:
-    DOMPromise(DeferredWrapper&& wrapper) : m_wrapper(WTFMove(wrapper)) { }
+    DOMPromise(Ref<DeferredWrapper>&& wrapper)
+        : m_wrapper(WTFMove(wrapper))
+    {
+    }
+
     DOMPromise(DOMPromise&& promise) : m_wrapper(WTFMove(promise.m_wrapper)) { }
 
     DOMPromise(const DOMPromise&) = default;
     DOMPromise& operator=(DOMPromise const&) = default;
 
-    void resolve(typename PromiseResultInspector<Value>::Type value) { m_wrapper.resolve(value); }
+    void resolve(typename PromiseResultInspector<Value>::Type value) { m_wrapper->resolve(value); }
 
-    template<typename... ErrorType> void reject(ErrorType&&... error) { m_wrapper.reject(std::forward<ErrorType>(error)...); }
+    template<typename... ErrorType> void reject(ErrorType&&... error) { m_wrapper->reject(std::forward<ErrorType>(error)...); }
 
     DeferredWrapper& deferredWrapper() { return m_wrapper; }
 
 private:
-    DeferredWrapper m_wrapper;
+    Ref<DeferredWrapper> m_wrapper;
 };
 
 template<class ResolveResultType>
 inline void DeferredWrapper::resolveWithValue(ResolveResultType&& result)
 {
-    ASSERT(m_deferred);
+    if (isSuspended())
+        return;
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
@@ -185,6 +205,8 @@
 template<class ResolveResultType>
 inline void DeferredWrapper::resolveWithNewlyCreated(Ref<ResolveResultType>&& result)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
@@ -195,6 +217,8 @@
 template<class RejectResultType>
 inline void DeferredWrapper::rejectWithValue(RejectResultType&& result)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
@@ -205,6 +229,8 @@
 template<>
 inline void DeferredWrapper::resolve(bool result)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
@@ -215,6 +241,8 @@
 template<>
 inline void DeferredWrapper::resolve(JSC::JSValue value)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
@@ -225,6 +253,8 @@
 template<>
 inline void DeferredWrapper::reject(JSC::JSValue value)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
@@ -235,6 +265,8 @@
 template<>
 inline void DeferredWrapper::resolve(std::nullptr_t)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
@@ -245,6 +277,8 @@
 template<>
 inline void DeferredWrapper::reject(std::nullptr_t)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
@@ -255,6 +289,8 @@
 template<>
 inline void DeferredWrapper::resolve(const String& result)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
@@ -265,6 +301,8 @@
 template<>
 inline void DeferredWrapper::reject(const String& result)
 {
+    if (isSuspended())
+        return;
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();

Modified: trunk/Source/WebCore/bindings/js/JSFontFaceCustom.cpp (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSFontFaceCustom.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSFontFaceCustom.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -39,8 +39,8 @@
 {
     if (!m_loaded) {
         if (!wrapped().promise()) {
-            DeferredWrapper promise(&state, globalObject(), JSC::JSPromiseDeferred::create(&state, globalObject()));
-            m_loaded.set(state.vm(), this, promise.promise());
+            Ref<DeferredWrapper> promise = DeferredWrapper::create(&state, globalObject(), JSC::JSPromiseDeferred::create(&state, globalObject()));
+            m_loaded.set(state.vm(), this, promise->promise());
             wrapped().registerLoaded(WTFMove(promise));
         } else
             m_loaded.set(state.vm(), this, wrapped().promise().value().deferredWrapper().promise());

Modified: trunk/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -34,8 +34,8 @@
 JSC::JSValue JSFontFaceSet::ready(JSC::ExecState& state) const
 {
     if (!m_ready) {
-        DeferredWrapper promise(&state, globalObject(), JSC::JSPromiseDeferred::create(&state, globalObject()));
-        m_ready.set(state.vm(), this, promise.promise());
+        Ref<DeferredWrapper> promise = DeferredWrapper::create(&state, globalObject(), JSC::JSPromiseDeferred::create(&state, globalObject()));
+        m_ready.set(state.vm(), this, promise->promise());
         wrapped().registerReady(WTFMove(promise));
     }
     return m_ready.get();

Modified: trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -391,7 +391,7 @@
     auto audioConstraints = MediaConstraintsImpl::create(WTFMove(mandatoryAudioConstraints), WTFMove(advancedAudioConstraints), areAudioConstraintsValid);
     auto videoConstraints = MediaConstraintsImpl::create(WTFMove(mandatoryVideoConstraints), WTFMove(advancedVideoConstraints), areVideoConstraintsValid);
     JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&state, globalObject());
-    wrapped().getUserMedia(WTFMove(audioConstraints), WTFMove(videoConstraints), DeferredWrapper(&state, globalObject(), promiseDeferred), ec);
+    wrapped().getUserMedia(WTFMove(audioConstraints), WTFMove(videoConstraints), DeferredWrapper::create(&state, globalObject(), promiseDeferred), ec);
     setDOMException(&state, ec);
     return promiseDeferred->promise();
 }

Modified: trunk/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -44,7 +44,7 @@
     m_controller.set(state.vm(), jsSource, state.argument(0));
 
     JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&state, globalObject());
-    wrapped().start(ReadableStreamDefaultController(controller), DeferredWrapper(&state, globalObject(), promiseDeferred));
+    wrapped().start(ReadableStreamDefaultController(controller), DeferredWrapper::create(&state, globalObject(), promiseDeferred));
     return promiseDeferred->promise();
 }
 

Modified: trunk/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp (205256 => 205257)


--- trunk/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp	2016-08-31 18:36:46 UTC (rev 205257)
@@ -174,12 +174,12 @@
 
     
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
-        fulfillPromiseWithArrayBuffer(wrapper, result.data(), result.size());
+        fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
     };
     auto failureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     ExceptionCode ec = 0;
@@ -229,12 +229,12 @@
     }
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
-        fulfillPromiseWithArrayBuffer(wrapper, result.data(), result.size());
+        fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
     };
     auto failureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     ExceptionCode ec = 0;
@@ -284,12 +284,12 @@
     }
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
-        fulfillPromiseWithArrayBuffer(wrapper, result.data(), result.size());
+        fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
     };
     auto failureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     ExceptionCode ec = 0;
@@ -345,12 +345,12 @@
     }
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](bool result) mutable {
-        wrapper.resolve(result);
+        wrapper->resolve(result);
     };
     auto failureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     ExceptionCode ec = 0;
@@ -390,12 +390,12 @@
     }
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
-        fulfillPromiseWithArrayBuffer(wrapper, result.data(), result.size());
+        fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
     };
     auto failureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     ExceptionCode ec = 0;
@@ -444,17 +444,17 @@
     }
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](CryptoKey* key, CryptoKeyPair* keyPair) mutable {
         ASSERT(key || keyPair);
         ASSERT(!key || !keyPair);
         if (key)
-            wrapper.resolve(key);
+            wrapper->resolve(key);
         else
-            wrapper.resolve(keyPair);
+            wrapper->resolve(keyPair);
     };
     auto failureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     ExceptionCode ec = 0;
@@ -581,12 +581,12 @@
     }
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](CryptoKey& result) mutable {
-        wrapper.resolve(result);
+        wrapper->resolve(result);
     };
     auto failureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     WebCore::importKey(state, keyFormat, data, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback));
@@ -650,12 +650,12 @@
         return throwTypeError(&state, scope);
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
-        fulfillPromiseWithArrayBuffer(wrapper, result.data(), result.size());
+        fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
     };
     auto failureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     WebCore::exportKey(state, keyFormat, *key, WTFMove(successCallback), WTFMove(failureCallback));
@@ -706,25 +706,25 @@
     }
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
 
     auto exportSuccessCallback = [keyFormat, algorithm, parameters, wrappingKey, wrapper](const Vector<uint8_t>& exportedKeyData) mutable {
         auto encryptSuccessCallback = [wrapper](const Vector<uint8_t>& encryptedData) mutable {
-            fulfillPromiseWithArrayBuffer(wrapper, encryptedData.data(), encryptedData.size());
+            fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), encryptedData.data(), encryptedData.size());
         };
         auto encryptFailureCallback = [wrapper]() mutable {
-            wrapper.reject(nullptr);
+            wrapper->reject(nullptr);
         };
         ExceptionCode ec = 0;
         algorithm->encryptForWrapKey(*parameters, *wrappingKey, std::make_pair(exportedKeyData.data(), exportedKeyData.size()), WTFMove(encryptSuccessCallback), WTFMove(encryptFailureCallback), ec);
         if (ec) {
             // FIXME: Report failure details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
-            wrapper.reject(nullptr);
+            wrapper->reject(nullptr);
         }
     };
 
     auto exportFailureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     ExceptionCode ec = 0;
@@ -809,15 +809,15 @@
     }
 
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
-    DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
+    RefPtr<DeferredWrapper> wrapper = DeferredWrapper::create(&state, globalObject(), promiseDeferred);
     Strong<JSDOMGlobalObject> domGlobalObject(state.vm(), globalObject());
 
     auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable {
         auto importSuccessCallback = [wrapper](CryptoKey& key) mutable {
-            wrapper.resolve(key);
+            wrapper->resolve(key);
         };
         auto importFailureCallback = [wrapper]() mutable {
-            wrapper.reject(nullptr);
+            wrapper->reject(nullptr);
         };
         ExecState& state = *domGlobalObject->globalExec();
         WebCore::importKey(state, keyFormat, std::make_pair(result.data(), result.size()), unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, WTFMove(importSuccessCallback), WTFMove(importFailureCallback));
@@ -824,12 +824,12 @@
         if (state.hadException()) {
             // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
             state.clearException();
-            wrapper.reject(nullptr);
+            wrapper->reject(nullptr);
         }
     };
 
     auto decryptFailureCallback = [wrapper]() mutable {
-        wrapper.reject(nullptr);
+        wrapper->reject(nullptr);
     };
 
     ExceptionCode ec = 0;

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (205256 => 205257)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-08-31 18:36:46 UTC (rev 205257)
@@ -4114,9 +4114,9 @@
 
     if (IsReturningPromise($function)) {
         if ($function->isStatic) {
-            push(@arguments, "DeferredWrapper(state, jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), promiseDeferred)");
+            push(@arguments, "DeferredWrapper::create(state, jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), promiseDeferred)");
         } else {
-            push(@arguments, "DeferredWrapper(state, castedThis->globalObject(), promiseDeferred)");
+            push(@arguments, "DeferredWrapper::create(state, castedThis->globalObject(), promiseDeferred)");
         }
     }
     push(@arguments, "ec") if $function->signature->extendedAttributes->{"RaisesException"} || $function->signature->extendedAttributes->{"RaisesExceptionWithMessage"};

Modified: trunk/Source/WebKit2/CMakeLists.txt (205256 => 205257)


--- trunk/Source/WebKit2/CMakeLists.txt	2016-08-31 17:44:22 UTC (rev 205256)
+++ trunk/Source/WebKit2/CMakeLists.txt	2016-08-31 18:36:46 UTC (rev 205257)
@@ -88,6 +88,7 @@
     "${WEBCORE_DIR}/Modules/vibration"
     "${WEBCORE_DIR}/Modules/webdatabase"
     "${WEBCORE_DIR}/accessibility"
+    "${WEBCORE_DIR}/bindings/generic"
     "${WEBCORE_DIR}/bindings/js"
     "${WEBCORE_DIR}/bindings"
     "${WEBCORE_DIR}/bridge"
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to