From 2656cc78426f85d0b55ad09fa57476052beb38c8 Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Tue, 17 Jun 2025 21:21:37 -0700 Subject: [PATCH] Add basic tests for CSSStyleSheet --- src/browser/cssom/css_rule.zig | 35 ---------------- src/browser/cssom/css_rule_list.zig | 62 ++++++++++++++++++++++++++++ src/browser/cssom/css_stylesheet.zig | 36 +++++++++------- src/browser/cssom/cssom.zig | 2 + 4 files changed, 86 insertions(+), 49 deletions(-) create mode 100644 src/browser/cssom/css_rule_list.zig diff --git a/src/browser/cssom/css_rule.zig b/src/browser/cssom/css_rule.zig index 686f5b00..dceff93c 100644 --- a/src/browser/cssom/css_rule.zig +++ b/src/browser/cssom/css_rule.zig @@ -43,38 +43,3 @@ pub const CSSImportRule = struct { style_sheet: CSSStyleSheet, supports_text: ?[]const u8, }; - -// pub const CSSGroupingRule = struct { -// pub const prototype = *CSSRule; -// list: std.ArrayListUnmanaged(CSSRule), - -// pub fn _insertRule(self: *CSSGroupingRule, rule: []const u8, _index: ?usize, page: *Page) !usize { -// const index = _index orelse 0; -// if (index > self.list.items.len) return error.IndexSizeError; - -// const css_rule: CSSRule = .{ .css_text = rule, .parent_rule = null, .parent_stylesheet = null }; -// try self.list.insert(page.arena, index, css_rule); -// return self.list.items.len; -// } - -// pub fn _deleteRule(self: *CSSGroupingRule, index: usize) !void { -// if (index > self.list.items.len) return error.IndexSizeError; -// _ = self.list.orderedRemove(index); -// } -// }; - -// pub const CSSStyleRule = struct { -// pub const prototype = *CSSGroupingRule; -// selector_text: []const u8, -// style: CSSStyleDeclaration, -// }; - -// pub const CSSFontFaceRule = struct { -// pub const prototype = *CSSRule; -// }; - -// pub const CSSPageRule = struct { -// pub const prototype = *CSSGroupingRule; -// selector_text: []const u8, -// style: CSSStyleDeclaration, -// }; diff --git a/src/browser/cssom/css_rule_list.zig b/src/browser/cssom/css_rule_list.zig new file mode 100644 index 00000000..18993b7a --- /dev/null +++ b/src/browser/cssom/css_rule_list.zig @@ -0,0 +1,62 @@ +// Copyright (C) 2023-2024 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const std = @import("std"); + +const Page = @import("../page.zig").Page; +const StyleSheet = @import("stylesheet.zig").StyleSheet; + +const CSSRule = @import("css_rule.zig").CSSRule; +const CSSImportRule = @import("css_rule.zig").CSSImportRule; + +pub const CSSRuleList = struct { + list: std.ArrayListUnmanaged([]const u8), + + pub fn constructor() CSSRuleList { + return .{ .list = .empty }; + } + + pub fn _item(self: *CSSRuleList, _index: u32) ?CSSRule { + const index: usize = @intCast(_index); + + if (index > self.list.items.len) { + return null; + } + + // todo: for now, just return null. + // this depends on properly parsing CSSRule + return null; + } + + pub fn get_length(self: *CSSRuleList) u32 { + return @intCast(self.list.items.len); + } +}; + +const testing = @import("../../testing.zig"); +test "Browser.CSS.CSSRuleList" { + var runner = try testing.jsRunner(testing.tracking_allocator, .{}); + defer runner.deinit(); + + try runner.testCases(&.{ + .{ "let list = new CSSRuleList()", "undefined" }, + .{ "list instanceof CSSRuleList", "true" }, + .{ "list.length", "0" }, + .{ "list.item(0)", "null" }, + }, .{}); +} diff --git a/src/browser/cssom/css_stylesheet.zig b/src/browser/cssom/css_stylesheet.zig index 910110db..454117ed 100644 --- a/src/browser/cssom/css_stylesheet.zig +++ b/src/browser/cssom/css_stylesheet.zig @@ -21,55 +21,57 @@ const std = @import("std"); const Page = @import("../page.zig").Page; const StyleSheet = @import("stylesheet.zig").StyleSheet; -const CSSRule = @import("css_rule.zig").CSSRule; +const CSSRuleList = @import("css_rule_list.zig").CSSRuleList; const CSSImportRule = @import("css_rule.zig").CSSImportRule; pub const CSSStyleSheet = struct { pub const prototype = *StyleSheet; - // TODO: For now, we won't parse any rules. - css_rules: std.ArrayListUnmanaged([]const u8), - - // TODO: Support owner_rule here. + css_rules: *CSSRuleList, + owner_rule: ?*CSSImportRule, const CSSStyleSheetOpts = struct { - base_url: ?[]const u8, + base_url: ?[]const u8 = null, // TODO: Suupport media disabled: bool = false, }; - pub fn constructor(_opts: ?CSSStyleSheetOpts) CSSStyleSheet { + pub fn constructor(_opts: ?CSSStyleSheetOpts, page: *Page) !CSSStyleSheet { const opts = _opts orelse CSSStyleSheetOpts{}; _ = opts; - return .{ .css_rules = .empty, .owner_rule = null }; + const arena = page.arena; + const rules = try arena.create(CSSRuleList); + rules.* = .constructor(); + + return .{ .css_rules = rules, .owner_rule = null }; } pub fn get_ownerRule(_: *CSSStyleSheet) ?*CSSImportRule { return null; } - pub fn get_cssRules(self: *CSSStyleSheet) *std.ArrayListUnmanaged([]const u8) { + pub fn get_cssRules(self: *CSSStyleSheet) *CSSRuleList { return self.css_rules; } pub fn _insertRule(self: *CSSStyleSheet, rule: []const u8, _index: ?usize, page: *Page) !usize { const index = _index orelse 0; - if (index > self.css_rules.items.len) { + if (index > self.css_rules.list.items.len) { return error.IndexSize; } const arena = page.arena; - try self.css_rules.insert(arena, index, arena.dupe(u8, rule)); + try self.css_rules.list.insert(arena, index, try arena.dupe(u8, rule)); return index; } pub fn _deleteRule(self: *CSSStyleSheet, index: usize) !void { - if (index > self.css_rules.items.len) { + if (index > self.css_rules.list.items.len) { return error.IndexSize; } - _ = self.css_rules.orderedRemove(index); + _ = self.css_rules.list.orderedRemove(index); } }; @@ -79,6 +81,12 @@ test "Browser.CSS.StyleSheet" { defer runner.deinit(); try runner.testCases(&.{ - .{ "let css = new CSSStylesheet()", "" }, + .{ "let css = new CSSStyleSheet()", "undefined" }, + .{ "css instanceof CSSStyleSheet", "true" }, + .{ "css.cssRules.length", "0" }, + .{ "css.ownerRule", "null" }, + .{ "let index1 = css.insertRule('body { color: red; }', 0)", "undefined" }, + .{ "index1", "0" }, + .{ "css.cssRules.length", "1" }, }, .{}); } diff --git a/src/browser/cssom/cssom.zig b/src/browser/cssom/cssom.zig index 6635430e..ffd2eabb 100644 --- a/src/browser/cssom/cssom.zig +++ b/src/browser/cssom/cssom.zig @@ -19,10 +19,12 @@ pub const Stylesheet = @import("stylesheet.zig").StyleSheet; pub const CSSStylesheet = @import("css_stylesheet.zig").CSSStyleSheet; pub const CSSStyleDeclaration = @import("css_style_declaration.zig").CSSStyleDeclaration; +pub const CSSRuleList = @import("css_rule_list.zig").CSSRuleList; pub const Interfaces = .{ Stylesheet, CSSStylesheet, CSSStyleDeclaration, + CSSRuleList, @import("css_rule.zig").Interfaces, };