mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-16 00:08:59 +00:00
Merge pull request #157 from lightpanda-io/window-event-target
Window: add EventTargetBase
This commit is contained in:
@@ -313,10 +313,13 @@ pub const Page = struct {
|
|||||||
|
|
||||||
// TODO wait for deferred scripts
|
// TODO wait for deferred scripts
|
||||||
|
|
||||||
// TODO dispatch DOMContentLoaded before the transition to "complete",
|
// dispatch DOMContentLoaded before the transition to "complete",
|
||||||
// at the point where all subresources apart from async script elements
|
// at the point where all subresources apart from async script elements
|
||||||
// have loaded.
|
// have loaded.
|
||||||
// https://html.spec.whatwg.org/#reporting-document-loading-status
|
// https://html.spec.whatwg.org/#reporting-document-loading-status
|
||||||
|
const evt = try parser.eventCreate();
|
||||||
|
try parser.eventInit(evt, "DOMContentLoaded", .{ .bubbles = true, .cancelable = true });
|
||||||
|
_ = try parser.eventTargetDispatchEvent(parser.toEventTarget(parser.DocumentHTML, html_doc), evt);
|
||||||
|
|
||||||
// eval async scripts.
|
// eval async scripts.
|
||||||
for (sasync.items) |e| {
|
for (sasync.items) |e| {
|
||||||
@@ -326,6 +329,11 @@ pub const Page = struct {
|
|||||||
// TODO wait for async scripts
|
// TODO wait for async scripts
|
||||||
|
|
||||||
// TODO set document.readyState to complete
|
// TODO set document.readyState to complete
|
||||||
|
|
||||||
|
// dispatch window.load event
|
||||||
|
const loadevt = try parser.eventCreate();
|
||||||
|
try parser.eventInit(loadevt, "load", .{});
|
||||||
|
_ = try parser.eventTargetDispatchEvent(parser.toEventTarget(Window, &self.session.window), loadevt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// evalScript evaluates the src in priority.
|
// evalScript evaluates the src in priority.
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ pub const Window = struct {
|
|||||||
pub const prototype = *EventTarget;
|
pub const prototype = *EventTarget;
|
||||||
pub const mem_guarantied = true;
|
pub const mem_guarantied = true;
|
||||||
|
|
||||||
|
// Extend libdom event target for pure zig struct.
|
||||||
|
base: parser.EventTargetTBase = parser.EventTargetTBase{},
|
||||||
|
|
||||||
document: ?*parser.Document = null,
|
document: ?*parser.Document = null,
|
||||||
target: []const u8,
|
target: []const u8,
|
||||||
|
|
||||||
@@ -42,6 +45,4 @@ pub const Window = struct {
|
|||||||
pub fn get_name(self: *Window) []const u8 {
|
pub fn get_name(self: *Window) []const u8 {
|
||||||
return self.target;
|
return self.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO we need to re-implement EventTarget interface.
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const std = @import("std");
|
|||||||
const c = @cImport({
|
const c = @cImport({
|
||||||
@cInclude("dom/dom.h");
|
@cInclude("dom/dom.h");
|
||||||
@cInclude("dom/bindings/hubbub/parser.h");
|
@cInclude("dom/bindings/hubbub/parser.h");
|
||||||
|
@cInclude("events/event_target.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
const Callback = @import("jsruntime").Callback;
|
const Callback = @import("jsruntime").Callback;
|
||||||
@@ -476,6 +477,11 @@ fn eventTargetVtable(et: *EventTarget) c.dom_event_target_vtable {
|
|||||||
return getVtable(c.dom_event_target_vtable, EventTarget, et);
|
return getVtable(c.dom_event_target_vtable, EventTarget, et);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn toEventTarget(comptime T: type, v: *T) *EventTarget {
|
||||||
|
const et_aligned: *align(@alignOf(EventTarget)) T = @alignCast(v);
|
||||||
|
return @as(*EventTarget, @ptrCast(et_aligned));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eventTargetHasListener(
|
pub fn eventTargetHasListener(
|
||||||
et: *EventTarget,
|
et: *EventTarget,
|
||||||
typ: []const u8,
|
typ: []const u8,
|
||||||
@@ -622,6 +628,46 @@ pub fn eventTargetDispatchEvent(et: *EventTarget, event: *Event) !bool {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EventTargetBase is used to implement EventTarget for pure zig struct.
|
||||||
|
pub const EventTargetTBase = struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
vtable: ?*const c.struct_dom_event_target_vtable = &c.struct_dom_event_target_vtable{
|
||||||
|
.dispatch_event = dispatch_event,
|
||||||
|
.remove_event_listener = remove_event_listener,
|
||||||
|
.add_event_listener = add_event_listener,
|
||||||
|
.iter_event_listener = iter_event_listener,
|
||||||
|
},
|
||||||
|
eti: c.dom_event_target_internal = c.dom_event_target_internal{ .listeners = null },
|
||||||
|
|
||||||
|
pub fn add_event_listener(et: [*c]c.dom_event_target, t: [*c]c.dom_string, l: ?*c.struct_dom_event_listener, capture: bool) callconv(.C) c.dom_exception {
|
||||||
|
const self = @as(*Self, @ptrCast(et));
|
||||||
|
return c._dom_event_target_add_event_listener(&self.eti, t, l, capture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch_event(et: [*c]c.dom_event_target, evt: ?*c.struct_dom_event, res: [*c]bool) callconv(.C) c.dom_exception {
|
||||||
|
const self = @as(*Self, @ptrCast(et));
|
||||||
|
return c._dom_event_target_dispatch(et, &self.eti, evt, c.DOM_BUBBLING_PHASE, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_event_listener(et: [*c]c.dom_event_target, t: [*c]c.dom_string, l: ?*c.struct_dom_event_listener, capture: bool) callconv(.C) c.dom_exception {
|
||||||
|
const self = @as(*Self, @ptrCast(et));
|
||||||
|
return c._dom_event_target_remove_event_listener(&self.eti, t, l, capture);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_event_listener(
|
||||||
|
et: [*c]c.dom_event_target,
|
||||||
|
t: [*c]c.dom_string,
|
||||||
|
capture: bool,
|
||||||
|
cur: [*c]c.struct_listener_entry,
|
||||||
|
next: [*c][*c]c.struct_listener_entry,
|
||||||
|
l: [*c]?*c.struct_dom_event_listener,
|
||||||
|
) callconv(.C) c.dom_exception {
|
||||||
|
const self = @as(*Self, @ptrCast(et));
|
||||||
|
return c._dom_event_target_iter_event_listener(self.eti, t, capture, cur, next, l);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// NodeType
|
// NodeType
|
||||||
|
|
||||||
pub const NodeType = enum(u4) {
|
pub const NodeType = enum(u4) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const generate = @import("generate.zig");
|
|||||||
|
|
||||||
const parser = @import("netsurf.zig");
|
const parser = @import("netsurf.zig");
|
||||||
const apiweb = @import("apiweb.zig");
|
const apiweb = @import("apiweb.zig");
|
||||||
|
const Window = @import("html/window.zig").Window;
|
||||||
|
|
||||||
const documentTestExecFn = @import("dom/document.zig").testExecFn;
|
const documentTestExecFn = @import("dom/document.zig").testExecFn;
|
||||||
const HTMLDocumentTestExecFn = @import("html/document.zig").testExecFn;
|
const HTMLDocumentTestExecFn = @import("html/document.zig").testExecFn;
|
||||||
@@ -135,3 +136,13 @@ test "run browser tests" {
|
|||||||
|
|
||||||
try dump.HTMLFileTestFn(out);
|
try dump.HTMLFileTestFn(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Window is a libdom event target" {
|
||||||
|
var window = Window.create(null);
|
||||||
|
|
||||||
|
const event = try parser.eventCreate();
|
||||||
|
try parser.eventInit(event, "foo", .{});
|
||||||
|
|
||||||
|
const et = @as(*parser.EventTarget, @ptrCast(&window));
|
||||||
|
_ = try parser.eventTargetDispatchEvent(et, event);
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,12 +40,19 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
|
|||||||
try js_env.start(alloc);
|
try js_env.start(alloc);
|
||||||
defer js_env.stop();
|
defer js_env.stop();
|
||||||
|
|
||||||
// add document object
|
// display console logs
|
||||||
try js_env.addObject(html_doc, "document");
|
defer {
|
||||||
|
var res = evalJS(js_env, alloc, "console.join('\\n');", "console") catch unreachable;
|
||||||
|
defer res.deinit(alloc);
|
||||||
|
if (res.result.len > 0) {
|
||||||
|
std.debug.print("-- CONSOLE LOG\n{s}\n--\n", .{res.result});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// alias global as self and window
|
// setup global env vars.
|
||||||
try js_env.attachObject(try js_env.getGlobal(), "self", null);
|
try js_env.attachObject(try js_env.getGlobal(), "self", null);
|
||||||
try js_env.attachObject(try js_env.getGlobal(), "window", null);
|
try js_env.attachObject(try js_env.getGlobal(), "window", null);
|
||||||
|
try js_env.addObject(html_doc, "document");
|
||||||
|
|
||||||
// thanks to the arena, we don't need to deinit res.
|
// thanks to the arena, we don't need to deinit res.
|
||||||
var res: jsruntime.JSResult = undefined;
|
var res: jsruntime.JSResult = undefined;
|
||||||
@@ -114,12 +121,6 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// display console logs
|
|
||||||
res = try evalJS(js_env, alloc, "console.join(', ');", "console");
|
|
||||||
if (res.result.len > 0) {
|
|
||||||
std.debug.print("-- CONSOLE LOG\n{s}\n--\n", .{res.result});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the final test status.
|
// Check the final test status.
|
||||||
res = try evalJS(js_env, alloc, "report.status;", "teststatus");
|
res = try evalJS(js_env, alloc, "report.status;", "teststatus");
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
@@ -148,7 +149,7 @@ pub fn find(allocator: std.mem.Allocator, comptime path: []const u8, list: *std.
|
|||||||
if (entry.kind != .file) {
|
if (entry.kind != .file) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!std.mem.endsWith(u8, entry.basename, ".html")) {
|
if (!std.mem.endsWith(u8, entry.basename, ".html") and !std.mem.endsWith(u8, entry.basename, ".htm")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user