mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
Bug 933378 part 1. Introduce a TErrorResult class that will serve as a base class for various ErrorResult-like subclasses. No actual behavior changes so far. r=bkelly
This commit is contained in:
parent
c5ce5bdb84
commit
4e44fce24b
@ -143,9 +143,12 @@ ThrowNoSetterArg(JSContext* aCx, prototypes::ID aProtoId)
|
|||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
||||||
struct ErrorResult::Message {
|
namespace binding_danger {
|
||||||
Message() { MOZ_COUNT_CTOR(ErrorResult::Message); }
|
|
||||||
~Message() { MOZ_COUNT_DTOR(ErrorResult::Message); }
|
template<typename CleanupPolicy>
|
||||||
|
struct TErrorResult<CleanupPolicy>::Message {
|
||||||
|
Message() { MOZ_COUNT_CTOR(TErrorResult::Message); }
|
||||||
|
~Message() { MOZ_COUNT_DTOR(TErrorResult::Message); }
|
||||||
|
|
||||||
nsTArray<nsString> mArgs;
|
nsTArray<nsString> mArgs;
|
||||||
dom::ErrNum mErrorNumber;
|
dom::ErrNum mErrorNumber;
|
||||||
@ -156,8 +159,10 @@ struct ErrorResult::Message {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
nsTArray<nsString>&
|
nsTArray<nsString>&
|
||||||
ErrorResult::CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType)
|
TErrorResult<CleanupPolicy>::CreateErrorMessageHelper(const dom::ErrNum errorNumber,
|
||||||
|
nsresult errorType)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
mResult = errorType;
|
mResult = errorType;
|
||||||
@ -167,8 +172,9 @@ ErrorResult::CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult er
|
|||||||
return mMessage->mArgs;
|
return mMessage->mArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::SerializeMessage(IPC::Message* aMsg) const
|
TErrorResult<CleanupPolicy>::SerializeMessage(IPC::Message* aMsg) const
|
||||||
{
|
{
|
||||||
using namespace IPC;
|
using namespace IPC;
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
@ -178,8 +184,10 @@ ErrorResult::SerializeMessage(IPC::Message* aMsg) const
|
|||||||
WriteParam(aMsg, mMessage->mErrorNumber);
|
WriteParam(aMsg, mMessage->mErrorNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
bool
|
bool
|
||||||
ErrorResult::DeserializeMessage(const IPC::Message* aMsg, PickleIterator* aIter)
|
TErrorResult<CleanupPolicy>::DeserializeMessage(const IPC::Message* aMsg,
|
||||||
|
PickleIterator* aIter)
|
||||||
{
|
{
|
||||||
using namespace IPC;
|
using namespace IPC;
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
@ -200,8 +208,9 @@ ErrorResult::DeserializeMessage(const IPC::Message* aMsg, PickleIterator* aIter)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::SetPendingExceptionWithMessage(JSContext* aCx)
|
TErrorResult<CleanupPolicy>::SetPendingExceptionWithMessage(JSContext* aCx)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
MOZ_ASSERT(mMessage, "SetPendingExceptionWithMessage() can be called only once");
|
MOZ_ASSERT(mMessage, "SetPendingExceptionWithMessage() can be called only once");
|
||||||
@ -224,8 +233,9 @@ ErrorResult::SetPendingExceptionWithMessage(JSContext* aCx)
|
|||||||
mResult = NS_OK;
|
mResult = NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::ClearMessage()
|
TErrorResult<CleanupPolicy>::ClearMessage()
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
MOZ_ASSERT(IsErrorWithMessage());
|
MOZ_ASSERT(IsErrorWithMessage());
|
||||||
@ -236,8 +246,9 @@ ErrorResult::ClearMessage()
|
|||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn)
|
TErrorResult<CleanupPolicy>::ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
MOZ_ASSERT(mMightHaveUnreportedJSException,
|
MOZ_ASSERT(mMightHaveUnreportedJSException,
|
||||||
@ -249,7 +260,7 @@ ErrorResult::ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn)
|
|||||||
// don't set it to exn yet, because we don't want to do that until after we
|
// don't set it to exn yet, because we don't want to do that until after we
|
||||||
// root.
|
// root.
|
||||||
mJSException.setUndefined();
|
mJSException.setUndefined();
|
||||||
if (!js::AddRawValueRoot(cx, &mJSException, "ErrorResult::mJSException")) {
|
if (!js::AddRawValueRoot(cx, &mJSException, "TErrorResult::mJSException")) {
|
||||||
// Don't use NS_ERROR_DOM_JS_EXCEPTION, because that indicates we have
|
// Don't use NS_ERROR_DOM_JS_EXCEPTION, because that indicates we have
|
||||||
// in fact rooted mJSException.
|
// in fact rooted mJSException.
|
||||||
mResult = NS_ERROR_OUT_OF_MEMORY;
|
mResult = NS_ERROR_OUT_OF_MEMORY;
|
||||||
@ -262,8 +273,9 @@ ErrorResult::ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::SetPendingJSException(JSContext* cx)
|
TErrorResult<CleanupPolicy>::SetPendingJSException(JSContext* cx)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
MOZ_ASSERT(!mMightHaveUnreportedJSException,
|
MOZ_ASSERT(!mMightHaveUnreportedJSException,
|
||||||
@ -285,7 +297,8 @@ ErrorResult::SetPendingJSException(JSContext* cx)
|
|||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ErrorResult::DOMExceptionInfo {
|
template<typename CleanupPolicy>
|
||||||
|
struct TErrorResult<CleanupPolicy>::DOMExceptionInfo {
|
||||||
DOMExceptionInfo(nsresult rv, const nsACString& message)
|
DOMExceptionInfo(nsresult rv, const nsACString& message)
|
||||||
: mMessage(message)
|
: mMessage(message)
|
||||||
, mRv(rv)
|
, mRv(rv)
|
||||||
@ -295,8 +308,9 @@ struct ErrorResult::DOMExceptionInfo {
|
|||||||
nsresult mRv;
|
nsresult mRv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::SerializeDOMExceptionInfo(IPC::Message* aMsg) const
|
TErrorResult<CleanupPolicy>::SerializeDOMExceptionInfo(IPC::Message* aMsg) const
|
||||||
{
|
{
|
||||||
using namespace IPC;
|
using namespace IPC;
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
@ -306,8 +320,10 @@ ErrorResult::SerializeDOMExceptionInfo(IPC::Message* aMsg) const
|
|||||||
WriteParam(aMsg, mDOMExceptionInfo->mRv);
|
WriteParam(aMsg, mDOMExceptionInfo->mRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
bool
|
bool
|
||||||
ErrorResult::DeserializeDOMExceptionInfo(const IPC::Message* aMsg, PickleIterator* aIter)
|
TErrorResult<CleanupPolicy>::DeserializeDOMExceptionInfo(const IPC::Message* aMsg,
|
||||||
|
PickleIterator* aIter)
|
||||||
{
|
{
|
||||||
using namespace IPC;
|
using namespace IPC;
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
@ -327,8 +343,10 @@ ErrorResult::DeserializeDOMExceptionInfo(const IPC::Message* aMsg, PickleIterato
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::ThrowDOMException(nsresult rv, const nsACString& message)
|
TErrorResult<CleanupPolicy>::ThrowDOMException(nsresult rv,
|
||||||
|
const nsACString& message)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
ClearUnionData();
|
ClearUnionData();
|
||||||
@ -340,8 +358,9 @@ ErrorResult::ThrowDOMException(nsresult rv, const nsACString& message)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::SetPendingDOMException(JSContext* cx)
|
TErrorResult<CleanupPolicy>::SetPendingDOMException(JSContext* cx)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
MOZ_ASSERT(mDOMExceptionInfo,
|
MOZ_ASSERT(mDOMExceptionInfo,
|
||||||
@ -354,8 +373,9 @@ ErrorResult::SetPendingDOMException(JSContext* cx)
|
|||||||
mResult = NS_OK;
|
mResult = NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::ClearDOMExceptionInfo()
|
TErrorResult<CleanupPolicy>::ClearDOMExceptionInfo()
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
MOZ_ASSERT(IsDOMException());
|
MOZ_ASSERT(IsDOMException());
|
||||||
@ -367,8 +387,9 @@ ErrorResult::ClearDOMExceptionInfo()
|
|||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::ClearUnionData()
|
TErrorResult<CleanupPolicy>::ClearUnionData()
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
if (IsJSException()) {
|
if (IsJSException()) {
|
||||||
@ -386,8 +407,9 @@ ErrorResult::ClearUnionData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::SetPendingGenericErrorException(JSContext* cx)
|
TErrorResult<CleanupPolicy>::SetPendingGenericErrorException(JSContext* cx)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
MOZ_ASSERT(!IsErrorWithMessage());
|
MOZ_ASSERT(!IsErrorWithMessage());
|
||||||
@ -397,8 +419,9 @@ ErrorResult::SetPendingGenericErrorException(JSContext* cx)
|
|||||||
mResult = NS_OK;
|
mResult = NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorResult&
|
template<typename CleanupPolicy>
|
||||||
ErrorResult::operator=(ErrorResult&& aRHS)
|
TErrorResult<CleanupPolicy>&
|
||||||
|
TErrorResult<CleanupPolicy>::operator=(TErrorResult<CleanupPolicy>&& aRHS)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
aRHS.AssertInOwningThread();
|
aRHS.AssertInOwningThread();
|
||||||
@ -417,7 +440,7 @@ ErrorResult::operator=(ErrorResult&& aRHS)
|
|||||||
JSContext* cx = nsContentUtils::RootingCx();
|
JSContext* cx = nsContentUtils::RootingCx();
|
||||||
MOZ_ASSERT(cx);
|
MOZ_ASSERT(cx);
|
||||||
mJSException.setUndefined();
|
mJSException.setUndefined();
|
||||||
if (!js::AddRawValueRoot(cx, &mJSException, "ErrorResult::mJSException")) {
|
if (!js::AddRawValueRoot(cx, &mJSException, "TErrorResult::mJSException")) {
|
||||||
MOZ_CRASH("Could not root mJSException, we're about to OOM");
|
MOZ_CRASH("Could not root mJSException, we're about to OOM");
|
||||||
}
|
}
|
||||||
mJSException = aRHS.mJSException;
|
mJSException = aRHS.mJSException;
|
||||||
@ -443,8 +466,9 @@ ErrorResult::operator=(ErrorResult&& aRHS)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::CloneTo(ErrorResult& aRv) const
|
TErrorResult<CleanupPolicy>::CloneTo(TErrorResult& aRv) const
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
aRv.AssertInOwningThread();
|
aRv.AssertInOwningThread();
|
||||||
@ -478,8 +502,9 @@ ErrorResult::CloneTo(ErrorResult& aRv) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::SuppressException()
|
TErrorResult<CleanupPolicy>::SuppressException()
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
WouldReportJSException();
|
WouldReportJSException();
|
||||||
@ -489,8 +514,9 @@ ErrorResult::SuppressException()
|
|||||||
mResult = NS_OK;
|
mResult = NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::SetPendingException(JSContext* cx)
|
TErrorResult<CleanupPolicy>::SetPendingException(JSContext* cx)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
if (IsUncatchableException()) {
|
if (IsUncatchableException()) {
|
||||||
@ -522,8 +548,9 @@ ErrorResult::SetPendingException(JSContext* cx)
|
|||||||
SetPendingGenericErrorException(cx);
|
SetPendingGenericErrorException(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::StealExceptionFromJSContext(JSContext* cx)
|
TErrorResult<CleanupPolicy>::StealExceptionFromJSContext(JSContext* cx)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
MOZ_ASSERT(mMightHaveUnreportedJSException,
|
MOZ_ASSERT(mMightHaveUnreportedJSException,
|
||||||
@ -539,8 +566,9 @@ ErrorResult::StealExceptionFromJSContext(JSContext* cx)
|
|||||||
JS_ClearPendingException(cx);
|
JS_ClearPendingException(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CleanupPolicy>
|
||||||
void
|
void
|
||||||
ErrorResult::NoteJSContextException(JSContext* aCx)
|
TErrorResult<CleanupPolicy>::NoteJSContextException(JSContext* aCx)
|
||||||
{
|
{
|
||||||
AssertInOwningThread();
|
AssertInOwningThread();
|
||||||
if (JS_IsExceptionPending(aCx)) {
|
if (JS_IsExceptionPending(aCx)) {
|
||||||
@ -550,6 +578,10 @@ ErrorResult::NoteJSContextException(JSContext* aCx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class TErrorResult<JustAssertCleanupPolicy>;
|
||||||
|
|
||||||
|
} // namespace binding_danger
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -5,9 +5,10 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A struct for tracking exceptions that need to be thrown to JS.
|
* A set of structs for tracking exceptions that need to be thrown to JS:
|
||||||
|
* ErrorResult and IgnoredErrorResult.
|
||||||
*
|
*
|
||||||
* Conceptually, an ErrorResult represents either success or an exception in the
|
* Conceptually, these structs represent either success or an exception in the
|
||||||
* process of being thrown. This means that a failing ErrorResult _must_ be
|
* process of being thrown. This means that a failing ErrorResult _must_ be
|
||||||
* handled in one of the following ways before coming off the stack:
|
* handled in one of the following ways before coming off the stack:
|
||||||
*
|
*
|
||||||
@ -17,6 +18,8 @@
|
|||||||
* MaybeSetPendingException.
|
* MaybeSetPendingException.
|
||||||
* 4) Converted to an exception JS::Value (probably to then reject a Promise
|
* 4) Converted to an exception JS::Value (probably to then reject a Promise
|
||||||
* with) via dom::ToJSValue.
|
* with) via dom::ToJSValue.
|
||||||
|
*
|
||||||
|
* An IgnoredErrorResult will automatically do the first of those four things.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef mozilla_ErrorResult_h
|
#ifndef mozilla_ErrorResult_h
|
||||||
@ -88,9 +91,25 @@ struct StringArrayAppender
|
|||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
||||||
class ErrorResult {
|
class ErrorResult;
|
||||||
|
|
||||||
|
namespace binding_danger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Templated implementation class for various ErrorResult-like things. The
|
||||||
|
* instantiations differ only in terms of their cleanup policies (used in the
|
||||||
|
* destructor), which they can specify via the template argument. Note that
|
||||||
|
* this means it's safe to reinterpret_cast between the instantiations unless
|
||||||
|
* you plan to invoke the destructor through such a cast pointer.
|
||||||
|
*
|
||||||
|
* A cleanup policy consists of two booleans: whether to assert that we've been
|
||||||
|
* reported or suppressed, and whether to then go ahead and suppress the
|
||||||
|
* exception.
|
||||||
|
*/
|
||||||
|
template<typename CleanupPolicy>
|
||||||
|
class TErrorResult {
|
||||||
public:
|
public:
|
||||||
ErrorResult()
|
TErrorResult()
|
||||||
: mResult(NS_OK)
|
: mResult(NS_OK)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
, mMightHaveUnreportedJSException(false)
|
, mMightHaveUnreportedJSException(false)
|
||||||
@ -99,29 +118,35 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
~TErrorResult() {
|
||||||
~ErrorResult() {
|
NS_ASSERT_OWNINGTHREAD(TErrorResult);
|
||||||
// Consumers should have called one of MaybeSetPendingException
|
|
||||||
// (possibly via ToJSValue), StealNSResult, and SuppressException
|
|
||||||
MOZ_ASSERT(!Failed());
|
|
||||||
MOZ_ASSERT(!mMightHaveUnreportedJSException);
|
|
||||||
MOZ_ASSERT(mUnionState == HasNothing);
|
|
||||||
NS_ASSERT_OWNINGTHREAD(ErrorResult);
|
|
||||||
}
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
ErrorResult(ErrorResult&& aRHS)
|
if (CleanupPolicy::assertHandled) {
|
||||||
|
// Consumers should have called one of MaybeSetPendingException
|
||||||
|
// (possibly via ToJSValue), StealNSResult, and SuppressException
|
||||||
|
AssertReportedOrSuppressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CleanupPolicy::suppress) {
|
||||||
|
SuppressException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// And now assert that we're in a good final state.
|
||||||
|
AssertReportedOrSuppressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
TErrorResult(TErrorResult&& aRHS)
|
||||||
// Initialize mResult and whatever else we need to default-initialize, so
|
// Initialize mResult and whatever else we need to default-initialize, so
|
||||||
// the ClearUnionData call in our operator= will do the right thing
|
// the ClearUnionData call in our operator= will do the right thing
|
||||||
// (nothing).
|
// (nothing).
|
||||||
: ErrorResult()
|
: TErrorResult()
|
||||||
{
|
{
|
||||||
*this = Move(aRHS);
|
*this = Move(aRHS);
|
||||||
}
|
}
|
||||||
ErrorResult& operator=(ErrorResult&& aRHS);
|
TErrorResult& operator=(TErrorResult&& aRHS);
|
||||||
|
|
||||||
explicit ErrorResult(nsresult aRv)
|
explicit TErrorResult(nsresult aRv)
|
||||||
: ErrorResult()
|
: TErrorResult()
|
||||||
{
|
{
|
||||||
AssignErrorCode(aRv);
|
AssignErrorCode(aRv);
|
||||||
}
|
}
|
||||||
@ -131,18 +156,18 @@ public:
|
|||||||
AssignErrorCode(rv);
|
AssignErrorCode(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duplicate our current state on the given ErrorResult object. Any existing
|
// Duplicate our current state on the given TErrorResult object. Any
|
||||||
// errors or messages on the target will be suppressed before cloning. Our
|
// existing errors or messages on the target will be suppressed before
|
||||||
// own error state remains unchanged.
|
// cloning. Our own error state remains unchanged.
|
||||||
void CloneTo(ErrorResult& aRv) const;
|
void CloneTo(TErrorResult& aRv) const;
|
||||||
|
|
||||||
// Use SuppressException when you want to suppress any exception that might be
|
// Use SuppressException when you want to suppress any exception that might be
|
||||||
// on the ErrorResult. After this call, the ErrorResult will be back a "no
|
// on the TErrorResult. After this call, the TErrorResult will be back a "no
|
||||||
// exception thrown" state.
|
// exception thrown" state.
|
||||||
void SuppressException();
|
void SuppressException();
|
||||||
|
|
||||||
// Use StealNSResult() when you want to safely convert the ErrorResult to an
|
// Use StealNSResult() when you want to safely convert the TErrorResult to
|
||||||
// nsresult that you will then return to a caller. This will
|
// an nsresult that you will then return to a caller. This will
|
||||||
// SuppressException(), since there will no longer be a way to report it.
|
// SuppressException(), since there will no longer be a way to report it.
|
||||||
nsresult StealNSResult() {
|
nsresult StealNSResult() {
|
||||||
nsresult rv = ErrorCode();
|
nsresult rv = ErrorCode();
|
||||||
@ -150,11 +175,11 @@ public:
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use MaybeSetPendingException to convert an ErrorResult to a pending
|
// Use MaybeSetPendingException to convert a TErrorResult to a pending
|
||||||
// exception on the given JSContext. This is the normal "throw an exception"
|
// exception on the given JSContext. This is the normal "throw an exception"
|
||||||
// codepath.
|
// codepath.
|
||||||
//
|
//
|
||||||
// The return value is false if the ErrorResult represents success, true
|
// The return value is false if the TErrorResult represents success, true
|
||||||
// otherwise. This does mean that in JSAPI method implementations you can't
|
// otherwise. This does mean that in JSAPI method implementations you can't
|
||||||
// just use this as |return rv.MaybeSetPendingException(cx)| (though you could
|
// just use this as |return rv.MaybeSetPendingException(cx)| (though you could
|
||||||
// |return !rv.MaybeSetPendingException(cx)|), but in practice pretty much any
|
// |return !rv.MaybeSetPendingException(cx)|), but in practice pretty much any
|
||||||
@ -175,7 +200,7 @@ public:
|
|||||||
// considered equivalent to a JSAPI failure in terms of what callers should do
|
// considered equivalent to a JSAPI failure in terms of what callers should do
|
||||||
// after true is returned.
|
// after true is returned.
|
||||||
//
|
//
|
||||||
// After this call, the ErrorResult will no longer return true from Failed(),
|
// After this call, the TErrorResult will no longer return true from Failed(),
|
||||||
// since the exception will have moved to the JSContext.
|
// since the exception will have moved to the JSContext.
|
||||||
bool MaybeSetPendingException(JSContext* cx)
|
bool MaybeSetPendingException(JSContext* cx)
|
||||||
{
|
{
|
||||||
@ -189,7 +214,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use StealExceptionFromJSContext to convert a pending exception on a
|
// Use StealExceptionFromJSContext to convert a pending exception on a
|
||||||
// JSContext to an ErrorResult. This function must be called only when a
|
// JSContext to a TErrorResult. This function must be called only when a
|
||||||
// JSAPI operation failed. It assumes that lack of pending exception on the
|
// JSAPI operation failed. It assumes that lack of pending exception on the
|
||||||
// JSContext means an uncatchable exception was thrown.
|
// JSContext means an uncatchable exception was thrown.
|
||||||
//
|
//
|
||||||
@ -217,11 +242,11 @@ public:
|
|||||||
bool IsErrorWithMessage() const { return ErrorCode() == NS_ERROR_TYPE_ERR || ErrorCode() == NS_ERROR_RANGE_ERR; }
|
bool IsErrorWithMessage() const { return ErrorCode() == NS_ERROR_TYPE_ERR || ErrorCode() == NS_ERROR_RANGE_ERR; }
|
||||||
|
|
||||||
// Facilities for throwing a preexisting JS exception value via this
|
// Facilities for throwing a preexisting JS exception value via this
|
||||||
// ErrorResult. The contract is that any code which might end up calling
|
// TErrorResult. The contract is that any code which might end up calling
|
||||||
// ThrowJSException() or StealExceptionFromJSContext() must call
|
// ThrowJSException() or StealExceptionFromJSContext() must call
|
||||||
// MightThrowJSException() even if no exception is being thrown. Code that
|
// MightThrowJSException() even if no exception is being thrown. Code that
|
||||||
// conditionally calls ToJSValue on this ErrorResult only if Failed() must
|
// conditionally calls ToJSValue on this TErrorResult only if Failed() must
|
||||||
// first call WouldReportJSException even if this ErrorResult has not failed.
|
// first call WouldReportJSException even if this TErrorResult has not failed.
|
||||||
//
|
//
|
||||||
// The exn argument to ThrowJSException can be in any compartment. It does
|
// The exn argument to ThrowJSException can be in any compartment. It does
|
||||||
// not have to be in the compartment of cx. If someone later uses it, they
|
// not have to be in the compartment of cx. If someone later uses it, they
|
||||||
@ -237,12 +262,12 @@ public:
|
|||||||
void ThrowDOMException(nsresult rv, const nsACString& message = EmptyCString());
|
void ThrowDOMException(nsresult rv, const nsACString& message = EmptyCString());
|
||||||
bool IsDOMException() const { return ErrorCode() == NS_ERROR_DOM_DOMEXCEPTION; }
|
bool IsDOMException() const { return ErrorCode() == NS_ERROR_DOM_DOMEXCEPTION; }
|
||||||
|
|
||||||
// Flag on the ErrorResult that whatever needs throwing has been
|
// Flag on the TErrorResult that whatever needs throwing has been
|
||||||
// thrown on the JSContext already and we should not mess with it.
|
// thrown on the JSContext already and we should not mess with it.
|
||||||
// If nothing was thrown, this becomes an uncatchable exception.
|
// If nothing was thrown, this becomes an uncatchable exception.
|
||||||
void NoteJSContextException(JSContext* aCx);
|
void NoteJSContextException(JSContext* aCx);
|
||||||
|
|
||||||
// Check whether the ErrorResult says to just throw whatever is on
|
// Check whether the TErrorResult says to just throw whatever is on
|
||||||
// the JSContext already.
|
// the JSContext already.
|
||||||
bool IsJSContextException() {
|
bool IsJSContextException() {
|
||||||
return ErrorCode() == NS_ERROR_DOM_EXCEPTION_ON_JSCONTEXT;
|
return ErrorCode() == NS_ERROR_DOM_EXCEPTION_ON_JSCONTEXT;
|
||||||
@ -308,6 +333,7 @@ private:
|
|||||||
};
|
};
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
|
friend struct IPC::ParamTraits<TErrorResult>;
|
||||||
friend struct IPC::ParamTraits<ErrorResult>;
|
friend struct IPC::ParamTraits<ErrorResult>;
|
||||||
void SerializeMessage(IPC::Message* aMsg) const;
|
void SerializeMessage(IPC::Message* aMsg) const;
|
||||||
bool DeserializeMessage(const IPC::Message* aMsg, PickleIterator* aIter);
|
bool DeserializeMessage(const IPC::Message* aMsg, PickleIterator* aIter);
|
||||||
@ -315,7 +341,7 @@ private:
|
|||||||
void SerializeDOMExceptionInfo(IPC::Message* aMsg) const;
|
void SerializeDOMExceptionInfo(IPC::Message* aMsg) const;
|
||||||
bool DeserializeDOMExceptionInfo(const IPC::Message* aMsg, PickleIterator* aIter);
|
bool DeserializeDOMExceptionInfo(const IPC::Message* aMsg, PickleIterator* aIter);
|
||||||
|
|
||||||
// Helper method that creates a new Message for this ErrorResult,
|
// Helper method that creates a new Message for this TErrorResult,
|
||||||
// and returns the arguments array from that Message.
|
// and returns the arguments array from that Message.
|
||||||
nsTArray<nsString>& CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType);
|
nsTArray<nsString>& CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType);
|
||||||
|
|
||||||
@ -339,7 +365,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AssertInOwningThread() const {
|
void AssertInOwningThread() const {
|
||||||
NS_ASSERT_OWNINGTHREAD(ErrorResult);
|
NS_ASSERT_OWNINGTHREAD(TErrorResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssignErrorCode(nsresult aRv) {
|
void AssignErrorCode(nsresult aRv) {
|
||||||
@ -377,6 +403,12 @@ private:
|
|||||||
void SetPendingDOMException(JSContext* cx);
|
void SetPendingDOMException(JSContext* cx);
|
||||||
void SetPendingGenericErrorException(JSContext* cx);
|
void SetPendingGenericErrorException(JSContext* cx);
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE void AssertReportedOrSuppressed()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!Failed());
|
||||||
|
MOZ_ASSERT(!mMightHaveUnreportedJSException);
|
||||||
|
MOZ_ASSERT(mUnionState == HasNothing);
|
||||||
|
}
|
||||||
|
|
||||||
// Special values of mResult:
|
// Special values of mResult:
|
||||||
// NS_ERROR_TYPE_ERR -- ThrowTypeError() called on us.
|
// NS_ERROR_TYPE_ERR -- ThrowTypeError() called on us.
|
||||||
@ -411,10 +443,54 @@ private:
|
|||||||
// something.
|
// something.
|
||||||
UnionState mUnionState;
|
UnionState mUnionState;
|
||||||
|
|
||||||
// The thread that created this ErrorResult
|
// The thread that created this TErrorResult
|
||||||
NS_DECL_OWNINGTHREAD;
|
NS_DECL_OWNINGTHREAD;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Not to be implemented, to make sure people always pass this by
|
||||||
|
// reference, not by value.
|
||||||
|
TErrorResult(const TErrorResult&) = delete;
|
||||||
|
void operator=(const TErrorResult&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct JustAssertCleanupPolicy {
|
||||||
|
static const bool assertHandled = true;
|
||||||
|
static const bool suppress = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace binding_danger
|
||||||
|
|
||||||
|
// A class people should normally use on the stack when they plan to actually
|
||||||
|
// do something with the exception.
|
||||||
|
class ErrorResult : public binding_danger::TErrorResult<binding_danger::JustAssertCleanupPolicy>
|
||||||
|
{
|
||||||
|
typedef binding_danger::TErrorResult<binding_danger::JustAssertCleanupPolicy> BaseErrorResult;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ErrorResult()
|
||||||
|
: BaseErrorResult()
|
||||||
|
{}
|
||||||
|
|
||||||
|
ErrorResult(ErrorResult&& aRHS)
|
||||||
|
: BaseErrorResult(Move(aRHS))
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit ErrorResult(nsresult aRv)
|
||||||
|
: BaseErrorResult(aRv)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator=(nsresult rv)
|
||||||
|
{
|
||||||
|
BaseErrorResult::operator=(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorResult& operator=(ErrorResult&& aRHS)
|
||||||
|
{
|
||||||
|
BaseErrorResult::operator=(Move(aRHS));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
// Not to be implemented, to make sure people always pass this by
|
// Not to be implemented, to make sure people always pass this by
|
||||||
// reference, not by value.
|
// reference, not by value.
|
||||||
ErrorResult(const ErrorResult&) = delete;
|
ErrorResult(const ErrorResult&) = delete;
|
||||||
|
Loading…
Reference in New Issue
Block a user