mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 23:23:28 +00:00
merge all states
This commit is contained in:
65
src/browser/State.zig
Normal file
65
src/browser/State.zig
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
|
||||||
|
//
|
||||||
|
// Francis Bouvier <francis@lightpanda.io>
|
||||||
|
// Pierre Tachoire <pierre@lightpanda.io>
|
||||||
|
//
|
||||||
|
// 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/>.
|
||||||
|
|
||||||
|
// Sometimes we need to extend libdom. For example, its HTMLDocument doesn't
|
||||||
|
// have a readyState. We have a couple different options, such as making the
|
||||||
|
// correction in libdom directly. Another option stems from the fact that every
|
||||||
|
// libdom node has an opaque embedder_data field. This is the struct that we
|
||||||
|
// lazily load into that field.
|
||||||
|
//
|
||||||
|
// It didn't originally start off as a collection of every single extension, but
|
||||||
|
// this quickly proved necessary, since different fields are needed on the same
|
||||||
|
// data at different levels of the prototype chain. This isn't memory efficient.
|
||||||
|
|
||||||
|
const Env = @import("env.zig").Env;
|
||||||
|
const parser = @import("netsurf.zig");
|
||||||
|
const CSSStyleDeclaration = @import("cssom/css_style_declaration.zig").CSSStyleDeclaration;
|
||||||
|
|
||||||
|
// for HTMLScript (but probably needs to be added to more)
|
||||||
|
onload: ?Env.Function = null,
|
||||||
|
onerror: ?Env.Function = null,
|
||||||
|
|
||||||
|
// for HTMLElement
|
||||||
|
style: CSSStyleDeclaration = .empty,
|
||||||
|
|
||||||
|
// for html/document
|
||||||
|
ready_state: ReadyState = .loading,
|
||||||
|
|
||||||
|
// for dom/document
|
||||||
|
active_element: ?*parser.Element = null,
|
||||||
|
|
||||||
|
// for HTMLSelectElement
|
||||||
|
// By default, if no option is explicitly selected, the first option should
|
||||||
|
// be selected. However, libdom doesn't do this, and it sets the
|
||||||
|
// selectedIndex to -1, which is a valid value for "nothing selected".
|
||||||
|
// Therefore, when libdom says the selectedIndex == -1, we don't know if
|
||||||
|
// it means that nothing is selected, or if the first option is selected by
|
||||||
|
// default.
|
||||||
|
// There are cases where this won't work, but when selectedIndex is
|
||||||
|
// explicitly set, we set this boolean flag. Then, when we're getting then
|
||||||
|
// selectedIndex, if this flag is == false, which is to say that if
|
||||||
|
// selectedIndex hasn't been explicitly set AND if we have at least 1 option
|
||||||
|
// AND if it isn't a multi select, we can make the 1st item selected by
|
||||||
|
// default (by returning selectedIndex == 0).
|
||||||
|
explicit_index_set: bool = false,
|
||||||
|
|
||||||
|
const ReadyState = enum {
|
||||||
|
loading,
|
||||||
|
interactive,
|
||||||
|
complete,
|
||||||
|
};
|
||||||
@@ -21,6 +21,7 @@ const std = @import("std");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
|
|
||||||
|
const State = @import("State.zig");
|
||||||
const Env = @import("env.zig").Env;
|
const Env = @import("env.zig").Env;
|
||||||
const App = @import("../app.zig").App;
|
const App = @import("../app.zig").App;
|
||||||
const Session = @import("session.zig").Session;
|
const Session = @import("session.zig").Session;
|
||||||
@@ -41,6 +42,7 @@ pub const Browser = struct {
|
|||||||
session_arena: ArenaAllocator,
|
session_arena: ArenaAllocator,
|
||||||
transfer_arena: ArenaAllocator,
|
transfer_arena: ArenaAllocator,
|
||||||
notification: *Notification,
|
notification: *Notification,
|
||||||
|
state_pool: std.heap.MemoryPool(State),
|
||||||
|
|
||||||
pub fn init(app: *App) !Browser {
|
pub fn init(app: *App) !Browser {
|
||||||
const allocator = app.allocator;
|
const allocator = app.allocator;
|
||||||
@@ -61,6 +63,7 @@ pub const Browser = struct {
|
|||||||
.page_arena = ArenaAllocator.init(allocator),
|
.page_arena = ArenaAllocator.init(allocator),
|
||||||
.session_arena = ArenaAllocator.init(allocator),
|
.session_arena = ArenaAllocator.init(allocator),
|
||||||
.transfer_arena = ArenaAllocator.init(allocator),
|
.transfer_arena = ArenaAllocator.init(allocator),
|
||||||
|
.state_pool = std.heap.MemoryPool(State).init(allocator),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +74,7 @@ pub const Browser = struct {
|
|||||||
self.session_arena.deinit();
|
self.session_arena.deinit();
|
||||||
self.transfer_arena.deinit();
|
self.transfer_arena.deinit();
|
||||||
self.notification.deinit();
|
self.notification.deinit();
|
||||||
|
self.state_pool.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn newSession(self: *Browser) !*Session {
|
pub fn newSession(self: *Browser) !*Session {
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ const NodeUnion = @import("node.zig").Union;
|
|||||||
const collection = @import("html_collection.zig");
|
const collection = @import("html_collection.zig");
|
||||||
const css = @import("css.zig");
|
const css = @import("css.zig");
|
||||||
|
|
||||||
const State = @import("../state/Document.zig");
|
|
||||||
const Element = @import("element.zig").Element;
|
const Element = @import("element.zig").Element;
|
||||||
const ElementUnion = @import("element.zig").Union;
|
const ElementUnion = @import("element.zig").Union;
|
||||||
const TreeWalker = @import("tree_walker.zig").TreeWalker;
|
const TreeWalker = @import("tree_walker.zig").TreeWalker;
|
||||||
@@ -245,7 +244,7 @@ pub const Document = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_activeElement(self: *parser.Document, page: *Page) !?ElementUnion {
|
pub fn get_activeElement(self: *parser.Document, page: *Page) !?ElementUnion {
|
||||||
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
|
const state = try page.getOrCreateNodeState(@ptrCast(self));
|
||||||
if (state.active_element) |ae| {
|
if (state.active_element) |ae| {
|
||||||
return try Element.toInterface(ae);
|
return try Element.toInterface(ae);
|
||||||
}
|
}
|
||||||
@@ -262,7 +261,7 @@ pub const Document = struct {
|
|||||||
// we could look for the "disabled" attribute, but that's only meaningful
|
// 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.
|
// 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 {
|
pub fn setFocus(self: *parser.Document, e: *parser.ElementHTML, page: *Page) !void {
|
||||||
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
|
const state = try page.getOrCreateNodeState(@ptrCast(self));
|
||||||
state.active_element = @ptrCast(e);
|
state.active_element = @ptrCast(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ const NodeList = @import("../dom/nodelist.zig").NodeList;
|
|||||||
const Location = @import("location.zig").Location;
|
const Location = @import("location.zig").Location;
|
||||||
|
|
||||||
const collection = @import("../dom/html_collection.zig");
|
const collection = @import("../dom/html_collection.zig");
|
||||||
const State = @import("../state/Document.zig");
|
|
||||||
const Walker = @import("../dom/walker.zig").WalkerDepthFirst;
|
const Walker = @import("../dom/walker.zig").WalkerDepthFirst;
|
||||||
const Cookie = @import("../storage/cookie.zig").Cookie;
|
const Cookie = @import("../storage/cookie.zig").Cookie;
|
||||||
|
|
||||||
@@ -185,7 +184,7 @@ pub const HTMLDocument = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_readyState(self: *parser.DocumentHTML, page: *Page) ![]const u8 {
|
pub fn get_readyState(self: *parser.DocumentHTML, page: *Page) ![]const u8 {
|
||||||
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
|
const state = try page.getOrCreateNodeState(@ptrCast(self));
|
||||||
return @tagName(state.ready_state);
|
return @tagName(state.ready_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +263,7 @@ pub const HTMLDocument = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn documentIsLoaded(self: *parser.DocumentHTML, page: *Page) !void {
|
pub fn documentIsLoaded(self: *parser.DocumentHTML, page: *Page) !void {
|
||||||
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
|
const state = try page.getOrCreateNodeState(@ptrCast(self));
|
||||||
state.ready_state = .interactive;
|
state.ready_state = .interactive;
|
||||||
|
|
||||||
const evt = try parser.eventCreate();
|
const evt = try parser.eventCreate();
|
||||||
@@ -279,7 +278,7 @@ pub const HTMLDocument = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn documentIsComplete(self: *parser.DocumentHTML, page: *Page) !void {
|
pub fn documentIsComplete(self: *parser.DocumentHTML, page: *Page) !void {
|
||||||
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
|
const state = try page.getOrCreateNodeState(@ptrCast(self));
|
||||||
state.ready_state = .complete;
|
state.ready_state = .complete;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ const Page = @import("../page.zig").Page;
|
|||||||
const urlStitch = @import("../../url.zig").URL.stitch;
|
const urlStitch = @import("../../url.zig").URL.stitch;
|
||||||
const URL = @import("../url/url.zig").URL;
|
const URL = @import("../url/url.zig").URL;
|
||||||
const Node = @import("../dom/node.zig").Node;
|
const Node = @import("../dom/node.zig").Node;
|
||||||
const State = @import("../state/HTMLElement.zig");
|
|
||||||
const Element = @import("../dom/element.zig").Element;
|
const Element = @import("../dom/element.zig").Element;
|
||||||
|
|
||||||
const CSSStyleDeclaration = @import("../cssom/css_style_declaration.zig").CSSStyleDeclaration;
|
const CSSStyleDeclaration = @import("../cssom/css_style_declaration.zig").CSSStyleDeclaration;
|
||||||
@@ -114,7 +113,7 @@ pub const HTMLElement = struct {
|
|||||||
pub const subtype = .node;
|
pub const subtype = .node;
|
||||||
|
|
||||||
pub fn get_style(e: *parser.ElementHTML, page: *Page) !*CSSStyleDeclaration {
|
pub fn get_style(e: *parser.ElementHTML, page: *Page) !*CSSStyleDeclaration {
|
||||||
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(e));
|
const state = try page.getOrCreateNodeState(@ptrCast(e));
|
||||||
return &state.style;
|
return &state.style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -954,22 +953,22 @@ pub const HTMLScriptElement = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_onload(self: *parser.Script, page: *Page) !?Env.Function {
|
pub fn get_onload(self: *parser.Script, page: *Page) !?Env.Function {
|
||||||
const state = page.getNodeWrapper(State, @ptrCast(self)) orelse return null;
|
const state = page.getNodeState(@ptrCast(self)) orelse return null;
|
||||||
return state.onload;
|
return state.onload;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_onload(self: *parser.Script, function: ?Env.Function, page: *Page) !void {
|
pub fn set_onload(self: *parser.Script, function: ?Env.Function, page: *Page) !void {
|
||||||
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
|
const state = try page.getOrCreateNodeState(@ptrCast(self));
|
||||||
state.onload = function;
|
state.onload = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_onerror(self: *parser.Script, page: *Page) !?Env.Function {
|
pub fn get_onerror(self: *parser.Script, page: *Page) !?Env.Function {
|
||||||
const state = page.getNodeWrapper(State, @ptrCast(self)) orelse return null;
|
const state = page.getNodeState(@ptrCast(self)) orelse return null;
|
||||||
return state.onerror;
|
return state.onerror;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_onerror(self: *parser.Script, function: ?Env.Function, page: *Page) !void {
|
pub fn set_onerror(self: *parser.Script, function: ?Env.Function, page: *Page) !void {
|
||||||
const state = try page.getOrCreateNodeWrapper(State, @ptrCast(self));
|
const state = try page.getOrCreateNodeState(@ptrCast(self));
|
||||||
state.onerror = function;
|
state.onerror = function;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,20 +26,6 @@ pub const HTMLSelectElement = struct {
|
|||||||
pub const prototype = *HTMLElement;
|
pub const prototype = *HTMLElement;
|
||||||
pub const subtype = .node;
|
pub const subtype = .node;
|
||||||
|
|
||||||
// By default, if no option is explicitly selected, the first option should
|
|
||||||
// be selected. However, libdom doesn't do this, and it sets the
|
|
||||||
// selectedIndex to -1, which is a valid value for "nothing selected".
|
|
||||||
// Therefore, when libdom says the selectedIndex == -1, we don't know if
|
|
||||||
// it means that nothing is selected, or if the first option is selected by
|
|
||||||
// default.
|
|
||||||
// There are cases where this won't work, but when selectedIndex is
|
|
||||||
// explicitly set, we set this boolean flag. Then, when we're getting then
|
|
||||||
// selectedIndex, if this flag is == false, which is to say that if
|
|
||||||
// selectedIndex hasn't been explicitly set AND if we have at least 1 option
|
|
||||||
// AND if it isn't a multi select, we can make the 1st item selected by
|
|
||||||
// default (by returning selectedIndex == 0).
|
|
||||||
explicit_index_set: bool = false,
|
|
||||||
|
|
||||||
pub fn get_length(select: *parser.Select) !u32 {
|
pub fn get_length(select: *parser.Select) !u32 {
|
||||||
return parser.selectGetLength(select);
|
return parser.selectGetLength(select);
|
||||||
}
|
}
|
||||||
@@ -70,11 +56,11 @@ pub const HTMLSelectElement = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_selectedIndex(select: *parser.Select, page: *Page) !i32 {
|
pub fn get_selectedIndex(select: *parser.Select, page: *Page) !i32 {
|
||||||
const self = try page.getOrCreateNodeWrapper(HTMLSelectElement, @ptrCast(select));
|
const state = try page.getOrCreateNodeState(@ptrCast(select));
|
||||||
const selected_index = try parser.selectGetSelectedIndex(select);
|
const selected_index = try parser.selectGetSelectedIndex(select);
|
||||||
|
|
||||||
// See the explicit_index_set field documentation
|
// See the explicit_index_set field documentation
|
||||||
if (!self.explicit_index_set) {
|
if (!state.explicit_index_set) {
|
||||||
if (selected_index == -1) {
|
if (selected_index == -1) {
|
||||||
if (try parser.selectGetMultiple(select) == false) {
|
if (try parser.selectGetMultiple(select) == false) {
|
||||||
if (try get_length(select) > 0) {
|
if (try get_length(select) > 0) {
|
||||||
@@ -89,8 +75,8 @@ pub const HTMLSelectElement = struct {
|
|||||||
// Libdom's dom_html_select_select_set_selected_index will crash if index
|
// Libdom's dom_html_select_select_set_selected_index will crash if index
|
||||||
// is out of range, and it doesn't properly unset options
|
// is out of range, and it doesn't properly unset options
|
||||||
pub fn set_selectedIndex(select: *parser.Select, index: i32, page: *Page) !void {
|
pub fn set_selectedIndex(select: *parser.Select, index: i32, page: *Page) !void {
|
||||||
var self = try page.getOrCreateNodeWrapper(HTMLSelectElement, @ptrCast(select));
|
var state = try page.getOrCreateNodeState(@ptrCast(select));
|
||||||
self.explicit_index_set = true;
|
state.explicit_index_set = true;
|
||||||
|
|
||||||
const options = try parser.selectGetOptions(select);
|
const options = try parser.selectGetOptions(select);
|
||||||
const len = try parser.optionCollectionGetLength(options);
|
const len = try parser.optionCollectionGetLength(options);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ const builtin = @import("builtin");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const Dump = @import("dump.zig");
|
const Dump = @import("dump.zig");
|
||||||
|
const State = @import("State.zig");
|
||||||
const Env = @import("env.zig").Env;
|
const Env = @import("env.zig").Env;
|
||||||
const Mime = @import("mime.zig").Mime;
|
const Mime = @import("mime.zig").Mime;
|
||||||
const DataURI = @import("datauri.zig").DataURI;
|
const DataURI = @import("datauri.zig").DataURI;
|
||||||
@@ -95,6 +96,8 @@ pub const Page = struct {
|
|||||||
// indicates intention to navigate to another page on the next loop execution.
|
// indicates intention to navigate to another page on the next loop execution.
|
||||||
delayed_navigation: bool = false,
|
delayed_navigation: bool = false,
|
||||||
|
|
||||||
|
state_pool: *std.heap.MemoryPool(State),
|
||||||
|
|
||||||
pub fn init(self: *Page, arena: Allocator, session: *Session) !void {
|
pub fn init(self: *Page, arena: Allocator, session: *Session) !void {
|
||||||
const browser = session.browser;
|
const browser = session.browser;
|
||||||
self.* = .{
|
self.* = .{
|
||||||
@@ -106,6 +109,7 @@ pub const Page = struct {
|
|||||||
.call_arena = undefined,
|
.call_arena = undefined,
|
||||||
.loop = browser.app.loop,
|
.loop = browser.app.loop,
|
||||||
.renderer = Renderer.init(arena),
|
.renderer = Renderer.init(arena),
|
||||||
|
.state_pool = &browser.state_pool,
|
||||||
.cookie_jar = &session.cookie_jar,
|
.cookie_jar = &session.cookie_jar,
|
||||||
.microtask_node = .{ .func = microtaskCallback },
|
.microtask_node = .{ .func = microtaskCallback },
|
||||||
.window_clicked_event_node = .{ .func = windowClicked },
|
.window_clicked_event_node = .{ .func = windowClicked },
|
||||||
@@ -597,21 +601,21 @@ pub const Page = struct {
|
|||||||
_ = try self.loop.timeout(0, &navi.navigate_node);
|
_ = try self.loop.timeout(0, &navi.navigate_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOrCreateNodeWrapper(self: *Page, comptime T: type, node: *parser.Node) !*T {
|
pub fn getOrCreateNodeState(self: *Page, node: *parser.Node) !*State {
|
||||||
if (self.getNodeWrapper(T, node)) |wrap| {
|
if (self.getNodeState(node)) |wrap| {
|
||||||
return wrap;
|
return wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wrap = try self.arena.create(T);
|
const state = try self.state_pool.create();
|
||||||
wrap.* = T{};
|
state.* = .{};
|
||||||
|
|
||||||
parser.nodeSetEmbedderData(node, wrap);
|
parser.nodeSetEmbedderData(node, state);
|
||||||
return wrap;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getNodeWrapper(_: *const Page, comptime T: type, node: *parser.Node) ?*T {
|
pub fn getNodeState(_: *const Page, node: *parser.Node) ?*State {
|
||||||
if (parser.nodeGetEmbedderData(node)) |wrap| {
|
if (parser.nodeGetEmbedderData(node)) |state| {
|
||||||
return @alignCast(@ptrCast(wrap));
|
return @alignCast(@ptrCast(state));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -743,8 +747,7 @@ const Script = struct {
|
|||||||
// attached to it. But this seems quite unlikely and it does help
|
// attached to it. But this seems quite unlikely and it does help
|
||||||
// optimize loading scripts, of which there can be hundreds for a
|
// optimize loading scripts, of which there can be hundreds for a
|
||||||
// page.
|
// page.
|
||||||
const State = @import("state/HTMLElement.zig");
|
if (page.getNodeState(@ptrCast(e))) |se| {
|
||||||
if (page.getNodeWrapper(State, @ptrCast(e))) |se| {
|
|
||||||
if (se.onload) |function| {
|
if (se.onload) |function| {
|
||||||
onload = .{ .function = function };
|
onload = .{ .function = function };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ pub const Session = struct {
|
|||||||
|
|
||||||
const page_arena = &self.browser.page_arena;
|
const page_arena = &self.browser.page_arena;
|
||||||
_ = page_arena.reset(.{ .retain_with_limit = 1 * 1024 * 1024 });
|
_ = page_arena.reset(.{ .retain_with_limit = 1 * 1024 * 1024 });
|
||||||
|
_ = self.browser.state_pool.reset(.{ .retain_with_limit = 4 * 1024 });
|
||||||
|
|
||||||
self.page = @as(Page, undefined);
|
self.page = @as(Page, undefined);
|
||||||
const page = &self.page.?;
|
const page = &self.page.?;
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
|
|
||||||
//
|
|
||||||
// Francis Bouvier <francis@lightpanda.io>
|
|
||||||
// Pierre Tachoire <pierre@lightpanda.io>
|
|
||||||
//
|
|
||||||
// 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,
|
|
||||||
};
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
|
|
||||||
//
|
|
||||||
// Francis Bouvier <francis@lightpanda.io>
|
|
||||||
// Pierre Tachoire <pierre@lightpanda.io>
|
|
||||||
//
|
|
||||||
// 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,
|
|
||||||
Reference in New Issue
Block a user