Skip to content

Commit b3f7fb7

Browse files
committed
dom: implement navigator.userAgent
1 parent 9fb51a1 commit b3f7fb7

File tree

6 files changed

+75
-5
lines changed

6 files changed

+75
-5
lines changed

src/browser/browser.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,15 @@ const polyfill = @import("../polyfill/polyfill.zig");
4646

4747
const log = std.log.scoped(.browser);
4848

49+
const user_agent = "Lightpanda.io/1.0";
50+
4951
// Browser is an instance of the browser.
5052
// You can create multiple browser instances.
5153
// A browser contains only one session.
5254
// TODO allow multiple sessions per browser.
5355
pub const Browser = struct {
5456
session: Session = undefined,
57+
agent: []const u8 = user_agent,
5558

5659
const uri = "about:blank";
5760

@@ -111,7 +114,7 @@ pub const Session = struct {
111114
.uri = uri,
112115
.alloc = alloc,
113116
.arena = std.heap.ArenaAllocator.init(alloc),
114-
.window = Window.create(null),
117+
.window = Window.create(null, .{ .agent = user_agent }),
115118
.loader = Loader.init(alloc),
116119
.storageShed = storage.Shed.init(alloc),
117120
.httpClient = undefined,

src/html/html.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ const generate = @import("../generate.zig");
2121
const HTMLDocument = @import("document.zig").HTMLDocument;
2222
const HTMLElem = @import("elements.zig");
2323
const Window = @import("window.zig").Window;
24+
const Navigator = @import("navigator.zig").Navigator;
2425

2526
pub const Interfaces = generate.Tuple(.{
2627
HTMLDocument,
2728
HTMLElem.HTMLElement,
2829
HTMLElem.HTMLMediaElement,
2930
HTMLElem.Interfaces,
3031
Window,
32+
Navigator,
3133
});

src/html/navigator.zig

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <[email protected]>
4+
// Pierre Tachoire <[email protected]>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
21+
const parser = @import("netsurf");
22+
const jsruntime = @import("jsruntime");
23+
const Callback = jsruntime.Callback;
24+
const CallbackArg = jsruntime.CallbackArg;
25+
const Loop = jsruntime.Loop;
26+
27+
const Case = jsruntime.test_utils.Case;
28+
const checkCases = jsruntime.test_utils.checkCases;
29+
30+
const EventTarget = @import("../dom/event_target.zig").EventTarget;
31+
32+
const storage = @import("../storage/storage.zig");
33+
34+
// https://html.spec.whatwg.org/multipage/system-state.html#navigator
35+
pub const Navigator = struct {
36+
pub const mem_guarantied = true;
37+
38+
agent: []const u8 = "",
39+
40+
pub fn get_userAgent(self: *Navigator) []const u8 {
41+
return self.agent;
42+
}
43+
};
44+
45+
// Tests
46+
// -----
47+
48+
pub fn testExecFn(
49+
_: std.mem.Allocator,
50+
js_env: *jsruntime.Env,
51+
) anyerror!void {
52+
var navigator = [_]Case{
53+
.{ .src = "navigator.userAgent", .ex = "" },
54+
};
55+
try checkCases(js_env, &navigator);
56+
}

src/html/window.zig

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const CallbackArg = jsruntime.CallbackArg;
2525
const Loop = jsruntime.Loop;
2626

2727
const EventTarget = @import("../dom/event_target.zig").EventTarget;
28+
const Navigator = @import("navigator.zig").Navigator;
2829

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

@@ -48,9 +49,12 @@ pub const Window = struct {
4849
timeoutid: u32 = 0,
4950
timeoutids: [512]u64 = undefined,
5051

51-
pub fn create(target: ?[]const u8) Window {
52+
navigator: Navigator,
53+
54+
pub fn create(target: ?[]const u8, navigator: ?Navigator) Window {
5255
return Window{
5356
.target = target orelse "",
57+
.navigator = navigator orelse .{},
5458
};
5559
}
5660

@@ -66,6 +70,10 @@ pub const Window = struct {
6670
return self;
6771
}
6872

73+
pub fn get_navigator(self: *Window) *Navigator {
74+
return &self.navigator;
75+
}
76+
6977
pub fn get_self(self: *Window) *Window {
7078
return self;
7179
}

src/run_tests.zig

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ fn testExecFn(
9696
});
9797

9898
// alias global as self and window
99-
var window = Window.create(null);
99+
var window = Window.create(null, null);
100100

101101
window.replaceDocument(doc);
102102
window.setStorageShelf(&storageShelf);
@@ -137,6 +137,7 @@ fn testsAllExecFn(
137137
HTMLElementTestExecFn,
138138
MutationObserverTestExecFn,
139139
@import("polyfill/fetch.zig").testExecFn,
140+
@import("html/navigator.zig").testExecFn,
140141
};
141142

142143
inline for (testFns) |testFn| {
@@ -359,7 +360,7 @@ test "bug document html parsing #4" {
359360
}
360361

361362
test "Window is a libdom event target" {
362-
var window = Window.create(null);
363+
var window = Window.create(null, null);
363364

364365
const event = try parser.eventCreate();
365366
try parser.eventInit(event, "foo", .{});

src/wpt/run.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
9090
}
9191

9292
// setup global env vars.
93-
var window = Window.create(null);
93+
var window = Window.create(null, null);
9494
window.replaceDocument(html_doc);
9595
window.setStorageShelf(&storageShelf);
9696
try js_env.bindGlobal(&window);

0 commit comments

Comments
 (0)