diff --git a/Tests/LibWeb/Text/expected/css/FontFaceSet-setlike.txt b/Tests/LibWeb/Text/expected/css/FontFaceSet-setlike.txt
new file mode 100644
index 00000000000..753b4d98167
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/css/FontFaceSet-setlike.txt
@@ -0,0 +1,23 @@
+-- Empty FontFaceSet --
+fontFaceSet.size: 0
+fontFaceSet.has(fontFace): false
+fontFaceSet.status: loaded
+deleteBeforeAdd: false
+-- Add Font --
+fontFaceSet.size: 1
+fontFaceSet.has(fontFace): true
+fontFaceKey.name: Hash Sans
+FIXME: fontFaceSet.status: loaded
+-- Delete Font --
+fontFaceSet.size: 0
+fontFaceSet.has(fontFace): false
+didDelete: true
+fontFaceSet.status: loaded
+-- Add Font again --
+fontFaceSet.size: 1
+fontFaceSet.has(fontFace): true
+FIXME: fontFaceSet.status: loaded
+-- Clear FontFaceSet --
+fontFaceSet.size: 0
+fontFaceSet.has(fontFace): false
+fontFaceSet.status: loaded
diff --git a/Tests/LibWeb/Text/input/css/FontFaceSet-setlike.html b/Tests/LibWeb/Text/input/css/FontFaceSet-setlike.html
new file mode 100644
index 00000000000..4b03b722df4
--- /dev/null
+++ b/Tests/LibWeb/Text/input/css/FontFaceSet-setlike.html
@@ -0,0 +1,50 @@
+
+
+
diff --git a/Userland/Libraries/LibWeb/CSS/FontFaceSet.cpp b/Userland/Libraries/LibWeb/CSS/FontFaceSet.cpp
index 35fbd076bcc..d3995826601 100644
--- a/Userland/Libraries/LibWeb/CSS/FontFaceSet.cpp
+++ b/Userland/Libraries/LibWeb/CSS/FontFaceSet.cpp
@@ -6,8 +6,10 @@
#include
#include
+#include
#include
#include
+#include
#include
#include
@@ -15,10 +17,20 @@ namespace Web::CSS {
JS_DEFINE_ALLOCATOR(FontFaceSet);
-JS::NonnullGCPtr FontFaceSet::construct_impl(JS::Realm& realm, Vector> initial_faces)
+// https://drafts.csswg.org/css-font-loading/#dom-fontfaceset-fontfaceset
+JS::NonnullGCPtr FontFaceSet::construct_impl(JS::Realm& realm, Vector> const& initial_faces)
{
- auto promise = WebIDL::create_promise(realm);
- return realm.heap().allocate(realm, realm, promise, move(initial_faces));
+ auto ready_promise = WebIDL::create_promise(realm);
+ auto set_entries = JS::Set::create(realm);
+
+ // The FontFaceSet constructor, when called, must iterate its initialFaces argument and add each value to its set entries.
+ for (auto const& face : initial_faces)
+ set_entries->set_add(face);
+
+ if (set_entries->set_size() == 0)
+ WebIDL::resolve_promise(realm, *ready_promise);
+
+ return realm.heap().allocate(realm, realm, ready_promise, set_entries);
}
JS::NonnullGCPtr FontFaceSet::create(JS::Realm& realm)
@@ -26,14 +38,13 @@ JS::NonnullGCPtr FontFaceSet::create(JS::Realm& realm)
return construct_impl(realm, {});
}
-FontFaceSet::FontFaceSet(JS::Realm& realm, JS::NonnullGCPtr ready_promise, Vector>)
+FontFaceSet::FontFaceSet(JS::Realm& realm, JS::NonnullGCPtr ready_promise, JS::NonnullGCPtr set_entries)
: Bindings::PlatformObject(realm)
+ , m_set_entries(set_entries)
, m_ready_promise(ready_promise)
{
- // FIXME: Only set this after all the initial faces have been loaded
- m_status = Bindings::FontFaceSetLoadStatus::Loaded;
- // FIXME: Only resolve the promise after all the initial faces have been loaded
- WebIDL::resolve_promise(realm, *m_ready_promise);
+ bool const is_ready = ready()->state() == JS::Promise::State::Fulfilled;
+ m_status = is_ready ? Bindings::FontFaceSetLoadStatus::Loaded : Bindings::FontFaceSetLoadStatus::Loading;
}
void FontFaceSet::initialize(JS::Realm& realm)
@@ -46,16 +57,32 @@ void FontFaceSet::initialize(JS::Realm& realm)
void FontFaceSet::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
+ visitor.visit(m_set_entries);
visitor.visit(m_ready_promise);
}
// https://drafts.csswg.org/css-font-loading/#dom-fontfaceset-add
-JS::NonnullGCPtr FontFaceSet::add(JS::Handle)
+JS::NonnullGCPtr FontFaceSet::add(JS::Handle face)
{
- // FIXME: Do the steps
+ // FIXME: Do the actual spec steps
+ m_set_entries->set_add(face);
return *this;
}
+// https://drafts.csswg.org/css-font-loading/#dom-fontfaceset-delete
+bool FontFaceSet::delete_(JS::Handle face)
+{
+ // FIXME: Do the actual spec steps
+ return m_set_entries->set_remove(face);
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontfaceset-clear
+void FontFaceSet::clear()
+{
+ // FIXME: Do the actual spec steps
+ m_set_entries->set_clear();
+}
+
// https://drafts.csswg.org/css-font-loading/#dom-fontfaceset-load
JS::ThrowCompletionOr> FontFaceSet::load(String const&, String const&)
{
diff --git a/Userland/Libraries/LibWeb/CSS/FontFaceSet.h b/Userland/Libraries/LibWeb/CSS/FontFaceSet.h
index a6bb5ec1e6e..98f0bbb6519 100644
--- a/Userland/Libraries/LibWeb/CSS/FontFaceSet.h
+++ b/Userland/Libraries/LibWeb/CSS/FontFaceSet.h
@@ -6,6 +6,8 @@
#pragma once
+#include
+#include
#include
#include
#include
@@ -17,23 +19,29 @@ class FontFaceSet final : public Bindings::PlatformObject {
JS_DECLARE_ALLOCATOR(FontFaceSet);
public:
- [[nodiscard]] static JS::NonnullGCPtr construct_impl(JS::Realm&, Vector> initial_faces);
+ [[nodiscard]] static JS::NonnullGCPtr construct_impl(JS::Realm&, Vector> const& initial_faces);
[[nodiscard]] static JS::NonnullGCPtr create(JS::Realm&);
virtual ~FontFaceSet() override = default;
- JS::NonnullGCPtr add(JS::Handle face);
+ JS::NonnullGCPtr set_entries() const { return m_set_entries; }
+
+ JS::NonnullGCPtr add(JS::Handle);
+ bool delete_(JS::Handle);
+ void clear();
JS::ThrowCompletionOr> load(String const& font, String const& text);
JS::NonnullGCPtr ready() const;
Bindings::FontFaceSetLoadStatus status() const { return m_status; }
private:
- FontFaceSet(JS::Realm&, JS::NonnullGCPtr ready_promise, Vector> initial_faces);
+ FontFaceSet(JS::Realm&, JS::NonnullGCPtr ready_promise, JS::NonnullGCPtr set_entries);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
+ JS::NonnullGCPtr m_set_entries;
JS::GCPtr m_ready_promise; // [[ReadyPromise]]
+
Bindings::FontFaceSetLoadStatus m_status { Bindings::FontFaceSetLoadStatus::Loading };
};
diff --git a/Userland/Libraries/LibWeb/CSS/FontFaceSet.idl b/Userland/Libraries/LibWeb/CSS/FontFaceSet.idl
index 30e13c4d5b4..de816d39889 100644
--- a/Userland/Libraries/LibWeb/CSS/FontFaceSet.idl
+++ b/Userland/Libraries/LibWeb/CSS/FontFaceSet.idl
@@ -18,10 +18,10 @@ enum FontFaceSetLoadStatus { "loading", "loaded" };
interface FontFaceSet : EventTarget {
constructor(sequence initialFaces);
- // FIXME: setlike;
+ setlike;
FontFaceSet add(FontFace font);
- [FIXME] boolean delete(FontFace font);
- [FIXME] undefined clear();
+ boolean delete(FontFace font);
+ undefined clear();
// events for when loading state changes
[FIXME] attribute EventHandler onloading;