summaryrefslogtreecommitdiff
path: root/dom/promise/PromiseCallback.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/promise/PromiseCallback.cpp')
-rw-r--r--dom/promise/PromiseCallback.cpp571
1 files changed, 0 insertions, 571 deletions
diff --git a/dom/promise/PromiseCallback.cpp b/dom/promise/PromiseCallback.cpp
deleted file mode 100644
index 6ecf983b79..0000000000
--- a/dom/promise/PromiseCallback.cpp
+++ /dev/null
@@ -1,571 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "PromiseCallback.h"
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/PromiseNativeHandler.h"
-
-#include "jsapi.h"
-#include "jsfriendapi.h"
-#include "jswrapper.h"
-
-namespace mozilla {
-namespace dom {
-
-#ifndef SPIDERMONKEY_PROMISE
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_0(PromiseCallback)
-
-PromiseCallback::PromiseCallback()
-{
-}
-
-PromiseCallback::~PromiseCallback()
-{
-}
-
-// ResolvePromiseCallback
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(ResolvePromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ResolvePromiseCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
- tmp->mGlobal = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ResolvePromiseCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResolvePromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ResolvePromiseCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_ADDREF_INHERITED(ResolvePromiseCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(ResolvePromiseCallback, PromiseCallback)
-
-ResolvePromiseCallback::ResolvePromiseCallback(Promise* aPromise,
- JS::Handle<JSObject*> aGlobal)
- : mPromise(aPromise)
- , mGlobal(aGlobal)
-{
- MOZ_ASSERT(aPromise);
- MOZ_ASSERT(aGlobal);
- HoldJSObjects(this);
-}
-
-ResolvePromiseCallback::~ResolvePromiseCallback()
-{
- DropJSObjects(this);
-}
-
-nsresult
-ResolvePromiseCallback::Call(JSContext* aCx,
- JS::Handle<JS::Value> aValue)
-{
- // Run resolver's algorithm with value and the synchronous flag set.
-
- JS::ExposeValueToActiveJS(aValue);
-
- JSAutoCompartment ac(aCx, mGlobal);
- JS::Rooted<JS::Value> value(aCx, aValue);
- if (!JS_WrapValue(aCx, &value)) {
- NS_WARNING("Failed to wrap value into the right compartment.");
- return NS_ERROR_FAILURE;
- }
-
- mPromise->ResolveInternal(aCx, value);
- return NS_OK;
-}
-
-// RejectPromiseCallback
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(RejectPromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RejectPromiseCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
- tmp->mGlobal = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(RejectPromiseCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(RejectPromiseCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(RejectPromiseCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_ADDREF_INHERITED(RejectPromiseCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(RejectPromiseCallback, PromiseCallback)
-
-RejectPromiseCallback::RejectPromiseCallback(Promise* aPromise,
- JS::Handle<JSObject*> aGlobal)
- : mPromise(aPromise)
- , mGlobal(aGlobal)
-{
- MOZ_ASSERT(aPromise);
- MOZ_ASSERT(mGlobal);
- HoldJSObjects(this);
-}
-
-RejectPromiseCallback::~RejectPromiseCallback()
-{
- DropJSObjects(this);
-}
-
-nsresult
-RejectPromiseCallback::Call(JSContext* aCx,
- JS::Handle<JS::Value> aValue)
-{
- // Run resolver's algorithm with value and the synchronous flag set.
-
- JS::ExposeValueToActiveJS(aValue);
-
- JSAutoCompartment ac(aCx, mGlobal);
- JS::Rooted<JS::Value> value(aCx, aValue);
- if (!JS_WrapValue(aCx, &value)) {
- NS_WARNING("Failed to wrap value into the right compartment.");
- return NS_ERROR_FAILURE;
- }
-
-
- mPromise->RejectInternal(aCx, value);
- return NS_OK;
-}
-
-// InvokePromiseFuncCallback
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(InvokePromiseFuncCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(InvokePromiseFuncCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromiseFunc)
- tmp->mGlobal = nullptr;
- tmp->mNextPromiseObj = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(InvokePromiseFuncCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromiseFunc)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(InvokePromiseFuncCallback)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNextPromiseObj)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(InvokePromiseFuncCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_ADDREF_INHERITED(InvokePromiseFuncCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(InvokePromiseFuncCallback, PromiseCallback)
-
-InvokePromiseFuncCallback::InvokePromiseFuncCallback(JS::Handle<JSObject*> aGlobal,
- JS::Handle<JSObject*> aNextPromiseObj,
- AnyCallback* aPromiseFunc)
- : mGlobal(aGlobal)
- , mNextPromiseObj(aNextPromiseObj)
- , mPromiseFunc(aPromiseFunc)
-{
- MOZ_ASSERT(aGlobal);
- MOZ_ASSERT(aNextPromiseObj);
- MOZ_ASSERT(aPromiseFunc);
- HoldJSObjects(this);
-}
-
-InvokePromiseFuncCallback::~InvokePromiseFuncCallback()
-{
- DropJSObjects(this);
-}
-
-nsresult
-InvokePromiseFuncCallback::Call(JSContext* aCx,
- JS::Handle<JS::Value> aValue)
-{
- // Run resolver's algorithm with value and the synchronous flag set.
-
- JS::ExposeValueToActiveJS(aValue);
-
- JSAutoCompartment ac(aCx, mGlobal);
- JS::Rooted<JS::Value> value(aCx, aValue);
- if (!JS_WrapValue(aCx, &value)) {
- NS_WARNING("Failed to wrap value into the right compartment.");
- return NS_ERROR_FAILURE;
- }
-
- ErrorResult rv;
- JS::Rooted<JS::Value> ignored(aCx);
- mPromiseFunc->Call(value, &ignored, rv);
- // Useful exceptions already got reported.
- rv.SuppressException();
- return NS_OK;
-}
-
-Promise*
-InvokePromiseFuncCallback::GetDependentPromise()
-{
- Promise* promise;
- if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
- return promise;
- }
-
- // Oh, well.
- return nullptr;
-}
-
-// WrapperPromiseCallback
-NS_IMPL_CYCLE_COLLECTION_CLASS(WrapperPromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WrapperPromiseCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mNextPromise)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveFunc)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectFunc)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
- tmp->mGlobal = nullptr;
- tmp->mNextPromiseObj = nullptr;
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WrapperPromiseCallback,
- PromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNextPromise)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveFunc)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectFunc)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WrapperPromiseCallback)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
- NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNextPromiseObj)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(WrapperPromiseCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_ADDREF_INHERITED(WrapperPromiseCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(WrapperPromiseCallback, PromiseCallback)
-
-WrapperPromiseCallback::WrapperPromiseCallback(Promise* aNextPromise,
- JS::Handle<JSObject*> aGlobal,
- AnyCallback* aCallback)
- : mNextPromise(aNextPromise)
- , mGlobal(aGlobal)
- , mCallback(aCallback)
-{
- MOZ_ASSERT(aNextPromise);
- MOZ_ASSERT(aGlobal);
- HoldJSObjects(this);
-}
-
-WrapperPromiseCallback::WrapperPromiseCallback(JS::Handle<JSObject*> aGlobal,
- AnyCallback* aCallback,
- JS::Handle<JSObject*> aNextPromiseObj,
- AnyCallback* aResolveFunc,
- AnyCallback* aRejectFunc)
- : mNextPromiseObj(aNextPromiseObj)
- , mResolveFunc(aResolveFunc)
- , mRejectFunc(aRejectFunc)
- , mGlobal(aGlobal)
- , mCallback(aCallback)
-{
- MOZ_ASSERT(mNextPromiseObj);
- MOZ_ASSERT(aResolveFunc);
- MOZ_ASSERT(aRejectFunc);
- MOZ_ASSERT(aGlobal);
- HoldJSObjects(this);
-}
-
-WrapperPromiseCallback::~WrapperPromiseCallback()
-{
- DropJSObjects(this);
-}
-
-nsresult
-WrapperPromiseCallback::Call(JSContext* aCx,
- JS::Handle<JS::Value> aValue)
-{
- JS::ExposeValueToActiveJS(aValue);
-
- JSAutoCompartment ac(aCx, mGlobal);
- JS::Rooted<JS::Value> value(aCx, aValue);
- if (!JS_WrapValue(aCx, &value)) {
- NS_WARNING("Failed to wrap value into the right compartment.");
- return NS_ERROR_FAILURE;
- }
-
- ErrorResult rv;
-
- // PromiseReactionTask step 6
- JS::Rooted<JS::Value> retValue(aCx);
- JSCompartment* compartment;
- if (mNextPromise) {
- compartment = mNextPromise->Compartment();
- } else {
- MOZ_ASSERT(mNextPromiseObj);
- compartment = js::GetObjectCompartment(mNextPromiseObj);
- }
- mCallback->Call(value, &retValue, rv, "promise callback",
- CallbackObject::eRethrowExceptions,
- compartment);
-
- rv.WouldReportJSException();
-
- // PromiseReactionTask step 7
- if (rv.Failed()) {
- if (rv.IsUncatchableException()) {
- // We have nothing to resolve/reject the promise with.
- return rv.StealNSResult();
- }
-
- JS::Rooted<JS::Value> value(aCx);
- { // Scope for JSAutoCompartment
- // Convert the ErrorResult to a JS exception object that we can reject
- // ourselves with. This will be exactly the exception that would get
- // thrown from a binding method whose ErrorResult ended up with whatever
- // is on "rv" right now. Do this in the promise reflector compartment.
- Maybe<JSAutoCompartment> ac;
- if (mNextPromise) {
- ac.emplace(aCx, mNextPromise->GlobalJSObject());
- } else {
- ac.emplace(aCx, mNextPromiseObj);
- }
- DebugOnly<bool> conversionResult = ToJSValue(aCx, rv, &value);
- MOZ_ASSERT(conversionResult);
- }
-
- if (mNextPromise) {
- mNextPromise->RejectInternal(aCx, value);
- } else {
- JS::Rooted<JS::Value> ignored(aCx);
- ErrorResult rejectRv;
- mRejectFunc->Call(value, &ignored, rejectRv);
- // This reported any JS exceptions; we just have a pointless exception on
- // there now.
- rejectRv.SuppressException();
- }
- return NS_OK;
- }
-
- // If the return value is the same as the promise itself, throw TypeError.
- if (retValue.isObject()) {
- JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject());
- valueObj = js::CheckedUnwrap(valueObj);
- JS::Rooted<JSObject*> nextPromiseObj(aCx);
- if (mNextPromise) {
- nextPromiseObj = mNextPromise->GetWrapper();
- } else {
- MOZ_ASSERT(mNextPromiseObj);
- nextPromiseObj = mNextPromiseObj;
- }
- // XXXbz shouldn't this check be over in ResolveInternal anyway?
- if (valueObj == nextPromiseObj) {
- const char* fileName = nullptr;
- uint32_t lineNumber = 0;
-
- // Try to get some information about the callback to report a sane error,
- // but don't try too hard (only deals with scripted functions).
- JS::Rooted<JSObject*> unwrapped(aCx,
- js::CheckedUnwrap(mCallback->Callback()));
-
- if (unwrapped) {
- JSAutoCompartment ac(aCx, unwrapped);
- if (JS_ObjectIsFunction(aCx, unwrapped)) {
- JS::Rooted<JS::Value> asValue(aCx, JS::ObjectValue(*unwrapped));
- JS::Rooted<JSFunction*> func(aCx, JS_ValueToFunction(aCx, asValue));
-
- MOZ_ASSERT(func);
- JSScript* script = JS_GetFunctionScript(aCx, func);
- if (script) {
- fileName = JS_GetScriptFilename(script);
- lineNumber = JS_GetScriptBaseLineNumber(aCx, script);
- }
- }
- }
-
- // We're back in aValue's compartment here.
- JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName));
- if (!fn) {
- // Out of memory. Promise will stay unresolved.
- JS_ClearPendingException(aCx);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- JS::Rooted<JSString*> message(aCx,
- JS_NewStringCopyZ(aCx,
- "then() cannot return same Promise that it resolves."));
- if (!message) {
- // Out of memory. Promise will stay unresolved.
- JS_ClearPendingException(aCx);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- JS::Rooted<JS::Value> typeError(aCx);
- if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, fn, lineNumber, 0,
- nullptr, message, &typeError)) {
- // Out of memory. Promise will stay unresolved.
- JS_ClearPendingException(aCx);
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- if (mNextPromise) {
- mNextPromise->RejectInternal(aCx, typeError);
- } else {
- JS::Rooted<JS::Value> ignored(aCx);
- ErrorResult rejectRv;
- mRejectFunc->Call(typeError, &ignored, rejectRv);
- // This reported any JS exceptions; we just have a pointless exception
- // on there now.
- rejectRv.SuppressException();
- }
- return NS_OK;
- }
- }
-
- // Otherwise, run resolver's resolve with value.
- if (!JS_WrapValue(aCx, &retValue)) {
- NS_WARNING("Failed to wrap value into the right compartment.");
- return NS_ERROR_FAILURE;
- }
-
- if (mNextPromise) {
- mNextPromise->ResolveInternal(aCx, retValue);
- } else {
- JS::Rooted<JS::Value> ignored(aCx);
- ErrorResult resolveRv;
- mResolveFunc->Call(retValue, &ignored, resolveRv);
- // This reported any JS exceptions; we just have a pointless exception
- // on there now.
- resolveRv.SuppressException();
- }
-
- return NS_OK;
-}
-
-Promise*
-WrapperPromiseCallback::GetDependentPromise()
-{
- // Per spec, various algorithms like all() and race() are actually implemented
- // in terms of calling then() but passing it the resolve/reject functions that
- // are passed as arguments to function passed to the Promise constructor.
- // That will cause the promise in question to hold on to a
- // WrapperPromiseCallback, but the dependent promise should really be the one
- // whose constructor those functions came from, not the about-to-be-ignored
- // return value of "then". So try to determine whether we're in that case and
- // if so go ahead and dig the dependent promise out of the function we have.
- JSObject* callable = mCallback->Callable();
- // Unwrap it, in case it's a cross-compartment wrapper. Our caller here is
- // system, so it's really ok to just go and unwrap.
- callable = js::UncheckedUnwrap(callable);
- if (JS_IsNativeFunction(callable, Promise::JSCallback)) {
- JS::Value promiseVal =
- js::GetFunctionNativeReserved(callable, Promise::SLOT_PROMISE);
- Promise* promise;
- UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
- return promise;
- }
-
- if (mNextPromise) {
- return mNextPromise;
- }
-
- Promise* promise;
- if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
- return promise;
- }
-
- // Oh, well.
- return nullptr;
-}
-
-// NativePromiseCallback
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(NativePromiseCallback,
- PromiseCallback, mHandler)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NativePromiseCallback)
-NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
-
-NS_IMPL_ADDREF_INHERITED(NativePromiseCallback, PromiseCallback)
-NS_IMPL_RELEASE_INHERITED(NativePromiseCallback, PromiseCallback)
-
-NativePromiseCallback::NativePromiseCallback(PromiseNativeHandler* aHandler,
- Promise::PromiseState aState)
- : mHandler(aHandler)
- , mState(aState)
-{
- MOZ_ASSERT(aHandler);
-}
-
-NativePromiseCallback::~NativePromiseCallback()
-{
-}
-
-nsresult
-NativePromiseCallback::Call(JSContext* aCx,
- JS::Handle<JS::Value> aValue)
-{
- JS::ExposeValueToActiveJS(aValue);
-
- if (mState == Promise::Resolved) {
- mHandler->ResolvedCallback(aCx, aValue);
- return NS_OK;
- }
-
- if (mState == Promise::Rejected) {
- mHandler->RejectedCallback(aCx, aValue);
- return NS_OK;
- }
-
- NS_NOTREACHED("huh?");
- return NS_ERROR_FAILURE;
-}
-
-/* static */ PromiseCallback*
-PromiseCallback::Factory(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
- AnyCallback* aCallback, Task aTask)
-{
- MOZ_ASSERT(aNextPromise);
-
- // If we have a callback and a next resolver, we have to exec the callback and
- // then propagate the return value to the next resolver->resolve().
- if (aCallback) {
- return new WrapperPromiseCallback(aNextPromise, aGlobal, aCallback);
- }
-
- if (aTask == Resolve) {
- return new ResolvePromiseCallback(aNextPromise, aGlobal);
- }
-
- if (aTask == Reject) {
- return new RejectPromiseCallback(aNextPromise, aGlobal);
- }
-
- MOZ_ASSERT(false, "This should not happen");
- return nullptr;
-}
-
-#endif // SPIDERMONKEY_PROMISE
-
-} // namespace dom
-} // namespace mozilla