Bug 1709352 - Allow QMResult errors to use existing stack id and to increase the frame id during error propagation; r=dom-storage-reviewers,asuth,glandium

Differential Revision: https://phabricator.services.mozilla.com/D114243
This commit is contained in:
Jan Varga 2021-05-25 07:28:20 +00:00
Родитель 01123f15c4
Коммит c06f56c861
5 изменённых файлов: 79 добавлений и 1 удалений

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

@ -17,6 +17,39 @@
namespace mozilla {
// Allow QMResult errors to use existing stack id and to increase the frame id
// during error propagation.
template <>
class MOZ_MUST_USE_TYPE GenericErrorResult<QMResult> {
QMResult mErrorValue;
template <typename V, typename E2>
friend class Result;
public:
explicit GenericErrorResult(const QMResult& aErrorValue)
: mErrorValue(aErrorValue) {
MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult()));
}
explicit GenericErrorResult(QMResult&& aErrorValue)
: mErrorValue(std::move(aErrorValue)) {
MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult()));
}
explicit GenericErrorResult(const QMResult& aErrorValue,
const ErrorPropagationTag&)
: GenericErrorResult(aErrorValue.Propagate()) {}
explicit GenericErrorResult(QMResult&& aErrorValue,
const ErrorPropagationTag&)
: GenericErrorResult(aErrorValue.Propagate()) {}
operator QMResult() const { return mErrorValue; }
operator nsresult() const { return mErrorValue.NSResult(); }
};
inline Result<Ok, QMResult> ToResult(const QMResult& aValue) {
if (NS_FAILED(aValue.NSResult())) {
return Err(aValue);

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

@ -1076,6 +1076,10 @@ class MOZ_MUST_USE_TYPE GenericErrorResult<mozilla::ipc::IPCResult> {
MOZ_ASSERT(!aErrorValue);
}
GenericErrorResult(mozilla::ipc::IPCResult aErrorValue,
const ErrorPropagationTag&)
: GenericErrorResult(aErrorValue) {}
operator mozilla::ipc::IPCResult() const { return mErrorValue; }
};

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

@ -79,3 +79,24 @@ TEST(DOM_Quota_QMResult, ToResult)
ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE);
}
}
TEST(DOM_Quota_QMResult, ErrorPropagation)
{
Result<Ok, QMResult> valOrErr1 = ToResult(ToQMResult(NS_ERROR_FAILURE));
const auto& err1 = valOrErr1.inspectErr();
ASSERT_EQ(err1.StackId(), 7u);
ASSERT_EQ(err1.FrameId(), 1u);
ASSERT_EQ(err1.NSResult(), NS_ERROR_FAILURE);
Result<Ok, QMResult> valOrErr2 = valOrErr1.propagateErr();
const auto& err2 = valOrErr2.inspectErr();
ASSERT_EQ(err2.StackId(), 7u);
ASSERT_EQ(err2.FrameId(), 2u);
ASSERT_EQ(err2.NSResult(), NS_ERROR_FAILURE);
Result<Ok, QMResult> valOrErr3 = valOrErr2.propagateErr();
const auto& err3 = valOrErr3.inspectErr();
ASSERT_EQ(err3.StackId(), 7u);
ASSERT_EQ(err3.FrameId(), 3u);
ASSERT_EQ(err3.NSResult(), NS_ERROR_FAILURE);
}

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

@ -27,6 +27,15 @@ namespace mozilla {
*/
struct Ok {};
/**
* A tag used to differentiate between GenericErrorResult created by the Err
* function (completely new error) and GenericErrorResult created by the
* Result::propagateErr function (propagated error). This can be used to track
* error propagation and eventually produce error stacks for logging/debugging
* purposes.
*/
struct ErrorPropagationTag {};
template <typename E>
class GenericErrorResult;
template <typename V, typename E>
@ -563,7 +572,7 @@ class MOZ_MUST_USE_TYPE Result final {
*/
constexpr GenericErrorResult<E> propagateErr() {
MOZ_ASSERT(isErr());
return GenericErrorResult<E>{mImpl.unwrapErr()};
return GenericErrorResult<E>{mImpl.unwrapErr(), ErrorPropagationTag{}};
}
/**
@ -748,6 +757,12 @@ class MOZ_MUST_USE_TYPE GenericErrorResult {
explicit constexpr GenericErrorResult(E&& aErrorValue)
: mErrorValue(std::move(aErrorValue)) {}
constexpr GenericErrorResult(const E& aErrorValue, const ErrorPropagationTag&)
: GenericErrorResult(aErrorValue) {}
constexpr GenericErrorResult(E&& aErrorValue, const ErrorPropagationTag&)
: GenericErrorResult(std::move(aErrorValue)) {}
};
template <typename E>

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

@ -16,6 +16,8 @@
namespace mozilla {
struct ErrorPropagationTag;
// Allow nsresult errors to automatically convert to nsresult values, so MOZ_TRY
// can be used in XPCOM methods with Result<T, nserror> results.
template <>
@ -30,6 +32,9 @@ class MOZ_MUST_USE_TYPE GenericErrorResult<nsresult> {
MOZ_ASSERT(NS_FAILED(aErrorValue));
}
GenericErrorResult(nsresult aErrorValue, const ErrorPropagationTag&)
: GenericErrorResult(aErrorValue) {}
operator nsresult() const { return mErrorValue; }
};