Bug 1309867 - Part 2: Lazily create FontFace::mLoaded; r=heycam

This commit is contained in:
Bill McCloskey 2016-10-13 16:01:52 -07:00
parent 97a4ddfbdf
commit 9fd5d0bea3
2 changed files with 60 additions and 29 deletions

View File

@ -101,6 +101,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(FontFace)
FontFace::FontFace(nsISupports* aParent, FontFaceSet* aFontFaceSet)
: mParent(aParent)
, mLoadedRejection(NS_OK)
, mStatus(FontFaceLoadStatus::Unloaded)
, mSourceType(SourceType(0))
, mSourceBuffer(nullptr)
@ -109,16 +110,6 @@ FontFace::FontFace(nsISupports* aParent, FontFaceSet* aFontFaceSet)
, mInFontFaceSet(false)
{
MOZ_COUNT_CTOR(FontFace);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent);
// If the pref is not set, don't create the Promise (which the page wouldn't
// be able to get to anyway) as it causes the window.FontFace constructor
// to be created.
if (global && FontFaceSet::PrefEnabled()) {
ErrorResult rv;
mLoaded = Promise::Create(global, rv);
}
}
FontFace::~FontFace()
@ -198,13 +189,7 @@ FontFace::InitializeSource(const StringOrArrayBufferOrArrayBufferView& aSource)
if (!ParseDescriptor(eCSSFontDesc_Src,
aSource.GetAsString(),
mDescriptors->mSrc)) {
if (mLoaded) {
// The SetStatus call we are about to do assumes that for
// FontFace objects with sources other than ArrayBuffer(View)s, that the
// mLoaded Promise is rejected with a network error. We get
// in here beforehand to set it to the required syntax error.
mLoaded->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
}
Reject(NS_ERROR_DOM_SYNTAX_ERR);
SetStatus(FontFaceLoadStatus::Error);
return;
@ -378,6 +363,8 @@ FontFace::Load(ErrorResult& aRv)
{
mFontFaceSet->FlushUserFontSet();
EnsurePromise();
if (!mLoaded) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
@ -433,6 +420,8 @@ FontFace::GetLoaded(ErrorResult& aRv)
{
mFontFaceSet->FlushUserFontSet();
EnsurePromise();
if (!mLoaded) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
@ -467,17 +456,15 @@ FontFace::SetStatus(FontFaceLoadStatus aStatus)
otherSet->OnFontFaceStatusChanged(this);
}
if (!mLoaded) {
return;
}
if (mStatus == FontFaceLoadStatus::Loaded) {
mLoaded->MaybeResolve(this);
if (mLoaded) {
mLoaded->MaybeResolve(this);
}
} else if (mStatus == FontFaceLoadStatus::Error) {
if (mSourceType == eSourceType_Buffer) {
mLoaded->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
Reject(NS_ERROR_DOM_SYNTAX_ERR);
} else {
mLoaded->MaybeReject(NS_ERROR_DOM_NETWORK_ERR);
Reject(NS_ERROR_DOM_NETWORK_ERR);
}
}
}
@ -570,9 +557,7 @@ FontFace::SetDescriptors(const nsAString& aFamily,
// on the FontFace.
mDescriptors = new CSSFontFaceDescriptors;
if (mLoaded) {
mLoaded->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
}
Reject(NS_ERROR_DOM_SYNTAX_ERR);
SetStatus(FontFaceLoadStatus::Error);
return false;
@ -748,6 +733,40 @@ FontFace::RemoveFontFaceSet(FontFaceSet* aFontFaceSet)
}
}
void
FontFace::Reject(nsresult aResult)
{
if (mLoaded) {
mLoaded->MaybeReject(aResult);
} else if (mLoadedRejection == NS_OK) {
mLoadedRejection = aResult;
}
}
void
FontFace::EnsurePromise()
{
if (mLoaded) {
return;
}
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
// If the pref is not set, don't create the Promise (which the page wouldn't
// be able to get to anyway) as it causes the window.FontFace constructor
// to be created.
if (global && FontFaceSet::PrefEnabled()) {
ErrorResult rv;
mLoaded = Promise::Create(global, rv);
if (mStatus == FontFaceLoadStatus::Loaded) {
mLoaded->MaybeResolve(this);
} else if (mLoadedRejection != NS_OK) {
mLoaded->MaybeReject(mLoadedRejection);
}
}
}
// -- FontFace::Entry --------------------------------------------------------
/* virtual */ void

View File

@ -199,12 +199,24 @@ private:
*/
void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength);
// Acts like mLoaded->MaybeReject(aResult), except it doesn't create mLoaded
// if it doesn't already exist.
void Reject(nsresult aResult);
// Creates mLoaded if it doesn't already exist. It may immediately resolve or
// reject mLoaded based on mStatus and mLoadedRejection.
void EnsurePromise();
nsCOMPtr<nsISupports> mParent;
// A Promise that is fulfilled once the font represented by this FontFace
// is loaded, and is rejected if the load fails.
// A Promise that is fulfilled once the font represented by this FontFace is
// loaded, and is rejected if the load fails. This promise is created lazily
// when JS asks for it.
RefPtr<mozilla::dom::Promise> mLoaded;
// Saves the rejection code for mLoaded if mLoaded hasn't been created yet.
nsresult mLoadedRejection;
// The @font-face rule this FontFace object is reflecting, if it is a
// rule backed FontFace.
RefPtr<nsCSSFontFaceRule> mRule;