mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1213289 part 3. Add a way to throw a DOMException with a custom message on ErrorResult. r=bkelly
This commit is contained in:
parent
267ff39c13
commit
70e8c1f364
@ -147,3 +147,4 @@ DOM4_MSG_DEF(AbortError, "A request was aborted, for example through a call to F
|
||||
DOM4_MSG_DEF(QuotaExceededError, "The current file handle exceeded its quota limitations.", NS_ERROR_DOM_FILEHANDLE_QUOTA_ERR)
|
||||
|
||||
DOM_MSG_DEF(NS_ERROR_DOM_JS_EXCEPTION, "A callback threw an exception")
|
||||
DOM_MSG_DEF(NS_ERROR_DOM_DOMEXCEPTION, "A DOMException was thrown")
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/DOMErrorBinding.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/ElementBinding.h"
|
||||
#include "mozilla/dom/HTMLObjectElement.h"
|
||||
#include "mozilla/dom/HTMLObjectElementBinding.h"
|
||||
@ -142,6 +143,10 @@ ThrowMethodFailed(JSContext* cx, ErrorResult& rv)
|
||||
rv.ReportJSException(cx);
|
||||
return false;
|
||||
}
|
||||
if (rv.IsDOMException()) {
|
||||
rv.ReportDOMException(cx);
|
||||
return false;
|
||||
}
|
||||
rv.ReportGenericError(cx);
|
||||
return false;
|
||||
}
|
||||
@ -295,6 +300,81 @@ ErrorResult::StealJSException(JSContext* cx,
|
||||
mResult = NS_OK;
|
||||
}
|
||||
|
||||
struct ErrorResult::DOMExceptionInfo {
|
||||
DOMExceptionInfo(nsresult rv, const nsACString& message)
|
||||
: mMessage(message)
|
||||
, mRv(rv)
|
||||
{}
|
||||
|
||||
nsCString mMessage;
|
||||
nsresult mRv;
|
||||
};
|
||||
|
||||
void
|
||||
ErrorResult::SerializeDOMExceptionInfo(IPC::Message* aMsg) const
|
||||
{
|
||||
using namespace IPC;
|
||||
MOZ_ASSERT(mDOMExceptionInfo);
|
||||
MOZ_ASSERT(mHasDOMExceptionInfo);
|
||||
WriteParam(aMsg, mDOMExceptionInfo->mMessage);
|
||||
WriteParam(aMsg, mDOMExceptionInfo->mRv);
|
||||
}
|
||||
|
||||
bool
|
||||
ErrorResult::DeserializeDOMExceptionInfo(const IPC::Message* aMsg, void** aIter)
|
||||
{
|
||||
using namespace IPC;
|
||||
nsCString message;
|
||||
nsresult rv;
|
||||
if (!ReadParam(aMsg, aIter, &message) ||
|
||||
!ReadParam(aMsg, aIter, &rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mHasDOMExceptionInfo);
|
||||
MOZ_ASSERT(IsDOMException());
|
||||
mDOMExceptionInfo = new DOMExceptionInfo(rv, message);
|
||||
#ifdef DEBUG
|
||||
mHasDOMExceptionInfo = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ThrowDOMException(nsresult rv, const nsACString& message)
|
||||
{
|
||||
ClearUnionData();
|
||||
|
||||
mResult = NS_ERROR_DOM_DOMEXCEPTION;
|
||||
mDOMExceptionInfo = new DOMExceptionInfo(rv, message);
|
||||
#ifdef DEBUG
|
||||
mHasDOMExceptionInfo = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ReportDOMException(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(mDOMExceptionInfo, "ReportDOMException() can be called only once");
|
||||
MOZ_ASSERT(mHasDOMExceptionInfo);
|
||||
|
||||
dom::Throw(cx, mDOMExceptionInfo->mRv, mDOMExceptionInfo->mMessage);
|
||||
|
||||
ClearDOMExceptionInfo();
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ClearDOMExceptionInfo()
|
||||
{
|
||||
MOZ_ASSERT(IsDOMException());
|
||||
MOZ_ASSERT(mHasDOMExceptionInfo || !mDOMExceptionInfo);
|
||||
delete mDOMExceptionInfo;
|
||||
mDOMExceptionInfo = nullptr;
|
||||
#ifdef DEBUG
|
||||
mHasDOMExceptionInfo = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ClearUnionData()
|
||||
{
|
||||
@ -305,6 +385,8 @@ ErrorResult::ClearUnionData()
|
||||
js::RemoveRawValueRoot(cx, &mJSException);
|
||||
} else if (IsErrorWithMessage()) {
|
||||
ClearMessage();
|
||||
} else if (IsDOMException()) {
|
||||
ClearDOMExceptionInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,6 +395,7 @@ ErrorResult::ReportGenericError(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(!IsErrorWithMessage());
|
||||
MOZ_ASSERT(!IsJSException());
|
||||
MOZ_ASSERT(!IsDOMException());
|
||||
dom::Throw(cx, ErrorCode());
|
||||
}
|
||||
|
||||
@ -344,11 +427,19 @@ ErrorResult::operator=(ErrorResult&& aRHS)
|
||||
mJSException = aRHS.mJSException;
|
||||
aRHS.mJSException.setUndefined();
|
||||
js::RemoveRawValueRoot(cx, &aRHS.mJSException);
|
||||
} else if (aRHS.IsDOMException()) {
|
||||
mDOMExceptionInfo = aRHS.mDOMExceptionInfo;
|
||||
aRHS.mDOMExceptionInfo = nullptr;
|
||||
#ifdef DEBUG
|
||||
mHasDOMExceptionInfo = aRHS.mHasDOMExceptionInfo;
|
||||
aRHS.mHasDOMExceptionInfo = false;
|
||||
#endif // DEBUG
|
||||
} else {
|
||||
// Null out the union on both sides for hygiene purposes.
|
||||
mMessage = aRHS.mMessage = nullptr;
|
||||
#ifdef DEBUG
|
||||
mHasMessage = aRHS.mHasMessage = false;
|
||||
mHasDOMExceptionInfo = aRHS.mHasDOMExceptionInfo = false;
|
||||
#endif
|
||||
}
|
||||
// Note: It's important to do this last, since this affects the condition
|
||||
|
@ -42,8 +42,11 @@ struct ParamTraits<mozilla::ErrorResult>
|
||||
|
||||
WriteParam(aMsg, aParam.mResult);
|
||||
WriteParam(aMsg, aParam.IsErrorWithMessage());
|
||||
WriteParam(aMsg, aParam.IsDOMException());
|
||||
if (aParam.IsErrorWithMessage()) {
|
||||
aParam.SerializeMessage(aMsg);
|
||||
} else if (aParam.IsDOMException()) {
|
||||
aParam.SerializeDOMExceptionInfo(aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,8 +60,19 @@ struct ParamTraits<mozilla::ErrorResult>
|
||||
if (!ReadParam(aMsg, aIter, &hasMessage)) {
|
||||
return false;
|
||||
}
|
||||
bool hasDOMExceptionInfo = false;
|
||||
if (!ReadParam(aMsg, aIter, &hasDOMExceptionInfo)) {
|
||||
return false;
|
||||
}
|
||||
if (hasMessage && hasDOMExceptionInfo) {
|
||||
// Shouldn't have both!
|
||||
return false;
|
||||
}
|
||||
if (hasMessage && !readValue.DeserializeMessage(aMsg, aIter)) {
|
||||
return false;
|
||||
} else if (hasDOMExceptionInfo &&
|
||||
!readValue.DeserializeDOMExceptionInfo(aMsg, aIter)) {
|
||||
return false;
|
||||
}
|
||||
*aResult = Move(readValue);
|
||||
return true;
|
||||
|
@ -76,20 +76,23 @@ struct StringArrayAppender
|
||||
|
||||
class ErrorResult {
|
||||
public:
|
||||
ErrorResult() {
|
||||
mResult = NS_OK;
|
||||
|
||||
ErrorResult()
|
||||
: mResult(NS_OK)
|
||||
#ifdef DEBUG
|
||||
mMightHaveUnreportedJSException = false;
|
||||
mHasMessage = false;
|
||||
, mMightHaveUnreportedJSException(false)
|
||||
, mHasMessage(false)
|
||||
, mHasDOMExceptionInfo(false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
~ErrorResult() {
|
||||
MOZ_ASSERT_IF(IsErrorWithMessage(), !mMessage);
|
||||
MOZ_ASSERT_IF(IsDOMException(), !mDOMExceptionInfo);
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException);
|
||||
MOZ_ASSERT(!mHasMessage);
|
||||
MOZ_ASSERT(!mHasDOMExceptionInfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -157,6 +160,15 @@ public:
|
||||
void ReportJSException(JSContext* cx);
|
||||
bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
|
||||
|
||||
// Facilities for throwing a DOMException. If an empty message string is
|
||||
// passed to ThrowDOMException, the default message string for the given
|
||||
// nsresult will be used. The passed-in string must be UTF-8. The nsresult
|
||||
// passed in must be one we create DOMExceptions for; otherwise you may get an
|
||||
// XPConnect Exception.
|
||||
void ThrowDOMException(nsresult rv, const nsACString& message = EmptyCString());
|
||||
void ReportDOMException(JSContext* cx);
|
||||
bool IsDOMException() const { return ErrorCode() == NS_ERROR_DOM_DOMEXCEPTION; }
|
||||
|
||||
// Report a generic error. This should only be used if we're not
|
||||
// some more specific exception type.
|
||||
void ReportGenericError(JSContext* cx);
|
||||
@ -221,6 +233,9 @@ private:
|
||||
void SerializeMessage(IPC::Message* aMsg) const;
|
||||
bool DeserializeMessage(const IPC::Message* aMsg, void** aIter);
|
||||
|
||||
void SerializeDOMExceptionInfo(IPC::Message* aMsg) const;
|
||||
bool DeserializeDOMExceptionInfo(const IPC::Message* aMsg, void** aIter);
|
||||
|
||||
// Helper method that creates a new Message for this ErrorResult,
|
||||
// and returns the arguments array from that Message.
|
||||
nsTArray<nsString>& CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType);
|
||||
@ -249,28 +264,43 @@ private:
|
||||
MOZ_ASSERT(!IsErrorWithMessage(), "Don't overwrite errors with message");
|
||||
MOZ_ASSERT(aRv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
|
||||
MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
|
||||
MOZ_ASSERT(aRv != NS_ERROR_DOM_DOMEXCEPTION, "Use ThrowDOMException()");
|
||||
MOZ_ASSERT(!IsDOMException(), "Don't overwrite DOM exceptions");
|
||||
MOZ_ASSERT(aRv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "May need to bring back ThrowNotEnoughArgsError");
|
||||
mResult = aRv;
|
||||
}
|
||||
|
||||
void ClearMessage();
|
||||
void ClearDOMExceptionInfo();
|
||||
|
||||
// ClearUnionData will try to clear the data in our mMessage/mJSException
|
||||
// union. After this the union may be in an uninitialized state
|
||||
// (e.g. mMessage may be pointing to deleted memory) and the caller must
|
||||
// either reinitialize it or change mResult to something that will not involve
|
||||
// us touching the union anymore.
|
||||
// ClearUnionData will try to clear the data in our
|
||||
// mMessage/mJSException/mDOMExceptionInfo union. After this the union may be
|
||||
// in an uninitialized state (e.g. mMessage or mDOMExceptionInfo may be
|
||||
// pointing to deleted memory) and the caller must either reinitialize it or
|
||||
// change mResult to something that will not involve us touching the union
|
||||
// anymore.
|
||||
void ClearUnionData();
|
||||
|
||||
// Special values of mResult:
|
||||
// NS_ERROR_TYPE_ERR -- ThrowTypeError() called on us.
|
||||
// NS_ERROR_RANGE_ERR -- ThrowRangeError() called on us.
|
||||
// NS_ERROR_DOM_JS_EXCEPTION -- ThrowJSException() called on us.
|
||||
// NS_ERROR_UNCATCHABLE_EXCEPTION -- ThrowUncatchableException called on us.
|
||||
// NS_ERROR_DOM_DOMEXCEPTION -- ThrowDOMException() called on us.
|
||||
nsresult mResult;
|
||||
|
||||
struct Message;
|
||||
// mMessage is set by ThrowErrorWithMessage and cleared (and deallocated) by
|
||||
struct DOMExceptionInfo;
|
||||
// mMessage is set by ThrowErrorWithMessage and reported (and deallocated) by
|
||||
// ReportErrorWithMessage.
|
||||
// mJSException is set (and rooted) by ThrowJSException and unrooted
|
||||
// by ReportJSException.
|
||||
// mJSException is set (and rooted) by ThrowJSException and reported
|
||||
// (and unrooted) by ReportJSException.
|
||||
// mDOMExceptionInfo is set by ThrowDOMException and reported
|
||||
// (and deallocated) by ReportDOMException.
|
||||
union {
|
||||
Message* mMessage; // valid when IsErrorWithMessage()
|
||||
JS::Value mJSException; // valid when IsJSException()
|
||||
DOMExceptionInfo* mDOMExceptionInfo; // valid when IsDOMException()
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -281,6 +311,11 @@ private:
|
||||
// We need to check this in order to ensure that not attempting to
|
||||
// delete mMessage in DeserializeMessage doesn't leak memory.
|
||||
bool mHasMessage;
|
||||
// Used to keep track of whether mDOMExceptionInfo has ever been assigned
|
||||
// to. We need to check this in order to ensure that not attempting to
|
||||
// delete mDOMExceptionInfo in DeserializeDOMExceptionInfo doesn't leak
|
||||
// memory.
|
||||
bool mHasDOMExceptionInfo;
|
||||
#endif
|
||||
|
||||
// Not to be implemented, to make sure people always pass this by
|
||||
|
@ -543,6 +543,10 @@
|
||||
/* A way to represent uncatchable exceptions */
|
||||
ERROR(NS_ERROR_UNCATCHABLE_EXCEPTION, FAILURE(1016)),
|
||||
|
||||
/* An nsresult value to use in ErrorResult to indicate that we want to throw
|
||||
a DOMException */
|
||||
ERROR(NS_ERROR_DOM_DOMEXCEPTION, FAILURE(1017)),
|
||||
|
||||
/* May be used to indicate when e.g. setting a property value didn't
|
||||
* actually change the value, like for obj.foo = "bar"; obj.foo = "bar";
|
||||
* the second assignment throws NS_SUCCESS_DOM_NO_OPERATION.
|
||||
|
Loading…
Reference in New Issue
Block a user