Bug 765464 - Part c: Throw some TypeErrors; r=khuey

This commit is contained in:
Ms2ger 2012-07-18 12:36:08 +02:00
Родитель 2dcc5e0037
Коммит 23b178ab1f
6 изменённых файлов: 120 добавлений и 26 удалений

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

@ -4,6 +4,8 @@
* 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 <stdarg.h>
#include "BindingUtils.h"
#include "xpcprivate.h"
@ -12,6 +14,32 @@
namespace mozilla {
namespace dom {
JSErrorFormatString ErrorFormatString[] = {
#define MSG_DEF(_name, _argc, _str) \
{ _str, _argc, JSEXN_TYPEERR },
#include "mozilla/dom/Errors.msg"
#undef MSG_DEF
};
const JSErrorFormatString*
GetErrorMessage(void* aUserRef, const char* aLocale,
const unsigned aErrorNumber)
{
MOZ_ASSERT(aErrorNumber < ArrayLength(ErrorFormatString));
return &ErrorFormatString[aErrorNumber];
}
bool
ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...)
{
va_list ap;
va_start(ap, aErrorNumber);
JS_ReportErrorNumberVA(aCx, GetErrorMessage, NULL,
static_cast<const unsigned>(aErrorNumber), ap);
va_end(ap);
return false;
}
bool
DefineConstants(JSContext* cx, JSObject* obj, ConstantSpec* cs)
{

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

@ -29,6 +29,17 @@ 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, ...);
template<bool mainThread>
inline bool
Throw(JSContext* cx, nsresult rv)
@ -414,8 +425,38 @@ struct EnumEntry {
size_t length;
};
template<bool Fatal>
inline bool
EnumValueNotFound(JSContext* cx, const jschar* chars, size_t length,
const char* type)
{
return false;
}
template<>
inline bool
EnumValueNotFound<false>(JSContext* cx, const jschar* chars, size_t length,
const char* type)
{
// TODO: Log a warning to the console.
return true;
}
template<>
inline bool
EnumValueNotFound<true>(JSContext* cx, const jschar* chars, size_t length,
const char* type)
{
NS_LossyConvertUTF16toASCII deflated(static_cast<const PRUnichar*>(chars),
length);
return ThrowErrorMessage(cx, MSG_INVALID_ENUM_VALUE, deflated.get(), type);
}
template<bool InvalidValueFatal>
inline int
FindEnumStringIndex(JSContext* cx, JS::Value v, const EnumEntry* values, bool* ok)
FindEnumStringIndex(JSContext* cx, JS::Value v, const EnumEntry* values,
const char* type, bool* ok)
{
// JS_StringEqualsAscii is slow as molasses, so don't use it here.
JSString* str = JS_ValueToString(cx, v);
@ -451,7 +492,7 @@ FindEnumStringIndex(JSContext* cx, JS::Value v, const EnumEntry* values, bool* o
}
}
*ok = true;
*ok = EnumValueNotFound<InvalidValueFatal>(cx, chars, length, type);
return -1;
}

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

@ -2006,20 +2006,27 @@ for (uint32_t i = 0; i < length; ++i) {
raise TypeError("We don't support nullable enumerated arguments "
"yet")
enum = type.inner.identifier.name
if invalidEnumValueFatal:
handleInvalidEnumValueCode = " MOZ_ASSERT(index >= 0);\n"
else:
handleInvalidEnumValueCode = (
" if (index < 0) {\n"
" return true;\n"
" }\n")
return (
"{\n"
" bool ok;\n"
" int index = FindEnumStringIndex(cx, ${val}, %(values)s, &ok);\n"
" int index = FindEnumStringIndex<%(invalidEnumValueFatal)s>(cx, ${val}, %(values)s, \"%(enumtype)s\", &ok);\n"
" if (!ok) {\n"
" return false;\n"
" }\n"
" if (index < 0) {\n"
" return %(failureCode)s;\n"
" }\n"
"%(handleInvalidEnumValueCode)s"
" ${declName} = static_cast<%(enumtype)s>(index);\n"
"}" % { "enumtype" : enum,
"values" : enum + "Values::strings",
"failureCode" : "Throw<false>(cx, NS_ERROR_XPC_BAD_CONVERT_JS)" if invalidEnumValueFatal else "true" },
"invalidEnumValueFatal" : toStringBool(invalidEnumValueFatal),
"handleInvalidEnumValueCode" : handleInvalidEnumValueCode },
CGGeneric(enum), None, isOptional)
if type.isCallback():
@ -2767,6 +2774,8 @@ class CGMethodCall(CGThing):
def __init__(self, argsPre, nativeMethodName, static, descriptor, method):
CGThing.__init__(self)
methodName = '"%s.%s"' % (descriptor.interface.identifier.name, method.identifier.name)
def requiredArgCount(signature):
arguments = signature[1]
if len(arguments) == 0:
@ -2790,18 +2799,15 @@ class CGMethodCall(CGThing):
signature = signatures[0]
self.cgRoot = CGList([ CGIndenter(getPerSignatureCall(signature)) ])
requiredArgs = requiredArgCount(signature)
if requiredArgs > 0:
code = (
"if (argc < %d) {\n"
" return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n"
"}" % (requiredArgs, methodName))
self.cgRoot.prepend(
CGWrapper(
CGIndenter(
CGGeneric(
"if (argc < %d) {\n"
" return Throw<%s>(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);\n"
"}" % (requiredArgs,
toStringBool(not descriptor.workers)))
),
pre="\n", post="\n")
)
CGWrapper(CGIndenter(CGGeneric(code)), pre="\n", post="\n"))
return
# Need to find the right overload
@ -2975,11 +2981,10 @@ class CGMethodCall(CGThing):
overloadCGThings.append(
CGSwitch("argcount",
argCountCases,
CGGeneric("return Throw<%s>(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);" %
toStringBool(not descriptor.workers))))
CGGeneric("return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n" % methodName)))
overloadCGThings.append(
CGGeneric('MOZ_NOT_REACHED("We have an always-returning default case");\n'
'return false;'))
CGGeneric('MOZ_NOT_REACHED("We have an always-returning default case");\n'
'return false;'))
self.cgRoot = CGWrapper(CGIndenter(CGList(overloadCGThings, "\n")),
pre="\n")

23
dom/bindings/Errors.msg Normal file
Просмотреть файл

@ -0,0 +1,23 @@
/* 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/. */
/*
* The format for each error message is:
*
* MSG_DEF(<SYMBOLIC_NAME>, <ARGUMENT_COUNT>, <FORMAT_STRING>)
*
* where
*
* <SYMBOLIC_NAME> is a legal C++ identifer that will be used in the source.
*
* <ARGUMENT_COUNT> is an integer literal specifying the total number of
* replaceable arguments in the following format string.
*
* <FORMAT_STRING> is a string literal, containing <ARGUMENT_COUNT> sequences
* {X} where X is an integer representing the argument number that will
* be replaced with a string value when the error is reported.
*/
MSG_DEF(MSG_INVALID_ENUM_VALUE, 2, "Value '{0}' is not a valid value for enumeration '{1}'.")
MSG_DEF(MSG_MISSING_ARGUMENTS, 1, "Not enough arguments to {0}.")

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

@ -63,6 +63,7 @@ EXPORTS_mozilla = \
EXPORTS_$(binding_include_path) = \
DOMJSClass.h \
Errors.msg \
PrototypeList.h \
RegisterBindings.h \
Nullable.h \
@ -156,4 +157,4 @@ GARBAGE += \
# don't have issues with .cpp files being compiled before we've generated the
# headers they depend on. This is really only needed for the test files, since
# the non-test headers are all exported above anyway.
export:: $(binding_header_files)
export:: $(binding_header_files)

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

@ -1,9 +1,5 @@
{
"XMLHttpRequest interface constructor": true,
"XMLHttpRequest interface: calling open(DOMString,DOMString,boolean,DOMString,DOMString) on new XMLHttpRequest() with too few arguments must throw TypeError": true,
"XMLHttpRequest interface: calling setRequestHeader(DOMString,DOMString) on new XMLHttpRequest() with too few arguments must throw TypeError": true,
"XMLHttpRequest interface: calling getResponseHeader(DOMString) on new XMLHttpRequest() with too few arguments must throw TypeError": true,
"XMLHttpRequest interface: calling overrideMimeType(DOMString) on new XMLHttpRequest() with too few arguments must throw TypeError": true,
"FormData interface: existence and properties of interface object": true,
"FormData interface constructor": true,
"FormData interface: existence and properties of interface prototype object": true,