default:blank as default document

This commit is contained in:
sjorsdonkers
2025-05-20 12:31:40 +02:00
committed by Sjors
parent 0929bd217d
commit 967ab18d53
12 changed files with 34 additions and 36 deletions

View File

@@ -30,7 +30,7 @@ pub const Comment = struct {
pub fn constructor(data: ?[]const u8, state: *const SessionState) !*parser.Comment {
return parser.documentCreateComment(
parser.documentHTMLToDocument(state.window.document.?),
parser.documentHTMLToDocument(state.window.document),
data orelse "",
);
}

View File

@@ -41,12 +41,12 @@ pub const Document = struct {
pub fn constructor(state: *const SessionState) !*parser.DocumentHTML {
const doc = try parser.documentCreateDocument(
try parser.documentHTMLGetTitle(state.window.document.?),
try parser.documentHTMLGetTitle(state.window.document),
);
// we have to work w/ document instead of html document.
const ddoc = parser.documentHTMLToDocument(doc);
const ccur = parser.documentHTMLToDocument(state.window.document.?);
const ccur = parser.documentHTMLToDocument(state.window.document);
try parser.documentSetDocumentURI(ddoc, try parser.documentGetDocumentURI(ccur));
try parser.documentSetInputEncoding(ddoc, try parser.documentGetInputEncoding(ccur));

View File

@@ -29,7 +29,7 @@ pub const DocumentFragment = struct {
pub fn constructor(state: *const SessionState) !*parser.DocumentFragment {
return parser.documentCreateDocumentFragment(
parser.documentHTMLToDocument(state.window.document.?),
parser.documentHTMLToDocument(state.window.document),
);
}

View File

@@ -370,7 +370,7 @@ pub const Element = struct {
pub fn _getBoundingClientRect(self: *parser.Element, state: *SessionState) !DOMRect {
// Since we are lazy rendering we need to do this check. We could store the renderer in a viewport such that it could cache these, but it would require tracking changes.
const root = try parser.nodeGetRootNode(parser.elementToNode(self));
if (root != parser.documentToNode(parser.documentHTMLToDocument(state.window.document.?))) {
if (root != parser.documentToNode(parser.documentHTMLToDocument(state.window.document))) {
return DOMRect{ .x = 0, .y = 0, .width = 0, .height = 0 };
}
return state.renderer.getRect(self);
@@ -381,7 +381,7 @@ pub const Element = struct {
// Returns an empty array if the element is eventually detached from the main window
pub fn _getClientRects(self: *parser.Element, state: *SessionState) ![]DOMRect {
const root = try parser.nodeGetRootNode(parser.elementToNode(self));
if (root != parser.documentToNode(parser.documentHTMLToDocument(state.window.document.?))) {
if (root != parser.documentToNode(parser.documentHTMLToDocument(state.window.document))) {
return &.{};
}
const heap_ptr = try state.call_arena.create(DOMRect);

View File

@@ -50,7 +50,7 @@ pub const IntersectionObserver = struct {
// new IntersectionObserver(callback, options) [not supported yet]
pub fn constructor(callback: Env.Callback, options_: ?IntersectionObserverOptions, state: *SessionState) !IntersectionObserver {
var options = IntersectionObserverOptions{
.root = parser.documentToNode(parser.documentHTMLToDocument(state.window.document.?)),
.root = parser.documentToNode(parser.documentHTMLToDocument(state.window.document)),
.rootMargin = "0px 0px 0px 0px",
.threshold = &.{0.0},
};
@@ -142,7 +142,7 @@ pub const IntersectionObserverEntry = struct {
// Returns a DOMRectReadOnly for the intersection observer's root.
pub fn get_rootBounds(self: *const IntersectionObserverEntry) !Element.DOMRect {
const root = self.options.root.?;
if (@intFromPtr(root) == @intFromPtr(self.state.window.document.?)) {
if (@intFromPtr(root) == @intFromPtr(self.state.window.document)) {
return self.state.renderer.boundingRect();
}

View File

@@ -41,7 +41,7 @@ pub const ProcessingInstruction = struct {
// a simple workaround.
pub fn _cloneNode(self: *parser.ProcessingInstruction, _: ?bool, state: *SessionState) !*parser.ProcessingInstruction {
return try parser.documentCreateProcessingInstruction(
@ptrCast(state.window.document.?),
@ptrCast(state.window.document),
try get_target(self),
(try get_data(self)) orelse "",
);

View File

@@ -34,7 +34,7 @@ pub const Text = struct {
pub fn constructor(data: ?[]const u8, state: *const SessionState) !*parser.Text {
return parser.documentCreateTextNode(
parser.documentHTMLToDocument(state.window.document.?),
parser.documentHTMLToDocument(state.window.document),
data orelse "",
);
}

View File

@@ -255,10 +255,10 @@ pub const HTMLDocument = struct {
// Thus we can add the HtmlHtmlElement and it's child HTMLBodyElement to the returned list.
// TBD Should we instead return every parent that is an element? Note that a child does not physically need to be overlapping the parent.
// Should we do a render pass on demand?
const doc_elem = try parser.documentGetDocumentElement(parser.documentHTMLToDocument(state.window.document.?)) orelse {
const doc_elem = try parser.documentGetDocumentElement(parser.documentHTMLToDocument(state.window.document)) orelse {
return list.items;
};
if (try parser.documentHTMLBody(state.window.document.?)) |body| {
if (try parser.documentHTMLBody(state.window.document)) |body| {
list.appendAssumeCapacity(try Element.toInterface(parser.bodyToElement(body)));
}
list.appendAssumeCapacity(try Element.toInterface(doc_elem));
@@ -383,12 +383,12 @@ test "Browser.HTML.Document" {
.{ "document.readyState", "loading" },
}, .{});
try HTMLDocument.documentIsLoaded(runner.window.document.?, &runner.state);
try HTMLDocument.documentIsLoaded(runner.window.document, &runner.state);
try runner.testCases(&.{
.{ "document.readyState", "interactive" },
}, .{});
try HTMLDocument.documentIsComplete(runner.window.document.?, &runner.state);
try HTMLDocument.documentIsComplete(runner.window.document, &runner.state);
try runner.testCases(&.{
.{ "document.readyState", "complete" },
}, .{});

View File

@@ -44,7 +44,7 @@ pub const Window = struct {
// Extend libdom event target for pure zig struct.
base: parser.EventTargetTBase = parser.EventTargetTBase{},
document: ?*parser.DocumentHTML = null,
document: *parser.DocumentHTML,
target: []const u8 = "",
history: History = .{},
location: Location = .{},
@@ -60,7 +60,13 @@ pub const Window = struct {
performance: Performance,
pub fn create(target: ?[]const u8, navigator: ?Navigator) !Window {
var fbs = std.io.fixedBufferStream("");
const html_doc = try parser.documentHTMLParse(fbs.reader(), "utf-8");
const doc = parser.documentHTMLToDocument(html_doc);
try parser.documentSetDocumentURI(doc, "about:blank");
return .{
.document = html_doc,
.target = target orelse "",
.navigator = navigator orelse .{},
.performance = .{ .time_origin = try std.time.Timer.start() },
@@ -69,9 +75,7 @@ pub const Window = struct {
pub fn replaceLocation(self: *Window, loc: Location) !void {
self.location = loc;
if (self.document) |doc| {
try parser.documentHTMLSetLocation(Location, doc, &self.location);
}
try parser.documentHTMLSetLocation(Location, self.document, &self.location);
}
pub fn replaceDocument(self: *Window, doc: *parser.DocumentHTML) !void {

View File

@@ -60,8 +60,6 @@ pub const Page = struct {
// Serves are the root object of our JavaScript environment
window: Window,
doc: ?*parser.Document,
// The URL of the page
url: URL,
@@ -87,7 +85,6 @@ pub const Page = struct {
self.* = .{
.window = try Window.create(null, null),
.arena = arena,
.doc = null,
.raw_data = null,
.url = URL.empty,
.session = session,
@@ -121,15 +118,14 @@ pub const Page = struct {
// dump writes the page content into the given file.
pub fn dump(self: *const Page, out: std.fs.File) !void {
// if no HTML document pointer available, dump the data content only.
if (self.doc == null) {
// no data loaded, nothing to do.
if (self.raw_data == null) return;
return try out.writeAll(self.raw_data.?);
if (self.raw_data) |raw_data| {
// raw_data was set if the document was not HTML, dump the data content only.
return try out.writeAll(raw_data);
}
// if the page has a pointer to a document, dumps the HTML.
try Dump.writeHTML(self.doc.?, out);
const doc = parser.documentHTMLToDocument(self.window.document);
try Dump.writeHTML(doc, out);
}
pub fn fetchModuleSource(ctx: *anyopaque, specifier: []const u8) !?[]const u8 {
@@ -187,7 +183,7 @@ pub const Page = struct {
try self.loadHTMLDoc(fbs.reader(), "utf-8");
// We do not processHTMLDoc here as we know we don't have any scripts
// This assumption may be false when CDP Page.addScriptToEvaluateOnNewDocument is implemented
try HTMLDocument.documentIsComplete(self.window.document.?, &self.state);
try HTMLDocument.documentIsComplete(self.window.document, &self.state);
return;
}
@@ -229,6 +225,7 @@ pub const Page = struct {
} orelse .unknown;
if (mime.isHTML()) {
self.raw_data = null;
try self.loadHTMLDoc(&response, mime.charset orelse "utf-8");
try self.processHTMLDoc();
} else {
@@ -256,9 +253,6 @@ pub const Page = struct {
const html_doc = try parser.documentHTMLParse(reader, ccharset);
const doc = parser.documentHTMLToDocument(html_doc);
// save a document's pointer in the page.
self.doc = doc;
// inject the URL to the document including the fragment.
try parser.documentSetDocumentURI(doc, self.url.raw);
@@ -270,8 +264,8 @@ pub const Page = struct {
}
fn processHTMLDoc(self: *Page) !void {
const doc = self.doc.?;
const html_doc = self.window.document.?;
const html_doc = self.window.document;
const doc = parser.documentHTMLToDocument(html_doc);
const document_element = (try parser.documentGetDocumentElement(doc)) orelse return error.DocumentElementError;
try parser.eventTargetAddEventListener(

View File

@@ -59,7 +59,7 @@ fn getDocument(cmd: anytype) !void {
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
const doc = page.doc orelse return error.DocumentNotLoaded;
const doc = parser.documentHTMLToDocument(page.window.document);
const node = try bc.node_registry.register(parser.documentToNode(doc));
return cmd.sendResult(.{ .root = bc.nodeWriter(node, .{}) }, .{});
@@ -74,7 +74,7 @@ fn performSearch(cmd: anytype) !void {
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
const doc = page.doc orelse return error.DocumentNotLoaded;
const doc = parser.documentHTMLToDocument(page.window.document);
const allocator = cmd.cdp.allocator;
var list = try css.querySelectorAll(allocator, parser.documentToNode(doc), params.query);

View File

@@ -116,7 +116,7 @@ fn run(arena: Allocator, test_file: []const u8, loader: *FileLoader, err_out: *?
try polyfill.load(arena, runner.scope);
// loop over the scripts.
const doc = parser.documentHTMLToDocument(runner.state.window.document.?);
const doc = parser.documentHTMLToDocument(runner.state.window.document);
const scripts = try parser.documentGetElementsByTagName(doc, "script");
const script_count = try parser.nodeListLength(scripts);
for (0..script_count) |i| {