Skip to content

Commit

Permalink
Merge pull request #356 from lightpanda-io/location
Browse files Browse the repository at this point in the history
dom: first draft for location
  • Loading branch information
krichprollsch authored Jan 27, 2025
2 parents 0c89fa7 + 7b35bb4 commit 3fb1677
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 6 deletions.
23 changes: 22 additions & 1 deletion src/browser/browser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ const apiweb = @import("../apiweb.zig");
const Window = @import("../html/window.zig").Window;
const Walker = @import("../dom/walker.zig").WalkerDepthFirst;

const URL = @import("../url/url.zig").URL;
const Location = @import("../html/location.zig").Location;

const storage = @import("../storage/storage.zig");

const FetchResult = @import("../http/Client.zig").Client.FetchResult;
Expand Down Expand Up @@ -102,7 +105,9 @@ pub const Session = struct {
loader: Loader,
env: Env = undefined,
inspector: ?jsruntime.Inspector = null,

window: Window,

// TODO move the shed to the browser?
storageShed: storage.Shed,
page: ?Page = null,
Expand Down Expand Up @@ -201,6 +206,10 @@ pub const Page = struct {
uri: std.Uri = undefined,
origin: ?[]const u8 = null,

// html url and location
url: ?URL = null,
location: Location = .{},

raw_data: ?[]const u8 = null,

fn init(
Expand Down Expand Up @@ -244,6 +253,13 @@ pub const Page = struct {
self.session.env.stop();
// TODO unload document: https://html.spec.whatwg.org/#unloading-documents

if (self.url) |*u| u.deinit(self.arena.allocator());
self.url = null;
self.location.url = null;
self.session.window.replaceLocation(&self.location) catch |e| {
log.err("reset window location: {any}", .{e});
};

// clear netsurf memory arena.
parser.deinit();

Expand Down Expand Up @@ -308,6 +324,11 @@ pub const Page = struct {
self.rawuri = try alloc.dupe(u8, uri);
self.uri = std.Uri.parse(self.rawuri.?) catch try std.Uri.parseAfterScheme("", self.rawuri.?);

if (self.url) |*prev| prev.deinit(alloc);
self.url = try URL.constructor(alloc, self.rawuri.?, null);
self.location.url = &self.url.?;
try self.session.window.replaceLocation(&self.location);

// prepare origin value.
var buf = std.ArrayList(u8).init(alloc);
defer buf.deinit();
Expand Down Expand Up @@ -391,7 +412,7 @@ pub const Page = struct {

// TODO set the referrer to the document.

self.session.window.replaceDocument(html_doc);
try self.session.window.replaceDocument(html_doc);
self.session.window.setStorageShelf(
try self.session.storageShed.getOrPut(self.origin orelse "null"),
);
Expand Down
5 changes: 5 additions & 0 deletions src/html/document.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const Node = @import("../dom/node.zig").Node;
const Document = @import("../dom/document.zig").Document;
const NodeList = @import("../dom/nodelist.zig").NodeList;
const HTMLElem = @import("elements.zig");
const Location = @import("location.zig").Location;

const collection = @import("../dom/html_collection.zig");
const Walker = @import("../dom/walker.zig").WalkerDepthFirst;
Expand Down Expand Up @@ -157,6 +158,10 @@ pub const HTMLDocument = struct {
return try parser.documentHTMLGetCurrentScript(self);
}

pub fn get_location(self: *parser.DocumentHTML) !?*Location {
return try parser.documentHTMLGetLocation(Location, self);
}

pub fn get_designMode(_: *parser.DocumentHTML) []const u8 {
return "off";
}
Expand Down
2 changes: 2 additions & 0 deletions src/html/html.zig
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const HTMLElem = @import("elements.zig");
const Window = @import("window.zig").Window;
const Navigator = @import("navigator.zig").Navigator;
const History = @import("history.zig").History;
const Location = @import("location.zig").Location;

pub const Interfaces = generate.Tuple(.{
HTMLDocument,
Expand All @@ -32,4 +33,5 @@ pub const Interfaces = generate.Tuple(.{
Window,
Navigator,
History,
Location,
});
129 changes: 129 additions & 0 deletions src/html/location.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// 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 std = @import("std");

const builtin = @import("builtin");
const jsruntime = @import("jsruntime");

const URL = @import("../url/url.zig").URL;

const Case = jsruntime.test_utils.Case;
const checkCases = jsruntime.test_utils.checkCases;

// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-location-interface
pub const Location = struct {
pub const mem_guarantied = true;

url: ?*URL = null,

pub fn deinit(_: *Location, _: std.mem.Allocator) void {}

pub fn get_href(self: *Location, alloc: std.mem.Allocator) ![]const u8 {
if (self.url) |u| return u.get_href(alloc);

return "";
}

pub fn get_protocol(self: *Location, alloc: std.mem.Allocator) ![]const u8 {
if (self.url) |u| return u.get_protocol(alloc);

return "";
}

pub fn get_host(self: *Location, alloc: std.mem.Allocator) ![]const u8 {
if (self.url) |u| return u.get_host(alloc);

return "";
}

pub fn get_hostname(self: *Location) []const u8 {
if (self.url) |u| return u.get_hostname();

return "";
}

pub fn get_port(self: *Location, alloc: std.mem.Allocator) ![]const u8 {
if (self.url) |u| return u.get_port(alloc);

return "";
}

pub fn get_pathname(self: *Location) []const u8 {
if (self.url) |u| return u.get_pathname();

return "";
}

pub fn get_search(self: *Location, alloc: std.mem.Allocator) ![]const u8 {
if (self.url) |u| return u.get_search(alloc);

return "";
}

pub fn get_hash(self: *Location, alloc: std.mem.Allocator) ![]const u8 {
if (self.url) |u| return u.get_hash(alloc);

return "";
}

pub fn get_origin(self: *Location, alloc: std.mem.Allocator) ![]const u8 {
if (self.url) |u| return u.get_origin(alloc);

return "";
}

// TODO
pub fn _assign(_: *Location, url: []const u8) !void {
_ = url;
}

// TODO
pub fn _replace(_: *Location, url: []const u8) !void {
_ = url;
}

// TODO
pub fn _reload(_: *Location) !void {}

pub fn _toString(self: *Location, alloc: std.mem.Allocator) ![]const u8 {
return try self.get_href(alloc);
}
};

// Tests
// -----

pub fn testExecFn(
_: std.mem.Allocator,
js_env: *jsruntime.Env,
) anyerror!void {
var location = [_]Case{
.{ .src = "location.href", .ex = "https://lightpanda.io/opensource-browser/" },
.{ .src = "document.location.href", .ex = "https://lightpanda.io/opensource-browser/" },

.{ .src = "location.host", .ex = "lightpanda.io" },
.{ .src = "location.hostname", .ex = "lightpanda.io" },
.{ .src = "location.origin", .ex = "https://lightpanda.io" },
.{ .src = "location.pathname", .ex = "/opensource-browser/" },
.{ .src = "location.hash", .ex = "" },
.{ .src = "location.port", .ex = "" },
.{ .src = "location.search", .ex = "" },
};
try checkCases(js_env, &location);
}
19 changes: 18 additions & 1 deletion src/html/window.zig
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@ const Loop = jsruntime.Loop;
const EventTarget = @import("../dom/event_target.zig").EventTarget;
const Navigator = @import("navigator.zig").Navigator;
const History = @import("history.zig").History;
const Location = @import("location.zig").Location;

const storage = @import("../storage/storage.zig");

var emptyLocation = Location{};

// https://dom.spec.whatwg.org/#interface-window-extensions
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#window
pub const Window = struct {
Expand All @@ -43,6 +46,7 @@ pub const Window = struct {
document: ?*parser.DocumentHTML = null,
target: []const u8,
history: History = .{},
location: *Location = &emptyLocation,

storageShelf: ?*storage.Shelf = null,

Expand All @@ -60,8 +64,17 @@ pub const Window = struct {
};
}

pub fn replaceDocument(self: *Window, doc: *parser.DocumentHTML) void {
pub fn replaceLocation(self: *Window, loc: *Location) !void {
self.location = loc;

if (self.document != null) {
try parser.documentHTMLSetLocation(Location, self.document.?, self.location);
}
}

pub fn replaceDocument(self: *Window, doc: *parser.DocumentHTML) !void {
self.document = doc;
try parser.documentHTMLSetLocation(Location, doc, self.location);
}

pub fn setStorageShelf(self: *Window, shelf: *storage.Shelf) void {
Expand All @@ -76,6 +89,10 @@ pub const Window = struct {
return &self.navigator;
}

pub fn get_location(self: *Window) *Location {
return self.location;
}

pub fn get_self(self: *Window) *Window {
return self;
}
Expand Down
2 changes: 1 addition & 1 deletion src/main_shell.zig
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn execJS(

// alias global as self and window
var window = Window.create(null, null);
window.replaceDocument(doc);
try window.replaceDocument(doc);
window.setStorageShelf(&storageShelf);
try js_env.bindGlobal(window);

Expand Down
17 changes: 17 additions & 0 deletions src/netsurf/netsurf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2264,3 +2264,20 @@ pub fn documentHTMLGetCurrentScript(doc: *DocumentHTML) !?*Script {
if (elem == null) return null;
return @ptrCast(elem.?);
}

pub fn documentHTMLSetLocation(T: type, doc: *DocumentHTML, location: *T) !void {
const l = @as(*anyopaque, @ptrCast(location));
const err = documentHTMLVtable(doc).set_location.?(doc, l);
try DOMErr(err);
}

pub fn documentHTMLGetLocation(T: type, doc: *DocumentHTML) !?*T {
var l: ?*anyopaque = undefined;
const err = documentHTMLVtable(doc).get_location.?(doc, &l);
try DOMErr(err);

if (l == null) return null;

const ptr: *align(@alignOf(*T)) anyopaque = @alignCast(l.?);
return @as(*T, @ptrCast(ptr));
}
10 changes: 9 additions & 1 deletion src/run_tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ const Window = @import("html/window.zig").Window;
const xhr = @import("xhr/xhr.zig");
const storage = @import("storage/storage.zig");
const url = @import("url/url.zig");
const URL = url.URL;
const urlquery = @import("url/query.zig");
const Client = @import("asyncio").Client;
const Location = @import("html/location.zig").Location;

const documentTestExecFn = @import("dom/document.zig").testExecFn;
const HTMLDocumentTestExecFn = @import("html/document.zig").testExecFn;
Expand Down Expand Up @@ -98,7 +100,12 @@ fn testExecFn(
// alias global as self and window
var window = Window.create(null, null);

window.replaceDocument(doc);
var u = try URL.constructor(alloc, "https://lightpanda.io/opensource-browser/", null);
defer u.deinit(alloc);
var location = Location{ .url = &u };
try window.replaceLocation(&location);

try window.replaceDocument(doc);
window.setStorageShelf(&storageShelf);

try js_env.bindGlobal(window);
Expand Down Expand Up @@ -139,6 +146,7 @@ fn testsAllExecFn(
@import("polyfill/fetch.zig").testExecFn,
@import("html/navigator.zig").testExecFn,
@import("html/history.zig").testExecFn,
@import("html/location.zig").testExecFn,
};

inline for (testFns) |testFn| {
Expand Down
2 changes: 1 addition & 1 deletion src/wpt/run.zig
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const

// setup global env vars.
var window = Window.create(null, null);
window.replaceDocument(html_doc);
try window.replaceDocument(html_doc);
window.setStorageShelf(&storageShelf);
try js_env.bindGlobal(&window);

Expand Down
2 changes: 1 addition & 1 deletion vendor/netsurf/libdom

0 comments on commit 3fb1677

Please sign in to comment.