Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/browser/dom/document.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
20 changes: 20 additions & 0 deletions src/browser/events/custom_event.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -55,6 +56,25 @@ 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,
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.
self.detail = detail;
}
};

const testing = @import("../../testing.zig");
Expand Down
2 changes: 1 addition & 1 deletion src/browser/netsurf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
22 changes: 21 additions & 1 deletion src/tests/dom/document.html
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -167,3 +167,23 @@
acss.push(new CSSStyleSheet());
testing.expectEqual(1, acss.length);
</script>

<script id=createEvent>
const event = document.createEvent("Event");

testing.expectEqual(true, event instanceof Event);
testing.expectEqual("", event.type);

const customEvent = document.createEvent("CustomEvent");
customEvent.initCustomEvent("hey", false, false);

testing.expectEqual(true, customEvent instanceof CustomEvent);
testing.expectEqual(true, customEvent instanceof Event);

testing.withError(
(err) => {
// TODO: Check the error type.
},
() => document.createEvent("InvalidType"),
);
</script>
Loading