зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1357463 Add CopyableErrorResult to opt in to auto-cloning ErrorResult values. r=bz
This commit is contained in:
Родитель
f3a5cf22ea
Коммит
d4090dc614
|
@ -182,6 +182,12 @@ struct TErrorResult<CleanupPolicy>::Message {
|
|||
{
|
||||
return GetErrorArgCount(mErrorNumber) == mArgs.Length();
|
||||
}
|
||||
|
||||
bool operator==(const TErrorResult<CleanupPolicy>::Message& aRight)
|
||||
{
|
||||
return mErrorNumber == aRight.mErrorNumber &&
|
||||
mArgs == aRight.mArgs;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CleanupPolicy>
|
||||
|
@ -333,6 +339,12 @@ struct TErrorResult<CleanupPolicy>::DOMExceptionInfo {
|
|||
|
||||
nsCString mMessage;
|
||||
nsresult mRv;
|
||||
|
||||
bool operator==(const TErrorResult<CleanupPolicy>::DOMExceptionInfo& aRight)
|
||||
{
|
||||
return mRv == aRight.mRv &&
|
||||
mMessage == aRight.mMessage;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CleanupPolicy>
|
||||
|
@ -502,7 +514,6 @@ TErrorResult<CleanupPolicy>::CloneTo(TErrorResult& aRv) const
|
|||
{
|
||||
AssertInOwningThread();
|
||||
aRv.AssertInOwningThread();
|
||||
|
||||
aRv.ClearUnionData();
|
||||
aRv.mResult = mResult;
|
||||
#ifdef DEBUG
|
||||
|
@ -612,6 +623,7 @@ TErrorResult<CleanupPolicy>::NoteJSContextException(JSContext* aCx)
|
|||
template class TErrorResult<JustAssertCleanupPolicy>;
|
||||
template class TErrorResult<AssertAndSuppressCleanupPolicy>;
|
||||
template class TErrorResult<JustSuppressCleanupPolicy>;
|
||||
template class TErrorResult<ThreadSafeJustSuppressCleanupPolicy>;
|
||||
|
||||
} // namespace binding_danger
|
||||
|
||||
|
|
|
@ -79,6 +79,23 @@ struct ParamTraits<mozilla::ErrorResult>
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::CopyableErrorResult>
|
||||
{
|
||||
typedef mozilla::CopyableErrorResult paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
ParamTraits<mozilla::ErrorResult>::Write(aMsg, aParam);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
mozilla::ErrorResult& ref = static_cast<mozilla::ErrorResult&>(*aResult);
|
||||
return ParamTraits<mozilla::ErrorResult>::Read(aMsg, aIter, &ref);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif
|
||||
|
|
|
@ -165,6 +165,7 @@ public:
|
|||
}
|
||||
|
||||
operator ErrorResult&();
|
||||
operator const ErrorResult&() const;
|
||||
operator OOMReporter&();
|
||||
|
||||
void MOZ_MUST_RETURN_FROM_CALLER Throw(nsresult rv) {
|
||||
|
@ -391,6 +392,8 @@ public:
|
|||
return static_cast<uint32_t>(ErrorCode());
|
||||
}
|
||||
|
||||
bool operator==(const ErrorResult& aRight) const;
|
||||
|
||||
protected:
|
||||
nsresult ErrorCode() const {
|
||||
return mResult;
|
||||
|
@ -439,7 +442,9 @@ private:
|
|||
|
||||
MOZ_ALWAYS_INLINE void AssertInOwningThread() const {
|
||||
#ifdef DEBUG
|
||||
NS_ASSERT_OWNINGTHREAD(TErrorResult);
|
||||
if (CleanupPolicy::assertSameThread) {
|
||||
NS_ASSERT_OWNINGTHREAD(TErrorResult);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -566,16 +571,25 @@ private:
|
|||
struct JustAssertCleanupPolicy {
|
||||
static const bool assertHandled = true;
|
||||
static const bool suppress = false;
|
||||
static const bool assertSameThread = true;
|
||||
};
|
||||
|
||||
struct AssertAndSuppressCleanupPolicy {
|
||||
static const bool assertHandled = true;
|
||||
static const bool suppress = true;
|
||||
static const bool assertSameThread = true;
|
||||
};
|
||||
|
||||
struct JustSuppressCleanupPolicy {
|
||||
static const bool assertHandled = false;
|
||||
static const bool suppress = true;
|
||||
static const bool assertSameThread = true;
|
||||
};
|
||||
|
||||
struct ThreadSafeJustSuppressCleanupPolicy {
|
||||
static const bool assertHandled = false;
|
||||
static const bool suppress = true;
|
||||
static const bool assertSameThread = false;
|
||||
};
|
||||
|
||||
} // namespace binding_danger
|
||||
|
@ -625,6 +639,39 @@ binding_danger::TErrorResult<CleanupPolicy>::operator ErrorResult&()
|
|||
reinterpret_cast<TErrorResult<AssertAndSuppressCleanupPolicy>*>(this));
|
||||
}
|
||||
|
||||
template<typename CleanupPolicy>
|
||||
binding_danger::TErrorResult<CleanupPolicy>::operator const ErrorResult&() const
|
||||
{
|
||||
return *static_cast<const ErrorResult*>(
|
||||
reinterpret_cast<const TErrorResult<AssertAndSuppressCleanupPolicy>*>(this));
|
||||
}
|
||||
|
||||
template<typename CleanupPolicy>
|
||||
bool
|
||||
binding_danger::TErrorResult<CleanupPolicy>::operator==(const ErrorResult& aRight) const
|
||||
{
|
||||
auto right = reinterpret_cast<const TErrorResult<CleanupPolicy>*>(&aRight);
|
||||
|
||||
if (mResult != right->mResult) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsJSException()) {
|
||||
// js exceptions are always non-equal
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsErrorWithMessage()) {
|
||||
return *mExtra.mMessage == *right->mExtra.mMessage;
|
||||
}
|
||||
|
||||
if (IsDOMException()) {
|
||||
return *mExtra.mDOMExceptionInfo == *right->mExtra.mDOMExceptionInfo;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// A class for use when an ErrorResult should just automatically be ignored.
|
||||
// This doesn't inherit from ErrorResult so we don't make two separate calls to
|
||||
// SuppressException.
|
||||
|
@ -633,6 +680,74 @@ class IgnoredErrorResult :
|
|||
{
|
||||
};
|
||||
|
||||
// A class for use when an ErrorResult needs to be copied to a lambda, into
|
||||
// an IPDL structure, etc. Since this will often involve crossing thread
|
||||
// boundaries this class will assert if you try to copy a JS exception. Only
|
||||
// use this if you are propagating internal errors. In general its best
|
||||
// to use ErrorResult by default and only convert to a CopyableErrorResult when
|
||||
// you need it.
|
||||
class CopyableErrorResult :
|
||||
public binding_danger::TErrorResult<binding_danger::ThreadSafeJustSuppressCleanupPolicy>
|
||||
{
|
||||
typedef binding_danger::TErrorResult<binding_danger::ThreadSafeJustSuppressCleanupPolicy> BaseErrorResult;
|
||||
|
||||
public:
|
||||
CopyableErrorResult()
|
||||
: BaseErrorResult()
|
||||
{}
|
||||
|
||||
explicit CopyableErrorResult(const ErrorResult& aRight)
|
||||
: BaseErrorResult()
|
||||
{
|
||||
auto val = reinterpret_cast<const CopyableErrorResult&>(aRight);
|
||||
operator=(val);
|
||||
}
|
||||
|
||||
CopyableErrorResult(CopyableErrorResult&& aRHS)
|
||||
: BaseErrorResult(Move(aRHS))
|
||||
{}
|
||||
|
||||
explicit CopyableErrorResult(nsresult aRv)
|
||||
: BaseErrorResult(aRv)
|
||||
{}
|
||||
|
||||
void operator=(nsresult rv)
|
||||
{
|
||||
BaseErrorResult::operator=(rv);
|
||||
}
|
||||
|
||||
CopyableErrorResult& operator=(CopyableErrorResult&& aRHS)
|
||||
{
|
||||
BaseErrorResult::operator=(Move(aRHS));
|
||||
return *this;
|
||||
}
|
||||
|
||||
CopyableErrorResult(const CopyableErrorResult& aRight)
|
||||
: BaseErrorResult()
|
||||
{
|
||||
operator=(aRight);
|
||||
}
|
||||
|
||||
CopyableErrorResult&
|
||||
operator=(const CopyableErrorResult& aRight)
|
||||
{
|
||||
// We must not copy JS exceptions since it can too easily lead to
|
||||
// off-thread use. Assert this and fall back to a generic error
|
||||
// in release builds.
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsJSException(),
|
||||
"Attempt to copy to ErrorResult with a JS exception value.");
|
||||
MOZ_DIAGNOSTIC_ASSERT(!aRight.IsJSException(),
|
||||
"Attempt to copy from ErrorResult with a JS exception value.");
|
||||
if (aRight.IsJSException()) {
|
||||
SuppressException();
|
||||
Throw(NS_ERROR_FAILURE);
|
||||
} else {
|
||||
aRight.CloneTo(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
namespace dom {
|
||||
namespace binding_detail {
|
||||
class FastErrorResult :
|
||||
|
|
Загрузка…
Ссылка в новой задаче