Bug 1224664 - Assert if an ErrorResult is accessed on a thread different than the one it's created on, r=khuey

This commit is contained in:
Emilio Cobos Álvarez 2016-07-15 22:35:13 -04:00
Родитель be759d0233
Коммит 12929ea07e
3 изменённых файлов: 35 добавлений и 1 удалений

Просмотреть файл

@ -159,6 +159,7 @@ struct ErrorResult::Message {
nsTArray<nsString>&
ErrorResult::CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType)
{
AssertInOwningThread();
mResult = errorType;
mMessage = new Message();
@ -170,6 +171,7 @@ void
ErrorResult::SerializeMessage(IPC::Message* aMsg) const
{
using namespace IPC;
AssertInOwningThread();
MOZ_ASSERT(mUnionState == HasMessage);
MOZ_ASSERT(mMessage);
WriteParam(aMsg, mMessage->mArgs);
@ -180,6 +182,7 @@ bool
ErrorResult::DeserializeMessage(const IPC::Message* aMsg, PickleIterator* aIter)
{
using namespace IPC;
AssertInOwningThread();
nsAutoPtr<Message> readMessage(new Message());
if (!ReadParam(aMsg, aIter, &readMessage->mArgs) ||
!ReadParam(aMsg, aIter, &readMessage->mErrorNumber)) {
@ -200,6 +203,7 @@ ErrorResult::DeserializeMessage(const IPC::Message* aMsg, PickleIterator* aIter)
void
ErrorResult::SetPendingExceptionWithMessage(JSContext* aCx)
{
AssertInOwningThread();
MOZ_ASSERT(mMessage, "SetPendingExceptionWithMessage() can be called only once");
MOZ_ASSERT(mUnionState == HasMessage);
@ -223,6 +227,7 @@ ErrorResult::SetPendingExceptionWithMessage(JSContext* aCx)
void
ErrorResult::ClearMessage()
{
AssertInOwningThread();
MOZ_ASSERT(IsErrorWithMessage());
delete mMessage;
mMessage = nullptr;
@ -234,6 +239,7 @@ ErrorResult::ClearMessage()
void
ErrorResult::ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn)
{
AssertInOwningThread();
MOZ_ASSERT(mMightHaveUnreportedJSException,
"Why didn't you tell us you planned to throw a JS exception?");
@ -259,6 +265,7 @@ ErrorResult::ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn)
void
ErrorResult::SetPendingJSException(JSContext* cx)
{
AssertInOwningThread();
MOZ_ASSERT(!mMightHaveUnreportedJSException,
"Why didn't you tell us you planned to handle JS exceptions?");
MOZ_ASSERT(mUnionState == HasJSException);
@ -292,6 +299,7 @@ void
ErrorResult::SerializeDOMExceptionInfo(IPC::Message* aMsg) const
{
using namespace IPC;
AssertInOwningThread();
MOZ_ASSERT(mDOMExceptionInfo);
MOZ_ASSERT(mUnionState == HasDOMExceptionInfo);
WriteParam(aMsg, mDOMExceptionInfo->mMessage);
@ -302,6 +310,7 @@ bool
ErrorResult::DeserializeDOMExceptionInfo(const IPC::Message* aMsg, PickleIterator* aIter)
{
using namespace IPC;
AssertInOwningThread();
nsCString message;
nsresult rv;
if (!ReadParam(aMsg, aIter, &message) ||
@ -321,6 +330,7 @@ ErrorResult::DeserializeDOMExceptionInfo(const IPC::Message* aMsg, PickleIterato
void
ErrorResult::ThrowDOMException(nsresult rv, const nsACString& message)
{
AssertInOwningThread();
ClearUnionData();
mResult = NS_ERROR_DOM_DOMEXCEPTION;
@ -333,6 +343,7 @@ ErrorResult::ThrowDOMException(nsresult rv, const nsACString& message)
void
ErrorResult::SetPendingDOMException(JSContext* cx)
{
AssertInOwningThread();
MOZ_ASSERT(mDOMExceptionInfo,
"SetPendingDOMException() can be called only once");
MOZ_ASSERT(mUnionState == HasDOMExceptionInfo);
@ -346,6 +357,7 @@ ErrorResult::SetPendingDOMException(JSContext* cx)
void
ErrorResult::ClearDOMExceptionInfo()
{
AssertInOwningThread();
MOZ_ASSERT(IsDOMException());
MOZ_ASSERT(mUnionState == HasDOMExceptionInfo || !mDOMExceptionInfo);
delete mDOMExceptionInfo;
@ -358,6 +370,7 @@ ErrorResult::ClearDOMExceptionInfo()
void
ErrorResult::ClearUnionData()
{
AssertInOwningThread();
if (IsJSException()) {
JSContext* cx = nsContentUtils::RootingCx();
MOZ_ASSERT(cx);
@ -376,6 +389,7 @@ ErrorResult::ClearUnionData()
void
ErrorResult::SetPendingGenericErrorException(JSContext* cx)
{
AssertInOwningThread();
MOZ_ASSERT(!IsErrorWithMessage());
MOZ_ASSERT(!IsJSException());
MOZ_ASSERT(!IsDOMException());
@ -386,6 +400,8 @@ ErrorResult::SetPendingGenericErrorException(JSContext* cx)
ErrorResult&
ErrorResult::operator=(ErrorResult&& aRHS)
{
AssertInOwningThread();
aRHS.AssertInOwningThread();
// Clear out any union members we may have right now, before we
// start writing to it.
ClearUnionData();
@ -430,6 +446,9 @@ ErrorResult::operator=(ErrorResult&& aRHS)
void
ErrorResult::CloneTo(ErrorResult& aRv) const
{
AssertInOwningThread();
aRv.AssertInOwningThread();
aRv.ClearUnionData();
aRv.mResult = mResult;
#ifdef DEBUG
@ -462,6 +481,7 @@ ErrorResult::CloneTo(ErrorResult& aRv) const
void
ErrorResult::SuppressException()
{
AssertInOwningThread();
WouldReportJSException();
ClearUnionData();
// We don't use AssignErrorCode, because we want to override existing error
@ -472,6 +492,7 @@ ErrorResult::SuppressException()
void
ErrorResult::SetPendingException(JSContext* cx)
{
AssertInOwningThread();
if (IsUncatchableException()) {
// Nuke any existing exception on cx, to make sure we're uncatchable.
JS_ClearPendingException(cx);
@ -504,6 +525,7 @@ ErrorResult::SetPendingException(JSContext* cx)
void
ErrorResult::StealExceptionFromJSContext(JSContext* cx)
{
AssertInOwningThread();
MOZ_ASSERT(mMightHaveUnreportedJSException,
"Why didn't you tell us you planned to throw a JS exception?");
@ -520,6 +542,7 @@ ErrorResult::StealExceptionFromJSContext(JSContext* cx)
void
ErrorResult::NoteJSContextException(JSContext* aCx)
{
AssertInOwningThread();
if (JS_IsExceptionPending(aCx)) {
mResult = NS_ERROR_DOM_EXCEPTION_ON_JSCONTEXT;
} else {

Просмотреть файл

@ -106,7 +106,7 @@ IsNonProxyDOMClass(const JSClass* clasp)
return IsNonProxyDOMClass(js::Valueify(clasp));
}
// Returns true if the JSClass is used for DOM interface and interface
// Returns true if the JSClass is used for DOM interface and interface
// prototype objects.
inline bool
IsDOMIfaceAndProtoClass(const JSClass* clasp)

Просмотреть файл

@ -31,6 +31,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Move.h"
#include "nsTArray.h"
#include "nsISupportsImpl.h"
namespace IPC {
class Message;
@ -105,6 +106,7 @@ public:
MOZ_ASSERT(!Failed());
MOZ_ASSERT(!mMightHaveUnreportedJSException);
MOZ_ASSERT(mUnionState == HasNothing);
NS_ASSERT_OWNINGTHREAD(ErrorResult);
}
#endif // DEBUG
@ -336,6 +338,12 @@ private:
#endif // DEBUG
}
MOZ_ALWAYS_INLINE void AssertInOwningThread() const {
#ifdef DEBUG
NS_ASSERT_OWNINGTHREAD(ErrorResult);
#endif
}
void AssignErrorCode(nsresult aRv) {
MOZ_ASSERT(aRv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
MOZ_ASSERT(aRv != NS_ERROR_RANGE_ERR, "Use ThrowRangeError()");
@ -404,6 +412,9 @@ private:
// we should have something, if we have already cleaned up the
// something.
UnionState mUnionState;
// The thread that created this ErrorResult
NS_DECL_OWNINGTHREAD;
#endif
// Not to be implemented, to make sure people always pass this by