diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index d5866d5b9ec..a64bff6f73d 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -4,6 +4,7 @@ * 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/. */ +#include #include #include "BindingUtils.h" @@ -44,6 +45,58 @@ ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...) return false; } +} // namespace dom + +struct ErrorResult::Message { + nsTArray mArgs; + dom::ErrNum mErrorNumber; +}; + +void +ErrorResult::ThrowTypeError(const dom::ErrNum errorNumber, ...) +{ + va_list ap; + va_start(ap, errorNumber); + if (IsTypeError()) { + delete mMessage; + } + mResult = NS_ERROR_TYPE_ERR; + Message* message = new Message(); + message->mErrorNumber = errorNumber; + uint16_t argCount = + dom::GetErrorMessage(nullptr, nullptr, errorNumber)->argCount; + MOZ_ASSERT(argCount <= 10); + argCount = std::min(argCount, 10); + while (argCount--) { + message->mArgs.AppendElement(*va_arg(ap, nsString*)); + } + mMessage = message; + va_end(ap); +} + +void +ErrorResult::ReportTypeError(JSContext* aCx) +{ + MOZ_ASSERT(mMessage, "ReportTypeError() can be called only once"); + + Message* message = mMessage; + const uint32_t argCount = message->mArgs.Length(); + const jschar* args[11]; + for (uint32_t i = 0; i < argCount; ++i) { + args[i] = message->mArgs.ElementAt(i).get(); + } + args[argCount] = nullptr; + + JS_ReportErrorNumberUCArray(aCx, dom::GetErrorMessage, nullptr, + static_cast(message->mErrorNumber), + argCount > 0 ? args : nullptr); + + delete message; + mMessage = nullptr; +} + +namespace dom { + bool DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs) { diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 228d6d69a1a..54940639cde 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -31,14 +31,6 @@ class nsGlobalWindow; namespace mozilla { namespace dom { -enum ErrNum { -#define MSG_DEF(_name, _argc, _str) \ - _name, -#include "mozilla/dom/Errors.msg" -#undef MSG_DEF - Err_Limit -}; - bool ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...); @@ -61,10 +53,14 @@ Throw(JSContext* cx, nsresult rv) template inline bool -ThrowMethodFailedWithDetails(JSContext* cx, const ErrorResult& rv, +ThrowMethodFailedWithDetails(JSContext* cx, ErrorResult& rv, const char* /* ifaceName */, const char* /* memberName */) { + if (rv.IsTypeError()) { + rv.ReportTypeError(cx); + return false; + } return Throw(cx, rv.ErrorCode()); } diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index cdb22c234ac..6f7d6a2241a 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -353,14 +353,9 @@ DOMInterfaces = { }, 'TextEncoder': { - 'headerFile': 'mozilla/dom/TextEncoder.h', 'implicitJSContext': [ 'encode' ], }, -'TextDecoder': { - 'headerFile': 'mozilla/dom/TextDecoder.h', -}, - 'WebGLActiveInfo': { 'nativeType': 'mozilla::WebGLActiveInfo', 'headerFile': 'WebGLContext.h', diff --git a/dom/bindings/ErrorResult.h b/dom/bindings/ErrorResult.h index bbd9404a865..d8b0a6994f8 100644 --- a/dom/bindings/ErrorResult.h +++ b/dom/bindings/ErrorResult.h @@ -11,22 +11,48 @@ #ifndef mozilla_ErrorResult_h #define mozilla_ErrorResult_h +#include + +#include "jsapi.h" #include "nscore.h" #include "mozilla/Assertions.h" namespace mozilla { +namespace dom { + +enum ErrNum { +#define MSG_DEF(_name, _argc, _str) \ + _name, +#include "mozilla/dom/Errors.msg" +#undef MSG_DEF + Err_Limit +}; + +} // namespace dom + class ErrorResult { public: ErrorResult() { mResult = NS_OK; } +#ifdef DEBUG + ~ErrorResult() { + MOZ_ASSERT_IF(IsTypeError(), !mMessage); + } +#endif void Throw(nsresult rv) { MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success"); + MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()"); + MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError"); mResult = rv; } + void ThrowTypeError(const dom::ErrNum errorNumber, ...); + void ReportTypeError(JSContext* cx); + bool IsTypeError() const { return ErrorCode() == NS_ERROR_TYPE_ERR; } + // In the future, we can add overloads of Throw that take more // interesting things, like strings or DOM exception types or // something if desired. @@ -35,6 +61,8 @@ public: // Throw() here because people can easily pass success codes to // this. void operator=(nsresult rv) { + MOZ_ASSERT(rv != NS_ERROR_TYPE_ERR, "Use ThrowTypeError()"); + MOZ_ASSERT(!IsTypeError(), "Don't overwite TypeError"); mResult = rv; } @@ -48,6 +76,9 @@ public: private: nsresult mResult; + struct Message; + // Do not use nsAutoPtr to avoid extra initalizatoin and check. + Message* mMessage; // Not to be implemented, to make sure people always pass this by // reference, not by value. diff --git a/dom/bindings/Errors.msg b/dom/bindings/Errors.msg index 8236a1ae755..ad89f271cf9 100644 --- a/dom/bindings/Errors.msg +++ b/dom/bindings/Errors.msg @@ -32,3 +32,5 @@ MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, "Value is out of range for {0}.") MSG_DEF(MSG_NOT_SEQUENCE, 0, "object can not be converted to a sequence") MSG_DEF(MSG_INVALID_ARG, 2, "argument {0} is not valid for any of the {1}-argument overloads") MSG_DEF(MSG_GLOBAL_NOT_NATIVE, 0, "global is not a native object") +MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, "The given encoding '{0}' is not supported.") +MSG_DEF(MSG_DOM_ENCODING_NOT_UTF, 0, "The encoding must be utf-8, utf-16, or utf-16be.")