Skip to content

Commit edd41b3

Browse files
authored
Merge pull request #1033 from lightpanda-io/nikneym/custom-event
Support for CustomEvent in document.createEvent
2 parents 139d003 + 9c83b26 commit edd41b3

File tree

4 files changed

+59
-7
lines changed

4 files changed

+59
-7
lines changed

src/browser/dom/document.zig

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ const CSSStyleSheet = @import("../cssom/CSSStyleSheet.zig");
3636
const NodeIterator = @import("node_iterator.zig").NodeIterator;
3737
const Range = @import("range.zig").Range;
3838

39+
const CustomEvent = @import("../events/custom_event.zig").CustomEvent;
40+
3941
const Env = @import("../env.zig").Env;
4042

4143
const DOMImplementation = @import("implementation.zig").DOMImplementation;
@@ -110,13 +112,21 @@ pub const Document = struct {
110112
return try parser.documentGetDoctype(self);
111113
}
112114

113-
pub fn _createEvent(_: *parser.Document, eventCstr: []const u8) !*parser.Event {
114-
// TODO: for now only "Event" constructor is supported
115-
// see table on https://dom.spec.whatwg.org/#dom-document-createevent $2
115+
pub fn _createEvent(_: *parser.Document, eventCstr: []const u8) !union(enum) {
116+
base: *parser.Event,
117+
custom: CustomEvent,
118+
} {
116119
if (std.ascii.eqlIgnoreCase(eventCstr, "Event") or std.ascii.eqlIgnoreCase(eventCstr, "Events")) {
117-
return try parser.eventCreate();
120+
return .{ .base = try parser.eventCreate() };
121+
}
122+
123+
// Not documented in MDN but supported in Chrome.
124+
// This is actually both instance of `Event` and `CustomEvent`.
125+
if (std.ascii.eqlIgnoreCase(eventCstr, "CustomEvent")) {
126+
return .{ .custom = try CustomEvent.constructor(eventCstr, null) };
118127
}
119-
return parser.DOMError.NotSupported;
128+
129+
return error.NotSupported;
120130
}
121131

122132
pub fn _getElementById(self: *parser.Document, id: []const u8) !?ElementUnion {

src/browser/events/custom_event.zig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
const parser = @import("../netsurf.zig");
2020
const Event = @import("event.zig").Event;
2121
const JsObject = @import("../env.zig").JsObject;
22+
const netsurf = @import("../netsurf.zig");
2223

2324
// https://dom.spec.whatwg.org/#interface-customevent
2425
pub const CustomEvent = struct {
@@ -55,6 +56,27 @@ pub const CustomEvent = struct {
5556
pub fn get_detail(self: *CustomEvent) ?JsObject {
5657
return self.detail;
5758
}
59+
60+
// Initializes an already created `CustomEvent`.
61+
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/initCustomEvent
62+
pub fn _initCustomEvent(
63+
self: *CustomEvent,
64+
event_type: []const u8,
65+
can_bubble: bool,
66+
cancelable: bool,
67+
maybe_detail: ?JsObject,
68+
) !void {
69+
// This function can only be called after the constructor has called.
70+
// So we assume proto is initialized already by constructor.
71+
self.proto.type = try netsurf.strFromData(event_type);
72+
self.proto.bubble = can_bubble;
73+
self.proto.cancelable = cancelable;
74+
self.proto.is_initialised = true;
75+
// Detail is stored separately.
76+
if (maybe_detail) |detail| {
77+
self.detail = try detail.persist();
78+
}
79+
}
5880
};
5981

6082
const testing = @import("../../testing.zig");

src/browser/netsurf.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ inline fn strToData(s: *String) []const u8 {
106106
return data[0..c.dom_string_byte_length(s)];
107107
}
108108

109-
inline fn strFromData(data: []const u8) !*String {
109+
pub inline fn strFromData(data: []const u8) !*String {
110110
var s: ?*String = null;
111111
const err = c.dom_string_create(data.ptr, data.len, &s);
112112
try DOMErr(err);

src/tests/dom/document.html

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
let byTagNameAll = document.getElementsByTagName('*');
6161
// If you add a script block (or change the HTML in any other way on this
6262
// page), this test will break. Adjust it accordingly.
63-
testing.expectEqual(20, byTagNameAll.length);
63+
testing.expectEqual(21, byTagNameAll.length);
6464
testing.expectEqual('html', byTagNameAll.item(0).localName);
6565
testing.expectEqual('SCRIPT', byTagNameAll.item(11).tagName);
6666

@@ -167,3 +167,23 @@
167167
acss.push(new CSSStyleSheet());
168168
testing.expectEqual(1, acss.length);
169169
</script>
170+
171+
<script id=createEvent>
172+
const event = document.createEvent("Event");
173+
174+
testing.expectEqual(true, event instanceof Event);
175+
testing.expectEqual("", event.type);
176+
177+
const customEvent = document.createEvent("CustomEvent");
178+
customEvent.initCustomEvent("hey", false, false);
179+
180+
testing.expectEqual(true, customEvent instanceof CustomEvent);
181+
testing.expectEqual(true, customEvent instanceof Event);
182+
183+
testing.withError(
184+
(err) => {
185+
// TODO: Check the error type.
186+
},
187+
() => document.createEvent("InvalidType"),
188+
);
189+
</script>

0 commit comments

Comments
 (0)