add dummy implementation of font face set

This commit is contained in:
Pierre Tachoire
2026-02-22 14:59:41 +01:00
parent dec051a6e0
commit 8b95211055
4 changed files with 130 additions and 0 deletions

View File

@@ -713,6 +713,7 @@ pub const JsApis = flattenTypes(&.{
@import("../webapi/css/CSSStyleRule.zig"), @import("../webapi/css/CSSStyleRule.zig"),
@import("../webapi/css/CSSStyleSheet.zig"), @import("../webapi/css/CSSStyleSheet.zig"),
@import("../webapi/css/CSSStyleProperties.zig"), @import("../webapi/css/CSSStyleProperties.zig"),
@import("../webapi/css/FontFaceSet.zig"),
@import("../webapi/css/MediaQueryList.zig"), @import("../webapi/css/MediaQueryList.zig"),
@import("../webapi/css/StyleSheetList.zig"), @import("../webapi/css/StyleSheetList.zig"),
@import("../webapi/Document.zig"), @import("../webapi/Document.zig"),

View File

@@ -0,0 +1,58 @@
<!DOCTYPE html>
<script src="../testing.js"></script>
<script id="document_fonts_exists">
{
testing.expectTrue(document.fonts !== undefined);
testing.expectTrue(document.fonts !== null);
}
</script>
<script id="document_fonts_same_instance">
{
// Should return same instance each time
const f1 = document.fonts;
const f2 = document.fonts;
testing.expectTrue(f1 === f2);
}
</script>
<script id="document_fonts_status">
{
testing.expectEqual('loaded', document.fonts.status);
}
</script>
<script id="document_fonts_size">
{
testing.expectEqual(0, document.fonts.size);
}
</script>
<script id="document_fonts_ready_is_promise">
{
const ready = document.fonts.ready;
testing.expectTrue(ready instanceof Promise);
}
</script>
<script id="document_fonts_ready_resolves">
{
let resolved = false;
document.fonts.ready.then(() => { resolved = true; });
// Promise resolution is async; just confirm .then() does not throw
testing.expectTrue(typeof document.fonts.ready.then === 'function');
}
</script>
<script id="document_fonts_check">
{
testing.expectTrue(document.fonts.check('16px sans-serif'));
}
</script>
<script id="document_fonts_constructor_name">
{
testing.expectEqual('FontFaceSet', document.fonts.constructor.name);
}
</script>

View File

@@ -34,6 +34,7 @@ const DOMTreeWalker = @import("DOMTreeWalker.zig");
const DOMNodeIterator = @import("DOMNodeIterator.zig"); const DOMNodeIterator = @import("DOMNodeIterator.zig");
const DOMImplementation = @import("DOMImplementation.zig"); const DOMImplementation = @import("DOMImplementation.zig");
const StyleSheetList = @import("css/StyleSheetList.zig"); const StyleSheetList = @import("css/StyleSheetList.zig");
const FontFaceSet = @import("css/FontFaceSet.zig");
const Selection = @import("Selection.zig"); const Selection = @import("Selection.zig");
pub const XMLDocument = @import("XMLDocument.zig"); pub const XMLDocument = @import("XMLDocument.zig");
@@ -52,6 +53,7 @@ _elements_by_id: std.StringHashMapUnmanaged(*Element) = .empty,
_removed_ids: std.StringHashMapUnmanaged(void) = .empty, _removed_ids: std.StringHashMapUnmanaged(void) = .empty,
_active_element: ?*Element = null, _active_element: ?*Element = null,
_style_sheets: ?*StyleSheetList = null, _style_sheets: ?*StyleSheetList = null,
_fonts: ?*FontFaceSet = null,
_write_insertion_point: ?*Node = null, _write_insertion_point: ?*Node = null,
_script_created_parser: ?Parser.Streaming = null, _script_created_parser: ?Parser.Streaming = null,
_adopted_style_sheets: ?js.Object.Global = null, _adopted_style_sheets: ?js.Object.Global = null,
@@ -422,6 +424,15 @@ pub fn getStyleSheets(self: *Document, page: *Page) !*StyleSheetList {
return sheets; return sheets;
} }
pub fn getFonts(self: *Document, page: *Page) !*FontFaceSet {
if (self._fonts) |fonts| {
return fonts;
}
const fonts = try FontFaceSet.init(page);
self._fonts = fonts;
return fonts;
}
pub fn adoptNode(_: *const Document, node: *Node, page: *Page) !*Node { pub fn adoptNode(_: *const Document, node: *Node, page: *Page) !*Node {
if (node._type == .document) { if (node._type == .document) {
return error.NotSupported; return error.NotSupported;
@@ -955,6 +966,7 @@ pub const JsApi = struct {
pub const implementation = bridge.accessor(Document.getImplementation, null, .{}); pub const implementation = bridge.accessor(Document.getImplementation, null, .{});
pub const activeElement = bridge.accessor(Document.getActiveElement, null, .{}); pub const activeElement = bridge.accessor(Document.getActiveElement, null, .{});
pub const styleSheets = bridge.accessor(Document.getStyleSheets, null, .{}); pub const styleSheets = bridge.accessor(Document.getStyleSheets, null, .{});
pub const fonts = bridge.accessor(Document.getFonts, null, .{});
pub const contentType = bridge.accessor(Document.getContentType, null, .{}); pub const contentType = bridge.accessor(Document.getContentType, null, .{});
pub const domain = bridge.accessor(Document.getDomain, null, .{}); pub const domain = bridge.accessor(Document.getDomain, null, .{});
pub const createElement = bridge.function(Document.createElement, .{ .dom_exception = true }); pub const createElement = bridge.function(Document.createElement, .{ .dom_exception = true });

View File

@@ -0,0 +1,59 @@
const std = @import("std");
const js = @import("../../js/js.zig");
const Page = @import("../../Page.zig");
const FontFaceSet = @This();
// Padding to avoid zero-size struct, which causes identity_map pointer collisions.
_pad: bool = false,
pub fn init(page: *Page) !*FontFaceSet {
return page._factory.create(FontFaceSet{});
}
// FontFaceSet.ready - returns an already-resolved Promise.
// In a headless browser there is no font loading, so fonts are always ready.
pub fn getReady(_: *FontFaceSet, page: *Page) !js.Promise {
return page.js.local.?.resolvePromise({});
}
pub fn getStatus(_: *const FontFaceSet) []const u8 {
return "loaded";
}
pub fn getSize(_: *const FontFaceSet) u32 {
return 0;
}
// check(font, text?) - always true; headless has no real fonts to check.
pub fn check(_: *const FontFaceSet, font: []const u8) bool {
_ = font;
return true;
}
// load(font, text?) - resolves immediately with an empty array.
pub fn load(_: *FontFaceSet, font: []const u8, page: *Page) !js.Promise {
_ = font;
return page.js.local.?.resolvePromise({});
}
pub const JsApi = struct {
pub const bridge = js.Bridge(FontFaceSet);
pub const Meta = struct {
pub const name = "FontFaceSet";
pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined;
};
pub const ready = bridge.accessor(FontFaceSet.getReady, null, .{});
pub const status = bridge.accessor(FontFaceSet.getStatus, null, .{});
pub const size = bridge.accessor(FontFaceSet.getSize, null, .{});
pub const check = bridge.function(FontFaceSet.check, .{});
pub const load = bridge.function(FontFaceSet.load, .{});
};
const testing = @import("../../../testing.zig");
test "WebApi: FontFaceSet" {
try testing.htmlRunner("css/font_face_set.html", .{});
}