Skip to content

Commit 2dd6c5e

Browse files
emiliorvandermeulen
authored andcommitted
Bug 1986533 - Improve font face error reporting. r=layout-reviewers,firefox-style-system-reviewers,dshin a=RyanVM DONTBUILD
With this patch, something like: let ff = new FontFace("content:Segoe", "https://foo.com"); ff.load(); Generates an exception like: > Uncaught (in promise) DOMException: Invalid font descriptor font-family: content:Segoe Rather than the error in the bug.
1 parent 7e29dbd commit 2dd6c5e

File tree

5 files changed

+70
-44
lines changed

5 files changed

+70
-44
lines changed

layout/style/FontFace.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
#include "mozilla/dom/UnionTypes.h"
2525
#include "nsStyleUtil.h"
2626

27-
namespace mozilla {
28-
namespace dom {
27+
namespace mozilla::dom {
2928

3029
// -- Utility functions ------------------------------------------------------
3130

@@ -71,9 +70,7 @@ NS_INTERFACE_MAP_END
7170
NS_IMPL_CYCLE_COLLECTING_ADDREF(FontFace)
7271
NS_IMPL_CYCLE_COLLECTING_RELEASE(FontFace)
7372

74-
FontFace::FontFace(nsIGlobalObject* aParent) : mLoadedRejection(NS_OK) {
75-
BindToOwner(aParent);
76-
}
73+
FontFace::FontFace(nsIGlobalObject* aParent) { BindToOwner(aParent); }
7774

7875
FontFace::~FontFace() {
7976
// Assert that we don't drop any FontFace objects during a Servo traversal,
@@ -285,20 +282,29 @@ void FontFace::MaybeResolve() {
285282
mLoaded->MaybeResolve(this);
286283
}
287284

288-
void FontFace::MaybeReject(nsresult aResult) {
285+
void FontFace::MaybeReject(FontFaceLoadedRejectReason aReason,
286+
nsCString&& aMessage) {
289287
gfxFontUtils::AssertSafeThreadOrServoFontMetricsLocked();
290288

291289
if (ServoStyleSet* ss = gfxFontUtils::CurrentServoStyleSet()) {
292290
// See comments in Gecko_GetFontMetrics.
293-
ss->AppendTask(
294-
PostTraversalTask::RejectFontFaceLoadedPromise(this, aResult));
291+
ss->AppendTask(PostTraversalTask::RejectFontFaceLoadedPromise(
292+
this, aReason, std::move(aMessage)));
295293
return;
296294
}
297295

298296
if (mLoaded) {
299-
mLoaded->MaybeReject(aResult);
300-
} else if (mLoadedRejection == NS_OK) {
301-
mLoadedRejection = aResult;
297+
switch (aReason) {
298+
case FontFaceLoadedRejectReason::Network:
299+
mLoaded->MaybeRejectWithNetworkError(aMessage);
300+
break;
301+
case FontFaceLoadedRejectReason::Syntax:
302+
mLoaded->MaybeRejectWithSyntaxError(aMessage);
303+
break;
304+
}
305+
} else if (!mLoadedRejection) {
306+
mLoadedRejection = MakeUnique<FontFaceLoadedRejection>(
307+
FontFaceLoadedRejection{aReason, std::move(aMessage)});
302308
}
303309
}
304310

@@ -307,15 +313,14 @@ void FontFace::EnsurePromise() {
307313
return;
308314
}
309315

310-
ErrorResult rv;
311-
mLoaded = Promise::Create(GetOwnerGlobal(), rv);
316+
mLoaded = Promise::CreateInfallible(GetOwnerGlobal());
312317

313318
if (mImpl->Status() == FontFaceLoadStatus::Loaded) {
314319
mLoaded->MaybeResolve(this);
315-
} else if (mLoadedRejection != NS_OK) {
316-
mLoaded->MaybeReject(mLoadedRejection);
320+
} else if (mLoadedRejection) {
321+
auto rejection = std::move(mLoadedRejection);
322+
MaybeReject(rejection->mReason, std::move(rejection->mMessage));
317323
}
318324
}
319325

320-
} // namespace dom
321-
} // namespace mozilla
326+
} // namespace mozilla::dom

layout/style/FontFace.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ class FontFaceSet;
3030
class FontFaceSetImpl;
3131
class Promise;
3232
class UTF8StringOrArrayBufferOrArrayBufferView;
33-
} // namespace dom
34-
} // namespace mozilla
3533

36-
namespace mozilla::dom {
34+
enum class FontFaceLoadedRejectReason : uint8_t { Syntax, Network };
35+
struct FontFaceLoadedRejection {
36+
const FontFaceLoadedRejectReason mReason;
37+
nsCString mMessage;
38+
};
3739

3840
class FontFace final : public GlobalTeardownObserver, public nsWrapperCache {
3941
friend class mozilla::PostTraversalTask;
@@ -92,7 +94,8 @@ class FontFace final : public GlobalTeardownObserver, public nsWrapperCache {
9294

9395
void Destroy();
9496
void MaybeResolve();
95-
void MaybeReject(nsresult aResult);
97+
98+
void MaybeReject(FontFaceLoadedRejectReason, nsCString&& aRejectMessage);
9699

97100
private:
98101
explicit FontFace(nsIGlobalObject* aParent);
@@ -115,9 +118,10 @@ class FontFace final : public GlobalTeardownObserver, public nsWrapperCache {
115118
RefPtr<Promise> mLoaded;
116119

117120
// Saves the rejection code for mLoaded if mLoaded hasn't been created yet.
118-
nsresult mLoadedRejection;
121+
UniquePtr<FontFaceLoadedRejection> mLoadedRejection;
119122
};
120123

121-
} // namespace mozilla::dom
124+
} // namespace dom
125+
} // namespace mozilla
122126

123127
#endif // !defined(mozilla_dom_FontFace_h)

layout/style/FontFaceImpl.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
#include "mozilla/dom/FontFaceBinding.h"
1717
#include "mozilla/dom/FontFaceSetImpl.h"
1818

19-
namespace mozilla {
20-
namespace dom {
19+
namespace mozilla::dom {
2120

2221
// -- FontFaceBufferSource ---------------------------------------------------
2322

@@ -122,7 +121,9 @@ void FontFaceImpl::InitializeSourceURL(const nsACString& aURL) {
122121
IgnoredErrorResult rv;
123122
SetDescriptor(eCSSFontDesc_Src, aURL, rv);
124123
if (rv.Failed()) {
125-
mOwner->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
124+
mOwner->MaybeReject(FontFaceLoadedRejectReason::Syntax,
125+
nsPrintfCString("Invalid source url %s",
126+
PromiseFlatCString(aURL).get()));
126127
SetStatus(FontFaceLoadStatus::Error);
127128
}
128129
}
@@ -402,9 +403,10 @@ void FontFaceImpl::UpdateOwnerPromise() {
402403
mOwner->MaybeResolve();
403404
} else if (mStatus == FontFaceLoadStatus::Error) {
404405
if (mSourceType == eSourceType_Buffer) {
405-
mOwner->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
406+
mOwner->MaybeReject(FontFaceLoadedRejectReason::Syntax,
407+
nsCString("Invalid source buffer"_ns));
406408
} else {
407-
mOwner->MaybeReject(NS_ERROR_DOM_NETWORK_ERR);
409+
mOwner->MaybeReject(FontFaceLoadedRejectReason::Network, nsCString());
408410
}
409411
}
410412

@@ -443,7 +445,10 @@ bool FontFaceImpl::SetDescriptor(nsCSSFontDesc aFontDesc,
443445
bool changed;
444446
if (!Servo_FontFaceRule_SetDescriptor(GetData(), aFontDesc, &aValue, url,
445447
&changed)) {
446-
aRv.ThrowSyntaxError("Invalid font descriptor");
448+
aRv.ThrowSyntaxError(
449+
nsPrintfCString("Invalid font descriptor %s: %s",
450+
nsCSSProps::GetStringValue(aFontDesc).get(),
451+
PromiseFlatCString(aValue).get()));
447452
return false;
448453
}
449454

@@ -465,11 +470,18 @@ bool FontFaceImpl::SetDescriptors(const nsACString& aFamily,
465470

466471
mDescriptors = Servo_FontFaceRule_CreateEmpty().Consume();
467472

473+
nsCString errorMessage;
468474
// Helper to call SetDescriptor and return true on success, false on failure.
469-
auto setDesc = [=](nsCSSFontDesc aDesc, const nsACString& aVal) -> bool {
475+
auto setDesc = [&](nsCSSFontDesc aDesc, const nsACString& aVal) -> bool {
470476
IgnoredErrorResult rv;
471477
SetDescriptor(aDesc, aVal, rv);
472-
return !rv.Failed();
478+
if (!rv.Failed()) {
479+
return true;
480+
}
481+
errorMessage = nsPrintfCString("Invalid font descriptor %s: %s",
482+
nsCSSProps::GetStringValue(aDesc).get(),
483+
PromiseFlatCString(aVal).get());
484+
return false;
473485
};
474486

475487
// Parse all of the mDescriptors in aInitializer, which are the values
@@ -497,7 +509,8 @@ bool FontFaceImpl::SetDescriptors(const nsACString& aFamily,
497509
mDescriptors = Servo_FontFaceRule_CreateEmpty().Consume();
498510

499511
if (mOwner) {
500-
mOwner->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
512+
mOwner->MaybeReject(FontFaceLoadedRejectReason::Syntax,
513+
std::move(errorMessage));
501514
}
502515

503516
SetStatus(FontFaceLoadStatus::Error);
@@ -860,5 +873,4 @@ void FontFaceImpl::Entry::RemoveFontFace(FontFaceImpl* aFontFace) {
860873
CheckUserFontSetLocked();
861874
}
862875

863-
} // namespace dom
864-
} // namespace mozilla
876+
} // namespace mozilla::dom

layout/style/PostTraversalTask.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ void PostTraversalTask::Run() {
2525
break;
2626

2727
case Type::RejectFontFaceLoadedPromise:
28-
static_cast<FontFace*>(mTarget)->MaybeReject(mResult);
28+
static_cast<FontFace*>(mTarget)->MaybeReject(mResult.extract(),
29+
std::move(mMessage));
2930
break;
3031

3132
case Type::DispatchLoadingEventAndReplaceReadyPromise:

layout/style/PostTraversalTask.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
#ifndef mozilla_PostTraversalTask_h
88
#define mozilla_PostTraversalTask_h
99

10+
#include "nsString.h"
1011
#include "nscore.h"
1112

1213
/* a task to be performed immediately after a Servo traversal */
1314

1415
namespace mozilla {
1516
class ServoStyleSet;
1617
namespace dom {
18+
enum class FontFaceLoadedRejectReason : uint8_t;
1719
class FontFace;
1820
class FontFaceSet;
1921
class FontFaceSetImpl;
@@ -43,11 +45,13 @@ class PostTraversalTask {
4345
return task;
4446
}
4547

46-
static PostTraversalTask RejectFontFaceLoadedPromise(dom::FontFace* aFontFace,
47-
nsresult aResult) {
48+
static PostTraversalTask RejectFontFaceLoadedPromise(
49+
dom::FontFace* aFontFace, dom::FontFaceLoadedRejectReason aReason,
50+
nsCString&& aMessage) {
4851
auto task = PostTraversalTask(Type::ResolveFontFaceLoadedPromise);
4952
task.mTarget = aFontFace;
50-
task.mResult = aResult;
53+
task.mResult.emplace(aReason);
54+
task.mMessage = std::move(aMessage);
5155
return task;
5256
}
5357

@@ -96,7 +100,7 @@ class PostTraversalTask {
96100
ResolveFontFaceLoadedPromise,
97101

98102
// mTarget (FontFace*)
99-
// mResult
103+
// mResult / mMessage
100104
RejectFontFaceLoadedPromise,
101105

102106
// mTarget (FontFaceSet*)
@@ -115,12 +119,12 @@ class PostTraversalTask {
115119
FontInfoUpdate,
116120
};
117121

118-
explicit PostTraversalTask(Type aType)
119-
: mType(aType), mTarget(nullptr), mResult(NS_OK) {}
122+
explicit PostTraversalTask(Type aType) : mType(aType) {}
120123

121-
Type mType;
122-
void* mTarget;
123-
nsresult mResult;
124+
const Type mType;
125+
void* mTarget = nullptr;
126+
nsCString mMessage;
127+
Maybe<dom::FontFaceLoadedRejectReason> mResult;
124128
};
125129

126130
} // namespace mozilla

0 commit comments

Comments
 (0)