Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/browser/dom/document.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const NodeUnion = @import("node.zig").Union;
const collection = @import("html_collection.zig");
const css = @import("css.zig");

const State = @import("../state/Document.zig");
const Element = @import("element.zig").Element;
const ElementUnion = @import("element.zig").Union;
const TreeWalker = @import("tree_walker.zig").TreeWalker;
Expand All @@ -42,8 +43,6 @@ pub const Document = struct {
pub const prototype = *Node;
pub const subtype = .node;

active_element: ?*parser.Element = null,

pub fn constructor(page: *const Page) !*parser.DocumentHTML {
const doc = try parser.documentCreateDocument(
try parser.documentHTMLGetTitle(page.window.document),
Expand Down Expand Up @@ -245,17 +244,26 @@ pub const Document = struct {
return try TreeWalker.init(root, what_to_show, filter);
}

pub fn get_activeElement(doc: *parser.Document, page: *Page) !?ElementUnion {
const self = try page.getOrCreateNodeWrapper(Document, @ptrCast(doc));
if (self.active_element) |ae| {
pub fn get_activeElement(self: *parser.Document, page: *Page) !?ElementUnion {
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
if (state.active_element) |ae| {
return try Element.toInterface(ae);
}

if (try parser.documentHTMLBody(page.window.document)) |body| {
return try Element.toInterface(@ptrCast(body));
}

return get_documentElement(doc);
return get_documentElement(self);
}

// TODO: some elements can't be focused, like if they're disabled
// but there doesn't seem to be a generic way to check this. For example
// we could look for the "disabled" attribute, but that's only meaningful
// on certain types, and libdom's vtable doesn't seem to expose this.
pub fn setFocus(self: *parser.Document, e: *parser.ElementHTML, page: *Page) !void {
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
state.active_element = @ptrCast(e);
}
};

Expand Down
29 changes: 11 additions & 18 deletions src/browser/html/document.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const NodeList = @import("../dom/nodelist.zig").NodeList;
const Location = @import("location.zig").Location;

const collection = @import("../dom/html_collection.zig");
const State = @import("../state/Document.zig");
const Walker = @import("../dom/walker.zig").WalkerDepthFirst;
const Cookie = @import("../storage/cookie.zig").Cookie;

Expand All @@ -39,14 +40,6 @@ pub const HTMLDocument = struct {
pub const prototype = *Document;
pub const subtype = .node;

ready_state: ReadyState = .loading,

const ReadyState = enum {
loading,
interactive,
complete,
};

// JS funcs
// --------

Expand Down Expand Up @@ -191,9 +184,9 @@ pub const HTMLDocument = struct {
return &page.window;
}

pub fn get_readyState(node: *parser.DocumentHTML, page: *Page) ![]const u8 {
const self = try page.getOrCreateNodeWrapper(HTMLDocument, @ptrCast(node));
return @tagName(self.ready_state);
pub fn get_readyState(self: *parser.DocumentHTML, page: *Page) ![]const u8 {
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
return @tagName(state.ready_state);
}

// noop legacy functions
Expand Down Expand Up @@ -270,9 +263,9 @@ pub const HTMLDocument = struct {
return list.items;
}

pub fn documentIsLoaded(html_doc: *parser.DocumentHTML, page: *Page) !void {
const self = try page.getOrCreateNodeWrapper(HTMLDocument, @ptrCast(html_doc));
self.ready_state = .interactive;
pub fn documentIsLoaded(self: *parser.DocumentHTML, page: *Page) !void {
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
state.ready_state = .interactive;

const evt = try parser.eventCreate();
defer parser.eventDestroy(evt);
Expand All @@ -282,12 +275,12 @@ pub const HTMLDocument = struct {
.source = "document",
});
try parser.eventInit(evt, "DOMContentLoaded", .{ .bubbles = true, .cancelable = true });
_ = try parser.eventTargetDispatchEvent(parser.toEventTarget(parser.DocumentHTML, html_doc), evt);
_ = try parser.eventTargetDispatchEvent(parser.toEventTarget(parser.DocumentHTML, self), evt);
}

pub fn documentIsComplete(html_doc: *parser.DocumentHTML, page: *Page) !void {
const self = try page.getOrCreateNodeWrapper(HTMLDocument, @ptrCast(html_doc));
self.ready_state = .complete;
pub fn documentIsComplete(self: *parser.DocumentHTML, page: *Page) !void {
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
state.ready_state = .complete;
}
};

Expand Down
45 changes: 17 additions & 28 deletions src/browser/html/elements.zig
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const Page = @import("../page.zig").Page;
const urlStitch = @import("../../url.zig").URL.stitch;
const URL = @import("../url/url.zig").URL;
const Node = @import("../dom/node.zig").Node;
const State = @import("../state/HTMLElement.zig");
const Element = @import("../dom/element.zig").Element;

const CSSStyleDeclaration = @import("../cssom/css_style_declaration.zig").CSSStyleDeclaration;
Expand Down Expand Up @@ -112,11 +113,9 @@ pub const HTMLElement = struct {
pub const prototype = *Element;
pub const subtype = .node;

style: CSSStyleDeclaration = .empty,

pub fn get_style(e: *parser.ElementHTML, page: *Page) !*CSSStyleDeclaration {
const self = try page.getOrCreateNodeWrapper(HTMLElement, @ptrCast(e));
return &self.style;
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(e));
return &state.style;
}

pub fn get_innerText(e: *parser.ElementHTML) ![]const u8 {
Expand Down Expand Up @@ -159,16 +158,9 @@ pub const HTMLElement = struct {
return;
}

const root_node = try parser.nodeGetRootNode(@ptrCast(e));

const Document = @import("../dom/document.zig").Document;
const document = try page.getOrCreateNodeWrapper(Document, @ptrCast(root_node));

// TODO: some elements can't be focused, like if they're disabled
// but there doesn't seem to be a generic way to check this. For example
// we could look for the "disabled" attribute, but that's only meaningful
// on certain types, and libdom's vtable doesn't seem to expose this.
document.active_element = @ptrCast(e);
const root_node = try parser.nodeGetRootNode(@ptrCast(e));
try Document.setFocus(@ptrCast(root_node), e, page);
}
};

Expand Down Expand Up @@ -852,9 +844,6 @@ pub const HTMLScriptElement = struct {
pub const prototype = *HTMLElement;
pub const subtype = .node;

onload: ?Env.Function = null,
onerror: ?Env.Function = null,

pub fn get_src(self: *parser.Script) !?[]const u8 {
return try parser.elementGetAttribute(
parser.scriptToElt(self),
Expand Down Expand Up @@ -964,24 +953,24 @@ pub const HTMLScriptElement = struct {
return try parser.elementRemoveAttribute(parser.scriptToElt(self), "nomodule");
}

pub fn get_onload(script: *parser.Script, page: *Page) !?Env.Function {
const self = page.getNodeWrapper(HTMLScriptElement, @ptrCast(script)) orelse return null;
return self.onload;
pub fn get_onload(self: *parser.Script, page: *Page) !?Env.Function {
const state = page.getNodeWrapper(State, @ptrCast(self)) orelse return null;
return state.onload;
}

pub fn set_onload(script: *parser.Script, function: ?Env.Function, page: *Page) !void {
const self = try page.getOrCreateNodeWrapper(HTMLScriptElement, @ptrCast(script));
self.onload = function;
pub fn set_onload(self: *parser.Script, function: ?Env.Function, page: *Page) !void {
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
state.onload = function;
}

pub fn get_onerror(script: *parser.Script, page: *Page) !?Env.Function {
const self = page.getNodeWrapper(HTMLScriptElement, @ptrCast(script)) orelse return null;
return self.onerror;
pub fn get_onerror(self: *parser.Script, page: *Page) !?Env.Function {
const state = page.getNodeWrapper(State, @ptrCast(self)) orelse return null;
return state.onerror;
}

pub fn set_onerror(script: *parser.Script, function: ?Env.Function, page: *Page) !void {
const self = try page.getOrCreateNodeWrapper(HTMLScriptElement, @ptrCast(script));
self.onerror = function;
pub fn set_onerror(self: *parser.Script, function: ?Env.Function, page: *Page) !void {
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
state.onerror = function;
}
};

Expand Down
4 changes: 2 additions & 2 deletions src/browser/page.zig
Original file line number Diff line number Diff line change
Expand Up @@ -743,8 +743,8 @@ const Script = struct {
// attached to it. But this seems quite unlikely and it does help
// optimize loading scripts, of which there can be hundreds for a
// page.
const HTMLScriptElement = @import("html/elements.zig").HTMLScriptElement;
if (page.getNodeWrapper(HTMLScriptElement, @ptrCast(e))) |se| {
const State = @import("state/HTMLElement.zig");
if (page.getNodeWrapper(State, @ptrCast(e))) |se| {
if (se.onload) |function| {
onload = .{ .function = function };
}
Expand Down
31 changes: 31 additions & 0 deletions src/browser/state/Document.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
//
// Francis Bouvier <[email protected]>
// Pierre Tachoire <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

const parser = @import("../netsurf.zig");

// proxy-owner for html/document
ready_state: ReadyState = .loading,

// proxy-owner for dom/document
active_element: ?*parser.Element = null,

const ReadyState = enum {
loading,
interactive,
complete,
};
24 changes: 24 additions & 0 deletions src/browser/state/HTMLElement.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
//
// Francis Bouvier <[email protected]>
// Pierre Tachoire <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

const Env = @import("../env.zig").Env;
const CSSStyleDeclaration = @import("../cssom/css_style_declaration.zig").CSSStyleDeclaration;

onload: ?Env.Function = null,
onerror: ?Env.Function = null,
style: CSSStyleDeclaration = .empty,