From cc3a49829480a11e984e8c8fb10c230bb1bde25e Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Thu, 25 Dec 2025 16:47:08 +0800 Subject: [PATCH] legacy tests --- src/browser/tests/document/document.html | 24 ++++++++ src/browser/tests/event/custom_event.html | 7 +++ src/browser/tests/legacy/dom/document.html | 10 +--- .../legacy/dom/intersection_observer.html | 6 +- .../tests/legacy/dom/message_channel.html | 60 ------------------- src/browser/tests/legacy/dom/shadow_root.html | 49 --------------- src/browser/webapi/Document.zig | 52 +++++++++++++++- src/browser/webapi/event/CustomEvent.zig | 21 +++++++ 8 files changed, 109 insertions(+), 120 deletions(-) delete mode 100644 src/browser/tests/legacy/dom/message_channel.html delete mode 100644 src/browser/tests/legacy/dom/shadow_root.html diff --git a/src/browser/tests/document/document.html b/src/browser/tests/document/document.html index 4ec11411..5f4e3e7f 100644 --- a/src/browser/tests/document/document.html +++ b/src/browser/tests/document/document.html @@ -258,3 +258,27 @@ testing.expectEqual('text node', body.childNodes[0].textContent); } + + + + diff --git a/src/browser/tests/event/custom_event.html b/src/browser/tests/event/custom_event.html index 97f114d8..1835b205 100644 --- a/src/browser/tests/event/custom_event.html +++ b/src/browser/tests/event/custom_event.html @@ -56,7 +56,14 @@ { const event = document.createEvent('CustomEvent'); testing.expectEqual('', event.type); + testing.expectEqual(false, event.bubbles); + testing.expectEqual(false, event.cancelable); testing.expectEqual(null, event.detail); + + event.initCustomEvent('tea', true, true); + testing.expectEqual('tea', event.type); + testing.expectEqual(true, event.bubbles); + testing.expectEqual(true, event.cancelable); } diff --git a/src/browser/tests/legacy/dom/document.html b/src/browser/tests/legacy/dom/document.html index 822134d0..1eb53db4 100644 --- a/src/browser/tests/legacy/dom/document.html +++ b/src/browser/tests/legacy/dom/document.html @@ -85,9 +85,6 @@ v = document.createTextNode('foo'); testing.expectEqual('#text', v.nodeName); - v = document.createCDATASection('foo'); - testing.expectEqual('#cdata-section', v.nodeName); - v = document.createAttribute('foo'); testing.expectEqual('foo', v.nodeName); @@ -108,7 +105,7 @@ - --> - diff --git a/src/browser/tests/legacy/dom/shadow_root.html b/src/browser/tests/legacy/dom/shadow_root.html deleted file mode 100644 index 88a302db..00000000 --- a/src/browser/tests/legacy/dom/shadow_root.html +++ /dev/null @@ -1,49 +0,0 @@ - -
node
- - - diff --git a/src/browser/webapi/Document.zig b/src/browser/webapi/Document.zig index 54aa7f94..a4d20ed1 100644 --- a/src/browser/webapi/Document.zig +++ b/src/browser/webapi/Document.zig @@ -51,6 +51,7 @@ _active_element: ?*Element = null, _style_sheets: ?*StyleSheetList = null, _write_insertion_point: ?*Node = null, _script_created_parser: ?Parser.Streaming = null, +_adopted_style_sheets: ?js.Object = null, pub const Type = union(enum) { generic, @@ -250,7 +251,7 @@ pub fn createTextNode(_: *const Document, data: []const u8, page: *Page) !*Node pub fn createCDATASection(self: *const Document, data: []const u8, page: *Page) !*Node { switch (self._type) { - .html => return error.NotSupported, + .html => return error.NotSupported, // cannot create a CDataSection in an HTMLDocument .xml => return page.createCDATASection(data), .generic => return page.createCDATASection(data), } @@ -537,6 +538,51 @@ pub fn close(self: *Document, page: *Page) !void { page.documentIsComplete(); } +pub fn getFirstElementChild(self: *Document) ?*Element { + var it = self.asNode().childrenIterator(); + while (it.next()) |child| { + if (child.is(Element)) |el| { + return el; + } + } + return null; +} + +pub fn getLastElementChild(self: *Document) ?*Element { + var maybe_child = self.asNode().lastChild(); + while (maybe_child) |child| { + if (child.is(Element)) |el| { + return el; + } + maybe_child = child.previousSibling(); + } + return null; +} + +pub fn getChildElementCount(self: *Document) u32 { + var i: u32 = 0; + var it = self.asNode().childrenIterator(); + while (it.next()) |child| { + if (child.is(Element) != null) { + i += 1; + } + } + return i; +} + + pub fn getAdoptedStyleSheets(self: *Document, page: *Page) !js.Object { + if (self._adopted_style_sheets) |ass| { + return ass; + } + const obj = try page.js.createArray(0).persist(); + self._adopted_style_sheets = obj; + return obj; +} + +pub fn setAdoptedStyleSheets(self: *Document, sheets: js.Object) !void { + self._adopted_style_sheets = try sheets.persist(); +} + const ReadyState = enum { loading, interactive, @@ -603,6 +649,10 @@ pub const JsApi = struct { pub const open = bridge.function(Document.open, .{ .dom_exception = true }); pub const close = bridge.function(Document.close, .{ .dom_exception = true }); pub const doctype = bridge.accessor(Document.getDocType, null, .{}); + pub const firstElementChild = bridge.accessor(Document.getFirstElementChild, null, .{}); + pub const lastElementChild = bridge.accessor(Document.getLastElementChild, null, .{}); + pub const childElementCount = bridge.accessor(Document.getChildElementCount, null, .{}); + pub const adoptedStyleSheets = bridge.accessor(Document.getAdoptedStyleSheets, Document.setAdoptedStyleSheets, .{}); pub const defaultView = bridge.accessor(struct { fn defaultView(_: *const Document, page: *Page) *@import("Window.zig") { diff --git a/src/browser/webapi/event/CustomEvent.zig b/src/browser/webapi/event/CustomEvent.zig index 1e420e8c..6456b6cf 100644 --- a/src/browser/webapi/event/CustomEvent.zig +++ b/src/browser/webapi/event/CustomEvent.zig @@ -18,6 +18,7 @@ const std = @import("std"); const js = @import("../../js/js.zig"); +const String = @import("../../..//string.zig").String; const Page = @import("../../Page.zig"); const Event = @import("../Event.zig"); @@ -52,6 +53,25 @@ pub fn init(typ: []const u8, opts_: ?Options, page: *Page) !*CustomEvent { return event; } + pub fn initCustomEvent( + self: *CustomEvent, + event_string: []const u8, + bubbles: bool, + cancelable: bool, + detail_: ?js.Object, + page: *Page, +) !void { + // This function can only be called after the constructor has called. + // So we assume proto is initialized already by constructor. + self._proto._type_string = try String.init(page.arena, event_string, .{}); + self._proto._bubbles = bubbles; + self._proto._cancelable = cancelable; + // Detail is stored separately. + if (detail_) |detail| { + self._detail = try detail.persist(); + } +} + pub fn asEvent(self: *CustomEvent) *Event { return self._proto; } @@ -71,6 +91,7 @@ pub const JsApi = struct { pub const constructor = bridge.constructor(CustomEvent.init, .{}); pub const detail = bridge.accessor(CustomEvent.getDetail, null, .{}); + pub const initCustomEvent = bridge.function(CustomEvent.initCustomEvent, .{}); }; const testing = @import("../../../testing.zig");