From ba948184153921836239daf649d8321190dd0aef Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Tue, 3 Jun 2025 13:33:06 -0700 Subject: [PATCH 1/5] add CSSStyleSheet --- src/browser/cssom/css_rule.zig | 80 ++++++++++++++++++++ src/browser/cssom/css_style_declaration.zig | 8 +- src/browser/cssom/css_stylesheet.zig | 84 +++++++++++++++++++++ src/browser/cssom/cssom.zig | 28 +++++++ src/browser/cssom/stylesheet.zig | 55 ++++++++++++++ src/browser/env.zig | 2 +- 6 files changed, 249 insertions(+), 8 deletions(-) create mode 100644 src/browser/cssom/css_rule.zig create mode 100644 src/browser/cssom/css_stylesheet.zig create mode 100644 src/browser/cssom/cssom.zig create mode 100644 src/browser/cssom/stylesheet.zig diff --git a/src/browser/cssom/css_rule.zig b/src/browser/cssom/css_rule.zig new file mode 100644 index 000000000..686f5b004 --- /dev/null +++ b/src/browser/cssom/css_rule.zig @@ -0,0 +1,80 @@ +// 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 CSSStyleDeclaration = @import("css_style_declaration.zig").CSSStyleDeclaration; +const CSSStyleSheet = @import("css_stylesheet.zig").CSSStyleSheet; + +pub const Interfaces = .{ + CSSRule, + CSSImportRule, +}; + +// https://developer.mozilla.org/en-US/docs/Web/API/CSSRule +pub const CSSRule = struct { + css_text: []const u8, + parent_rule: ?*CSSRule = null, + parent_stylesheet: ?*CSSStyleSheet = null, +}; + +pub const CSSImportRule = struct { + pub const prototype = *CSSRule; + href: []const u8, + layer_name: ?[]const u8, + media: void, + 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_style_declaration.zig b/src/browser/cssom/css_style_declaration.zig index 98a9015d5..6ec1d880e 100644 --- a/src/browser/cssom/css_style_declaration.zig +++ b/src/browser/cssom/css_style_declaration.zig @@ -20,15 +20,9 @@ const std = @import("std"); const CSSParser = @import("./css_parser.zig").CSSParser; const CSSValueAnalyzer = @import("./css_value_analyzer.zig").CSSValueAnalyzer; +const CSSRule = @import("css_rule.zig").CSSRule; const Page = @import("../page.zig").Page; -pub const Interfaces = .{ - CSSStyleDeclaration, - CSSRule, -}; - -const CSSRule = struct {}; - pub const CSSStyleDeclaration = struct { store: std.StringHashMapUnmanaged(Property), order: std.ArrayListUnmanaged([]const u8), diff --git a/src/browser/cssom/css_stylesheet.zig b/src/browser/cssom/css_stylesheet.zig new file mode 100644 index 000000000..910110dba --- /dev/null +++ b/src/browser/cssom/css_stylesheet.zig @@ -0,0 +1,84 @@ +// 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 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. + + const CSSStyleSheetOpts = struct { + base_url: ?[]const u8, + // TODO: Suupport media + disabled: bool = false, + }; + + pub fn constructor(_opts: ?CSSStyleSheetOpts) CSSStyleSheet { + const opts = _opts orelse CSSStyleSheetOpts{}; + _ = opts; + + return .{ .css_rules = .empty, .owner_rule = null }; + } + + pub fn get_ownerRule(_: *CSSStyleSheet) ?*CSSImportRule { + return null; + } + + pub fn get_cssRules(self: *CSSStyleSheet) *std.ArrayListUnmanaged([]const u8) { + 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) { + return error.IndexSize; + } + + const arena = page.arena; + try self.css_rules.insert(arena, index, arena.dupe(u8, rule)); + return index; + } + + pub fn _deleteRule(self: *CSSStyleSheet, index: usize) !void { + if (index > self.css_rules.items.len) { + return error.IndexSize; + } + + _ = self.css_rules.orderedRemove(index); + } +}; + +const testing = @import("../../testing.zig"); +test "Browser.CSS.StyleSheet" { + var runner = try testing.jsRunner(testing.tracking_allocator, .{}); + defer runner.deinit(); + + try runner.testCases(&.{ + .{ "let css = new CSSStylesheet()", "" }, + }, .{}); +} diff --git a/src/browser/cssom/cssom.zig b/src/browser/cssom/cssom.zig new file mode 100644 index 000000000..6635430e9 --- /dev/null +++ b/src/browser/cssom/cssom.zig @@ -0,0 +1,28 @@ +// 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 . + +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 Interfaces = .{ + Stylesheet, + CSSStylesheet, + CSSStyleDeclaration, + @import("css_rule.zig").Interfaces, +}; diff --git a/src/browser/cssom/stylesheet.zig b/src/browser/cssom/stylesheet.zig new file mode 100644 index 000000000..61fc4d40a --- /dev/null +++ b/src/browser/cssom/stylesheet.zig @@ -0,0 +1,55 @@ +// 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 parser = @import("../netsurf.zig"); + +// https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet#specifications +pub const StyleSheet = struct { + disabled: bool, + href: []const u8, + owner_node: *parser.Node, + parent_stylesheet: ?*StyleSheet, + title: []const u8, + type: []const u8, + + pub fn get_disabled(self: *StyleSheet) bool { + return self.disabled; + } + + pub fn get_href(self: *StyleSheet) []const u8 { + return self.href; + } + + // TODO: media + + pub fn get_ownerNode(self: *StyleSheet) *parser.Node { + return self.owner_node; + } + + pub fn get_parentStyleSheet(self: *StyleSheet) ?*StyleSheet { + return self.parent_stylesheet; + } + + pub fn get_title(self: *StyleSheet) []const u8 { + return self.title; + } + + pub fn get_type(self: *StyleSheet) []const u8 { + return self.type; + } +}; diff --git a/src/browser/env.zig b/src/browser/env.zig index 806391e5e..aa03c9be6 100644 --- a/src/browser/env.zig +++ b/src/browser/env.zig @@ -22,7 +22,7 @@ const WebApis = struct { pub const Interfaces = generate.Tuple(.{ @import("crypto/crypto.zig").Crypto, @import("console/console.zig").Console, - @import("cssom/css_style_declaration.zig").Interfaces, + @import("cssom/cssom.zig").Interfaces, @import("dom/dom.zig").Interfaces, @import("encoding/text_encoder.zig").Interfaces, @import("events/event.zig").Interfaces, From 2656cc78426f85d0b55ad09fa57476052beb38c8 Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Tue, 17 Jun 2025 21:21:37 -0700 Subject: [PATCH 2/5] 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 686f5b004..dceff93cf 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 000000000..18993b7a1 --- /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 910110dba..454117edb 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 6635430e9..ffd2eabb3 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, }; From 97bc19e4ae9930df49175747cdf03a791b5993be Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Wed, 18 Jun 2025 11:31:43 -0700 Subject: [PATCH 3/5] clean up various imports in CSSOM --- src/browser/cssom/css_rule.zig | 3 --- src/browser/cssom/css_rule_list.zig | 2 -- src/browser/cssom/css_stylesheet.zig | 21 +++++++++------------ src/browser/cssom/stylesheet.zig | 26 +++++++++++++------------- 4 files changed, 22 insertions(+), 30 deletions(-) diff --git a/src/browser/cssom/css_rule.zig b/src/browser/cssom/css_rule.zig index dceff93cf..857c0a8aa 100644 --- a/src/browser/cssom/css_rule.zig +++ b/src/browser/cssom/css_rule.zig @@ -18,9 +18,6 @@ const std = @import("std"); -const Page = @import("../page.zig").Page; - -const CSSStyleDeclaration = @import("css_style_declaration.zig").CSSStyleDeclaration; const CSSStyleSheet = @import("css_stylesheet.zig").CSSStyleSheet; pub const Interfaces = .{ diff --git a/src/browser/cssom/css_rule_list.zig b/src/browser/cssom/css_rule_list.zig index 18993b7a1..bf5222f28 100644 --- a/src/browser/cssom/css_rule_list.zig +++ b/src/browser/cssom/css_rule_list.zig @@ -18,9 +18,7 @@ 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; diff --git a/src/browser/cssom/css_stylesheet.zig b/src/browser/cssom/css_stylesheet.zig index 454117edb..e18e88bea 100644 --- a/src/browser/cssom/css_stylesheet.zig +++ b/src/browser/cssom/css_stylesheet.zig @@ -25,9 +25,8 @@ const CSSRuleList = @import("css_rule_list.zig").CSSRuleList; const CSSImportRule = @import("css_rule.zig").CSSImportRule; pub const CSSStyleSheet = struct { - pub const prototype = *StyleSheet; - - css_rules: *CSSRuleList, + proto: StyleSheet, + css_rules: CSSRuleList, owner_rule: ?*CSSImportRule, const CSSStyleSheetOpts = struct { @@ -36,15 +35,13 @@ pub const CSSStyleSheet = struct { disabled: bool = false, }; - pub fn constructor(_opts: ?CSSStyleSheetOpts, page: *Page) !CSSStyleSheet { + pub fn constructor(_opts: ?CSSStyleSheetOpts) !CSSStyleSheet { const opts = _opts orelse CSSStyleSheetOpts{}; - _ = opts; - - const arena = page.arena; - const rules = try arena.create(CSSRuleList); - rules.* = .constructor(); - - return .{ .css_rules = rules, .owner_rule = null }; + return .{ + .proto = StyleSheet{ .disabled = opts.disabled }, + .css_rules = .constructor(), + .owner_rule = null, + }; } pub fn get_ownerRule(_: *CSSStyleSheet) ?*CSSImportRule { @@ -52,7 +49,7 @@ pub const CSSStyleSheet = struct { } pub fn get_cssRules(self: *CSSStyleSheet) *CSSRuleList { - return self.css_rules; + return &self.css_rules; } pub fn _insertRule(self: *CSSStyleSheet, rule: []const u8, _index: ?usize, page: *Page) !usize { diff --git a/src/browser/cssom/stylesheet.zig b/src/browser/cssom/stylesheet.zig index 61fc4d40a..7086063ce 100644 --- a/src/browser/cssom/stylesheet.zig +++ b/src/browser/cssom/stylesheet.zig @@ -20,36 +20,36 @@ const parser = @import("../netsurf.zig"); // https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet#specifications pub const StyleSheet = struct { - disabled: bool, - href: []const u8, - owner_node: *parser.Node, - parent_stylesheet: ?*StyleSheet, - title: []const u8, - type: []const u8, - - pub fn get_disabled(self: *StyleSheet) bool { + disabled: bool = false, + href: []const u8 = "", + owner_node: ?*parser.Node = null, + parent_stylesheet: ?*StyleSheet = null, + title: []const u8 = "", + type: []const u8 = "text/css", + + pub fn get_disabled(self: *const StyleSheet) bool { return self.disabled; } - pub fn get_href(self: *StyleSheet) []const u8 { + pub fn get_href(self: *const StyleSheet) []const u8 { return self.href; } // TODO: media - pub fn get_ownerNode(self: *StyleSheet) *parser.Node { + pub fn get_ownerNode(self: *const StyleSheet) ?*parser.Node { return self.owner_node; } - pub fn get_parentStyleSheet(self: *StyleSheet) ?*StyleSheet { + pub fn get_parentStyleSheet(self: *const StyleSheet) ?*StyleSheet { return self.parent_stylesheet; } - pub fn get_title(self: *StyleSheet) []const u8 { + pub fn get_title(self: *const StyleSheet) []const u8 { return self.title; } - pub fn get_type(self: *StyleSheet) []const u8 { + pub fn get_type(self: *const StyleSheet) []const u8 { return self.type; } }; From 54bd55d45d66d44f74f98c55cb8ab88e9d5473d0 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Thu, 19 Jun 2025 10:25:13 +0800 Subject: [PATCH 4/5] fix CSSStyleSheet prototype --- src/browser/cssom/css_stylesheet.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/browser/cssom/css_stylesheet.zig b/src/browser/cssom/css_stylesheet.zig index e18e88bea..bb03d79cc 100644 --- a/src/browser/cssom/css_stylesheet.zig +++ b/src/browser/cssom/css_stylesheet.zig @@ -25,6 +25,8 @@ const CSSRuleList = @import("css_rule_list.zig").CSSRuleList; const CSSImportRule = @import("css_rule.zig").CSSImportRule; pub const CSSStyleSheet = struct { + pub const prototype = *StyleSheet; + proto: StyleSheet, css_rules: CSSRuleList, owner_rule: ?*CSSImportRule, From 2c940d4fd6c2177130e59946e0f1825b3d92768a Mon Sep 17 00:00:00 2001 From: sjorsdonkers <72333389+sjorsdonkers@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:59:28 +0200 Subject: [PATCH 5/5] browser context proxyServer --- src/cdp/cdp.zig | 3 +++ src/cdp/domains/target.zig | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/cdp/cdp.zig b/src/cdp/cdp.zig index ed3388a4e..275440639 100644 --- a/src/cdp/cdp.zig +++ b/src/cdp/cdp.zig @@ -320,6 +320,7 @@ pub fn BrowserContext(comptime CDP_T: type) type { inspector: Inspector, isolated_world: ?IsolatedWorld, + http_proxy_before: ??std.Uri = null, const Self = @This(); @@ -374,6 +375,8 @@ pub fn BrowserContext(comptime CDP_T: type) type { self.node_registry.deinit(); self.node_search_list.deinit(); self.cdp.browser.notification.unregisterAll(self); + + if (self.http_proxy_before) |prev_proxy| self.cdp.browser.http_client.http_proxy = prev_proxy; } pub fn reset(self: *Self) void { diff --git a/src/cdp/domains/target.zig b/src/cdp/domains/target.zig index c0d76ec00..5b2a4f736 100644 --- a/src/cdp/domains/target.zig +++ b/src/cdp/domains/target.zig @@ -66,11 +66,30 @@ fn getBrowserContexts(cmd: anytype) !void { } fn createBrowserContext(cmd: anytype) !void { + const params = try cmd.params(struct { + disposeOnDetach: bool = false, + proxyServer: ?[]const u8 = null, + proxyBypassList: ?[]const u8 = null, + originsWithUniversalNetworkAccess: ?[]const []const u8 = null, + }); + if (params) |p| { + if (p.disposeOnDetach or p.proxyBypassList != null or p.originsWithUniversalNetworkAccess != null) std.debug.print("Target.createBrowserContext: Not implemented param set\n", .{}); + } + const bc = cmd.createBrowserContext() catch |err| switch (err) { error.AlreadyExists => return cmd.sendError(-32000, "Cannot have more than one browser context at a time"), else => return err, }; + if (params) |p| { + if (p.proxyServer) |proxy| { + // For now the http client is not in the browser context so we assume there is just 1. + bc.http_proxy_before = cmd.cdp.browser.http_client.http_proxy; + const proxy_cp = try cmd.cdp.browser.http_client.allocator.dupe(u8, proxy); + cmd.cdp.browser.http_client.http_proxy = try std.Uri.parse(proxy_cp); + } + } + return cmd.sendResult(.{ .browserContextId = bc.id, }, .{});