mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-28 14:43:28 +00:00
Add document.readyState
To support this, add the ability to embedded data into libdom nodes, so that we can extend libdom without having to alter it.
This commit is contained in:
@@ -62,4 +62,16 @@ pub const SessionState = struct {
|
||||
// shorter-lived than the arena above, which
|
||||
// exists for the entire rendering of the page
|
||||
call_arena: std.mem.Allocator = undefined,
|
||||
|
||||
pub fn getNodeWrapper(self: *SessionState, comptime T: type, node: *parser.Node) !*T {
|
||||
if (parser.nodeGetEmbedderData(node)) |wrap| {
|
||||
return @alignCast(@ptrCast(wrap));
|
||||
}
|
||||
|
||||
const wrap = try self.arena.create(T);
|
||||
wrap.* = T{};
|
||||
|
||||
parser.nodeSetEmbedderData(node, wrap);
|
||||
return wrap;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,6 +36,14 @@ pub const HTMLDocument = struct {
|
||||
pub const prototype = *Document;
|
||||
pub const subtype = .node;
|
||||
|
||||
ready_state: ReadyState = .loading,
|
||||
|
||||
const ReadyState = enum {
|
||||
loading,
|
||||
interactive,
|
||||
complete,
|
||||
};
|
||||
|
||||
// JS funcs
|
||||
// --------
|
||||
|
||||
@@ -176,6 +184,11 @@ pub const HTMLDocument = struct {
|
||||
return state.window;
|
||||
}
|
||||
|
||||
pub fn get_readyState(node: *parser.DocumentHTML, state: *SessionState) ![]const u8 {
|
||||
const self = try state.getNodeWrapper(HTMLDocument, @ptrCast(node));
|
||||
return @tagName(self.ready_state);
|
||||
}
|
||||
|
||||
// noop legacy functions
|
||||
// https://html.spec.whatwg.org/#Document-partial
|
||||
pub fn _clear(_: *parser.DocumentHTML) void {}
|
||||
@@ -212,6 +225,22 @@ pub const HTMLDocument = struct {
|
||||
pub fn set_bgColor(_: *parser.DocumentHTML, _: []const u8) []const u8 {
|
||||
return "";
|
||||
}
|
||||
|
||||
pub fn documentIsLoaded(html_doc: *parser.DocumentHTML, state: *SessionState) !void {
|
||||
const self = try state.getNodeWrapper(HTMLDocument, @ptrCast(html_doc));
|
||||
self.ready_state = .interactive;
|
||||
|
||||
const evt = try parser.eventCreate();
|
||||
defer parser.eventDestroy(evt);
|
||||
|
||||
try parser.eventInit(evt, "DOMContentLoaded", .{ .bubbles = true, .cancelable = true });
|
||||
_ = try parser.eventTargetDispatchEvent(parser.toEventTarget(parser.DocumentHTML, html_doc), evt);
|
||||
}
|
||||
|
||||
pub fn documentIsComplete(html_doc: *parser.DocumentHTML, state: *SessionState) !void {
|
||||
const self = try state.getNodeWrapper(HTMLDocument, @ptrCast(html_doc));
|
||||
self.ready_state = .complete;
|
||||
}
|
||||
};
|
||||
|
||||
// Tests
|
||||
@@ -276,4 +305,18 @@ test "Browser.HTML.Document" {
|
||||
try runner.testCases(&.{
|
||||
.{ "document.defaultView.document == document", "true" },
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "document.readyState", "loading" },
|
||||
}, .{});
|
||||
|
||||
try HTMLDocument.documentIsLoaded(runner.state.document.?, &runner.state);
|
||||
try runner.testCases(&.{
|
||||
.{ "document.readyState", "interactive" },
|
||||
}, .{});
|
||||
|
||||
try HTMLDocument.documentIsComplete(runner.state.document.?, &runner.state);
|
||||
try runner.testCases(&.{
|
||||
.{ "document.readyState", "complete" },
|
||||
}, .{});
|
||||
}
|
||||
|
||||
@@ -1274,6 +1274,14 @@ pub fn nodeGetPrefix(node: *Node) !?[]const u8 {
|
||||
return strToData(s.?);
|
||||
}
|
||||
|
||||
pub fn nodeGetEmbedderData(node: *Node) ?*anyopaque {
|
||||
return c._dom_node_get_embedder_data(node);
|
||||
}
|
||||
|
||||
pub fn nodeSetEmbedderData(node: *Node, data: *anyopaque) void {
|
||||
c._dom_node_set_embedder_data(node, data);
|
||||
}
|
||||
|
||||
// nodeToElement is an helper to convert a node to an element.
|
||||
pub inline fn nodeToElement(node: *Node) *Element {
|
||||
return @as(*Element, @ptrCast(node));
|
||||
|
||||
@@ -31,6 +31,7 @@ const Window = @import("html/window.zig").Window;
|
||||
const Walker = @import("dom/walker.zig").WalkerDepthFirst;
|
||||
const Env = @import("env.zig").Env;
|
||||
const Loop = @import("../runtime/loop.zig").Loop;
|
||||
const HTMLDocument = @import("html/document.zig").HTMLDocument;
|
||||
|
||||
const URL = @import("../url.zig").URL;
|
||||
|
||||
@@ -351,16 +352,11 @@ pub const Page = struct {
|
||||
self.evalScript(&s) catch |err| log.warn("evaljs: {any}", .{err});
|
||||
try parser.documentHTMLSetCurrentScript(html_doc, null);
|
||||
}
|
||||
|
||||
// dispatch DOMContentLoaded before the transition to "complete",
|
||||
// at the point where all subresources apart from async script elements
|
||||
// have loaded.
|
||||
// https://html.spec.whatwg.org/#reporting-document-loading-status
|
||||
const evt = try parser.eventCreate();
|
||||
defer parser.eventDestroy(evt);
|
||||
|
||||
try parser.eventInit(evt, "DOMContentLoaded", .{ .bubbles = true, .cancelable = true });
|
||||
_ = try parser.eventTargetDispatchEvent(parser.toEventTarget(parser.DocumentHTML, html_doc), evt);
|
||||
try HTMLDocument.documentIsLoaded(html_doc, &self.state);
|
||||
|
||||
// eval async scripts.
|
||||
for (async_scripts.items) |s| {
|
||||
@@ -369,9 +365,7 @@ pub const Page = struct {
|
||||
try parser.documentHTMLSetCurrentScript(html_doc, null);
|
||||
}
|
||||
|
||||
// TODO wait for async scripts
|
||||
|
||||
// TODO set document.readyState to complete
|
||||
try HTMLDocument.documentIsComplete(html_doc, &self.state);
|
||||
|
||||
// dispatch window.load event
|
||||
const loadevt = try parser.eventCreate();
|
||||
|
||||
2
vendor/netsurf/libdom
vendored
2
vendor/netsurf/libdom
vendored
Submodule vendor/netsurf/libdom updated: b2c17b1476...b0f4a43147
Reference in New Issue
Block a user