dom/bindings/ErrorResult.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
michael@0 2 /* vim: set ts=2 sw=2 et tw=79: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /**
michael@0 8 * A struct for tracking exceptions that need to be thrown to JS.
michael@0 9 */
michael@0 10
michael@0 11 #ifndef mozilla_ErrorResult_h
michael@0 12 #define mozilla_ErrorResult_h
michael@0 13
michael@0 14 #include <stdarg.h>
michael@0 15
michael@0 16 #include "js/Value.h"
michael@0 17 #include "nscore.h"
michael@0 18 #include "nsStringGlue.h"
michael@0 19 #include "mozilla/Assertions.h"
michael@0 20
michael@0 21 namespace mozilla {
michael@0 22
michael@0 23 namespace dom {
michael@0 24
michael@0 25 enum ErrNum {
michael@0 26 #define MSG_DEF(_name, _argc, _str) \
michael@0 27 _name,
michael@0 28 #include "mozilla/dom/Errors.msg"
michael@0 29 #undef MSG_DEF
michael@0 30 Err_Limit
michael@0 31 };
michael@0 32
michael@0 33 bool
michael@0 34 ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...);
michael@0 35
michael@0 36 } // namespace dom
michael@0 37
michael@0 38 class ErrorResult {
michael@0 39 public:
michael@0 40 ErrorResult() {
michael@0 41 mResult = NS_OK;
michael@0 42
michael@0 43 #ifdef DEBUG
michael@0 44 // ErrorResult is extremely performance-sensitive code, where literally
michael@0 45 // every machine instruction matters. Initialize mMessage only to suppress
michael@0 46 // a debug-only warning from gcc 4.6.
michael@0 47 mMessage = nullptr;
michael@0 48 mMightHaveUnreportedJSException = false;
michael@0 49 #endif
michael@0 50 }
michael@0 51
michael@0 52 #ifdef DEBUG
michael@0 53 ~ErrorResult() {
michael@0 54 MOZ_ASSERT_IF(IsTypeError(), !mMessage);
michael@0 55 MOZ_ASSERT(!mMightHaveUnreportedJSException);
michael@0 56 }
michael@0 57 #endif
michael@0 58
michael@0 59 void Throw(nsresult rv) {
michael@0 60 MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
michael@0 61 MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
michael@0 62 MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError");
michael@0 63 MOZ_ASSERT(rv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
michael@0 64 MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
michael@0 65 MOZ_ASSERT(rv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
michael@0 66 MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
michael@0 67 mResult = rv;
michael@0 68 }
michael@0 69
michael@0 70 void ThrowTypeError(const dom::ErrNum errorNumber, ...);
michael@0 71 void ReportTypeError(JSContext* cx);
michael@0 72 void ClearMessage();
michael@0 73 bool IsTypeError() const { return ErrorCode() == NS_ERROR_TYPE_ERR; }
michael@0 74
michael@0 75 // Facilities for throwing a preexisting JS exception value via this
michael@0 76 // ErrorResult. The contract is that any code which might end up calling
michael@0 77 // ThrowJSException() must call MightThrowJSException() even if no exception
michael@0 78 // is being thrown. Code that would call ReportJSException* or
michael@0 79 // StealJSException as needed must first call WouldReportJSException even if
michael@0 80 // this ErrorResult has not failed.
michael@0 81 //
michael@0 82 // The exn argument to ThrowJSException can be in any compartment. It does
michael@0 83 // not have to be in the compartment of cx. If someone later uses it, they
michael@0 84 // will wrap it into whatever compartment they're working in, as needed.
michael@0 85 void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
michael@0 86 void ReportJSException(JSContext* cx);
michael@0 87 // Used to implement throwing exceptions from the JS implementation of
michael@0 88 // bindings to callers of the binding.
michael@0 89 void ReportJSExceptionFromJSImplementation(JSContext* aCx);
michael@0 90 bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
michael@0 91
michael@0 92 void ThrowNotEnoughArgsError() { mResult = NS_ERROR_XPC_NOT_ENOUGH_ARGS; }
michael@0 93 void ReportNotEnoughArgsError(JSContext* cx,
michael@0 94 const char* ifaceName,
michael@0 95 const char* memberName);
michael@0 96 bool IsNotEnoughArgsError() const { return ErrorCode() == NS_ERROR_XPC_NOT_ENOUGH_ARGS; }
michael@0 97
michael@0 98 // StealJSException steals the JS Exception from the object. This method must
michael@0 99 // be called only if IsJSException() returns true. This method also resets the
michael@0 100 // ErrorCode() to NS_OK.
michael@0 101 void StealJSException(JSContext* cx, JS::MutableHandle<JS::Value> value);
michael@0 102
michael@0 103 void MOZ_ALWAYS_INLINE MightThrowJSException()
michael@0 104 {
michael@0 105 #ifdef DEBUG
michael@0 106 mMightHaveUnreportedJSException = true;
michael@0 107 #endif
michael@0 108 }
michael@0 109 void MOZ_ALWAYS_INLINE WouldReportJSException()
michael@0 110 {
michael@0 111 #ifdef DEBUG
michael@0 112 mMightHaveUnreportedJSException = false;
michael@0 113 #endif
michael@0 114 }
michael@0 115
michael@0 116 // In the future, we can add overloads of Throw that take more
michael@0 117 // interesting things, like strings or DOM exception types or
michael@0 118 // something if desired.
michael@0 119
michael@0 120 // Backwards-compat to make conversion simpler. We don't call
michael@0 121 // Throw() here because people can easily pass success codes to
michael@0 122 // this.
michael@0 123 void operator=(nsresult rv) {
michael@0 124 MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()");
michael@0 125 MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError");
michael@0 126 MOZ_ASSERT(rv != NS_ERROR_DOM_JS_EXCEPTION, "Use ThrowJSException()");
michael@0 127 MOZ_ASSERT(!IsJSException(), "Don't overwrite JS exceptions");
michael@0 128 MOZ_ASSERT(rv != NS_ERROR_XPC_NOT_ENOUGH_ARGS, "Use ThrowNotEnoughArgsError()");
michael@0 129 MOZ_ASSERT(!IsNotEnoughArgsError(), "Don't overwrite not enough args error");
michael@0 130 mResult = rv;
michael@0 131 }
michael@0 132
michael@0 133 bool Failed() const {
michael@0 134 return NS_FAILED(mResult);
michael@0 135 }
michael@0 136
michael@0 137 nsresult ErrorCode() const {
michael@0 138 return mResult;
michael@0 139 }
michael@0 140
michael@0 141 private:
michael@0 142 nsresult mResult;
michael@0 143 struct Message;
michael@0 144 // mMessage is set by ThrowTypeError and cleared (and deallocatd) by
michael@0 145 // ReportTypeError.
michael@0 146 // mJSException is set (and rooted) by ThrowJSException and unrooted
michael@0 147 // by ReportJSException.
michael@0 148 union {
michael@0 149 Message* mMessage; // valid when IsTypeError()
michael@0 150 JS::Value mJSException; // valid when IsJSException()
michael@0 151 };
michael@0 152
michael@0 153 #ifdef DEBUG
michael@0 154 // Used to keep track of codepaths that might throw JS exceptions,
michael@0 155 // for assertion purposes.
michael@0 156 bool mMightHaveUnreportedJSException;
michael@0 157 #endif
michael@0 158
michael@0 159 // Not to be implemented, to make sure people always pass this by
michael@0 160 // reference, not by value.
michael@0 161 ErrorResult(const ErrorResult&) MOZ_DELETE;
michael@0 162 };
michael@0 163
michael@0 164 /******************************************************************************
michael@0 165 ** Macros for checking results
michael@0 166 ******************************************************************************/
michael@0 167
michael@0 168 #define ENSURE_SUCCESS(res, ret) \
michael@0 169 do { \
michael@0 170 if (res.Failed()) { \
michael@0 171 nsCString msg; \
michael@0 172 msg.AppendPrintf("ENSURE_SUCCESS(%s, %s) failed with " \
michael@0 173 "result 0x%X", #res, #ret, res.ErrorCode()); \
michael@0 174 NS_WARNING(msg.get()); \
michael@0 175 return ret; \
michael@0 176 } \
michael@0 177 } while(0)
michael@0 178
michael@0 179 #define ENSURE_SUCCESS_VOID(res) \
michael@0 180 do { \
michael@0 181 if (res.Failed()) { \
michael@0 182 nsCString msg; \
michael@0 183 msg.AppendPrintf("ENSURE_SUCCESS_VOID(%s) failed with " \
michael@0 184 "result 0x%X", #res, res.ErrorCode()); \
michael@0 185 NS_WARNING(msg.get()); \
michael@0 186 return; \
michael@0 187 } \
michael@0 188 } while(0)
michael@0 189
michael@0 190 } // namespace mozilla
michael@0 191
michael@0 192 #endif /* mozilla_ErrorResult_h */

mercurial