mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +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
|
// shorter-lived than the arena above, which
|
||||||
// exists for the entire rendering of the page
|
// exists for the entire rendering of the page
|
||||||
call_arena: std.mem.Allocator = undefined,
|
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 prototype = *Document;
|
||||||
pub const subtype = .node;
|
pub const subtype = .node;
|
||||||
|
|
||||||
|
ready_state: ReadyState = .loading,
|
||||||
|
|
||||||
|
const ReadyState = enum {
|
||||||
|
loading,
|
||||||
|
interactive,
|
||||||
|
complete,
|
||||||
|
};
|
||||||
|
|
||||||
// JS funcs
|
// JS funcs
|
||||||
// --------
|
// --------
|
||||||
|
|
||||||
@@ -176,6 +184,11 @@ pub const HTMLDocument = struct {
|
|||||||
return state.window;
|
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
|
// noop legacy functions
|
||||||
// https://html.spec.whatwg.org/#Document-partial
|
// https://html.spec.whatwg.org/#Document-partial
|
||||||
pub fn _clear(_: *parser.DocumentHTML) void {}
|
pub fn _clear(_: *parser.DocumentHTML) void {}
|
||||||
@@ -212,6 +225,22 @@ pub const HTMLDocument = struct {
|
|||||||
pub fn set_bgColor(_: *parser.DocumentHTML, _: []const u8) []const u8 {
|
pub fn set_bgColor(_: *parser.DocumentHTML, _: []const u8) []const u8 {
|
||||||
return "";
|
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
|
// Tests
|
||||||
@@ -276,4 +305,18 @@ test "Browser.HTML.Document" {
|
|||||||
try runner.testCases(&.{
|
try runner.testCases(&.{
|
||||||
.{ "document.defaultView.document == document", "true" },
|
.{ "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.?);
|
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.
|
// nodeToElement is an helper to convert a node to an element.
|
||||||
pub inline fn nodeToElement(node: *Node) *Element {
|
pub inline fn nodeToElement(node: *Node) *Element {
|
||||||
return @as(*Element, @ptrCast(node));
|
return @as(*Element, @ptrCast(node));
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ const Window = @import("html/window.zig").Window;
|
|||||||
const Walker = @import("dom/walker.zig").WalkerDepthFirst;
|
const Walker = @import("dom/walker.zig").WalkerDepthFirst;
|
||||||
const Env = @import("env.zig").Env;
|
const Env = @import("env.zig").Env;
|
||||||
const Loop = @import("../runtime/loop.zig").Loop;
|
const Loop = @import("../runtime/loop.zig").Loop;
|
||||||
|
const HTMLDocument = @import("html/document.zig").HTMLDocument;
|
||||||
|
|
||||||
const URL = @import("../url.zig").URL;
|
const URL = @import("../url.zig").URL;
|
||||||
|
|
||||||
@@ -351,16 +352,11 @@ pub const Page = struct {
|
|||||||
self.evalScript(&s) catch |err| log.warn("evaljs: {any}", .{err});
|
self.evalScript(&s) catch |err| log.warn("evaljs: {any}", .{err});
|
||||||
try parser.documentHTMLSetCurrentScript(html_doc, null);
|
try parser.documentHTMLSetCurrentScript(html_doc, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 HTMLDocument.documentIsLoaded(html_doc, &self.state);
|
||||||
defer parser.eventDestroy(evt);
|
|
||||||
|
|
||||||
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 (async_scripts.items) |s| {
|
for (async_scripts.items) |s| {
|
||||||
@@ -369,9 +365,7 @@ pub const Page = struct {
|
|||||||
try parser.documentHTMLSetCurrentScript(html_doc, null);
|
try parser.documentHTMLSetCurrentScript(html_doc, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO wait for async scripts
|
try HTMLDocument.documentIsComplete(html_doc, &self.state);
|
||||||
|
|
||||||
// TODO set document.readyState to complete
|
|
||||||
|
|
||||||
// dispatch window.load event
|
// dispatch window.load event
|
||||||
const loadevt = try parser.eventCreate();
|
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