Bug 1581173 part 1. Add a way to more easily throw TypeErrors and RangeErrors with custom message strings via ErrorResult. r=smaug

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Zbarsky 2019-09-20 02:19:18 +00:00
Родитель a2cb1e7480
Коммит e26682d684
16 изменённых файлов: 68 добавлений и 51 удалений

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

@ -148,7 +148,8 @@ bool WindowNamedPropertiesHandler::defineProperty(
JS::Handle<JS::PropertyDescriptor> aDesc,
JS::ObjectOpResult& result) const {
ErrorResult rv;
rv.ThrowTypeError<MSG_DEFINEPROPERTY_ON_GSP>();
rv.ThrowTypeError(
u"Not allowed to define a property on the named properties object.");
MOZ_ALWAYS_TRUE(rv.MaybeSetPendingException(aCx));
return false;
}

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

@ -287,12 +287,38 @@ class TErrorResult {
std::forward<Ts>(messageArgs)...);
}
// To be used when throwing a TypeError with a completely custom
// message string that's only used in one spot.
inline void ThrowTypeError(const nsAString& aMessage) {
this->template ThrowTypeError<dom::MSG_ONE_OFF_TYPEERR>(aMessage);
}
// To be used when throwing a TypeError with a completely custom
// message string that's a string literal that's only used in one spot.
template <int N>
void ThrowTypeError(const char16_t (&aMessage)[N]) {
ThrowTypeError(nsLiteralString(aMessage));
}
template <dom::ErrNum errorNumber, typename... Ts>
void ThrowRangeError(Ts&&... messageArgs) {
ThrowErrorWithMessage<errorNumber>(NS_ERROR_INTERNAL_ERRORRESULT_RANGEERROR,
std::forward<Ts>(messageArgs)...);
}
// To be used when throwing a RangeError with a completely custom
// message string that's only used in one spot.
inline void ThrowRangeError(const nsAString& aMessage) {
this->template ThrowRangeError<dom::MSG_ONE_OFF_RANGEERR>(aMessage);
}
// To be used when throwing a RangeError with a completely custom
// message string that's a string literal that's only used in one spot.
template <int N>
void ThrowRangeError(const char16_t (&aMessage)[N]) {
ThrowRangeError(nsLiteralString(aMessage));
}
bool IsErrorWithMessage() const {
return ErrorCode() == NS_ERROR_INTERNAL_ERRORRESULT_TYPEERROR ||
ErrorCode() == NS_ERROR_INTERNAL_ERRORRESULT_RANGEERROR;

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

@ -40,28 +40,18 @@ MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "Value is out of range
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_GLOBAL_NOT_NATIVE, 0, JSEXN_TYPEERR, "Global is not a native object.")
MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, JSEXN_RANGEERR, "The given encoding '{0}' is not supported.")
MSG_DEF(MSG_DOM_ENCODING_NOT_UTF, 0, JSEXN_RANGEERR, "The encoding must be utf-8, utf-16, or utf-16be.")
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_VERSION, 0, JSEXN_TYPEERR, "0 (Zero) is not a valid database version.")
MSG_DEF(MSG_INVALID_BYTESTRING, 2, JSEXN_TYPEERR, "Cannot convert string to ByteString because the character"
" at index {0} has value {1} which is greater than 255.")
MSG_DEF(MSG_NOT_DATE, 1, JSEXN_TYPEERR, "{0} is not a date.")
MSG_DEF(MSG_INVALID_ADVANCE_COUNT, 0, JSEXN_TYPEERR, "0 (Zero) is not a valid advance count.")
MSG_DEF(MSG_DEFINEPROPERTY_ON_GSP, 0, JSEXN_TYPEERR, "Not allowed to define a property on the named properties object.")
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_METADATA_NOT_CONFIGURED, 0, JSEXN_TYPEERR, "Either size or lastModified should be true.")
MSG_DEF(MSG_INVALID_READ_SIZE, 0, JSEXN_TYPEERR, "0 (Zero) is not a valid read size.")
MSG_DEF(MSG_HEADERS_IMMUTABLE, 0, JSEXN_TYPEERR, "Headers are immutable and cannot be modified.")
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_INVALID_HEADER_SEQUENCE, 0, JSEXN_TYPEERR, "Headers require name/value tuples when being initialized by a sequence.")
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_REQUEST_INTEGRITY_METADATA_NOT_EMPTY, 0, JSEXN_TYPEERR, "Request integrity metadata should be an empty string when in no-cors mode.")
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}.")
@ -69,20 +59,11 @@ MSG_DEF(MSG_CROSS_ORIGIN_REFERRER_URL, 2, JSEXN_TYPEERR, "Referrer URL {0} canno
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_NO_BODY_ALLOWED_FOR_GET_AND_HEAD, 0, JSEXN_TYPEERR, "HEAD or GET Request cannot have a body.")
MSG_DEF(MSG_RESPONSE_NULL_STATUS_WITH_BODY, 0, JSEXN_TYPEERR, "Response body is given with a null body status.")
MSG_DEF(MSG_DEFINE_NON_CONFIGURABLE_PROP_ON_WINDOW, 0, JSEXN_TYPEERR, "Not allowed to define a non-configurable property on the WindowProxy object")
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_RESPONSE_STATUSCODE_ERROR, 0, JSEXN_RANGEERR, "Invalid response status code.")
MSG_DEF(MSG_INVALID_REDIRECT_STATUSCODE_ERROR, 0, JSEXN_RANGEERR, "Invalid redirect status code.")
MSG_DEF(MSG_INVALID_URL_SCHEME, 2, JSEXN_TYPEERR, "{0} URL {1} must be either http:// or https://.")
MSG_DEF(MSG_RESPONSE_URL_IS_NULL, 0, JSEXN_TYPEERR, "Cannot set Response.finalURL when Response.url is null.")
MSG_DEF(MSG_RESPONSE_HAS_VARY_STAR, 0, JSEXN_TYPEERR, "Invalid Response object with a 'Vary: *' header.")
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_NOTIFICATION_PERMISSION_DENIED, 0, JSEXN_TYPEERR, "Permission to show Notification denied.")
MSG_DEF(MSG_NOTIFICATION_NO_CONSTRUCTOR_IN_SERVICEWORKER, 0, JSEXN_TYPEERR, "Notification constructor cannot be used in ServiceWorkerGlobalScope. Use registration.showNotification() instead.")
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")
@ -96,25 +77,18 @@ 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_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.")
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_WORKER_THREAD_SHUTTING_DOWN, 0, JSEXN_TYPEERR, "The Worker thread is shutting down.")
MSG_DEF(MSG_CACHE_OPEN_FAILED, 0, JSEXN_TYPEERR, "CacheStorage.open() failed to access the storage system.")
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_CURVE_DURATION_ERROR, 0, JSEXN_RANGEERR, "The curve duration for setValueCurveAtTime must be strictly positive.")
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_INVALID_AUDIOPARAM_EXPONENTIAL_VALUE_ERROR, 0, JSEXN_RANGEERR, "The value passed to exponentialRampToValueAtTime must be positive.")
MSG_DEF(MSG_INVALID_AUDIOPARAM_EXPONENTIAL_CONSTANT_ERROR, 0, JSEXN_RANGEERR, "The exponential constant passed to setTargetAtTime 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_INVALID_PANNERNODE_REFDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The refDistance value passed to PannerNode must not be negative.")
MSG_DEF(MSG_INVALID_PANNERNODE_MAXDISTANCE_ERROR, 0, JSEXN_RANGEERR, "The maxDistance value passed to PannerNode must be positive.")
MSG_DEF(MSG_INVALID_PANNERNODE_ROLLOFF_ERROR, 0, JSEXN_RANGEERR, "The rolloffFactor value passed to PannerNode must not be negative.")
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}")

3
dom/cache/CacheOpChild.cpp поставляемый
Просмотреть файл

@ -141,7 +141,8 @@ mozilla::ipc::IPCResult CacheOpChild::Recv__delete__(
MOZ_DIAGNOSTIC_ASSERT(actor);
if (!actor) {
ErrorResult status;
status.ThrowTypeError<MSG_CACHE_OPEN_FAILED>();
status.ThrowTypeError(
u"CacheStorage.open() failed to access the storage system.");
mPromise->MaybeReject(status);
break;
}

3
dom/cache/ReadStream.cpp поставляемый
Просмотреть файл

@ -208,7 +208,8 @@ void ReadStream::Inner::Serialize(
MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
if (mState != Open) {
aRv.ThrowTypeError<MSG_CACHE_STREAM_CLOSED>();
aRv.ThrowTypeError(
u"Response body is a cache file stream that has already been closed.");
return;
}

2
dom/cache/TypeUtils.cpp поставляемый
Просмотреть файл

@ -185,7 +185,7 @@ void TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut,
RefPtr<InternalHeaders> headers = aIn.UnfilteredHeaders();
MOZ_DIAGNOSTIC_ASSERT(headers);
if (HasVaryStar(headers)) {
aRv.ThrowTypeError<MSG_RESPONSE_HAS_VARY_STAR>();
aRv.ThrowTypeError(u"Invalid Response object with a 'Vary: *' header.");
return;
}
ToHeadersEntryList(aOut.headers(), headers);

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

@ -377,7 +377,7 @@ bool InternalHeaders::IsInvalidValue(const nsACString& aValue,
bool InternalHeaders::IsImmutable(ErrorResult& aRv) const {
if (mGuard == HeadersGuardEnum::Immutable) {
aRv.ThrowTypeError<MSG_HEADERS_IMMUTABLE>();
aRv.ThrowTypeError(u"Headers are immutable and cannot be modified.");
return true;
}
return false;
@ -418,7 +418,9 @@ void InternalHeaders::Fill(const Sequence<Sequence<nsCString>>& aInit,
for (uint32_t i = 0; i < aInit.Length() && !aRv.Failed(); ++i) {
const Sequence<nsCString>& tuple = aInit[i];
if (tuple.Length() != 2) {
aRv.ThrowTypeError<MSG_INVALID_HEADER_SEQUENCE>();
aRv.ThrowTypeError(
u"Headers require name/value tuples when being initialized by a "
u"sequence.");
return;
}
Append(tuple[0], tuple[1], aRv);

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

@ -541,7 +541,7 @@ already_AddRefed<Request> Request::Constructor(const GlobalObject& aGlobal,
request->GetMethod(method);
// method is guaranteed to be uppercase due to step 14.2 above.
if (method.EqualsLiteral("HEAD") || method.EqualsLiteral("GET")) {
aRv.ThrowTypeError<MSG_NO_BODY_ALLOWED_FOR_GET_AND_HEAD>();
aRv.ThrowTypeError(u"HEAD or GET Request cannot have a body.");
return nullptr;
}
}

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

@ -136,7 +136,7 @@ already_AddRefed<Response> Response::Redirect(const GlobalObject& aGlobal,
if (aStatus != 301 && aStatus != 302 && aStatus != 303 && aStatus != 307 &&
aStatus != 308) {
aRv.ThrowRangeError<MSG_INVALID_REDIRECT_STATUSCODE_ERROR>();
aRv.ThrowRangeError(u"Invalid redirect status code.");
return nullptr;
}
@ -175,7 +175,7 @@ already_AddRefed<Response> Response::Constructor(
}
if (aInit.mStatus < 200 || aInit.mStatus > 599) {
aRv.ThrowRangeError<MSG_INVALID_RESPONSE_STATUSCODE_ERROR>();
aRv.ThrowRangeError(u"Invalid response status code.");
return nullptr;
}
@ -263,7 +263,7 @@ already_AddRefed<Response> Response::Constructor(
if (!aBody.IsNull()) {
if (aInit.mStatus == 204 || aInit.mStatus == 205 || aInit.mStatus == 304) {
aRv.ThrowTypeError<MSG_RESPONSE_NULL_STATUS_WITH_BODY>();
aRv.ThrowTypeError(u"Response body is given with a null body status.");
return nullptr;
}

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

@ -570,7 +570,7 @@ void IDBCursor::Advance(uint32_t aCount, ErrorResult& aRv) {
AssertIsOnOwningThread();
if (!aCount) {
aRv.ThrowTypeError<MSG_INVALID_ADVANCE_COUNT>();
aRv.ThrowTypeError(u"0 (Zero) is not a valid advance count.");
return;
}

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

@ -631,7 +631,7 @@ already_AddRefed<IDBOpenDBRequest> IDBFactory::OpenInternal(
uint64_t version = 0;
if (!aDeleting && aVersion.WasPassed()) {
if (aVersion.Value() < 1) {
aRv.ThrowTypeError<MSG_INVALID_VERSION>();
aRv.ThrowTypeError(u"0 (Zero) is not a valid database version.");
return nullptr;
}
version = aVersion.Value();

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

@ -271,7 +271,7 @@ already_AddRefed<IDBFileRequest> IDBFileHandle::GetMetadata(
// Argument checking for get metadata.
if (!aParameters.mSize && !aParameters.mLastModified) {
aRv.ThrowTypeError<MSG_METADATA_NOT_CONFIGURED>();
aRv.ThrowTypeError(u"Either size or lastModified should be true.");
return nullptr;
}
@ -392,7 +392,7 @@ bool IDBFileHandle::CheckStateAndArgumentsForRead(uint64_t aSize,
// Argument checking for read
if (!aSize) {
aRv.ThrowTypeError<MSG_INVALID_READ_SIZE>();
aRv.ThrowTypeError(u"0 (Zero) is not a valid read size.");
return false;
}

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

@ -128,7 +128,9 @@ class AudioEventTimeline {
return false;
}
if (!WebAudioUtils::IsTimeValid(aEvent.mTimeConstant)) {
aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_EXPONENTIAL_CONSTANT_ERROR>();
aRv.ThrowRangeError(
u"The exponential constant passed to setTargetAtTime must be "
u"non-negative.");
return false;
}
@ -138,7 +140,9 @@ class AudioEventTimeline {
return false;
}
if (aEvent.mDuration <= 0) {
aRv.ThrowRangeError<MSG_INVALID_CURVE_DURATION_ERROR>();
aRv.ThrowRangeError(
u"The curve duration for setValueCurveAtTime must be strictly "
u"positive.");
return false;
}
}
@ -171,7 +175,9 @@ class AudioEventTimeline {
// Make sure that invalid values are not used for exponential curves
if (aEvent.mType == AudioTimelineEvent::ExponentialRamp) {
if (aEvent.mValue <= 0.f) {
aRv.ThrowRangeError<MSG_INVALID_AUDIOPARAM_EXPONENTIAL_VALUE_ERROR>();
aRv.ThrowRangeError(
u"The value passed to exponentialRampToValueAtTime must be "
u"positive.");
return false;
}
const AudioTimelineEvent* previousEvent =

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

@ -94,7 +94,8 @@ class PannerNode final : public AudioNode {
}
if (aRefDistance < 0) {
aRv.template ThrowRangeError<MSG_INVALID_PANNERNODE_REFDISTANCE_ERROR>();
aRv.ThrowRangeError(
u"The refDistance value passed to PannerNode must not be negative.");
return;
}
@ -109,7 +110,8 @@ class PannerNode final : public AudioNode {
}
if (aMaxDistance <= 0) {
aRv.template ThrowRangeError<MSG_INVALID_PANNERNODE_MAXDISTANCE_ERROR>();
aRv.ThrowRangeError(
u"The maxDistance value passed to PannerNode must be positive.");
return;
}
@ -124,7 +126,9 @@ class PannerNode final : public AudioNode {
}
if (aRolloffFactor < 0) {
aRv.template ThrowRangeError<MSG_INVALID_PANNERNODE_ROLLOFF_ERROR>();
aRv.ThrowRangeError(
u"The rolloffFactor value passed to PannerNode must not be "
u"negative.");
}
mRolloffFactor = aRolloffFactor;

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

@ -145,7 +145,7 @@ already_AddRefed<ConnectionWorker> ConnectionWorker::Create(
RefPtr<ConnectionWorker> c = new ConnectionWorker();
c->mProxy = ConnectionProxy::Create(aWorkerPrivate, c);
if (!c->mProxy) {
aRv.ThrowTypeError<MSG_WORKER_THREAD_SHUTTING_DOWN>();
aRv.ThrowTypeError(u"The Worker thread is shutting down.");
return nullptr;
}

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

@ -880,7 +880,9 @@ already_AddRefed<Notification> Notification::Constructor(
RefPtr<ServiceWorkerGlobalScope> scope;
UNWRAP_OBJECT(ServiceWorkerGlobalScope, aGlobal.Get(), scope);
if (scope) {
aRv.ThrowTypeError<MSG_NOTIFICATION_NO_CONSTRUCTOR_IN_SERVICEWORKER>();
aRv.ThrowTypeError(
u"Notification constructor cannot be used in ServiceWorkerGlobalScope. "
u"Use registration.showNotification() instead.");
return nullptr;
}
@ -2282,7 +2284,7 @@ already_AddRefed<Promise> Notification::ShowPersistentNotification(
if (NS_WARN_IF(aRv.Failed()) ||
permission == NotificationPermission::Denied) {
ErrorResult result;
result.ThrowTypeError<MSG_NOTIFICATION_PERMISSION_DENIED>();
result.ThrowTypeError(u"Permission to show Notification denied.");
p->MaybeReject(result);
return p.forget();
}