mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-05 14:57:11 +00:00
add Page._to_load and implement load even dispatching for Image
This commit is contained in:
@@ -41,8 +41,10 @@ const Parser = @import("parser/Parser.zig");
|
|||||||
const URL = @import("URL.zig");
|
const URL = @import("URL.zig");
|
||||||
const Node = @import("webapi/Node.zig");
|
const Node = @import("webapi/Node.zig");
|
||||||
const Event = @import("webapi/Event.zig");
|
const Event = @import("webapi/Event.zig");
|
||||||
|
const EventTarget = @import("webapi/EventTarget.zig");
|
||||||
const CData = @import("webapi/CData.zig");
|
const CData = @import("webapi/CData.zig");
|
||||||
const Element = @import("webapi/Element.zig");
|
const Element = @import("webapi/Element.zig");
|
||||||
|
const HtmlElement = @import("webapi/element/Html.zig");
|
||||||
const Window = @import("webapi/Window.zig");
|
const Window = @import("webapi/Window.zig");
|
||||||
const Location = @import("webapi/Location.zig");
|
const Location = @import("webapi/Location.zig");
|
||||||
const Document = @import("webapi/Document.zig");
|
const Document = @import("webapi/Document.zig");
|
||||||
@@ -124,6 +126,10 @@ _element_assigned_slots: Element.AssignedSlotLookup = .{},
|
|||||||
/// ```
|
/// ```
|
||||||
_element_attr_listeners: GlobalEventHandlersLookup = .{},
|
_element_attr_listeners: GlobalEventHandlersLookup = .{},
|
||||||
|
|
||||||
|
/// `load` events that'll be fired before window's `load` event.
|
||||||
|
/// A call to `documentIsComplete` (which calls `_documentIsComplete`) resets it.
|
||||||
|
_to_load: std.ArrayList(*Element) = .{},
|
||||||
|
|
||||||
_script_manager: ScriptManager,
|
_script_manager: ScriptManager,
|
||||||
|
|
||||||
// List of active MutationObservers
|
// List of active MutationObservers
|
||||||
@@ -344,6 +350,8 @@ fn reset(self: *Page, comptime initializing: bool) !void {
|
|||||||
|
|
||||||
self._element_attr_listeners = .{};
|
self._element_attr_listeners = .{};
|
||||||
|
|
||||||
|
self._to_load = .{};
|
||||||
|
|
||||||
self._notified_network_idle = .init;
|
self._notified_network_idle = .init;
|
||||||
self._notified_network_almost_idle = .init;
|
self._notified_network_almost_idle = .init;
|
||||||
|
|
||||||
@@ -699,15 +707,34 @@ pub fn documentIsComplete(self: *Page) void {
|
|||||||
fn _documentIsComplete(self: *Page) !void {
|
fn _documentIsComplete(self: *Page) !void {
|
||||||
self.document._ready_state = .complete;
|
self.document._ready_state = .complete;
|
||||||
|
|
||||||
// dispatch window.load event
|
|
||||||
const event = try Event.initTrusted("load", .{}, self);
|
const event = try Event.initTrusted("load", .{}, self);
|
||||||
// this event is weird, it's dispatched directly on the window, but
|
|
||||||
// with the document as the target
|
|
||||||
|
|
||||||
var ls: JS.Local.Scope = undefined;
|
var ls: JS.Local.Scope = undefined;
|
||||||
self.js.localScope(&ls);
|
self.js.localScope(&ls);
|
||||||
defer ls.deinit();
|
defer ls.deinit();
|
||||||
|
|
||||||
|
// Dispatch `_to_load` events before window.load.
|
||||||
|
for (self._to_load.items) |element| {
|
||||||
|
const maybe_inline_listener = self.getAttrListener(element, .onload);
|
||||||
|
|
||||||
|
try self._event_manager.dispatchWithFunction(
|
||||||
|
element.asEventTarget(),
|
||||||
|
event,
|
||||||
|
ls.toLocal(maybe_inline_listener),
|
||||||
|
.{ .context = "Page dispatch load events" },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (comptime IS_DEBUG) {
|
||||||
|
log.debug(.page, "load event for element", .{ .element = element });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// `_to_load` can be cleaned here.
|
||||||
|
self._to_load.clearAndFree(self.arena);
|
||||||
|
|
||||||
|
// Dispatch window.load event.
|
||||||
|
// This event is weird, it's dispatched directly on the window, but
|
||||||
|
// with the document as the target.
|
||||||
event._target = self.document.asEventTarget();
|
event._target = self.document.asEventTarget();
|
||||||
try self._event_manager.dispatchWithFunction(
|
try self._event_manager.dispatchWithFunction(
|
||||||
self.window.asEventTarget(),
|
self.window.asEventTarget(),
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ const HtmlElement = @import("../Html.zig");
|
|||||||
const Event = @import("../../Event.zig");
|
const Event = @import("../../Event.zig");
|
||||||
const log = @import("../../../../log.zig");
|
const log = @import("../../../../log.zig");
|
||||||
|
|
||||||
|
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||||
|
|
||||||
const Image = @This();
|
const Image = @This();
|
||||||
_proto: *HtmlElement,
|
_proto: *HtmlElement,
|
||||||
|
|
||||||
@@ -49,41 +51,6 @@ pub fn getSrc(self: *const Image, page: *Page) ![]const u8 {
|
|||||||
|
|
||||||
pub fn setSrc(self: *Image, value: []const u8, page: *Page) !void {
|
pub fn setSrc(self: *Image, value: []const u8, page: *Page) !void {
|
||||||
try self.asElement().setAttributeSafe(comptime .wrap("src"), .wrap(value), page);
|
try self.asElement().setAttributeSafe(comptime .wrap("src"), .wrap(value), page);
|
||||||
|
|
||||||
const event_target = self.asNode().asEventTarget();
|
|
||||||
|
|
||||||
// Have to do this since `Scheduler` only allow passing a single arg.
|
|
||||||
const SetSrcCallback = struct {
|
|
||||||
page: *Page,
|
|
||||||
event_target: *@import("../../EventTarget.zig"),
|
|
||||||
};
|
|
||||||
const args = try page._factory.create(SetSrcCallback{
|
|
||||||
.page = page,
|
|
||||||
.event_target = event_target,
|
|
||||||
});
|
|
||||||
errdefer page._factory.destroy(args);
|
|
||||||
|
|
||||||
// We don't actually fetch the media, here we fake the load call.
|
|
||||||
try page.scheduler.add(
|
|
||||||
args,
|
|
||||||
struct {
|
|
||||||
fn wrap(raw: *anyopaque) anyerror!?u32 {
|
|
||||||
const _args: *SetSrcCallback = @ptrCast(@alignCast(raw));
|
|
||||||
const _page = _args.page;
|
|
||||||
defer _page._factory.destroy(_args);
|
|
||||||
// Dispatch.
|
|
||||||
const event = try Event.initTrusted("load", .{}, _page);
|
|
||||||
try _page._event_manager.dispatch(_args.event_target, event);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}.wrap,
|
|
||||||
25,
|
|
||||||
.{
|
|
||||||
.low_priority = false,
|
|
||||||
.name = "Image.setSrc",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getAlt(self: *const Image) []const u8 {
|
pub fn getAlt(self: *const Image) []const u8 {
|
||||||
@@ -152,39 +119,18 @@ pub const JsApi = struct {
|
|||||||
pub const loading = bridge.accessor(Image.getLoading, Image.setLoading, .{});
|
pub const loading = bridge.accessor(Image.getLoading, Image.setLoading, .{});
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Argument passed to `dispatchLoadEvent`.
|
pub const Build = struct {
|
||||||
const CallbackParams = struct { page: *Page, element: *Element };
|
pub fn created(node: *Node, page: *Page) !void {
|
||||||
|
const self = node.as(Image);
|
||||||
|
const image = self.asElement();
|
||||||
|
// Exit if src not set.
|
||||||
|
// TODO: We might want to check if src point to valid image.
|
||||||
|
_ = image.getAttributeSafe(comptime .wrap("src")) orelse return;
|
||||||
|
|
||||||
/// Callback passed to `Scheduler` to execute load listeners.
|
// Push to `_to_load` to dispatch load event just before window load event.
|
||||||
fn dispatchLoadEvent(raw: *anyopaque) !?u32 {
|
return page._to_load.append(page.arena, image);
|
||||||
const _args: *CallbackParams = @ptrCast(@alignCast(raw));
|
|
||||||
const _page = _args.page;
|
|
||||||
defer _page._factory.destroy(_args);
|
|
||||||
|
|
||||||
const _element = _args.element;
|
|
||||||
const _img = _element.as(Image);
|
|
||||||
const event_target = _element.asEventTarget();
|
|
||||||
const event = try Event.initTrusted("load", .{}, _page);
|
|
||||||
|
|
||||||
// If onload provided, dispatch with it.
|
|
||||||
if (_img.getOnLoad(_page)) |_on_load| {
|
|
||||||
var ls: js.Local.Scope = undefined;
|
|
||||||
_page.js.localScope(&ls);
|
|
||||||
defer ls.deinit();
|
|
||||||
|
|
||||||
try _page._event_manager.dispatchWithFunction(
|
|
||||||
event_target,
|
|
||||||
event,
|
|
||||||
_on_load.local(&ls.local),
|
|
||||||
.{ .context = "Image.onload" },
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
// Dispatch to addEventListener listeners.
|
|
||||||
try _page._event_manager.dispatch(event_target, event);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const testing = @import("../../../../testing.zig");
|
const testing = @import("../../../../testing.zig");
|
||||||
test "WebApi: HTML.Image" {
|
test "WebApi: HTML.Image" {
|
||||||
|
|||||||
Reference in New Issue
Block a user