Files
palemoon27/dom/bindings/ErrorResult.h
T
roytam1 8f529f64f5 import changes from rmottola/Arctic-Fox:
- Bug 932865 - Add ThreadHangStats for collecting background hang telemetry; r=vladan (2f08a076b)
- Bug 932865 - Add way for telemetry to iterate over active threads; r=froydnj (535615d3d)
- Bug 1128768: Part 3 - Update BHR to allow for hang annotations; r=vladan (0b880a667)
- Bug 935092 - Add ThreadStackHelper to get a thread's pesudo-stack; r=BenWa (1422cfe4d)
- Bug 942488 - Don't report pseudo-stacks without SPS profiler. r=nchen (e160a7a08)
- Bug 946817 - Don't assert mPseudoStack on B2G. r=BenWa (9f846df3b)
- Bug 951431 - Don't get stacks during profiler runs on Linux; r=BenWa (15036e907)
- Bug 978262 - Ignore duplicate frames when getting BHR stack. r=froydnj (964721b1b)
- Bug 985155 - Add signal trampoline on ARM Linux to work around kernel bug. r=snorp (cb8a7846c)
- Bug 995730 - Convert xpcom/threads/ to Gecko style. r=froydnj (fe150404e)
- Bug 1013326 - Distinguish chrome and content scripts in pseudostack; r=snorp (81273c977)
- Bug 1023461 - Remove temporary stack buffer in ThreadStackHelper; r=snorp (cf5a717c2)
- Bug 1023461 - Record filename and line number for chrome JS entries; r=snorp (10c89808f)
- Bug 1022456 - Fix modelines in xpcom/{base,glue,io,string,threads}/. (48dbc0416)
- Bug 1016441 - Switch to using real-time signal in ThreadStackHelper; (2c5f818be)
- Bug 1016629 - b. Use RAII class to assign mStackToFill; r=snorp (769eae130)
- Bug 1016629 - c. Add define for ThreadStackHelper pseudostack support; r=snorp (67def0d2f)
- Bug 1016629 - d. Add and implement GetNativeStack method in ThreadStackHelper; r=snorp r=jseward (46c52f2be)
- Bug 1016629 - e. Implement platform-specific code for filling in context; r=snorp r=jseward (e6a66858b)
- Bug 1016629 - g. Avoid ASan flag when copying stack; r=snorp (0159628b5)
- Bug 1045176 - Unbreak build on non-SPS platforms after bug 1016629. (f1d60d838)
- Bug 1047123 - ThreadStackHelper should use UniquePtr<uint8_t[]>, not ScopedDeleteArray. r=jchen (0e4af313c)
- Bug 1049161 - Fix ThreadStackHelper thread handle permissions on Windows; r=snorp (c05172b1c)
- Bug 1050185 - Make ThreadStackHelper::FillThreadContext Valgrind-friendly. r=nchen (368725774)
- Bug 1050440 - Remove repeated js::RunScript frames in ThreadStackHelper (2a79600b3)
- Bug 1046841 - Fix more style violations in previously touched .cpp files in xpcom/. r=froydnj (02afe2493)
- Bug 1069694 - Remove or move around functions in OldDebugAPI. r=shu (177197302)
- Bug 1069694 - Remove OldDebugAPI from the browser. r=shu (b8c917d42)
- Bug 1100911 - For MacOS builds running on Valgrind, make ThreadStackHelper::GetStack be a no-op. r=nchen. (d99c02e16)
- Bug 1091758 - Report full paths for most chrome scripts; r=snorp (2b72e7878)
- Bug 1109291 - Include better paths for hanging chrome scripts in profile extensions directory; r=snorp r=bsmedberg (1997b9532)
- Bug 1113416 - Don't read stack labels inside hang monitor sighandler; r=nfroyd r=snorp (9688f6069)
- bug 1146027 - more final r=froydnj (7b0f295e5)
- Bug 1164090 - Check for Windows path separator in BHR file name; r=snorp (f014b4d78)
- Bug 1169034 - include <cstdlib> in ThreadStackHelper.cpp to declare correct overload for std::abs; r=jseward (874d4447e)
- Bug 1182996 - Fix and add missing namespace comments. rs=ehsan (054fc00b2)
- Bug 932865 - Collect thread hang stats in BackgroundHangMonitor; (ac80c8e9f)
- minor anticipated fixes to get it compiling (2bd701d15)
2020-02-01 08:07:15 +08:00

244 lines
8.4 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* vim: set ts=2 sw=2 et tw=79: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* A struct for tracking exceptions that need to be thrown to JS.
*/
#ifndef mozilla_ErrorResult_h
#define mozilla_ErrorResult_h
#include <stdarg.h>
#include "js/Value.h"
#include "nscore.h"
#include "nsStringGlue.h"
#include "mozilla/Assertions.h"
#include "mozilla/Move.h"
namespace IPC {
class Message;
template <typename> struct ParamTraits;
} // namespace IPC
namespace mozilla {
namespace dom {
enum ErrNum {
#define MSG_DEF(_name, _argc, _exn, _str) \
_name,
#include "mozilla/dom/Errors.msg"
#undef MSG_DEF
Err_Limit
};
bool
ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...);
} // namespace dom
class ErrorResult {
public:
ErrorResult() {
mResult = NS_OK;
#ifdef DEBUG
mMightHaveUnreportedJSException = false;
mHasMessage = false;
#endif
}
#ifdef DEBUG
~ErrorResult() {
MOZ_ASSERT_IF(IsErrorWithMessage(), !mMessage);
MOZ_ASSERT(!mMightHaveUnreportedJSException);
MOZ_ASSERT(!mHasMessage);
}
#endif
ErrorResult(ErrorResult&& aRHS)
{
*this = Move(aRHS);
}
ErrorResult& operator=(ErrorResult&& aRHS);
explicit ErrorResult(nsresult aRv)
: ErrorResult()
{
AssignErrorCode(aRv);
}
void Throw(nsresult rv) {
MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
AssignErrorCode(rv);
}
// Use SuppressException when you want to suppress any exception that might be
// on the ErrorResult. After this call, the ErrorResult will be back a "no
// exception thrown" state.
void SuppressException();
// Use StealNSResult() when you want to safely convert the ErrorResult to an
// nsresult that you will then return to a caller. This will
// SuppressException(), since there will no longer be a way to report it.
nsresult StealNSResult() {
nsresult rv = ErrorCode();
SuppressException();
return rv;
}
void ThrowTypeError(const dom::ErrNum errorNumber, ...);
void ThrowRangeError(const dom::ErrNum errorNumber, ...);
void ReportErrorWithMessage(JSContext* cx);
void ClearMessage();
bool IsErrorWithMessage() const { return ErrorCode() == NS_ERROR_TYPE_ERR || ErrorCode() == NS_ERROR_RANGE_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* or
// StealJSException as needed must first call WouldReportJSException even if
// this ErrorResult has not failed.
//
// The exn argument to ThrowJSException can be in any compartment. It does
// not have to be in the compartment of cx. If someone later uses it, they
// will wrap it into whatever compartment they're working in, as needed.
void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
void ReportJSException(JSContext* cx);
// Used to implement throwing exceptions from the JS implementation of
// bindings to callers of the binding.
void ReportJSExceptionFromJSImplementation(JSContext* aCx);
bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
void ThrowNotEnoughArgsError() { mResult = NS_ERROR_XPC_NOT_ENOUGH_ARGS; }
void ReportNotEnoughArgsError(JSContext* cx,
const char* ifaceName,
const char* memberName);
bool IsNotEnoughArgsError() const { return ErrorCode() == NS_ERROR_XPC_NOT_ENOUGH_ARGS; }
// Support for uncatchable exceptions.
void ThrowUncatchableException() {
Throw(NS_ERROR_UNCATCHABLE_EXCEPTION);
}
bool IsUncatchableException() const {
return ErrorCode() == NS_ERROR_UNCATCHABLE_EXCEPTION;
}
// StealJSException steals the JS Exception from the object. This method must
// be called only if IsJSException() returns true. This method also resets the
// ErrorCode() to NS_OK. The value will be ensured to be sanitized wrt to the
// current compartment of cx if it happens to be a DOMException.
void StealJSException(JSContext* cx, JS::MutableHandle<JS::Value> value);
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.
// Backwards-compat to make conversion simpler. We don't call
// Throw() here because people can easily pass success codes to
// this.
void operator=(nsresult rv) {
AssignErrorCode(rv);
}
bool Failed() const {
return NS_FAILED(mResult);
}
nsresult ErrorCode() const {
return mResult;
}
private:
friend struct IPC::ParamTraits<ErrorResult>;
void SerializeMessage(IPC::Message* aMsg) const;
bool DeserializeMessage(const IPC::Message* aMsg, void** aIter);
void ThrowErrorWithMessage(va_list ap, const dom::ErrNum errorNumber,
nsresult errorType);
void AssignErrorCode(nsresult aRv) {
MOZ_ASSERT(aRv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
MOZ_ASSERT(aRv != NS_ERROR_RANGE_ERR, "Use ThrowRangeError()");
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_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
mResult = aRv;
}
nsresult mResult;
struct Message;
// mMessage is set by ThrowErrorWithMessage and cleared (and deallocated) by
// ReportErrorWithMessage.
// mJSException is set (and rooted) by ThrowJSException and unrooted
// by ReportJSException.
union {
Message* mMessage; // valid when IsErrorWithMessage()
JS::Value mJSException; // valid when IsJSException()
};
#ifdef DEBUG
// Used to keep track of codepaths that might throw JS exceptions,
// for assertion purposes.
bool mMightHaveUnreportedJSException;
// Used to keep track of whether mMessage has ever been assigned to.
// We need to check this in order to ensure that not attempting to
// delete mMessage in DeserializeMessage doesn't leak memory.
bool mHasMessage;
#endif
// Not to be implemented, to make sure people always pass this by
// reference, not by value.
ErrorResult(const ErrorResult&) = delete;
void operator=(const ErrorResult&) = delete;
};
/******************************************************************************
** Macros for checking results
******************************************************************************/
#define ENSURE_SUCCESS(res, ret) \
do { \
if (res.Failed()) { \
nsCString msg; \
msg.AppendPrintf("ENSURE_SUCCESS(%s, %s) failed with " \
"result 0x%X", #res, #ret, res.ErrorCode()); \
NS_WARNING(msg.get()); \
return ret; \
} \
} while(0)
#define ENSURE_SUCCESS_VOID(res) \
do { \
if (res.Failed()) { \
nsCString msg; \
msg.AppendPrintf("ENSURE_SUCCESS_VOID(%s) failed with " \
"result 0x%X", #res, res.ErrorCode()); \
NS_WARNING(msg.get()); \
return; \
} \
} while(0)
} // namespace mozilla
#endif /* mozilla_ErrorResult_h */