diff --git a/src/browser/dom/document.zig b/src/browser/dom/document.zig index a82ec6e35..d3e71ff30 100644 --- a/src/browser/dom/document.zig +++ b/src/browser/dom/document.zig @@ -36,6 +36,8 @@ const CSSStyleSheet = @import("../cssom/CSSStyleSheet.zig"); const NodeIterator = @import("node_iterator.zig").NodeIterator; const Range = @import("range.zig").Range; +const CustomEvent = @import("../events/custom_event.zig").CustomEvent; + const Env = @import("../env.zig").Env; const DOMImplementation = @import("implementation.zig").DOMImplementation; @@ -110,13 +112,21 @@ pub const Document = struct { return try parser.documentGetDoctype(self); } - pub fn _createEvent(_: *parser.Document, eventCstr: []const u8) !*parser.Event { - // TODO: for now only "Event" constructor is supported - // see table on https://dom.spec.whatwg.org/#dom-document-createevent $2 + pub fn _createEvent(_: *parser.Document, eventCstr: []const u8) !union(enum) { + base: *parser.Event, + custom: CustomEvent, + } { if (std.ascii.eqlIgnoreCase(eventCstr, "Event") or std.ascii.eqlIgnoreCase(eventCstr, "Events")) { - return try parser.eventCreate(); + return .{ .base = try parser.eventCreate() }; + } + + // Not documented in MDN but supported in Chrome. + // This is actually both instance of `Event` and `CustomEvent`. + if (std.ascii.eqlIgnoreCase(eventCstr, "CustomEvent")) { + return .{ .custom = try CustomEvent.constructor(eventCstr, null) }; } - return parser.DOMError.NotSupported; + + return error.NotSupported; } pub fn _getElementById(self: *parser.Document, id: []const u8) !?ElementUnion { diff --git a/src/browser/events/custom_event.zig b/src/browser/events/custom_event.zig index 3bf8179f5..530eaf5c8 100644 --- a/src/browser/events/custom_event.zig +++ b/src/browser/events/custom_event.zig @@ -19,6 +19,7 @@ const parser = @import("../netsurf.zig"); const Event = @import("event.zig").Event; const JsObject = @import("../env.zig").JsObject; +const netsurf = @import("../netsurf.zig"); // https://dom.spec.whatwg.org/#interface-customevent pub const CustomEvent = struct { @@ -55,6 +56,27 @@ pub const CustomEvent = struct { pub fn get_detail(self: *CustomEvent) ?JsObject { return self.detail; } + + // Initializes an already created `CustomEvent`. + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/initCustomEvent + pub fn _initCustomEvent( + self: *CustomEvent, + event_type: []const u8, + can_bubble: bool, + cancelable: bool, + maybe_detail: ?JsObject, + ) !void { + // This function can only be called after the constructor has called. + // So we assume proto is initialized already by constructor. + self.proto.type = try netsurf.strFromData(event_type); + self.proto.bubble = can_bubble; + self.proto.cancelable = cancelable; + self.proto.is_initialised = true; + // Detail is stored separately. + if (maybe_detail) |detail| { + self.detail = try detail.persist(); + } + } }; const testing = @import("../../testing.zig"); diff --git a/src/browser/netsurf.zig b/src/browser/netsurf.zig index 079dfc0cc..026f5ade2 100644 --- a/src/browser/netsurf.zig +++ b/src/browser/netsurf.zig @@ -106,7 +106,7 @@ inline fn strToData(s: *String) []const u8 { return data[0..c.dom_string_byte_length(s)]; } -inline fn strFromData(data: []const u8) !*String { +pub inline fn strFromData(data: []const u8) !*String { var s: ?*String = null; const err = c.dom_string_create(data.ptr, data.len, &s); try DOMErr(err); diff --git a/src/tests/dom/document.html b/src/tests/dom/document.html index 6eb61f342..be95a0027 100644 --- a/src/tests/dom/document.html +++ b/src/tests/dom/document.html @@ -60,7 +60,7 @@ let byTagNameAll = document.getElementsByTagName('*'); // If you add a script block (or change the HTML in any other way on this // page), this test will break. Adjust it accordingly. - testing.expectEqual(20, byTagNameAll.length); + testing.expectEqual(21, byTagNameAll.length); testing.expectEqual('html', byTagNameAll.item(0).localName); testing.expectEqual('SCRIPT', byTagNameAll.item(11).tagName); @@ -167,3 +167,23 @@ acss.push(new CSSStyleSheet()); testing.expectEqual(1, acss.length); + +