Handle IDLPromise<> properly
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 May 2017 12:17:21 +0000 (12:17 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 May 2017 12:17:21 +0000 (12:17 +0000)
commit73e7e9f0e7f103eebd2705eb28135603f33be762
tree7737f6642578af437ba1f2096796f1d3b119c6be
parent0be7d3b0060026e1de5314b1d161da1b6da6b941
Handle IDLPromise<> properly
https://bugs.webkit.org/show_bug.cgi?id=166752

Reviewed by Youenn Fablet.

Source/JavaScriptCore:

Add JSPromise::resolve static function.
This applies `Promise.resolve()` conversion to a given value.

* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::promiseResolveFunction):
* runtime/JSPromise.cpp:
(JSC::JSPromise::resolve):
* runtime/JSPromise.h:

Source/WebCore:

This patch implements WebIDL Promise type conversion. According to the spec,
Promise takes a value and convert it to Promise by using Promise.resolve function.
We implement JSPromise::resolve in JSC and use it in JSDOMConvertPromise.

In conversion phase, we just convert the value to JSC::JSPromise* and hold it in
PromiseRejectionEvent. On the other hand, In this patch, we newly introduce a new
type DOMPromise and use it in RejectedPromiseTracker. And we also rename the previous
DOMPromise to DOMPromiseDeferred since it is corresponding to JSPromiseDeferred.
DOMPromise is DOMGuarded object. So it is strongly referenced from ScriptExecutionContext
and it is weakly referenced from the object itself. This is important since Strong<JSPromise>
reference in C++ object that has a wrapper (in this case, PromiseRejectionEvent) easily causes
cyclic reference. We hold it as DOMPromise instead of Strong<JSPromise> in RejectedPromiseTracker
to break the cyclic reference edge with weak reference.

In the meantime, we still use JSC::Strong<> in PromiseRejectionEvent. It leaks memory if promise
refers the wrapper object of PromiseRejectionEvent. CustomEvent also has the same problem.
This is a general problem that `attribute any` can create cyclic reference. And they should be
fixed in a different patch.

Currently, we do not take the following approach. e.g. There is C++ object that represents Promise.
And its wrapper object is JSPromise thing. When exposing the C++ object, it will be converted to a
wrapper object. We do not take this approach because PromiseRejectionEvent can take user-provided promise.
For example, users can create PromiseRejectionEvent in a form
`new PromiseRejectionEvent("...", { promise: promise })`. In this case, `event.promise === promise`
is required. And this is not suitable for the above C++ object model.

Large part of this patch is mechanical one to replace DOMPromise with DOMPromiseDeferred.

* CMakeLists.txt:
* Modules/applepay/ApplePaySession.cpp:
* Modules/encryptedmedia/MediaKeySession.h:
* Modules/encryptedmedia/MediaKeySystemAccess.h:
* Modules/encryptedmedia/MediaKeys.h:
* Modules/encryptedmedia/NavigatorEME.h:
* Modules/fetch/DOMWindowFetch.h:
* Modules/fetch/FetchBody.h:
* Modules/fetch/FetchBodyConsumer.h:
* Modules/fetch/FetchResponse.h:
* Modules/fetch/WorkerGlobalScopeFetch.h:
* Modules/mediastream/MediaDevices.h:
* Modules/mediastream/MediaEndpointPeerConnection.cpp:
(WebCore::MediaEndpointPeerConnection::replaceTrack):
(WebCore::MediaEndpointPeerConnection::replaceTrackTask):
* Modules/mediastream/MediaEndpointPeerConnection.h:
* Modules/mediastream/MediaStreamTrack.cpp:
(WebCore::MediaStreamTrack::applyConstraints):
* Modules/mediastream/MediaStreamTrack.h:
* Modules/mediastream/PeerConnectionBackend.cpp:
(WebCore::PeerConnectionBackend::setLocalDescription):
(WebCore::PeerConnectionBackend::setRemoteDescription):
(WebCore::PeerConnectionBackend::addIceCandidate):
* Modules/mediastream/PeerConnectionBackend.h:
(WebCore::PeerConnectionBackend::endOfIceCandidates):
* Modules/mediastream/RTCPeerConnection.cpp:
(WebCore::RTCPeerConnection::queuedSetLocalDescription):
(WebCore::RTCPeerConnection::queuedSetRemoteDescription):
(WebCore::RTCPeerConnection::queuedAddIceCandidate):
(WebCore::RTCPeerConnection::enqueueReplaceTrackTask):
(WebCore::RTCPeerConnection::replaceTrack):
* Modules/mediastream/RTCPeerConnection.h:
* Modules/mediastream/RTCRtpSender.cpp:
(WebCore::RTCRtpSender::replaceTrack):
* Modules/mediastream/RTCRtpSender.h:
* Modules/mediastream/UserMediaRequest.cpp:
(WebCore::UserMediaRequest::start):
(WebCore::UserMediaRequest::UserMediaRequest):
* Modules/mediastream/UserMediaRequest.h:
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
(WebCore::LibWebRTCPeerConnectionBackend::replaceTrack):
* Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h:
* Modules/streams/ReadableStreamSource.h:
(WebCore::ReadableStreamSource::start):
(WebCore::ReadableStreamSource::pull):
* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::addReaction):
(WebCore::AudioContext::setState):
(WebCore::AudioContext::suspend):
(WebCore::AudioContext::resume):
(WebCore::AudioContext::close):
* Modules/webaudio/AudioContext.h:
* WebCore.xcodeproj/project.pbxproj:
* bindings/IDLTypes.h:
* bindings/js/CachedModuleScriptLoaderClient.h:
* bindings/js/JSBindingsAllInOne.cpp:
* bindings/js/JSCustomElementRegistryCustom.cpp:
* bindings/js/JSDOMConvertPromise.h:
(WebCore::Converter<IDLPromise<T>>::convert):
(WebCore::JSConverter<IDLPromise<T>>::convert):
* bindings/js/JSDOMExceptionHandling.cpp:
* bindings/js/JSDOMGlobalObject.cpp:
* bindings/js/JSDOMGuardedObject.h:
* bindings/js/JSDOMPromise.h:
(WebCore::DOMPromise::create):
(WebCore::DOMPromise::promise):
(WebCore::DOMPromise::DOMPromise):
(WebCore::DeferredPromise::create): Deleted.
(WebCore::DeferredPromise::resolve): Deleted.
(WebCore::DeferredPromise::resolveWithNewlyCreated): Deleted.
(WebCore::DeferredPromise::reject): Deleted.
(WebCore::DeferredPromise::resolveWithCallback): Deleted.
(WebCore::DeferredPromise::rejectWithCallback): Deleted.
(WebCore::DeferredPromise::DeferredPromise): Deleted.
(WebCore::DeferredPromise::deferred): Deleted.
(WebCore::DOMPromiseBase::DOMPromiseBase): Deleted.
(WebCore::DOMPromiseBase::operator=): Deleted.
(WebCore::DOMPromiseBase::reject): Deleted.
(WebCore::DOMPromiseBase::rejectType): Deleted.
(WebCore::DOMPromiseBase::promise): Deleted.
(WebCore::DOMPromise::resolve): Deleted.
(WebCore::DOMPromise<void>::resolve): Deleted.
(WebCore::callPromiseFunction): Deleted.
(WebCore::bindingPromiseFunctionAdapter): Deleted.
* bindings/js/JSDOMPromiseDeferred.cpp: Renamed from Source/WebCore/bindings/js/JSDOMPromise.cpp.
(WebCore::DeferredPromise::promise):
(WebCore::DeferredPromise::callFunction):
(WebCore::DeferredPromise::reject):
(WebCore::rejectPromiseWithExceptionIfAny):
(WebCore::createDeferredPromise):
(WebCore::createRejectedPromiseWithTypeError):
(WebCore::parseAsJSON):
(WebCore::fulfillPromiseWithJSON):
(WebCore::fulfillPromiseWithArrayBuffer):
* bindings/js/JSDOMPromiseDeferred.h: Copied from Source/WebCore/bindings/js/JSDOMPromise.h.
(WebCore::DeferredPromise::create):
(WebCore::DeferredPromise::resolve):
(WebCore::DeferredPromise::resolveWithNewlyCreated):
(WebCore::DeferredPromise::reject):
(WebCore::DeferredPromise::resolveWithCallback):
(WebCore::DeferredPromise::rejectWithCallback):
(WebCore::DeferredPromise::DeferredPromise):
(WebCore::DeferredPromise::deferred):
(WebCore::DOMPromiseDeferredBase::DOMPromiseDeferredBase):
(WebCore::DOMPromiseDeferredBase::operator=):
(WebCore::DOMPromiseDeferredBase::reject):
(WebCore::DOMPromiseDeferredBase::rejectType):
(WebCore::DOMPromiseDeferredBase::promise):
(WebCore::DOMPromiseDeferred::resolve):
(WebCore::DOMPromiseDeferred<void>::resolve):
(WebCore::callPromiseFunction):
(WebCore::bindingPromiseFunctionAdapter):
* bindings/js/JSSubtleCryptoCustom.cpp:
* bindings/js/JSWebGPUCommandBufferCustom.cpp:
* bindings/js/JSWebKitSubtleCryptoCustom.cpp:
* bindings/scripts/test/JS/JSTestPromiseRejectionEvent.cpp: Added.
(WebCore::convertDictionary<TestPromiseRejectionEvent::Init>):
(WebCore::JSTestPromiseRejectionEventPrototype::create):
(WebCore::JSTestPromiseRejectionEventPrototype::createStructure):
(WebCore::JSTestPromiseRejectionEventPrototype::JSTestPromiseRejectionEventPrototype):
(WebCore::JSTestPromiseRejectionEventConstructor::construct):
(WebCore::JSTestPromiseRejectionEventConstructor::prototypeForStructure):
(WebCore::JSTestPromiseRejectionEventConstructor::initializeProperties):
(WebCore::JSTestPromiseRejectionEventPrototype::finishCreation):
(WebCore::JSTestPromiseRejectionEvent::JSTestPromiseRejectionEvent):
(WebCore::JSTestPromiseRejectionEvent::finishCreation):
(WebCore::JSTestPromiseRejectionEvent::createPrototype):
(WebCore::JSTestPromiseRejectionEvent::prototype):
(WebCore::BindingCaller<JSTestPromiseRejectionEvent>::castForAttribute):
(WebCore::jsTestPromiseRejectionEventPromise):
(WebCore::jsTestPromiseRejectionEventPromiseGetter):
(WebCore::jsTestPromiseRejectionEventReason):
(WebCore::jsTestPromiseRejectionEventReasonGetter):
(WebCore::jsTestPromiseRejectionEventConstructor):
(WebCore::setJSTestPromiseRejectionEventConstructor):
(WebCore::JSTestPromiseRejectionEvent::getConstructor):
(WebCore::toJSNewlyCreated):
(WebCore::toJS):
* bindings/scripts/test/JS/JSTestPromiseRejectionEvent.h: Added.
(WebCore::JSTestPromiseRejectionEvent::create):
(WebCore::JSTestPromiseRejectionEvent::createStructure):
(WebCore::JSTestPromiseRejectionEvent::wrapped):
(WebCore::toJS):
(WebCore::toJSNewlyCreated):
* bindings/scripts/test/TestPromiseRejectionEvent.idl: Copied from Source/WebCore/bindings/js/CachedModuleScriptLoaderClient.h.
* css/FontFace.h:
* css/FontFaceSet.h:
* dom/CustomElementRegistry.h:
* dom/PromiseRejectionEvent.h:
* dom/RejectedPromiseTracker.cpp:
(WebCore::UnhandledPromise::UnhandledPromise):
(WebCore::UnhandledPromise::callStack):
(WebCore::UnhandledPromise::promise):
(WebCore::RejectedPromiseTracker::promiseRejected):
(WebCore::RejectedPromiseTracker::promiseHandled):
(WebCore::RejectedPromiseTracker::reportUnhandledRejections):
(WebCore::RejectedPromiseTracker::reportRejectionHandled):
(WebCore::RejectedPromise::RejectedPromise): Deleted.
(WebCore::RejectedPromise::globalObject): Deleted.
(WebCore::RejectedPromise::promise): Deleted.
* dom/RejectedPromiseTracker.h:
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::rejectPendingPlayPromises):
(WebCore::HTMLMediaElement::resolvePendingPlayPromises):
(WebCore::HTMLMediaElement::play):
* html/HTMLMediaElement.h:
* platform/graphics/gpu/GPUCommandBuffer.h:
* testing/Internals.h:

LayoutTests:

* js/dom/promise-rejection-event-should-follow-webidl-promise-conversion-rule-expected.txt: Added.
* js/dom/promise-rejection-event-should-follow-webidl-promise-conversion-rule.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@216501 268f45cc-cd09-0410-ab3c-d52691b4dbfc
66 files changed:
LayoutTests/ChangeLog
LayoutTests/js/dom/promise-rejection-event-should-follow-webidl-promise-conversion-rule-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/promise-rejection-event-should-follow-webidl-promise-conversion-rule.html [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSPromise.cpp
Source/JavaScriptCore/runtime/JSPromise.h
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/applepay/ApplePaySession.cpp
Source/WebCore/Modules/encryptedmedia/MediaKeySession.h
Source/WebCore/Modules/encryptedmedia/MediaKeySystemAccess.h
Source/WebCore/Modules/encryptedmedia/MediaKeys.h
Source/WebCore/Modules/encryptedmedia/NavigatorEME.h
Source/WebCore/Modules/fetch/DOMWindowFetch.h
Source/WebCore/Modules/fetch/FetchBody.h
Source/WebCore/Modules/fetch/FetchBodyConsumer.h
Source/WebCore/Modules/fetch/FetchResponse.h
Source/WebCore/Modules/fetch/WorkerGlobalScopeFetch.h
Source/WebCore/Modules/mediastream/MediaDevices.h
Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp
Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.h
Source/WebCore/Modules/mediastream/MediaStreamTrack.cpp
Source/WebCore/Modules/mediastream/MediaStreamTrack.h
Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp
Source/WebCore/Modules/mediastream/PeerConnectionBackend.h
Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
Source/WebCore/Modules/mediastream/RTCPeerConnection.h
Source/WebCore/Modules/mediastream/RTCRtpSender.cpp
Source/WebCore/Modules/mediastream/RTCRtpSender.h
Source/WebCore/Modules/mediastream/UserMediaRequest.cpp
Source/WebCore/Modules/mediastream/UserMediaRequest.h
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.h
Source/WebCore/Modules/streams/ReadableStreamSource.h
Source/WebCore/Modules/webaudio/AudioContext.cpp
Source/WebCore/Modules/webaudio/AudioContext.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/IDLTypes.h
Source/WebCore/bindings/js/CachedModuleScriptLoaderClient.h
Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp
Source/WebCore/bindings/js/JSDOMConvertPromise.h
Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp
Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
Source/WebCore/bindings/js/JSDOMGuardedObject.h
Source/WebCore/bindings/js/JSDOMPromise.h
Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp [moved from Source/WebCore/bindings/js/JSDOMPromise.cpp with 99% similarity]
Source/WebCore/bindings/js/JSDOMPromiseDeferred.h [new file with mode: 0644]
Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp
Source/WebCore/bindings/js/JSWebGPUCommandBufferCustom.cpp
Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestPromiseRejectionEvent.cpp [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestPromiseRejectionEvent.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/TestPromiseRejectionEvent.idl [new file with mode: 0644]
Source/WebCore/css/FontFace.h
Source/WebCore/css/FontFaceSet.h
Source/WebCore/dom/CustomElementRegistry.h
Source/WebCore/dom/PromiseRejectionEvent.h
Source/WebCore/dom/RejectedPromiseTracker.cpp
Source/WebCore/dom/RejectedPromiseTracker.h
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h
Source/WebCore/testing/Internals.h