зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1613013 part 2. Change ThrowErrorMessage to be templated on the error number. r=peterv
This makes it easier to static_assert correct use. It caught several bugs in the next patch in this stack. I had to disambiguate some calls to the templated ThrowDOMException that are inside the binding_detail namespace, because otherwise they were trying to call teh non-template function of the same name that's declared in binding_detail. Differential Revision: https://phabricator.services.mozilla.com/D61522 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
747a4d9f0a
Коммит
09a1a6496e
|
@ -397,8 +397,8 @@ static bool ConvertKeyframeSequence(JSContext* aCx, dom::Document* aDocument,
|
|||
// or null/undefined (which gets treated as a default {} dictionary
|
||||
// value).
|
||||
if (!value.isObject() && !value.isNullOrUndefined()) {
|
||||
dom::ThrowErrorMessage(aCx, dom::MSG_NOT_OBJECT,
|
||||
"Element of sequence<Keyframe> argument");
|
||||
dom::ThrowErrorMessage<dom::MSG_NOT_OBJECT>(
|
||||
aCx, "Element of sequence<Keyframe> argument");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1266,11 +1266,11 @@ void GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
|
|||
}
|
||||
|
||||
bool ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
|
||||
return ThrowErrorMessage<MSG_ILLEGAL_CONSTRUCTOR>(cx);
|
||||
}
|
||||
|
||||
bool ThrowConstructorWithoutNew(JSContext* cx, const char* name) {
|
||||
return ThrowErrorMessage(cx, MSG_CONSTRUCTOR_WITHOUT_NEW, name);
|
||||
return ThrowErrorMessage<MSG_CONSTRUCTOR_WITHOUT_NEW>(cx, name);
|
||||
}
|
||||
|
||||
inline const NativePropertyHooks* GetNativePropertyHooksFromConstructorFunction(
|
||||
|
@ -2457,7 +2457,7 @@ bool GetContentGlobalForJSImplementedObject(JSContext* cx,
|
|||
}
|
||||
|
||||
if (!domImplVal.isObject()) {
|
||||
ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Value");
|
||||
ThrowErrorMessage<MSG_NOT_OBJECT>(cx, "Value");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2630,7 +2630,7 @@ bool ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
|
|||
char badCharArray[6];
|
||||
static_assert(sizeof(char16_t) <= 2, "badCharArray too small");
|
||||
SprintfLiteral(badCharArray, "%d", badChar);
|
||||
ThrowErrorMessage(cx, MSG_INVALID_BYTESTRING, index, badCharArray);
|
||||
ThrowErrorMessage<MSG_INVALID_BYTESTRING>(cx, index, badCharArray);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1285,8 +1285,8 @@ inline bool EnumValueNotFound<true>(JSContext* cx, JS::HandleString str,
|
|||
if (!deflated) {
|
||||
return false;
|
||||
}
|
||||
return ThrowErrorMessage(cx, MSG_INVALID_ENUM_VALUE, sourceDescription,
|
||||
deflated.get(), type);
|
||||
return ThrowErrorMessage<MSG_INVALID_ENUM_VALUE>(cx, sourceDescription,
|
||||
deflated.get(), type);
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
|
|
|
@ -23,7 +23,7 @@ bool CallbackInterface::GetCallableProperty(
|
|||
JS::RootedString propId(cx, JSID_TO_STRING(aPropId));
|
||||
JS::UniqueChars propName = JS_EncodeStringToUTF8(cx, propId);
|
||||
nsPrintfCString description("Property '%s'", propName.get());
|
||||
ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get());
|
||||
ThrowErrorMessage<MSG_NOT_CALLABLE>(cx, description.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -4456,7 +4456,7 @@ class FailureFatalCastableObjectUnwrapper(CastableObjectUnwrapper):
|
|||
isCallbackReturnValue, sourceDescription):
|
||||
CastableObjectUnwrapper.__init__(
|
||||
self, descriptor, source, mutableSource, target,
|
||||
'ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "%s", "%s");\n'
|
||||
'ThrowErrorMessage<MSG_DOES_NOT_IMPLEMENT_INTERFACE>(cx, "%s", "%s");\n'
|
||||
'%s' % (sourceDescription, descriptor.interface.identifier.name,
|
||||
exceptionCode),
|
||||
exceptionCode,
|
||||
|
@ -4766,25 +4766,25 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
def onFailureNotAnObject(failureCode):
|
||||
return CGGeneric(
|
||||
failureCode or
|
||||
('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n'
|
||||
('ThrowErrorMessage<MSG_NOT_OBJECT>(cx, "%s");\n'
|
||||
'%s' % (firstCap(sourceDescription), exceptionCode)))
|
||||
|
||||
def onFailureBadType(failureCode, typeName):
|
||||
return CGGeneric(
|
||||
failureCode or
|
||||
('ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "%s", "%s");\n'
|
||||
('ThrowErrorMessage<MSG_DOES_NOT_IMPLEMENT_INTERFACE>(cx, "%s", "%s");\n'
|
||||
'%s' % (firstCap(sourceDescription), typeName, exceptionCode)))
|
||||
|
||||
def onFailureIsShared(failureCode):
|
||||
return CGGeneric(
|
||||
failureCode or
|
||||
('ThrowErrorMessage(cx, MSG_TYPEDARRAY_IS_SHARED, "%s");\n'
|
||||
('ThrowErrorMessage<MSG_TYPEDARRAY_IS_SHARED>(cx, "%s");\n'
|
||||
'%s' % (firstCap(sourceDescription), exceptionCode)))
|
||||
|
||||
def onFailureNotCallable(failureCode):
|
||||
return CGGeneric(
|
||||
failureCode or
|
||||
('ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "%s");\n'
|
||||
('ThrowErrorMessage<MSG_NOT_CALLABLE>(cx, "%s");\n'
|
||||
'%s' % (firstCap(sourceDescription), exceptionCode)))
|
||||
|
||||
# A helper function for handling default values. Takes a template
|
||||
|
@ -4893,7 +4893,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
#pragma clang diagnostic ignored "-Wunreachable-code-return"
|
||||
#endif // __clang__
|
||||
if (($${passedToJSImpl}) && !CallerSubsumes($${val})) {
|
||||
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
|
||||
ThrowErrorMessage<MSG_PERMISSION_DENIED_TO_PASS_ARG>(cx, "${sourceDescription}");
|
||||
$*{exceptionCode}
|
||||
}
|
||||
#ifdef __clang__
|
||||
|
@ -4921,7 +4921,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
assert not isEnforceRange and not isClamp and not isAllowShared
|
||||
|
||||
if failureCode is None:
|
||||
notSequence = ('ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "%s");\n'
|
||||
notSequence = ('ThrowErrorMessage<MSG_NOT_SEQUENCE>(cx, "%s");\n'
|
||||
"%s" % (firstCap(sourceDescription), exceptionCode))
|
||||
else:
|
||||
notSequence = failureCode
|
||||
|
@ -5058,7 +5058,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
if type.isRecord():
|
||||
assert not isEnforceRange and not isClamp and not isAllowShared
|
||||
if failureCode is None:
|
||||
notRecord = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n'
|
||||
notRecord = ('ThrowErrorMessage<MSG_NOT_OBJECT>(cx, "%s");\n'
|
||||
"%s" % (firstCap(sourceDescription), exceptionCode))
|
||||
else:
|
||||
notRecord = failureCode
|
||||
|
@ -5407,7 +5407,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
$*{exceptionCode}
|
||||
}
|
||||
if (!done) {
|
||||
ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "${desc}", "${names}");
|
||||
ThrowErrorMessage<MSG_NOT_IN_UNION>(cx, "${desc}", "${names}");
|
||||
$*{exceptionCode}
|
||||
}
|
||||
""",
|
||||
|
@ -6213,7 +6213,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
#pragma clang diagnostic ignored "-Wunreachable-code-return"
|
||||
#endif // __clang__
|
||||
if (($${passedToJSImpl}) && !CallerSubsumes($${val})) {
|
||||
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
|
||||
ThrowErrorMessage<MSG_PERMISSION_DENIED_TO_PASS_ARG>(cx, "${sourceDescription}");
|
||||
$*{exceptionCode}
|
||||
}
|
||||
#ifdef __clang__
|
||||
|
@ -6408,7 +6408,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
if lenientFloatCode is not None:
|
||||
nonFiniteCode = lenientFloatCode
|
||||
else:
|
||||
nonFiniteCode = ('ThrowErrorMessage(cx, MSG_NOT_FINITE, "%s");\n'
|
||||
nonFiniteCode = ('ThrowErrorMessage<MSG_NOT_FINITE>(cx, "%s");\n'
|
||||
"%s" % (firstCap(sourceDescription), exceptionCode))
|
||||
|
||||
# We're appending to an if-block brace, so strip trailing whitespace
|
||||
|
@ -8735,7 +8735,7 @@ class CGMethodCall(CGThing):
|
|||
# Just throw; we have no idea what we're supposed to
|
||||
# do with this.
|
||||
caseBody.append(CGGeneric(
|
||||
'return ThrowErrorMessage(cx, MSG_OVERLOAD_RESOLUTION_FAILED, "%d", "%d", "%s");\n' %
|
||||
'return ThrowErrorMessage<MSG_OVERLOAD_RESOLUTION_FAILED>(cx, "%d", "%d", "%s");\n' %
|
||||
(distinguishingIndex + 1, argCount, methodName)))
|
||||
|
||||
argCountCases.append(CGCase(str(argCount), CGList(caseBody)))
|
||||
|
@ -8753,7 +8753,7 @@ class CGMethodCall(CGThing):
|
|||
// header. Let's not worry about it.
|
||||
nsAutoCString argCountStr;
|
||||
argCountStr.AppendPrintf("%u", args.length());
|
||||
return ThrowErrorMessage(cx, MSG_INVALID_OVERLOAD_ARGCOUNT, "${methodName}", argCountStr.get());
|
||||
return ThrowErrorMessage<MSG_INVALID_OVERLOAD_ARGCOUNT>(cx, "${methodName}", argCountStr.get());
|
||||
""",
|
||||
methodName=methodName))))
|
||||
overloadCGThings.append(
|
||||
|
@ -9615,7 +9615,7 @@ class CGSpecializedForwardingSetter(CGSpecializedSetter):
|
|||
}
|
||||
|
||||
if (!v.isObject()) {
|
||||
return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "${interface}.${attr}");
|
||||
return ThrowErrorMessage<MSG_NOT_OBJECT>(cx, "${interface}.${attr}");
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> targetObj(cx, &v.toObject());
|
||||
|
@ -10385,7 +10385,7 @@ def getUnionTypeTemplateVars(unionType, type, descriptorProvider,
|
|||
body = body + fill(
|
||||
"""
|
||||
if (passedToJSImpl && !CallerSubsumes(obj)) {
|
||||
ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "${sourceDescription}");
|
||||
ThrowErrorMessage<MSG_PERMISSION_DENIED_TO_PASS_ARG>(cx, "${sourceDescription}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -13846,7 +13846,7 @@ class CGDictionary(CGThing):
|
|||
body += dedent(
|
||||
"""
|
||||
if (!IsConvertibleToDictionary(val)) {
|
||||
return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
|
||||
return ThrowErrorMessage<MSG_NOT_DICTIONARY>(cx, sourceDescription);
|
||||
}
|
||||
|
||||
""")
|
||||
|
@ -14402,8 +14402,7 @@ class CGDictionary(CGThing):
|
|||
// Don't error out if we have no cx. In that
|
||||
// situation the caller is default-constructing us and we'll
|
||||
// just assume they know what they're doing.
|
||||
return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
|
||||
"%s");
|
||||
return ThrowErrorMessage<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(cx, "%s");
|
||||
}
|
||||
""" % self.getMemberSourceDescription(member))
|
||||
conversionReplacements["convert"] = indent(conversionReplacements["convert"]).rstrip()
|
||||
|
@ -16571,10 +16570,10 @@ class CGJSImplClass(CGBindingImplClass):
|
|||
return false;
|
||||
}
|
||||
if (!args[0].isObject()) {
|
||||
return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of ${ifaceName}._create");
|
||||
return ThrowErrorMessage<MSG_NOT_OBJECT>(cx, "Argument 1 of ${ifaceName}._create");
|
||||
}
|
||||
if (!args[1].isObject()) {
|
||||
return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of ${ifaceName}._create");
|
||||
return ThrowErrorMessage<MSG_NOT_OBJECT>(cx, "Argument 2 of ${ifaceName}._create");
|
||||
}
|
||||
|
||||
// GlobalObject will go through wrappers as needed for us, and
|
||||
|
@ -18073,7 +18072,7 @@ class CGIterableMethodGenerator(CGGeneric):
|
|||
CGGeneric.__init__(self, fill(
|
||||
"""
|
||||
if (!JS::IsCallable(arg0)) {
|
||||
ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 1 of ${ifaceName}.forEach");
|
||||
ThrowErrorMessage<MSG_NOT_CALLABLE>(cx, "Argument 1 of ${ifaceName}.forEach");
|
||||
return false;
|
||||
}
|
||||
JS::AutoValueArray<3> callArgs(cx);
|
||||
|
|
|
@ -75,10 +75,13 @@ namespace binding_detail {
|
|||
void ThrowErrorMessage(JSContext* aCx, const unsigned aErrorNumber, ...);
|
||||
} // namespace binding_detail
|
||||
|
||||
template <typename... Ts>
|
||||
inline bool ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber,
|
||||
Ts&&... aArgs) {
|
||||
binding_detail::ThrowErrorMessage(aCx, static_cast<unsigned>(aErrorNumber),
|
||||
template <ErrNum errorNumber, typename... Ts>
|
||||
inline bool ThrowErrorMessage(JSContext* aCx, Ts&&... aArgs) {
|
||||
#if defined(DEBUG) && (defined(__clang__) || defined(__GNUC__))
|
||||
static_assert(ErrorFormatNumArgs[errorNumber] == sizeof...(aArgs),
|
||||
"Pass in the right number of arguments");
|
||||
#endif
|
||||
binding_detail::ThrowErrorMessage(aCx, static_cast<unsigned>(errorNumber),
|
||||
std::forward<Ts>(aArgs)...);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -198,8 +198,8 @@ inline bool PrimitiveConversionTraits_EnforceRange(JSContext* cx,
|
|||
"This can only be applied to integers!");
|
||||
|
||||
if (!mozilla::IsFinite(d)) {
|
||||
return ThrowErrorMessage(cx, MSG_ENFORCE_RANGE_NON_FINITE,
|
||||
TypeName<T>::value());
|
||||
return ThrowErrorMessage<MSG_ENFORCE_RANGE_NON_FINITE>(
|
||||
cx, TypeName<T>::value());
|
||||
}
|
||||
|
||||
bool neg = (d < 0);
|
||||
|
@ -207,8 +207,8 @@ inline bool PrimitiveConversionTraits_EnforceRange(JSContext* cx,
|
|||
rounded = neg ? -rounded : rounded;
|
||||
if (rounded < PrimitiveConversionTraits_Limits<T>::min() ||
|
||||
rounded > PrimitiveConversionTraits_Limits<T>::max()) {
|
||||
return ThrowErrorMessage(cx, MSG_ENFORCE_RANGE_OUT_OF_RANGE,
|
||||
TypeName<T>::value());
|
||||
return ThrowErrorMessage<MSG_ENFORCE_RANGE_OUT_OF_RANGE>(
|
||||
cx, TypeName<T>::value());
|
||||
}
|
||||
|
||||
*retval = static_cast<T>(rounded);
|
||||
|
|
Загрузка…
Ссылка в новой задаче