Bug 801487 - Implement ErrorResult::ThrowTypeError. r=bz

This commit is contained in:
Masatoshi Kimura 2012-11-06 18:23:14 -05:00
parent 8ecc83b13b
commit 32a0cfd0f7
5 changed files with 91 additions and 14 deletions

View File

@ -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 <algorithm>
#include <stdarg.h>
#include "BindingUtils.h"
@ -44,6 +45,58 @@ ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...)
return false;
}
} // namespace dom
struct ErrorResult::Message {
nsTArray<nsString> 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<uint16_t>(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<const unsigned>(message->mErrorNumber),
argCount > 0 ? args : nullptr);
delete message;
mMessage = nullptr;
}
namespace dom {
bool
DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs)
{

View File

@ -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<bool mainThread>
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<mainThread>(cx, rv.ErrorCode());
}

View File

@ -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',

View File

@ -11,22 +11,48 @@
#ifndef mozilla_ErrorResult_h
#define mozilla_ErrorResult_h
#include <stdarg.h>
#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.

View File

@ -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.")