зеркало из https://github.com/mozilla/gecko-dev.git
Bug 765464 - Part c: Throw some TypeErrors; r=khuey
This commit is contained in:
Родитель
2dcc5e0037
Коммит
23b178ab1f
|
@ -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")
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче