mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 839088 part 1. Add a way to throw a JS::Value on an ErrorResult. r=peterv
This commit is contained in:
parent
e1e9b58bec
commit
25deb6d78c
@ -119,3 +119,5 @@ DOM4_MSG_DEF(ReadOnlyError, "A mutation operation was attempted in a READ_ONLY l
|
||||
|
||||
DOM4_MSG_DEF(InvalidStateError, "A mutation operation was attempted on a file storage that did not allow mutations.", NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR)
|
||||
DOM4_MSG_DEF(AbortError, "A request was aborted, for example through a call to LockedFile.abort.", NS_ERROR_DOM_FILEHANDLE_ABORT_ERR)
|
||||
|
||||
DOM_MSG_DEF(NS_ERROR_DOM_JS_EXCEPTION, "A callback threw an exception")
|
||||
|
@ -61,6 +61,14 @@ ErrorResult::ThrowTypeError(const dom::ErrNum errorNumber, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, errorNumber);
|
||||
if (IsJSException()) {
|
||||
// We have rooted our mJSException, and we don't have the info
|
||||
// needed to unroot here, so just bail.
|
||||
va_end(ap);
|
||||
MOZ_ASSERT(false,
|
||||
"Ignoring ThrowTypeError call because we have a JS exception");
|
||||
return;
|
||||
}
|
||||
if (IsTypeError()) {
|
||||
delete mMessage;
|
||||
}
|
||||
@ -107,6 +115,39 @@ ErrorResult::ClearMessage()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ThrowJSException(JSContext* cx, JS::Value exn)
|
||||
{
|
||||
MOZ_ASSERT(mMightHaveUnreportedJSException,
|
||||
"Why didn't you tell us you planned to throw a JS exception?");
|
||||
|
||||
if (IsTypeError()) {
|
||||
delete mMessage;
|
||||
}
|
||||
|
||||
if (!JS_AddNamedValueRoot(cx, &mJSException, "ErrorResult::mJSException")) {
|
||||
// Don't use NS_ERROR_DOM_JS_EXCEPTION, because that indicates we have
|
||||
// in fact rooted mJSException.
|
||||
mResult = NS_ERROR_OUT_OF_MEMORY;
|
||||
} else {
|
||||
mJSException = exn;
|
||||
mResult = NS_ERROR_DOM_JS_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ReportJSException(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException,
|
||||
"Why didn't you tell us you planned to handle JS exceptions?");
|
||||
if (JS_WrapValue(cx, &mJSException)) {
|
||||
JS_SetPendingException(cx, mJSException);
|
||||
}
|
||||
// If JS_WrapValue failed, not much we can do about it... No matter
|
||||
// what, go ahead and unroot mJSException.
|
||||
JS_RemoveValueRoot(cx, &mJSException);
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
|
||||
bool
|
||||
|
@ -62,6 +62,10 @@ ThrowMethodFailedWithDetails(JSContext* cx, ErrorResult& rv,
|
||||
rv.ReportTypeError(cx);
|
||||
return false;
|
||||
}
|
||||
if (rv.IsJSException()) {
|
||||
rv.ReportJSException(cx);
|
||||
return false;
|
||||
}
|
||||
return Throw<mainThread>(cx, rv.ErrorCode());
|
||||
}
|
||||
|
||||
|
@ -3686,6 +3686,7 @@ class CGCallGenerator(CGThing):
|
||||
|
||||
if isFallible:
|
||||
self.cgRoot.prepend(CGGeneric("ErrorResult rv;"))
|
||||
self.cgRoot.append(CGGeneric("rv.WouldReportJSException();"));
|
||||
self.cgRoot.append(CGGeneric("if (rv.Failed()) {"))
|
||||
self.cgRoot.append(CGIndenter(errorReport))
|
||||
self.cgRoot.append(CGGeneric("}"))
|
||||
|
@ -35,10 +35,15 @@ class ErrorResult {
|
||||
public:
|
||||
ErrorResult() {
|
||||
mResult = NS_OK;
|
||||
#ifdef DEBUG
|
||||
mMightHaveUnreportedJSException = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
~ErrorResult() {
|
||||
MOZ_ASSERT_IF(IsTypeError(), !mMessage);
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -46,6 +51,8 @@ public:
|
||||
MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
|
||||
MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
|
||||
MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError");
|
||||
MOZ_ASSERT(rv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
|
||||
MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
|
||||
mResult = rv;
|
||||
}
|
||||
|
||||
@ -54,6 +61,27 @@ public:
|
||||
void ClearMessage();
|
||||
bool IsTypeError() const { return ErrorCode() == NS_ERROR_TYPE_ERR; }
|
||||
|
||||
// Facilities for throwing a preexisting JS exception value via this
|
||||
// ErrorResult. The contract is that any code which might end up calling
|
||||
// ThrowJSException() must call MightThrowJSException() even if no exception
|
||||
// is being thrown. Code that would call ReportJSException as needed must
|
||||
// first call WouldReportJSException even if this ErrorResult has not failed.
|
||||
void ThrowJSException(JSContext* cx, JS::Value exn);
|
||||
void ReportJSException(JSContext* cx);
|
||||
bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
|
||||
void MOZ_ALWAYS_INLINE MightThrowJSException()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mMightHaveUnreportedJSException = true;
|
||||
#endif
|
||||
}
|
||||
void MOZ_ALWAYS_INLINE WouldReportJSException()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mMightHaveUnreportedJSException = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// In the future, we can add overloads of Throw that take more
|
||||
// interesting things, like strings or DOM exception types or
|
||||
// something if desired.
|
||||
@ -64,6 +92,8 @@ public:
|
||||
void operator=(nsresult rv) {
|
||||
MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
|
||||
MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError");
|
||||
MOZ_ASSERT(rv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
|
||||
MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
|
||||
mResult = rv;
|
||||
}
|
||||
|
||||
@ -78,8 +108,20 @@ public:
|
||||
private:
|
||||
nsresult mResult;
|
||||
struct Message;
|
||||
// Do not use nsAutoPtr to avoid extra initalizatoin and check.
|
||||
Message* mMessage;
|
||||
// mMessage is set by ThrowTypeError and cleared (and deallocatd) by
|
||||
// ReportTypeError.
|
||||
// mJSException is set (and rooted) by ThrowJSException and unrooted
|
||||
// by ReportJSException.
|
||||
union {
|
||||
Message* mMessage; // valid when IsTypeError()
|
||||
JS::Value mJSException; // valid when IsJSException()
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
// Used to keep track of codepaths that might throw JS exceptions,
|
||||
// for assertion purposes.
|
||||
bool mMightHaveUnreportedJSException;
|
||||
#endif
|
||||
|
||||
// Not to be implemented, to make sure people always pass this by
|
||||
// reference, not by value.
|
||||
|
@ -501,7 +501,7 @@
|
||||
/* ======================================================================= */
|
||||
#define MODULE NS_ERROR_MODULE_DOM
|
||||
/* XXX If you add a new DOM error code, also add an error string to
|
||||
* dom/src/base/domerr.msg */
|
||||
* dom/base/domerr.msg */
|
||||
|
||||
/* Standard DOM error codes: http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html */
|
||||
ERROR(NS_ERROR_DOM_INDEX_SIZE_ERR, FAILURE(1)),
|
||||
@ -548,6 +548,7 @@
|
||||
ERROR(NS_ERROR_DOM_BAD_URI, FAILURE(1012)),
|
||||
ERROR(NS_ERROR_DOM_RETVAL_UNDEFINED, FAILURE(1013)),
|
||||
ERROR(NS_ERROR_DOM_QUOTA_REACHED, FAILURE(1014)),
|
||||
ERROR(NS_ERROR_DOM_JS_EXCEPTION, FAILURE(1015)),
|
||||
#undef MODULE
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user