Bug 1016560. Remove the footgun of rejecting promises with arbitrary objects. r=khuey

This commit is contained in:
Boris Zbarsky 2014-06-03 11:38:38 -04:00
parent 9424c286ad
commit 253e2d6c68
10 changed files with 36 additions and 14 deletions

View File

@ -1497,7 +1497,7 @@ Navigator::GetFeature(const nsAString& aName)
if (XRE_GetProcessType() == GeckoProcessType_Default) {
uint32_t memLevel = mozilla::hal::GetTotalSystemMemoryLevel();
if (memLevel == 0) {
p->MaybeReject(NS_LITERAL_STRING("Abnormal"));
p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return p.forget();
}
p->MaybeResolve((int)memLevel);

View File

@ -150,7 +150,7 @@ RejectPromise(nsPIDOMWindow* aWindow, Promise* aPromise, nsresult aRv)
NS_LITERAL_STRING("An error occurred"));
}
aPromise->MaybeReject(error);
aPromise->MaybeRejectBrokenly(error);
}
void

View File

@ -122,7 +122,7 @@ CreateDirectoryTask::HandlerCallback()
if (HasError()) {
nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeReject(domError);
mPromise->MaybeRejectBrokenly(domError);
mPromise = nullptr;
return;
}

View File

@ -287,7 +287,7 @@ CreateFileTask::HandlerCallback()
if (HasError()) {
nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeReject(domError);
mPromise->MaybeRejectBrokenly(domError);
mPromise = nullptr;
return;
}

View File

@ -197,7 +197,7 @@ GetFileOrDirectoryTask::HandlerCallback()
if (HasError()) {
nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeReject(domError);
mPromise->MaybeRejectBrokenly(domError);
mPromise = nullptr;
return;
}

View File

@ -185,7 +185,7 @@ RemoveTask::HandlerCallback()
if (HasError()) {
nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeReject(domError);
mPromise->MaybeRejectBrokenly(domError);
mPromise = nullptr;
return;
}

View File

@ -1473,7 +1473,7 @@ ContentChild::RecvSystemMemoryAvailable(const uint64_t& aGetterId,
nsRefPtr<Promise> p = dont_AddRef(reinterpret_cast<Promise*>(aGetterId));
if (!aMemoryAvailable) {
p->MaybeReject(NS_LITERAL_STRING("Abnormal"));
p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return true;
}

View File

@ -7,6 +7,7 @@
#include "mozilla/dom/Promise.h"
#include "jsfriendapi.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/OwningNonNull.h"
#include "mozilla/dom/PromiseBinding.h"
#include "mozilla/CycleCollectedJSRuntime.h"
@ -1431,5 +1432,15 @@ PromiseWorkerProxy::CleanUp(JSContext* aCx)
mCleanedUp = true;
}
// Specializations of MaybeRejectBrokenly we actually support.
template<>
void Promise::MaybeRejectBrokenly(const nsRefPtr<DOMError>& aArg) {
MaybeSomething(aArg, &Promise::MaybeReject);
}
template<>
void Promise::MaybeRejectBrokenly(const nsAString& aArg) {
MaybeSomething(aArg, &Promise::MaybeReject);
}
} // namespace dom
} // namespace mozilla

View File

@ -26,6 +26,7 @@ namespace mozilla {
namespace dom {
class AnyCallback;
class DOMError;
class PromiseCallback;
class PromiseInit;
class PromiseNativeHandler;
@ -89,11 +90,21 @@ public:
MaybeSomething(aArg, &Promise::MaybeResolve);
}
// aArg is a const reference so we can pass rvalues like NS_ERROR_*
template <typename T>
void MaybeReject(const T& aArg) {
inline void MaybeReject(nsresult aArg) {
MOZ_ASSERT(NS_FAILED(aArg));
MaybeSomething(aArg, &Promise::MaybeReject);
}
// DO NOT USE MaybeRejectBrokenly with in new code. Promises should be
// rejected with Error instances.
// Note: MaybeRejectBrokenly is a template so we can use it with DOMError
// without instantiating the DOMError specialization of MaybeSomething in
// every translation unit that includes this header, because that would
// require use to include DOMError.h either here or in all those translation
// units.
template<typename T>
void MaybeRejectBrokenly(const T& aArg); // Not implemented by default; see
// specializations in the .cpp for
// the T values we support.
// WebIDL

View File

@ -76,7 +76,7 @@ public:
NS_IMETHODIMP
NotifyDialError(const nsAString& aError)
{
mPromise->MaybeReject(aError);
mPromise->MaybeRejectBrokenly(aError);
return NS_OK;
}
@ -255,13 +255,13 @@ Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber,
nsRefPtr<Promise> promise = new Promise(global);
if (!IsValidNumber(aNumber) || !IsValidServiceId(aServiceId)) {
promise->MaybeReject(NS_LITERAL_STRING("InvalidAccessError"));
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
// We only support one outgoing call at a time.
if (HasDialingCall()) {
promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
@ -269,7 +269,7 @@ Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber,
new Callback(this, promise, aServiceId, aNumber);
nsresult rv = mService->Dial(aServiceId, aNumber, aIsEmergency, callback);
if (NS_FAILED(rv)) {
promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}