Diff
Modified: trunk/Source/WebCore/ChangeLog (200545 => 200546)
--- trunk/Source/WebCore/ChangeLog 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/ChangeLog 2016-05-07 20:04:27 UTC (rev 200546)
@@ -1,3 +1,49 @@
+2016-05-07 Youenn Fablet <[email protected]>
+
+ Rework FontFace promise attribute handling
+ https://bugs.webkit.org/show_bug.cgi?id=157310
+
+ Reviewed by Myles C. Maxfield.
+
+ Making promise attributes cached attributes, so that they are created only once.
+ They are created in the custom binding code and passed to DOM class as needed.
+
+ Removed usage of ExecState& from DOM iterators.
+
+ No change should be visible from user scripts.
+
+ * Modules/fetch/FetchHeaders.cpp:
+ (WebCore::FetchHeaders::Iterator::next): Removing ExecState parameter.
+ * Modules/fetch/FetchHeaders.h:
+ * bindings/js/JSDOMIterator.h:
+ (WebCore::keyValueIteratorForEach):
+ (WebCore::JSDOMIterator<JSWrapper>::next): Ditto.
+ * bindings/js/JSDOMPromise.cpp:
+ (WebCore::DeferredWrapper::promise): Removed deferred() and added access to promise directly.
+ * bindings/js/JSDOMPromise.h:
+ * bindings/js/JSFontFaceCustom.cpp:
+ (WebCore::JSFontFace::loaded): Using cached attribute to call FontFace::loaded only once.
+ * bindings/js/JSFontFaceSetCustom.cpp:
+ (WebCore::JSFontFaceSet::ready): Using cached attribute to call FontFaceSet::ready only once.
+ * css/CSSFontFace.cpp:
+ (WebCore::CSSFontFace::wrapper): Removing ExecState parameter.
+ * css/CSSFontFace.h:
+ * css/FontFace.cpp:
+ (WebCore::FontFace::create): Ditto.
+ (WebCore::FontFace::FontFace): Ditto.
+ (WebCore::FontFace::fontStateChanged): Updating promise handling.
+ (WebCore::FontFace::registerLoaded): Resolving/rejecting promise if backing CSSFontFace loading is ended.
+ (WebCore::FontFace::load): Calling backing load.
+ * css/FontFace.h:
+ * css/FontFaceSet.cpp:
+ (WebCore::FontFaceSet::Iterator::next): Removing ExecState parameter.
+ (WebCore::FontFaceSet::load): Removing ExecState and ExceptionCode parameter.
+ (WebCore::FontFaceSet::registerReady): Resolving promise if ready otherwise storing it for resolving it later.
+ (WebCore::FontFaceSet::completedLoading): Resolving promise if any is stored.
+ (WebCore::FontFaceSet::create): Deleted.
+ * css/FontFaceSet.h:
+ * css/FontFaceSet.idl:
+
2016-05-07 Jeremy Huddleston Sequoia <[email protected]>
Fix an incorrect usage of OS(DARWIN) with PLATFORM(COCOA)
Modified: trunk/Source/WebCore/Modules/fetch/FetchHeaders.cpp (200545 => 200546)
--- trunk/Source/WebCore/Modules/fetch/FetchHeaders.cpp 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/Modules/fetch/FetchHeaders.cpp 2016-05-07 20:04:27 UTC (rev 200546)
@@ -177,7 +177,7 @@
}
}
-Optional<WTF::KeyValuePair<String, String>> FetchHeaders::Iterator::next(JSC::ExecState&)
+Optional<WTF::KeyValuePair<String, String>> FetchHeaders::Iterator::next()
{
while (m_currentIndex < m_keys.size()) {
String key = m_keys[m_currentIndex++];
Modified: trunk/Source/WebCore/Modules/fetch/FetchHeaders.h (200545 => 200546)
--- trunk/Source/WebCore/Modules/fetch/FetchHeaders.h 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/Modules/fetch/FetchHeaders.h 2016-05-07 20:04:27 UTC (rev 200546)
@@ -35,10 +35,6 @@
#include <wtf/HashTraits.h>
#include <wtf/Optional.h>
-namespace JSC {
-class ExecState;
-}
-
namespace WebCore {
typedef int ExceptionCode;
@@ -72,7 +68,7 @@
class Iterator {
public:
explicit Iterator(FetchHeaders&);
- Optional<WTF::KeyValuePair<String, String>> next(JSC::ExecState&);
+ Optional<WTF::KeyValuePair<String, String>> next();
private:
Ref<FetchHeaders> m_headers;
Modified: trunk/Source/WebCore/bindings/js/JSDOMIterator.h (200545 => 200546)
--- trunk/Source/WebCore/bindings/js/JSDOMIterator.h 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/bindings/js/JSDOMIterator.h 2016-05-07 20:04:27 UTC (rev 200546)
@@ -127,7 +127,7 @@
return throwVMTypeError(&state);
auto iterator = wrapper->wrapped().createIterator();
- while (auto value = iterator.next(state)) {
+ while (auto value = iterator.next()) {
JSC::MarkedArgumentBuffer arguments;
arguments.append(toJS(&state, wrapper->globalObject(), value.value().value));
arguments.append(toJS(&state, wrapper->globalObject(), value.value().key));
@@ -149,7 +149,7 @@
template<typename JSWrapper>
JSC::JSValue JSDOMIterator<JSWrapper>::next(JSC::ExecState& state)
{
- auto iteratorValue = m_iterator.next(state);
+ auto iteratorValue = m_iterator.next();
if (!iteratorValue)
return createIteratorResultObject(&state, JSC::jsUndefined(), true);
Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp (200545 => 200546)
--- trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp 2016-05-07 20:04:27 UTC (rev 200546)
@@ -46,10 +46,10 @@
return *m_globalObject.get();
}
-JSC::JSPromiseDeferred& DeferredWrapper::deferred() const
+JSC::JSValue DeferredWrapper::promise() const
{
ASSERT(m_deferred);
- return *m_deferred.get();
+ return m_deferred->promise();
}
void DeferredWrapper::callFunction(ExecState& exec, JSValue function, JSValue resolution)
Modified: trunk/Source/WebCore/bindings/js/JSDOMPromise.h (200545 => 200546)
--- trunk/Source/WebCore/bindings/js/JSDOMPromise.h 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromise.h 2016-05-07 20:04:27 UTC (rev 200546)
@@ -44,7 +44,7 @@
void reject(const RejectResultType&);
JSDOMGlobalObject& globalObject() const;
- JSC::JSPromiseDeferred& deferred() const;
+ JSC::JSValue promise() const;
private:
void callFunction(JSC::ExecState&, JSC::JSValue function, JSC::JSValue resolution);
@@ -83,8 +83,6 @@
void resolve(const Value& value) { m_wrapper.resolve<Value>(value); }
void reject(const Error& error) { m_wrapper.reject<Error>(error); }
- JSC::JSPromiseDeferred& deferred() const { return m_wrapper.deferred(); }
-
private:
DeferredWrapper m_wrapper;
};
Modified: trunk/Source/WebCore/bindings/js/JSFontFaceCustom.cpp (200545 => 200546)
--- trunk/Source/WebCore/bindings/js/JSFontFaceCustom.cpp 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/bindings/js/JSFontFaceCustom.cpp 2016-05-07 20:04:27 UTC (rev 200546)
@@ -35,10 +35,14 @@
namespace WebCore {
-JSC::JSValue JSFontFace::loaded(JSC::ExecState&) const
+JSC::JSValue JSFontFace::loaded(JSC::ExecState& state) const
{
- auto& promise = wrapped().promise();
- return promise.deferred().promise();
+ if (!m_loaded) {
+ DeferredWrapper promise(&state, globalObject(), JSC::JSPromiseDeferred::create(&state, globalObject()));
+ m_loaded.set(state.vm(), this, promise.promise());
+ wrapped().registerLoaded(WTFMove(promise));
+ }
+ return m_loaded.get();
}
JSC::JSValue JSFontFace::load(JSC::ExecState& state)
Modified: trunk/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp (200545 => 200546)
--- trunk/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp 2016-05-07 20:04:27 UTC (rev 200546)
@@ -31,10 +31,14 @@
namespace WebCore {
-JSC::JSValue JSFontFaceSet::ready(JSC::ExecState& execState) const
+JSC::JSValue JSFontFaceSet::ready(JSC::ExecState& state) const
{
- auto& promise = wrapped().promise(execState);
- return promise.deferred().promise();
+ if (!m_ready) {
+ DeferredWrapper promise(&state, globalObject(), JSC::JSPromiseDeferred::create(&state, globalObject()));
+ m_ready.set(state.vm(), this, promise.promise());
+ wrapped().registerReady(WTFMove(promise));
+ }
+ return m_ready.get();
}
}
Modified: trunk/Source/WebCore/css/CSSFontFace.cpp (200545 => 200546)
--- trunk/Source/WebCore/css/CSSFontFace.cpp 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/css/CSSFontFace.cpp 2016-05-07 20:04:27 UTC (rev 200546)
@@ -343,12 +343,12 @@
m_clients.remove(&client);
}
-Ref<FontFace> CSSFontFace::wrapper(JSC::ExecState& execState)
+Ref<FontFace> CSSFontFace::wrapper()
{
if (m_wrapper)
return Ref<FontFace>(*m_wrapper.get());
- Ref<FontFace> wrapper = FontFace::create(execState, *this);
+ Ref<FontFace> wrapper = FontFace::create(*this);
switch (m_status) {
case Status::Pending:
break;
Modified: trunk/Source/WebCore/css/CSSFontFace.h (200545 => 200546)
--- trunk/Source/WebCore/css/CSSFontFace.h 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/css/CSSFontFace.h 2016-05-07 20:04:27 UTC (rev 200546)
@@ -148,7 +148,7 @@
};
// We don't guarantee that the FontFace wrapper will be the same every time you ask for it.
- Ref<FontFace> wrapper(JSC::ExecState&);
+ Ref<FontFace> wrapper();
#if ENABLE(SVG_FONTS)
bool hasSVGFontFaceSource() const;
Modified: trunk/Source/WebCore/css/FontFace.cpp (200545 => 200546)
--- trunk/Source/WebCore/css/FontFace.cpp 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/css/FontFace.cpp 2016-05-07 20:04:27 UTC (rev 200546)
@@ -34,7 +34,7 @@
#include "CSSValuePool.h"
#include "Dictionary.h"
#include "Document.h"
-#include "ExceptionCodeDescription.h"
+#include "ExceptionCode.h"
#include "FontVariantBuilder.h"
#include "JSDOMCoreException.h"
#include "JSFontFace.h"
@@ -44,12 +44,6 @@
namespace WebCore {
-static FontFace::Promise createPromise(JSC::ExecState& exec)
-{
- JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(exec.lexicalGlobalObject());
- return FontFace::Promise(DeferredWrapper(&exec, &globalObject, JSC::JSPromiseDeferred::create(&exec, &globalObject)));
-}
-
static inline Optional<String> valueFromDictionary(const Dictionary& dictionary, const char* key)
{
String result;
@@ -64,7 +58,7 @@
return nullptr;
}
- Ref<FontFace> result = adoptRef(*new FontFace(execState, downcast<Document>(context).fontSelector()));
+ Ref<FontFace> result = adoptRef(*new FontFace(downcast<Document>(context).fontSelector()));
ec = 0;
result->setFamily(family, ec);
@@ -109,23 +103,21 @@
return result.ptr();
}
-Ref<FontFace> FontFace::create(JSC::ExecState& execState, CSSFontFace& face)
+Ref<FontFace> FontFace::create(CSSFontFace& face)
{
- return adoptRef(*new FontFace(execState, face));
+ return adoptRef(*new FontFace(face));
}
-FontFace::FontFace(JSC::ExecState& execState, CSSFontSelector& fontSelector)
+FontFace::FontFace(CSSFontSelector& fontSelector)
: m_weakPtrFactory(this)
, m_backing(CSSFontFace::create(&fontSelector, nullptr, this))
- , m_promise(createPromise(execState))
{
m_backing->addClient(*this);
}
-FontFace::FontFace(JSC::ExecState& execState, CSSFontFace& face)
+FontFace::FontFace(CSSFontFace& face)
: m_weakPtrFactory(this)
, m_backing(face)
- , m_promise(createPromise(execState))
{
m_backing->addClient(*this);
}
@@ -343,48 +335,44 @@
// We still need to resolve promises when loading completes, even if all references to use have fallen out of scope.
ref();
break;
- case CSSFontFace::Status::TimedOut:
- rejectPromise(NETWORK_ERR);
- deref();
- return;
case CSSFontFace::Status::Success:
- fulfillPromise();
+ if (m_promise)
+ std::exchange(m_promise, Nullopt)->resolve(*this);
deref();
return;
+ case CSSFontFace::Status::TimedOut:
case CSSFontFace::Status::Failure:
- rejectPromise(NETWORK_ERR);
+ if (m_promise)
+ std::exchange(m_promise, Nullopt)->reject(NETWORK_ERR);
deref();
return;
- default:
+ case CSSFontFace::Status::Pending:
+ ASSERT_NOT_REACHED();
return;
}
}
-void FontFace::load()
+void FontFace::registerLoaded(Promise&& promise)
{
- m_backing->load();
+ ASSERT(!m_promise);
+ switch (m_backing->status()) {
+ case CSSFontFace::Status::Loading:
+ case CSSFontFace::Status::Pending:
+ m_promise = WTFMove(promise);
+ return;
+ case CSSFontFace::Status::Success:
+ promise.resolve(*this);
+ return;
+ case CSSFontFace::Status::TimedOut:
+ case CSSFontFace::Status::Failure:
+ promise.reject(NETWORK_ERR);
+ return;
+ }
}
-void FontFace::fulfillPromise()
+void FontFace::load()
{
- // Normally, DeferredWrapper::callFunction resets the reference to the promise.
- // However, API semantics require our promise to live for the entire lifetime of the FontFace.
- // Let's make sure it stays alive.
-
- Promise guard(m_promise);
- m_promise.resolve(*this);
- m_promise = guard;
+ m_backing->load();
}
-void FontFace::rejectPromise(ExceptionCode code)
-{
- // Normally, DeferredWrapper::callFunction resets the reference to the promise.
- // However, API semantics require our promise to live for the entire lifetime of the FontFace.
- // Let's make sure it stays alive.
-
- Promise guard(m_promise);
- m_promise.reject(DOMCoreException::create(ExceptionCodeDescription(code)).get());
- m_promise = guard;
}
-
-}
Modified: trunk/Source/WebCore/css/FontFace.h (200545 => 200546)
--- trunk/Source/WebCore/css/FontFace.h 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/css/FontFace.h 2016-05-07 20:04:27 UTC (rev 200546)
@@ -28,8 +28,6 @@
#include "CSSFontFace.h"
#include "CSSPropertyNames.h"
-#include "DOMCoreException.h"
-#include "ExceptionCode.h"
#include "JSDOMPromise.h"
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
@@ -42,10 +40,12 @@
class CSSValue;
class Dictionary;
+using ExceptionCode = int;
+
class FontFace final : public RefCounted<FontFace>, public CSSFontFace::Client {
public:
static RefPtr<FontFace> create(JSC::ExecState&, ScriptExecutionContext&, const String& family, JSC::JSValue source, const Dictionary& descriptors, ExceptionCode&);
- static Ref<FontFace> create(JSC::ExecState&, CSSFontFace&);
+ static Ref<FontFace> create(CSSFontFace&);
virtual ~FontFace();
void setFamily(const String&, ExceptionCode&);
@@ -67,8 +67,8 @@
enum class LoadStatus { Unloaded, Loading, Loaded, Error };
LoadStatus status() const;
- typedef DOMPromise<FontFace&, DOMCoreException&> Promise;
- Promise& promise() { return m_promise; }
+ typedef DOMPromise<FontFace&, ExceptionCode> Promise;
+ void registerLoaded(Promise&&);
void load();
@@ -85,15 +85,12 @@
void deref() override { RefCounted<FontFace>::deref(); }
private:
- FontFace(JSC::ExecState&, CSSFontSelector&);
- FontFace(JSC::ExecState&, CSSFontFace&);
+ FontFace(CSSFontSelector&);
+ FontFace(CSSFontFace&);
- void fulfillPromise();
- void rejectPromise(ExceptionCode);
-
WeakPtrFactory<FontFace> m_weakPtrFactory;
Ref<CSSFontFace> m_backing;
- Promise m_promise;
+ Optional<Promise> m_promise;
};
}
Modified: trunk/Source/WebCore/css/FontFaceSet.cpp (200545 => 200546)
--- trunk/Source/WebCore/css/FontFaceSet.cpp 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/css/FontFaceSet.cpp 2016-05-07 20:04:27 UTC (rev 200546)
@@ -36,12 +36,6 @@
namespace WebCore {
-static FontFaceSet::Promise createPromise(JSC::ExecState& exec)
-{
- JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(exec.lexicalGlobalObject());
- return FontFaceSet::Promise(DeferredWrapper(&exec, &globalObject, JSC::JSPromiseDeferred::create(&exec, &globalObject)));
-}
-
Ref<FontFaceSet> FontFaceSet::create(Document& document, const Vector<RefPtr<FontFace>>& initialFaces)
{
Ref<FontFaceSet> result = adoptRef(*new FontFaceSet(document, initialFaces));
@@ -82,11 +76,11 @@
{
}
-Optional<WTF::KeyValuePair<RefPtr<FontFace>, RefPtr<FontFace>>> FontFaceSet::Iterator::next(JSC::ExecState& state)
+Optional<WTF::KeyValuePair<RefPtr<FontFace>, RefPtr<FontFace>>> FontFaceSet::Iterator::next()
{
if (m_index == m_target->size())
return Nullopt;
- RefPtr<FontFace> item = m_target->backing()[m_index++].wrapper(state);
+ RefPtr<FontFace> item = m_target->backing()[m_index++].wrapper();
return WTF::KeyValuePair<RefPtr<FontFace>, RefPtr<FontFace>>(item, item);
}
@@ -130,12 +124,14 @@
m_backing->remove(m_backing.get()[0]);
}
-void FontFaceSet::load(JSC::ExecState& execState, const String& font, const String& text, DeferredWrapper&& promise, ExceptionCode& ec)
+void FontFaceSet::load(const String& font, const String& text, DeferredWrapper&& promise)
{
- ec = 0;
+ ExceptionCode ec = 0;
auto matchingFaces = m_backing->matchingFaces(font, text, ec);
- if (ec)
+ if (ec) {
+ promise.reject(ec);
return;
+ }
if (matchingFaces.isEmpty()) {
promise.resolve(Vector<RefPtr<FontFace>>());
@@ -156,7 +152,7 @@
bool waiting = false;
for (auto& face : matchingFaces) {
- pendingPromise->faces.append(face.get().wrapper(execState));
+ pendingPromise->faces.append(face.get().wrapper());
if (face.get().status() == CSSFontFace::Status::Success)
continue;
waiting = true;
@@ -172,14 +168,14 @@
return m_backing->check(family, text, ec);
}
-auto FontFaceSet::promise(JSC::ExecState& execState) -> Promise&
+void FontFaceSet::registerReady(Promise&& promise)
{
- if (!m_promise) {
- m_promise = createPromise(execState);
- if (m_backing->status() == CSSFontFaceSet::Status::Loaded)
- fulfillPromise();
+ ASSERT(!m_promise);
+ if (m_isReady) {
+ promise.resolve(*this);
+ return;
}
- return m_promise.value();
+ m_promise = WTFMove(promise);
}
auto FontFaceSet::status() const -> LoadStatus
@@ -207,22 +203,10 @@
void FontFaceSet::completedLoading()
{
if (m_promise)
- fulfillPromise();
- m_promise = Nullopt;
- // FIXME: Fire a "loadingdone" and possibly a "loadingerror" event asynchronously.
+ std::exchange(m_promise, Nullopt)->resolve(*this);
+ m_isReady = true;
}
-void FontFaceSet::fulfillPromise()
-{
- // Normally, DeferredWrapper::callFunction resets the reference to the promise.
- // However, API semantics require our promise to live for the entire lifetime of the FontFace.
- // Let's make sure it stays alive.
-
- Promise guard(m_promise.value());
- m_promise.value().resolve(*this);
- m_promise = guard;
-}
-
void FontFaceSet::faceFinished(CSSFontFace& face, CSSFontFace::Status newStatus)
{
auto iterator = m_pendingPromises.find(&face);
Modified: trunk/Source/WebCore/css/FontFaceSet.h (200545 => 200546)
--- trunk/Source/WebCore/css/FontFaceSet.h 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/css/FontFaceSet.h 2016-05-07 20:04:27 UTC (rev 200546)
@@ -47,21 +47,21 @@
bool remove(FontFace&);
void clear();
- void load(JSC::ExecState&, const String& font, const String& text, DeferredWrapper&& promise, ExceptionCode&);
+ void load(const String& font, const String& text, DeferredWrapper&& promise);
bool check(const String& font, const String& text, ExceptionCode&);
enum class LoadStatus { Loading, Loaded };
LoadStatus status() const;
typedef DOMPromise<FontFaceSet&, DOMCoreException&> Promise;
- Promise& promise(JSC::ExecState&);
+ void registerReady(Promise&&);
CSSFontFaceSet& backing() { return m_backing; }
class Iterator {
public:
explicit Iterator(FontFaceSet&);
- Optional<WTF::KeyValuePair<RefPtr<FontFace>, RefPtr<FontFace>>> next(JSC::ExecState&);
+ Optional<WTF::KeyValuePair<RefPtr<FontFace>, RefPtr<FontFace>>> next();
private:
Ref<FontFaceSet> m_target;
@@ -93,8 +93,6 @@
FontFaceSet(Document&, const Vector<RefPtr<FontFace>>&);
FontFaceSet(Document&, CSSFontFaceSet&);
- void fulfillPromise();
-
// CSSFontFaceSetClient
void startedLoading() final;
void completedLoading() final;
@@ -113,6 +111,7 @@
Ref<CSSFontFaceSet> m_backing;
HashMap<RefPtr<CSSFontFace>, Vector<Ref<PendingPromise>>> m_pendingPromises;
Optional<Promise> m_promise;
+ bool m_isReady { false };
};
}
Modified: trunk/Source/WebCore/css/FontFaceSet.idl (200545 => 200546)
--- trunk/Source/WebCore/css/FontFaceSet.idl 2016-05-07 20:02:44 UTC (rev 200545)
+++ trunk/Source/WebCore/css/FontFaceSet.idl 2016-05-07 20:04:27 UTC (rev 200546)
@@ -48,9 +48,9 @@
attribute EventHandler onloadingdone;
attribute EventHandler onloadingerror;
- [RaisesException, CallWith=ScriptState] Promise load(DOMString font, optional DOMString text = " ");
+ Promise load(DOMString font, optional DOMString text = " ");
[RaisesException] boolean check(DOMString font, optional DOMString text = " ");
- [Custom] readonly attribute Promise ready;
+ [CustomGetter, CachedAttribute] readonly attribute Promise ready;
readonly attribute FontFaceSetLoadStatus status;
};