Bug 1613013 part 3. Annotate TypeErrors and RangeErrors from WebIDL implementations with the method they come from. r=peterv

Please review the changes to Errors.msg very carefully.  I caught a number of
mistakes there in self-review (e.g. not renumbering replacement markers
correctly when I added {0} to the beginnings of strings), and my confidence
that I caught them all is only middling.

A few lines (MSG_USELESS_SETTIMEOUT, MSG_TYPEDARRAY_IS_DETACHED,
MSG_NOT_SUBMIT_BUTTON) were removed from Errors.msg either because they were
already unused or because they either were single-user constant strings or
became such in the new setup and we could just use the string version of
ThrowTypeError.

Differential Revision: https://phabricator.services.mozilla.com/D61523

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Zbarsky 2020-02-06 21:22:32 +00:00
Родитель 09a1a6496e
Коммит 1395be1f23
20 изменённых файлов: 187 добавлений и 138 удалений

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

@ -223,7 +223,7 @@ void KeyframeEffect::SetKeyframes(JSContext* aContext,
JS::Handle<JSObject*> aKeyframes,
ErrorResult& aRv) {
nsTArray<Keyframe> keyframes = KeyframeUtils::GetKeyframesFromObject(
aContext, mDocument, aKeyframes, aRv);
aContext, mDocument, aKeyframes, "KeyframeEffect.setKeyframes: ", aRv);
if (aRv.Failed()) {
return;
}

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

@ -135,14 +135,13 @@ class ComputedOffsetComparator {
//
// ------------------------------------------------------------------
static void GetKeyframeListFromKeyframeSequence(JSContext* aCx,
dom::Document* aDocument,
JS::ForOfIterator& aIterator,
nsTArray<Keyframe>& aResult,
ErrorResult& aRv);
static void GetKeyframeListFromKeyframeSequence(
JSContext* aCx, dom::Document* aDocument, JS::ForOfIterator& aIterator,
nsTArray<Keyframe>& aResult, const char* aContext, ErrorResult& aRv);
static bool ConvertKeyframeSequence(JSContext* aCx, dom::Document* aDocument,
JS::ForOfIterator& aIterator,
const char* aContext,
nsTArray<Keyframe>& aResult);
static bool GetPropertyValuesPairs(JSContext* aCx,
@ -195,7 +194,7 @@ static void DistributeRange(const Range<Keyframe>& aRange);
/* static */
nsTArray<Keyframe> KeyframeUtils::GetKeyframesFromObject(
JSContext* aCx, dom::Document* aDocument, JS::Handle<JSObject*> aFrames,
ErrorResult& aRv) {
const char* aContext, ErrorResult& aRv) {
MOZ_ASSERT(!aRv.Failed());
nsTArray<Keyframe> keyframes;
@ -216,7 +215,8 @@ nsTArray<Keyframe> KeyframeUtils::GetKeyframesFromObject(
}
if (iter.valueIsIterable()) {
GetKeyframeListFromKeyframeSequence(aCx, aDocument, iter, keyframes, aRv);
GetKeyframeListFromKeyframeSequence(aCx, aDocument, iter, keyframes,
aContext, aRv);
} else {
GetKeyframeListFromPropertyIndexedKeyframe(aCx, aDocument, objectValue,
keyframes, aRv);
@ -341,21 +341,20 @@ bool KeyframeUtils::IsAnimatableProperty(nsCSSPropertyID aProperty) {
* object to iterate over as a sequence.
* @param aResult The array into which the resulting Keyframe objects will be
* appended.
* @param aContext The context string to prepend to thrown exceptions.
* @param aRv Out param to store any errors thrown by this function.
*/
static void GetKeyframeListFromKeyframeSequence(JSContext* aCx,
dom::Document* aDocument,
JS::ForOfIterator& aIterator,
nsTArray<Keyframe>& aResult,
ErrorResult& aRv) {
static void GetKeyframeListFromKeyframeSequence(
JSContext* aCx, dom::Document* aDocument, JS::ForOfIterator& aIterator,
nsTArray<Keyframe>& aResult, const char* aContext, ErrorResult& aRv) {
MOZ_ASSERT(!aRv.Failed());
MOZ_ASSERT(aResult.IsEmpty());
// Convert the object in aIterator to a sequence of keyframes producing
// an array of Keyframe objects.
if (!ConvertKeyframeSequence(aCx, aDocument, aIterator, aResult)) {
if (!ConvertKeyframeSequence(aCx, aDocument, aIterator, aContext, aResult)) {
aResult.Clear();
aRv.Throw(NS_ERROR_FAILURE);
aRv.NoteJSContextException(aCx);
return;
}
@ -381,6 +380,7 @@ static void GetKeyframeListFromKeyframeSequence(JSContext* aCx,
*/
static bool ConvertKeyframeSequence(JSContext* aCx, dom::Document* aDocument,
JS::ForOfIterator& aIterator,
const char* aContext,
nsTArray<Keyframe>& aResult) {
JS::Rooted<JS::Value> value(aCx);
ErrorResult parseEasingResult;
@ -398,7 +398,9 @@ static bool ConvertKeyframeSequence(JSContext* aCx, dom::Document* aDocument,
// value).
if (!value.isObject() && !value.isNullOrUndefined()) {
dom::ThrowErrorMessage<dom::MSG_NOT_OBJECT>(
aCx, "Element of sequence<Keyframe> argument");
aCx,
nsPrintfCString("%sElement of sequence<Keyframe> argument", aContext)
.get());
return false;
}

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

@ -49,6 +49,9 @@ class KeyframeUtils {
* @param aDocument The document to use when parsing CSS properties.
* @param aFrames The JS value, provided as an optional IDL |object?| value,
* that is the keyframe list specification.
* @param aContext Information about who is trying to get keyframes from the
* object, for use in error reporting. This must be be a non-null
* pointer representing a null-terminated ASCII string.
* @param aRv (out) Out-param to hold any error returned by this function.
* Must be initially empty.
* @return The set of processed keyframes. If an error occurs, aRv will be
@ -57,7 +60,7 @@ class KeyframeUtils {
*/
static nsTArray<Keyframe> GetKeyframesFromObject(
JSContext* aCx, dom::Document* aDocument, JS::Handle<JSObject*> aFrames,
ErrorResult& aRv);
const char* aContext, ErrorResult& aRv);
/**
* Calculate the computed offset of keyframes by evenly distributing keyframes

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

@ -647,18 +647,19 @@ int32_t CustomElementRegistry::InferNamespace(
}
bool CustomElementRegistry::JSObjectToAtomArray(
JSContext* aCx, JS::Handle<JSObject*> aConstructor, const char16_t* aName,
JSContext* aCx, JS::Handle<JSObject*> aConstructor, const nsString& aName,
nsTArray<RefPtr<nsAtom>>& aArray, ErrorResult& aRv) {
JS::RootedValue iterable(aCx, JS::UndefinedValue());
if (!JS_GetUCProperty(aCx, aConstructor, aName,
std::char_traits<char16_t>::length(aName), &iterable)) {
if (!JS_GetUCProperty(aCx, aConstructor, aName.get(), aName.Length(),
&iterable)) {
aRv.NoteJSContextException(aCx);
return false;
}
if (!iterable.isUndefined()) {
if (!iterable.isObject()) {
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(nsDependentString(aName));
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(
NS_LITERAL_STRING("CustomElementRegistry.define: ") + aName);
return false;
}
@ -669,7 +670,8 @@ bool CustomElementRegistry::JSObjectToAtomArray(
}
if (!iter.valueIsIterable()) {
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(nsDependentString(aName));
aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(
NS_LITERAL_STRING("CustomElementRegistry.define: ") + aName);
return false;
}
@ -868,8 +870,8 @@ void CustomElementRegistry::Define(
* 14.2. If Type(prototype) is not Object, then throw a TypeError exception.
*/
if (!prototype.isObject()) {
aRv.ThrowTypeError<MSG_NOT_OBJECT>(
NS_LITERAL_STRING("constructor.prototype"));
aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING(
"CustomElementRegistry.define: constructor.prototype"));
return;
}
@ -903,7 +905,8 @@ void CustomElementRegistry::Define(
* any exceptions from the conversion.
*/
if (callbacksHolder->mAttributeChangedCallback.WasPassed()) {
if (!JSObjectToAtomArray(aCx, constructor, u"observedAttributes",
if (!JSObjectToAtomArray(aCx, constructor,
NS_LITERAL_STRING("observedAttributes"),
observedAttributes, aRv)) {
return;
}
@ -919,7 +922,8 @@ void CustomElementRegistry::Define(
* Rethrow any exceptions from the conversion.
*/
if (StaticPrefs::dom_webcomponents_elementInternals_enabled()) {
if (!JSObjectToAtomArray(aCx, constructor, u"disabledFeatures",
if (!JSObjectToAtomArray(aCx, constructor,
NS_LITERAL_STRING("disabledFeatures"),
disabledFeatures, aRv)) {
return;
}

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

@ -469,7 +469,7 @@ class CustomElementRegistry final : public nsISupports, public nsWrapperCache {
~CustomElementRegistry();
bool JSObjectToAtomArray(JSContext* aCx, JS::Handle<JSObject*> aConstructor,
const char16_t* aName,
const nsString& aName,
nsTArray<RefPtr<nsAtom>>& aArray, ErrorResult& aRv);
static UniquePtr<CustomElementCallback> CreateCustomElementCallback(

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

@ -99,21 +99,22 @@ static const constructorGetterCallback sConstructorGetterCallback[] = {
#undef HTML_OTHER
};
const JSErrorFormatString ErrorFormatString[] = {
#define MSG_DEF(_name, _argc, _exn, _str) {#_name, _str, _argc, _exn},
static const JSErrorFormatString ErrorFormatString[] = {
#define MSG_DEF(_name, _argc, _has_context, _exn, _str) \
{#_name, _str, _argc, _exn},
#include "mozilla/dom/Errors.msg"
#undef MSG_DEF
};
#define MSG_DEF(_name, _argc, _exn, _str) \
static_assert( \
(_argc) < JS::MaxNumErrorArguments, #_name \
#define MSG_DEF(_name, _argc, _has_context, _exn, _str) \
static_assert( \
(_argc) < JS::MaxNumErrorArguments, #_name \
" must only have as many error arguments as the JS engine can support");
#include "mozilla/dom/Errors.msg"
#undef MSG_DEF
const JSErrorFormatString* GetErrorMessage(void* aUserRef,
const unsigned aErrorNumber) {
static const JSErrorFormatString* GetErrorMessage(void* aUserRef,
const unsigned aErrorNumber) {
MOZ_ASSERT(aErrorNumber < ArrayLength(ErrorFormatString));
return &ErrorFormatString[aErrorNumber];
}
@ -248,6 +249,15 @@ void TErrorResult<CleanupPolicy>::SetPendingExceptionWithMessage(
Message* message = mExtra.mMessage;
MOZ_RELEASE_ASSERT(message->HasCorrectNumberOfArguments());
if (dom::ErrorFormatHasContext[message->mErrorNumber]) {
MOZ_ASSERT(!message->mArgs.IsEmpty(), "How could we have no args here?");
MOZ_ASSERT(message->mArgs[0].IsEmpty(), "Context should not be set yet!");
if (context) {
// Prepend our context and ": "; see API documentation.
message->mArgs[0].AssignASCII(context);
message->mArgs[0].AppendLiteral(": ");
}
}
const uint32_t argCount = message->mArgs.Length();
const char16_t* args[JS::MaxNumErrorArguments + 1];
for (uint32_t i = 0; i < argCount; ++i) {
@ -1266,7 +1276,7 @@ void GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
}
bool ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp) {
return ThrowErrorMessage<MSG_ILLEGAL_CONSTRUCTOR>(cx);
return ThrowErrorMessage<MSG_ILLEGAL_CONSTRUCTOR>(cx, "");
}
bool ThrowConstructorWithoutNew(JSContext* cx, const char* name) {

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

@ -52,8 +52,8 @@ namespace dom {
class Promise;
enum ErrNum {
#define MSG_DEF(_name, _argc, _exn, _str) _name,
enum ErrNum : uint16_t {
#define MSG_DEF(_name, _argc, _has_context, _exn, _str) _name,
#include "mozilla/dom/Errors.msg"
#undef MSG_DEF
Err_Limit
@ -63,12 +63,19 @@ enum ErrNum {
// use in static_assert.
#if defined(DEBUG) && (defined(__clang__) || defined(__GNUC__))
uint16_t constexpr ErrorFormatNumArgs[] = {
# define MSG_DEF(_name, _argc, _exn, _str) _argc,
# define MSG_DEF(_name, _argc, _has_context, _exn, _str) _argc,
# include "mozilla/dom/Errors.msg"
# undef MSG_DEF
};
#endif
// Table of whether various error messages want a context arg.
bool constexpr ErrorFormatHasContext[] = {
#define MSG_DEF(_name, _argc, _has_context, _exn, _str) _has_context,
#include "mozilla/dom/Errors.msg"
#undef MSG_DEF
};
uint16_t GetErrorArgCount(const ErrNum aErrorNumber);
namespace binding_detail {
@ -450,9 +457,10 @@ class TErrorResult {
template <dom::ErrNum errorNumber, typename... Ts>
void ThrowErrorWithMessage(nsresult errorType, Ts&&... messageArgs) {
#if defined(DEBUG) && (defined(__clang__) || defined(__GNUC__))
static_assert(
dom::ErrorFormatNumArgs[errorNumber] == sizeof...(messageArgs),
"Pass in the right number of arguments");
static_assert(dom::ErrorFormatNumArgs[errorNumber] ==
sizeof...(messageArgs) +
int(dom::ErrorFormatHasContext[errorNumber]),
"Pass in the right number of arguments");
#endif
ClearUnionData();
@ -460,6 +468,16 @@ class TErrorResult {
nsTArray<nsString>& messageArgsArray =
CreateErrorMessageHelper(errorNumber, errorType);
uint16_t argCount = dom::GetErrorArgCount(errorNumber);
if (dom::ErrorFormatHasContext[errorNumber]) {
// Insert an empty string arg at the beginning and reduce our arg count to
// still be appended accordingly.
MOZ_ASSERT(argCount > 0,
"Must have at least one arg if we have a context!");
MOZ_ASSERT(messageArgsArray.Length() == 0,
"Why do we already have entries in the array?");
--argCount;
messageArgsArray.AppendElement();
}
dom::StringArrayAppender::Append(messageArgsArray, argCount,
std::forward<Ts>(messageArgs)...);
#ifdef DEBUG

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

@ -5,7 +5,7 @@
/*
* The format for each error message is:
*
* MSG_DEF(<SYMBOLIC_NAME>, <ARGUMENT_COUNT>, <JS_EXN_TYPE>, <FORMAT_STRING>)
* MSG_DEF(<SYMBOLIC_NAME>, <ARGUMENT_COUNT>, <CONTEXT_ARG>, <JS_EXN_TYPE>, <FORMAT_STRING>)
*
* where
*
@ -14,6 +14,13 @@
* <ARGUMENT_COUNT> is an integer literal specifying the total number of
* replaceable arguments in the following format string.
*
* <CONTEXT_ARG> is a boolean indicating whether the first arg should be
* replaced with the context string describing what's throwing the exception,
* if there is such a context. If false, there should be no such replacement.
* If true and there is no context, the first arg will be the empty string.
* That means that a true value here implies the string should begin with {0}
* with no space after it.
*
* <JS_EXN_TYPE> is a JSExnType which specifies which kind of error the JS
* engine should throw.
*
@ -22,71 +29,74 @@
* be replaced with a string value when the error is reported.
*/
MSG_DEF(MSG_INVALID_ENUM_VALUE, 3, JSEXN_TYPEERR, "{0} '{1}' is not a valid value for enumeration {2}.")
MSG_DEF(MSG_INVALID_OVERLOAD_ARGCOUNT, 2, JSEXN_TYPEERR, "{1} is not a valid argument count for any overload of {0}.")
MSG_DEF(MSG_NOT_OBJECT, 1, JSEXN_TYPEERR, "{0} is not an object.")
MSG_DEF(MSG_NOT_CALLABLE, 1, JSEXN_TYPEERR, "{0} is not callable.")
MSG_DEF(MSG_NOT_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} is not a constructor.")
MSG_DEF(MSG_DOES_NOT_IMPLEMENT_INTERFACE, 2, JSEXN_TYPEERR, "{0} does not implement interface {1}.")
MSG_DEF(MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 2, JSEXN_TYPEERR, "'{0}' called on an object that does not implement interface {1}.")
MSG_DEF(MSG_NOT_IN_UNION, 2, JSEXN_TYPEERR, "{0} could not be converted to any of: {1}.")
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Illegal constructor.")
MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, JSEXN_TYPEERR, "Constructor {0} requires 'new'")
MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, JSEXN_TYPEERR, "Non-finite value is out of range for {0}.")
MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "Value is out of range for {0}.")
MSG_DEF(MSG_NOT_SEQUENCE, 1, JSEXN_TYPEERR, "{0} can't be converted to a sequence.")
MSG_DEF(MSG_NOT_DICTIONARY, 1, JSEXN_TYPEERR, "{0} can't be converted to a dictionary.")
MSG_DEF(MSG_OVERLOAD_RESOLUTION_FAILED, 3, JSEXN_TYPEERR, "Argument {0} is not valid for any of the {1}-argument overloads of {2}.")
MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, JSEXN_RANGEERR, "The given encoding '{0}' is not supported.")
MSG_DEF(MSG_DOM_DECODING_FAILED, 0, JSEXN_TYPEERR, "Decoding failed.")
MSG_DEF(MSG_NOT_FINITE, 1, JSEXN_TYPEERR, "{0} is not a finite floating-point value.")
MSG_DEF(MSG_INVALID_BYTESTRING, 2, JSEXN_TYPEERR, "Cannot convert string to ByteString because the character"
MSG_DEF(MSG_INVALID_ENUM_VALUE, 3, false, JSEXN_TYPEERR, "{0} '{1}' is not a valid value for enumeration {2}.")
MSG_DEF(MSG_INVALID_OVERLOAD_ARGCOUNT, 2, false, JSEXN_TYPEERR, "{1} is not a valid argument count for any overload of {0}.")
MSG_DEF(MSG_NOT_OBJECT, 1, false, JSEXN_TYPEERR, "{0} is not an object.")
MSG_DEF(MSG_NOT_CALLABLE, 1, false, JSEXN_TYPEERR, "{0} is not callable.")
MSG_DEF(MSG_NOT_CONSTRUCTOR, 1, false, JSEXN_TYPEERR, "{0} is not a constructor.")
MSG_DEF(MSG_DOES_NOT_IMPLEMENT_INTERFACE, 2, false, JSEXN_TYPEERR, "{0} does not implement interface {1}.")
MSG_DEF(MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 2, false, JSEXN_TYPEERR, "'{0}' called on an object that does not implement interface {1}.")
MSG_DEF(MSG_NOT_IN_UNION, 2, false, JSEXN_TYPEERR, "{0} could not be converted to any of: {1}.")
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 1, true, JSEXN_TYPEERR, "{0}Illegal constructor.")
MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, false, JSEXN_TYPEERR, "{0} constructor: 'new' is required")
// It would be nice to give MSG_ENFORCE_RANGE_NON_FINITE a context, but it's
// not used with ErrorResult.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1613753 tracks threading the
// context through to it in a useful way.
MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, false, JSEXN_TYPEERR, "Non-finite value is out of range for {0}.")
MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 2, true, JSEXN_TYPEERR, "{0}Value is out of range for {1}.")
MSG_DEF(MSG_NOT_SEQUENCE, 1, false, JSEXN_TYPEERR, "{0} can't be converted to a sequence.")
MSG_DEF(MSG_NOT_DICTIONARY, 1, false, JSEXN_TYPEERR, "{0} can't be converted to a dictionary.")
MSG_DEF(MSG_OVERLOAD_RESOLUTION_FAILED, 3, false, JSEXN_TYPEERR, "Argument {0} is not valid for any of the {1}-argument overloads of {2}.")
MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 2, true, JSEXN_RANGEERR, "{0}The given encoding '{1}' is not supported.")
MSG_DEF(MSG_DOM_DECODING_FAILED, 1, true, JSEXN_TYPEERR, "{0}Decoding failed.")
MSG_DEF(MSG_NOT_FINITE, 1, false, JSEXN_TYPEERR, "{0} is not a finite floating-point value.")
// It would be nice to give MSG_INVALID_BYTESTRING a context, but it's not used
// with ErrorResult. https://bugzilla.mozilla.org/show_bug.cgi?id=1613755
// tracks threading the context through to the uses.
MSG_DEF(MSG_INVALID_BYTESTRING, 2, false, JSEXN_TYPEERR, "Cannot convert string to ByteString because the character"
" at index {0} has value {1} which is greater than 255.")
MSG_DEF(MSG_INVALID_URL, 1, JSEXN_TYPEERR, "{0} is not a valid URL.")
MSG_DEF(MSG_URL_HAS_CREDENTIALS, 1, JSEXN_TYPEERR, "{0} is an url with embedded credentials.")
MSG_DEF(MSG_INVALID_HEADER_NAME, 1, JSEXN_TYPEERR, "{0} is an invalid header name.")
MSG_DEF(MSG_INVALID_HEADER_VALUE, 1, JSEXN_TYPEERR, "{0} is an invalid header value.")
MSG_DEF(MSG_PERMISSION_DENIED_TO_PASS_ARG, 1, JSEXN_TYPEERR, "Permission denied to pass cross-origin object as {0}.")
MSG_DEF(MSG_MISSING_REQUIRED_DICTIONARY_MEMBER, 1, JSEXN_TYPEERR, "Missing required {0}.")
MSG_DEF(MSG_INVALID_REQUEST_METHOD, 1, JSEXN_TYPEERR, "Invalid request method {0}.")
MSG_DEF(MSG_INVALID_REQUEST_MODE, 1, JSEXN_TYPEERR, "Invalid request mode {0}.")
MSG_DEF(MSG_INVALID_REFERRER_URL, 1, JSEXN_TYPEERR, "Invalid referrer URL {0}.")
MSG_DEF(MSG_CROSS_ORIGIN_REFERRER_URL, 2, JSEXN_TYPEERR, "Referrer URL {0} cannot be cross-origin to the entry settings object ({1}).")
MSG_DEF(MSG_FETCH_BODY_CONSUMED_ERROR, 0, JSEXN_TYPEERR, "Body has already been consumed.")
MSG_DEF(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR, 0, JSEXN_TYPEERR, "Response statusText may not contain newline or carriage return.")
MSG_DEF(MSG_FETCH_FAILED, 0, JSEXN_TYPEERR, "NetworkError when attempting to fetch resource.")
MSG_DEF(MSG_INVALID_ZOOMANDPAN_VALUE_ERROR, 0, JSEXN_RANGEERR, "Invalid zoom and pan value.")
MSG_DEF(MSG_INVALID_TRANSFORM_ANGLE_ERROR, 0, JSEXN_RANGEERR, "Invalid transform angle.")
MSG_DEF(MSG_INVALID_URL_SCHEME, 2, JSEXN_TYPEERR, "{0} URL {1} must be either http:// or https://.")
MSG_DEF(MSG_BAD_FORMDATA, 0, JSEXN_TYPEERR, "Could not parse content as FormData.")
MSG_DEF(MSG_NO_ACTIVE_WORKER, 1, JSEXN_TYPEERR, "No active worker for scope {0}.")
MSG_DEF(MSG_INVALID_SCOPE, 2, JSEXN_TYPEERR, "Invalid scope trying to resolve {0} with base URL {1}.")
MSG_DEF(MSG_INVALID_KEYFRAME_OFFSETS, 0, JSEXN_TYPEERR, "Keyframes with specified offsets must be in order and all be in the range [0, 1].")
MSG_DEF(MSG_IS_NOT_PROMISE, 1, JSEXN_TYPEERR, "{0} is not a Promise")
MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a SharedArrayBuffer or an ArrayBufferView backed by a SharedArrayBuffer")
MSG_DEF(MSG_TYPEDARRAY_IS_DETACHED, 1, JSEXN_TYPEERR, "{0} can't be a detached buffer")
MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 3, JSEXN_TYPEERR, "Cache got {0} response with bad status {1} while trying to add request {2}")
MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0} because the registration has been {1} since the update was scheduled.")
MSG_DEF(MSG_INVALID_DURATION_ERROR, 1, JSEXN_TYPEERR, "Invalid duration '{0}'.")
MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN_TYPEERR, "Useless {0} call (missing quotes around argument?)")
MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "{0} is outside the supported range for time values.")
MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].")
MSG_DEF(MSG_MATRIX_INIT_CONFLICTING_VALUE, 2, JSEXN_TYPEERR, "Matrix init unexpectedly got different values for '{0}' and '{1}'.")
MSG_DEF(MSG_MATRIX_INIT_EXCEEDS_2D, 1, JSEXN_TYPEERR, "Matrix init has an unexpected 3D element '{0}' which cannot coexist with 'is2D: true'.")
MSG_DEF(MSG_MATRIX_INIT_LENGTH_WRONG, 1, JSEXN_TYPEERR, "Matrix init sequence must have a length of 6 or 16 (actual value: {0})")
MSG_DEF(MSG_INVALID_MEDIA_VIDEO_CONFIGURATION, 0, JSEXN_TYPEERR, "Invalid VideoConfiguration.")
MSG_DEF(MSG_INVALID_MEDIA_AUDIO_CONFIGURATION, 0, JSEXN_TYPEERR, "Invalid AudioConfiguration.")
MSG_DEF(MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR, 0, JSEXN_RANGEERR, "The start time for an AudioParam method must be non-negative.")
MSG_DEF(MSG_INVALID_AUDIOPARAM_METHOD_END_TIME_ERROR, 0, JSEXN_RANGEERR, "The end time for an AudioParam method must be non-negative.")
MSG_DEF(MSG_VALUE_OUT_OF_RANGE, 1, JSEXN_RANGEERR, "The value for the {0} is outside the valid range.")
MSG_DEF(MSG_NOT_ARRAY_NOR_UNDEFINED, 1, JSEXN_TYPEERR, "{0} is neither an array nor undefined.")
MSG_DEF(MSG_URL_NOT_LOADABLE, 1, JSEXN_TYPEERR, "Access to '{0}' from script denied.")
MSG_DEF(MSG_ONE_OFF_TYPEERR, 1, JSEXN_TYPEERR, "{0}")
MSG_DEF(MSG_ONE_OFF_RANGEERR, 1, JSEXN_RANGEERR, "{0}")
MSG_DEF(MSG_NO_CODECS_PARAMETER, 1, JSEXN_TYPEERR, "The provided type '{0}' does not have a 'codecs' parameter.")
MSG_DEF(MSG_NOT_SUBMIT_BUTTON, 0, JSEXN_TYPEERR, "The submitter is not a submit button.")
MSG_DEF(MSG_INVALID_URL, 2, true, JSEXN_TYPEERR, "{0}{1} is not a valid URL.")
MSG_DEF(MSG_URL_HAS_CREDENTIALS, 2, true, JSEXN_TYPEERR, "{0}{1} is an url with embedded credentials.")
MSG_DEF(MSG_INVALID_HEADER_NAME, 2, true, JSEXN_TYPEERR, "{0}{1} is an invalid header name.")
MSG_DEF(MSG_INVALID_HEADER_VALUE, 2, true, JSEXN_TYPEERR, "{0}{1} is an invalid header value.")
MSG_DEF(MSG_PERMISSION_DENIED_TO_PASS_ARG, 1, false, JSEXN_TYPEERR, "Permission denied to pass cross-origin object as {0}.")
MSG_DEF(MSG_MISSING_REQUIRED_DICTIONARY_MEMBER, 1, false, JSEXN_TYPEERR, "Missing required {0}.")
MSG_DEF(MSG_INVALID_REQUEST_METHOD, 2, true, JSEXN_TYPEERR, "{0}Invalid request method {1}.")
MSG_DEF(MSG_INVALID_REQUEST_MODE, 2, true, JSEXN_TYPEERR, "{0}Invalid request mode {1}.")
MSG_DEF(MSG_INVALID_REFERRER_URL, 2, true, JSEXN_TYPEERR, "{0}Invalid referrer URL {1}.")
MSG_DEF(MSG_FETCH_BODY_CONSUMED_ERROR, 1, true, JSEXN_TYPEERR, "{0}Body has already been consumed.")
MSG_DEF(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR, 1, true, JSEXN_TYPEERR, "{0}Response statusText may not contain newline or carriage return.")
MSG_DEF(MSG_FETCH_FAILED, 1, true, JSEXN_TYPEERR, "{0}NetworkError when attempting to fetch resource.")
MSG_DEF(MSG_INVALID_ZOOMANDPAN_VALUE_ERROR, 1, true, JSEXN_RANGEERR, "{0}Invalid zoom and pan value.")
MSG_DEF(MSG_INVALID_TRANSFORM_ANGLE_ERROR, 1, true, JSEXN_RANGEERR, "{0}Invalid transform angle.")
MSG_DEF(MSG_INVALID_URL_SCHEME, 3, true, JSEXN_TYPEERR, "{0}{1} URL {2} must be either http:// or https://.")
MSG_DEF(MSG_BAD_FORMDATA, 1, true, JSEXN_TYPEERR, "{0}Could not parse content as FormData.")
MSG_DEF(MSG_NO_ACTIVE_WORKER, 2, true, JSEXN_TYPEERR, "{0}No active worker for scope {1}.")
MSG_DEF(MSG_INVALID_SCOPE, 3, true, JSEXN_TYPEERR, "{0}Invalid scope trying to resolve {1} with base URL {2}.")
MSG_DEF(MSG_INVALID_KEYFRAME_OFFSETS, 1, true, JSEXN_TYPEERR, "{0}Keyframes with specified offsets must be in order and all be in the range [0, 1].")
MSG_DEF(MSG_IS_NOT_PROMISE, 1, true, JSEXN_TYPEERR, "{0}Argument is not a Promise")
MSG_DEF(MSG_SW_INSTALL_ERROR, 3, true, JSEXN_TYPEERR, "{0}ServiceWorker script at {1} for scope {2} encountered an error during installation.")
MSG_DEF(MSG_SW_SCRIPT_THREW, 3, true, JSEXN_TYPEERR, "{0}ServiceWorker script at {1} for scope {2} threw an exception during script evaluation.")
MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, false, JSEXN_TYPEERR, "{0} can't be a SharedArrayBuffer or an ArrayBufferView backed by a SharedArrayBuffer")
MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 4, true, JSEXN_TYPEERR, "{0}Cache got {1} response with bad status {2} while trying to add request {3}")
MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 3, true, JSEXN_TYPEERR, "{0}Failed to update the ServiceWorker for scope {1} because the registration has been {2} since the update was scheduled.")
MSG_DEF(MSG_INVALID_DURATION_ERROR, 2, true, JSEXN_TYPEERR, "{0}Invalid duration '{1}'.")
MSG_DEF(MSG_INVALID_EASING_ERROR, 2, true, JSEXN_TYPEERR, "{0}Invalid easing '{1}'.")
MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 3, true, JSEXN_TYPEERR, "{0}{1} attribute of <{2}> does not define any supported tokens")
MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 2, true, JSEXN_TYPEERR, "{0}{1} is outside the supported range for time values.")
MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 2, true, JSEXN_TYPEERR, "{0}Request mode '{1}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 1, true, JSEXN_RANGEERR, "{0}Threshold values must all be in the range [0, 1].")
MSG_DEF(MSG_MATRIX_INIT_CONFLICTING_VALUE, 3, true, JSEXN_TYPEERR, "{0}Matrix init unexpectedly got different values for '{1}' and '{2}'.")
MSG_DEF(MSG_MATRIX_INIT_EXCEEDS_2D, 2, true, JSEXN_TYPEERR, "{0}Matrix init has an unexpected 3D element '{1}' which cannot coexist with 'is2D: true'.")
MSG_DEF(MSG_MATRIX_INIT_LENGTH_WRONG, 2, true, JSEXN_TYPEERR, "{0}Matrix init sequence must have a length of 6 or 16 (actual value: {1})")
MSG_DEF(MSG_INVALID_MEDIA_VIDEO_CONFIGURATION, 1, true, JSEXN_TYPEERR, "{0}Invalid VideoConfiguration.")
MSG_DEF(MSG_INVALID_MEDIA_AUDIO_CONFIGURATION, 1, true, JSEXN_TYPEERR, "{0}Invalid AudioConfiguration.")
MSG_DEF(MSG_INVALID_AUDIOPARAM_METHOD_START_TIME_ERROR, 1, true, JSEXN_RANGEERR, "{0}The start time for an AudioParam method must be non-negative.")
MSG_DEF(MSG_INVALID_AUDIOPARAM_METHOD_END_TIME_ERROR, 1, true, JSEXN_RANGEERR, "{0}The end time for an AudioParam method must be non-negative.")
MSG_DEF(MSG_VALUE_OUT_OF_RANGE, 2, true, JSEXN_RANGEERR, "{0}The value for the {1} is outside the valid range.")
MSG_DEF(MSG_NOT_ARRAY_NOR_UNDEFINED, 2, true, JSEXN_TYPEERR, "{0}{1} is neither an array nor undefined.")
MSG_DEF(MSG_URL_NOT_LOADABLE, 2, true, JSEXN_TYPEERR, "{0}Access to '{1}' from script denied.")
MSG_DEF(MSG_ONE_OFF_TYPEERR, 2, true, JSEXN_TYPEERR, "{0}{1}")
MSG_DEF(MSG_ONE_OFF_RANGEERR, 2, true, JSEXN_RANGEERR, "{0}{1}")
MSG_DEF(MSG_NO_CODECS_PARAMETER, 2, true, JSEXN_TYPEERR, "{0}The provided type '{1}' does not have a 'codecs' parameter.")

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

@ -207,8 +207,9 @@ inline bool PrimitiveConversionTraits_EnforceRange(JSContext* cx,
rounded = neg ? -rounded : rounded;
if (rounded < PrimitiveConversionTraits_Limits<T>::min() ||
rounded > PrimitiveConversionTraits_Limits<T>::max()) {
// XXXbz a better context (first arg after cx) would sure be nice.
return ThrowErrorMessage<MSG_ENFORCE_RANGE_OUT_OF_RANGE>(
cx, TypeName<T>::value());
cx, "", TypeName<T>::value());
}
*retval = static_cast<T>(rounded);

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

@ -159,7 +159,9 @@ function testConstructorFatalOption(data, expectedString) {
function testConstructorEncodingOption(aData, aExpectedString) {
function errorMessage(encoding) {
return `The given encoding '${String(encoding).trim()}' is not supported.`;
return `TextDecoder constructor: The given encoding '${String(
encoding
).trim()}' is not supported.`;
}
// valid encoding passed

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

@ -301,7 +301,7 @@ void HTMLFormElement::RequestSubmit(nsGenericHTMLElement* aSubmitter,
// 1.1. If submitter is not a submit button, then throw a TypeError.
if (!fc || !fc->IsSubmitControl()) {
aRv.ThrowTypeError<MSG_NOT_SUBMIT_BUTTON>();
aRv.ThrowTypeError(u"The submitter is not a submit button.");
return;
}

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

@ -15,7 +15,7 @@
const name = window.location.pathname;
var testString = "Lorem ipsum his ponderum delicatissimi ne, at noster dolores urbanitas pro, cibo elaboraret no his. Ea dicunt maiorum usu. Ad appareat facilisis mediocritatem eos. Tale graeci mentitum in eos, hinc insolens at nam. Graecis nominavi aliquyam eu vix. Id solet assentior sadipscing pro. Et per atqui graecis, usu quot viris repudiandae ei, mollis evertitur an nam. At nam dolor ignota, liber labore omnesque ea mei, has movet voluptaria in. Vel an impetus omittantur. Vim movet option salutandi ex, ne mei ignota corrumpit. Mucius comprehensam id per. Est ea putant maiestatis.";
var typeErrString = "TypeError: Data size for read is too large.";
var typeErrMessage = "Data size for read is too large.";
var uint32Max = 0xFFFFFFFF;
for (let i = 0; i < 5; i++) {
@ -64,7 +64,9 @@
ok(false, "Should have thrown!");
} catch (e) {
ok(e instanceof TypeError, "Got TypeError");
ok(e == typeErrString, "Correct error string");
is(e.name, "TypeError", "Correct error name");
is(e.message, "IDBFileHandle.readAsText: " + typeErrMessage,
"Correct error mesage");
}
let resultString = event.target.result;
@ -87,7 +89,9 @@
ok(false, "Should have thrown!");
} catch (e) {
ok(e instanceof TypeError, "Got TypeError");
ok(e == typeErrString, "Correct error string");
is(e.name, "TypeError", "Correct error name");
is(e.message, "IDBFileHandle.readAsArrayBuffer: " + typeErrMessage,
"Correct error message");
}
let resultBuffer = event.target.result;

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

@ -112,7 +112,8 @@ already_AddRefed<Promise> MediaCapabilities::DecodingInfo(
if (!aConfiguration.mVideo.WasPassed() &&
!aConfiguration.mAudio.WasPassed()) {
aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
NS_LITERAL_STRING("'audio' or 'video'"));
NS_LITERAL_STRING("'audio' or 'video' member of argument of "
"MediaCapabilities.decodingInfo"));
return nullptr;
}
@ -458,7 +459,8 @@ already_AddRefed<Promise> MediaCapabilities::EncodingInfo(
if (!aConfiguration.mVideo.WasPassed() &&
!aConfiguration.mAudio.WasPassed()) {
aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
NS_LITERAL_STRING("'audio' or 'video'"));
NS_LITERAL_STRING("'audio' or 'video' member of argument of "
"MediaCapabilities.encodingInfo"));
return nullptr;
}

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

@ -606,8 +606,7 @@ already_AddRefed<Promise> AudioContext::DecodeAudioData(
if (!aBuffer.Data()) {
// Throw if the buffer is detached
aRv.ThrowTypeError<MSG_TYPEDARRAY_IS_DETACHED>(
NS_LITERAL_STRING("Argument of AudioContext.decodeAudioData"));
aRv.ThrowTypeError(u"Buffer argument can't be a detached buffer");
return nullptr;
}

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

@ -145,9 +145,8 @@ void AudioWorkletGlobalScope::RegisterProcessor(
}
if (!descriptors.isUndefined() && !isArray) {
aRv.ThrowTypeError<MSG_NOT_ARRAY_NOR_UNDEFINED>(NS_LITERAL_STRING(
"Argument 2 of AudioWorkletGlobalScope.registerProcessor "
"constructor.parameterDescriptors"));
aRv.ThrowTypeError<MSG_NOT_ARRAY_NOR_UNDEFINED>(
NS_LITERAL_STRING(".constructor.parameterDescriptors of argument 2"));
return;
}

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

@ -24,7 +24,7 @@ var testDecodeAudioDataOnDetachedBuffer = function(buffer) {
SimpleTest.finish();
}, function(r) {
SimpleTest.isa(r, TypeError);
is(r.message, "Argument of AudioContext.decodeAudioData can't be a detached buffer", "Incorrect message");
is(r.message, "BaseAudioContext.decodeAudioData: Buffer argument can't be a detached buffer", "Incorrect message");
SimpleTest.finish();
});
};
@ -47,4 +47,4 @@ addLoadEvent(function() {
</script>
</pre>
</body>
</html>
</html>

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

@ -78,8 +78,7 @@ void PromiseDebugging::GetState(GlobalObject& aGlobal,
// CheckedUnwrapStatic is fine, since we're looking for promises only.
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrapStatic(aPromise));
if (!obj || !JS::IsPromiseObject(obj)) {
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(
NS_LITERAL_STRING("Argument of PromiseDebugging.getState"));
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>();
return;
}
switch (JS::GetPromiseState(obj)) {
@ -105,8 +104,7 @@ void PromiseDebugging::GetPromiseID(GlobalObject& aGlobal,
// CheckedUnwrapStatic is fine, since we're looking for promises only.
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrapStatic(aPromise));
if (!obj || !JS::IsPromiseObject(obj)) {
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(
NS_LITERAL_STRING("Argument of PromiseDebugging.getState"));
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>();
return;
}
uint64_t promiseID = JS::GetPromiseID(obj);
@ -123,8 +121,7 @@ void PromiseDebugging::GetAllocationStack(GlobalObject& aGlobal,
// CheckedUnwrapStatic is fine, since we're looking for promises only.
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrapStatic(aPromise));
if (!obj || !JS::IsPromiseObject(obj)) {
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(
NS_LITERAL_STRING("Argument of PromiseDebugging.getAllocationStack"));
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>();
return;
}
aStack.set(JS::GetPromiseAllocationSite(obj));
@ -139,8 +136,7 @@ void PromiseDebugging::GetRejectionStack(GlobalObject& aGlobal,
// CheckedUnwrapStatic is fine, since we're looking for promises only.
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrapStatic(aPromise));
if (!obj || !JS::IsPromiseObject(obj)) {
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(
NS_LITERAL_STRING("Argument of PromiseDebugging.getRejectionStack"));
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>();
return;
}
aStack.set(JS::GetPromiseResolutionSite(obj));
@ -155,8 +151,7 @@ void PromiseDebugging::GetFullfillmentStack(GlobalObject& aGlobal,
// CheckedUnwrapStatic is fine, since we're looking for promises only.
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrapStatic(aPromise));
if (!obj || !JS::IsPromiseObject(obj)) {
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(
NS_LITERAL_STRING("Argument of PromiseDebugging.getFulfillmentStack"));
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>();
return;
}
aStack.set(JS::GetPromiseResolutionSite(obj));

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

@ -16,7 +16,7 @@ function configureTest() {
"TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor is not a constructor.",
"NotSupportedError: AudioWorkletGlobalScope.registerProcessor: Argument 1 should not be an empty string.",
"TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor is not an object.",
"TypeError: Argument 2 of AudioWorkletGlobalScope.registerProcessor constructor.parameterDescriptors is neither an array nor undefined.",
"TypeError: AudioWorkletGlobalScope.registerProcessor: .constructor.parameterDescriptors of argument 2 is neither an array nor undefined.",
"NotSupportedError: AudioWorkletGlobalScope.registerProcessor: Argument 1 is invalid: a class with the same name is already registered.",
"TypeError: Missing required 'name' member of AudioParamDescriptor.",
"TypeError: 'defaultValue' member of AudioParamDescriptor is not a finite floating-point value.",

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

@ -218,7 +218,7 @@ add_task(async function test_fetch_nonexistent() {
add_task(async function test_error_cases() {
Assert.throws(
() => PlacesUtils.history.fetch("3"),
/TypeError: 3 is not a valid /
/TypeError: URL constructor: 3 is not a valid /
);
Assert.throws(
() => PlacesUtils.history.fetch({ not: "a valid string or guid" }),

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

@ -1974,11 +1974,11 @@ add_task(async function test_invalid_uri_spec_throws() {
);
Assert.throws(
() => PT.Tag({ tag: "TheTag", urls: ["invalid uri spec"] }),
/TypeError: invalid uri spec is not a valid URL/
/TypeError: URL constructor: invalid uri spec is not a valid URL/
);
Assert.throws(
() => PT.Tag({ tag: "TheTag", urls: ["about:blank", "invalid uri spec"] }),
/TypeError: invalid uri spec is not a valid URL/
/TypeError: URL constructor: invalid uri spec is not a valid URL/
);
});