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");