Diff
Modified: trunk/Source/WebCore/ChangeLog (185403 => 185404)
--- trunk/Source/WebCore/ChangeLog 2015-06-10 05:59:54 UTC (rev 185403)
+++ trunk/Source/WebCore/ChangeLog 2015-06-10 06:26:57 UTC (rev 185404)
@@ -1,3 +1,53 @@
+2015-06-09 Youenn Fablet <[email protected]>
+
+ DeferredWrapper should clear its JS strong references once its promise is resolved/rejected
+ https://bugs.webkit.org/show_bug.cgi?id=145753
+
+ Reviewed by Darin Adler.
+
+ Clear strong references at the end of DeferredWrapper::resolve and DeferredWrapper::reject.
+ Added assertions to check that resolve or reject is called only once.
+
+ Removed DeferredWrapper constructor that creates internally its promise.
+ Reason is DeferredWrapper can be resolved synchronously and promise
+ will be lost when returning it at the end of the binding promise function.
+ Updated all custom bindings accordingly.
+
+ Covered by existing tests.
+
+ * bindings/js/JSAudioContextCustom.cpp:
+ (WebCore::JSAudioContext::suspend): Updated DeferredWrapper constructor to properly return the promise.
+ (WebCore::JSAudioContext::resume): Ditto.
+ (WebCore::JSAudioContext::close): Ditto.
+ * bindings/js/JSDOMPromise.cpp:
+ (WebCore::DeferredWrapper::resolve): Cleared strong references after promise resolution.
+ (WebCore::DeferredWrapper::reject): Cleared strong references after promise rejection.
+ * bindings/js/JSDOMPromise.h:
+ (WebCore::DeferredWrapper::resolve): Added ASSERT to check promise is not yet rejected/resolved.
+ (WebCore::DeferredWrapper::reject): Ditto.
+ (WebCore::DeferredWrapper::reject<ExceptionCode>): Ditto.
+ (WebCore::DeferredWrapper::resolve<String>): Ditto.
+ (WebCore::DeferredWrapper::resolve<bool>): Ditto.
+ (WebCore::DeferredWrapper::resolve<JSC::JSValue>): Ditto.
+ (WebCore::char>>):
+ (WebCore::DeferredWrapper::reject<String>): Ditto.
+ * bindings/js/JSMediaDevicesCustom.cpp:
+ (WebCore::JSMediaDevices::getUserMedia): Updated DeferredWrapper constructor to properly return the promise.
+ * bindings/js/JSReadableStreamReaderCustom.cpp:
+ (WebCore::JSReadableStreamReader::read): Ditto.
+ (WebCore::JSReadableStreamReader::closed): Ditto.
+ * bindings/js/JSSubtleCryptoCustom.cpp:
+ (WebCore::JSSubtleCrypto::encrypt): Ditto.
+ (WebCore::JSSubtleCrypto::decrypt): Ditto.
+ (WebCore::JSSubtleCrypto::sign): Ditto.
+ (WebCore::JSSubtleCrypto::verify): Ditto.
+ (WebCore::JSSubtleCrypto::digest): Ditto.
+ (WebCore::JSSubtleCrypto::generateKey): Ditto.
+ (WebCore::JSSubtleCrypto::importKey): Ditto.
+ (WebCore::JSSubtleCrypto::exportKey): Ditto.
+ (WebCore::JSSubtleCrypto::wrapKey): Ditto.
+ (WebCore::JSSubtleCrypto::unwrapKey): Ditto.
+
2015-06-09 Zalan Bujtas <[email protected]>
Protect FrameView from being destroyed in Document::recalcStyle()
Modified: trunk/Source/WebCore/bindings/js/JSAudioContextCustom.cpp (185403 => 185404)
--- trunk/Source/WebCore/bindings/js/JSAudioContextCustom.cpp 2015-06-10 05:59:54 UTC (rev 185403)
+++ trunk/Source/WebCore/bindings/js/JSAudioContextCustom.cpp 2015-06-10 06:26:57 UTC (rev 185404)
@@ -113,7 +113,8 @@
JSValue JSAudioContext::suspend(ExecState* exec)
{
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper]() mutable {
wrapper.resolve(nullptr);
};
@@ -123,12 +124,13 @@
impl().suspendContext(WTF::move(successCallback), WTF::move(failureCallback));
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSAudioContext::resume(ExecState* exec)
{
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper]() mutable {
wrapper.resolve(nullptr);
};
@@ -138,12 +140,13 @@
impl().resumeContext(WTF::move(successCallback), WTF::move(failureCallback));
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSAudioContext::close(ExecState* exec)
{
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper]() mutable {
wrapper.resolve(nullptr);
};
@@ -153,7 +156,7 @@
impl().closeContext(WTF::move(successCallback), WTF::move(failureCallback));
- return wrapper.promise();
+ return promiseDeferred->promise();
}
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp (185403 => 185404)
--- trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp 2015-06-10 05:59:54 UTC (rev 185403)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp 2015-06-10 06:26:57 UTC (rev 185404)
@@ -32,12 +32,6 @@
namespace WebCore {
-DeferredWrapper::DeferredWrapper(ExecState* exec, JSDOMGlobalObject* globalObject)
- : m_globalObject(exec->vm(), globalObject)
- , m_deferred(exec->vm(), JSPromiseDeferred::create(exec, globalObject))
-{
-}
-
DeferredWrapper::DeferredWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, JSPromiseDeferred* promiseDeferred)
: m_globalObject(exec->vm(), globalObject)
, m_deferred(exec->vm(), promiseDeferred)
@@ -46,6 +40,8 @@
JSObject* DeferredWrapper::promise() const
{
+ // FIXME: Remove this accessor once ReadableStreamReader custom binding does not need it.
+ ASSERT(m_deferred);
return m_deferred->promise();
}
@@ -61,6 +57,9 @@
arguments.append(resolution);
call(exec, deferredResolve, resolveCallType, resolveCallData, jsUndefined(), arguments);
+
+ m_globalObject.clear();
+ m_deferred.clear();
}
void DeferredWrapper::reject(ExecState* exec, JSValue reason)
@@ -75,6 +74,9 @@
arguments.append(reason);
call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), arguments);
+
+ m_globalObject.clear();
+ m_deferred.clear();
}
}
Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.h (185403 => 185404)
--- trunk/Source/WebCore/bindings/js/JSDOMPromise.h 2015-06-10 05:59:54 UTC (rev 185403)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.h 2015-06-10 06:26:57 UTC (rev 185404)
@@ -38,7 +38,6 @@
class DeferredWrapper {
public:
- DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*);
DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*, JSC::JSPromiseDeferred*);
template<class ResolveResultType>
@@ -60,6 +59,8 @@
template<class ResolveResultType>
inline void DeferredWrapper::resolve(const ResolveResultType& result)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
resolve(exec, toJS(exec, m_globalObject.get(), result));
@@ -68,6 +69,8 @@
template<class RejectResultType>
inline void DeferredWrapper::reject(const RejectResultType& result)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
reject(exec, toJS(exec, m_globalObject.get(), result));
@@ -76,6 +79,8 @@
template<>
inline void DeferredWrapper::reject(const std::nullptr_t&)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
reject(exec, JSC::jsNull());
@@ -84,6 +89,8 @@
template<>
inline void DeferredWrapper::reject(const JSC::JSValue& value)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
reject(exec, value);
@@ -92,6 +99,8 @@
template<>
inline void DeferredWrapper::reject<ExceptionCode>(const ExceptionCode& ec)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
reject(exec, createDOMException(exec, ec));
@@ -100,6 +109,8 @@
template<>
inline void DeferredWrapper::resolve<String>(const String& result)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
resolve(exec, jsString(exec, result));
@@ -108,6 +119,8 @@
template<>
inline void DeferredWrapper::resolve<bool>(const bool& result)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
resolve(exec, JSC::jsBoolean(result));
@@ -116,6 +129,8 @@
template<>
inline void DeferredWrapper::resolve<JSC::JSValue>(const JSC::JSValue& value)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
resolve(exec, value);
@@ -123,6 +138,8 @@
template<>
inline void DeferredWrapper::resolve<Vector<unsigned char>>(const Vector<unsigned char>& result)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(result.data(), result.size());
@@ -132,6 +149,8 @@
template<>
inline void DeferredWrapper::resolve(const std::nullptr_t&)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
resolve(exec, JSC::jsUndefined());
@@ -140,6 +159,8 @@
template<>
inline void DeferredWrapper::reject<String>(const String& result)
{
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
JSC::ExecState* exec = m_globalObject->globalExec();
JSC::JSLockHolder locker(exec);
reject(exec, jsString(exec, result));
Modified: trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp (185403 => 185404)
--- trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp 2015-06-10 05:59:54 UTC (rev 185403)
+++ trunk/Source/WebCore/bindings/js/JSMediaDevicesCustom.cpp 2015-06-10 06:26:57 UTC (rev 185404)
@@ -47,20 +47,21 @@
JSValue JSMediaDevices::getUserMedia(ExecState* exec)
{
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
Dictionary options(exec, exec->argument(0));
if (exec->hadException()) {
Exception* exception = exec->exception();
exec->clearException();
wrapper.reject(exception->value());
- return wrapper.promise();
+ return promiseDeferred->promise();
}
if (!options.isObject()) {
JSValue error = createTypeError(exec, "First argument of getUserMedia must be a valid Dictionary");
wrapper.reject(error);
- return wrapper.promise();
+ return promiseDeferred->promise();
}
auto resolveCallback = [wrapper](MediaStream& stream) mutable {
@@ -75,7 +76,7 @@
if (ec)
wrapper.reject(ec);
- return wrapper.promise();
+ return promiseDeferred->promise();
}
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/js/JSReadableStreamReaderCustom.cpp (185403 => 185404)
--- trunk/Source/WebCore/bindings/js/JSReadableStreamReaderCustom.cpp 2015-06-10 05:59:54 UTC (rev 185403)
+++ trunk/Source/WebCore/bindings/js/JSReadableStreamReaderCustom.cpp 2015-06-10 06:26:57 UTC (rev 185404)
@@ -46,7 +46,9 @@
JSValue JSReadableStreamReader::read(ExecState* exec)
{
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
+
auto successCallback = [wrapper](JSValue value) mutable {
JSValue result = createIteratorResultObject(wrapper.promise()->globalObject()->globalExec(), value, false);
wrapper.resolve(result);
@@ -61,7 +63,7 @@
impl().read(WTF::move(successCallback), WTF::move(endCallback), WTF::move(failureCallback));
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSReadableStreamReader::closed(ExecState* exec) const
@@ -81,7 +83,7 @@
impl().closed(WTF::move(successCallback), WTF::move(failureCallback));
- return wrapper.promise();
+ return m_closedPromiseDeferred->promise();
}
JSValue JSReadableStreamReader::cancel(ExecState* exec)
Modified: trunk/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp (185403 => 185404)
--- trunk/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp 2015-06-10 05:59:54 UTC (rev 185403)
+++ trunk/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp 2015-06-10 06:26:57 UTC (rev 185404)
@@ -162,7 +162,8 @@
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
wrapper.resolve(result);
};
@@ -177,7 +178,7 @@
return jsUndefined();
}
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSSubtleCrypto::decrypt(ExecState* exec)
@@ -213,7 +214,8 @@
return jsUndefined();
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
wrapper.resolve(result);
};
@@ -228,7 +230,7 @@
return jsUndefined();
}
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSSubtleCrypto::sign(ExecState* exec)
@@ -264,7 +266,8 @@
return jsUndefined();
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
wrapper.resolve(result);
};
@@ -279,7 +282,7 @@
return jsUndefined();
}
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSSubtleCrypto::verify(ExecState* exec)
@@ -321,7 +324,8 @@
return jsUndefined();
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper](bool result) mutable {
wrapper.resolve(result);
};
@@ -336,7 +340,7 @@
return jsUndefined();
}
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSSubtleCrypto::digest(ExecState* exec)
@@ -362,7 +366,8 @@
return jsUndefined();
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
wrapper.resolve(result);
};
@@ -377,7 +382,7 @@
return jsUndefined();
}
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSSubtleCrypto::generateKey(ExecState* exec)
@@ -412,7 +417,8 @@
}
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper](CryptoKey* key, CryptoKeyPair* keyPair) mutable {
ASSERT(key || keyPair);
ASSERT(!key || !keyPair);
@@ -432,7 +438,7 @@
return jsUndefined();
}
- return wrapper.promise();
+ return promiseDeferred->promise();
}
static void importKey(ExecState* exec, CryptoKeyFormat keyFormat, CryptoOperationData data, std::unique_ptr<CryptoAlgorithm> algorithm, std::unique_ptr<CryptoAlgorithmParameters> parameters, bool extractable, CryptoKeyUsage keyUsages, CryptoAlgorithm::KeyCallback callback, CryptoAlgorithm::VoidCallback failureCallback)
@@ -539,7 +545,8 @@
}
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper](CryptoKey& result) mutable {
wrapper.resolve(&result);
};
@@ -551,7 +558,7 @@
if (exec->hadException())
return jsUndefined();
- return wrapper.promise();
+ return promiseDeferred->promise();
}
static void exportKey(ExecState* exec, CryptoKeyFormat keyFormat, const CryptoKey& key, CryptoAlgorithm::VectorCallback callback, CryptoAlgorithm::VoidCallback failureCallback)
@@ -601,7 +608,8 @@
if (!key)
return throwTypeError(exec);
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
wrapper.resolve(result);
};
@@ -613,7 +621,7 @@
if (exec->hadException())
return jsUndefined();
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSSubtleCrypto::wrapKey(ExecState* exec)
@@ -653,7 +661,8 @@
return jsUndefined();
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
CryptoAlgorithm* algorithmPtr = algorithm.release();
CryptoAlgorithmParameters* parametersPtr = parameters.release();
@@ -692,7 +701,7 @@
return jsUndefined();
}
- return wrapper.promise();
+ return promiseDeferred->promise();
}
JSValue JSSubtleCrypto::unwrapKey(ExecState* exec)
@@ -765,7 +774,8 @@
}
}
- DeferredWrapper wrapper(exec, globalObject());
+ JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
+ DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
Strong<JSDOMGlobalObject> domGlobalObject(exec->vm(), globalObject());
CryptoAlgorithm* unwrappedKeyAlgorithmPtr = unwrappedKeyAlgorithm.release();
@@ -802,7 +812,7 @@
return jsUndefined();
}
- return wrapper.promise();
+ return promiseDeferred->promise();
}
} // namespace WebCore