From fec212ab94c80e57d548691d9cf35931b3ce4d05 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Mon, 26 Feb 2024 10:57:51 +0100 Subject: [PATCH 1/3] window: use window as global object --- src/browser/browser.zig | 4 +--- src/html/window.zig | 1 + src/main.zig | 10 ++++------ src/main_get.zig | 1 + src/main_shell.zig | 10 ++++------ src/main_wpt.zig | 1 + src/run_tests.zig | 10 ++++------ src/wpt/run.zig | 26 +++++--------------------- vendor/jsruntime-lib | 2 +- 9 files changed, 22 insertions(+), 43 deletions(-) diff --git a/src/browser/browser.zig b/src/browser/browser.zig index da44f684..f901b2c3 100644 --- a/src/browser/browser.zig +++ b/src/browser/browser.zig @@ -240,9 +240,7 @@ pub const Page = struct { // add global objects log.debug("setup global env", .{}); - try self.session.env.addObject(self.session.window, "window"); - try self.session.env.addObject(self.session.window, "self"); - try self.session.env.addObject(html_doc, "document"); + try self.session.env.bindGlobal(self.session.window); // browse the DOM tree to retrieve scripts // TODO execute the synchronous scripts during the HTL parsing. diff --git a/src/html/window.zig b/src/html/window.zig index b61c11f0..e1080267 100644 --- a/src/html/window.zig +++ b/src/html/window.zig @@ -9,6 +9,7 @@ const EventTarget = @import("../dom/event_target.zig").EventTarget; pub const Window = struct { pub const prototype = *EventTarget; pub const mem_guarantied = true; + pub const global_type = true; // Extend libdom event target for pure zig struct. base: parser.EventTargetTBase = parser.EventTargetTBase{}, diff --git a/src/main.zig b/src/main.zig index 4469cddb..7bb1a24d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,6 +4,7 @@ const jsruntime = @import("jsruntime"); const parser = @import("netsurf.zig"); const apiweb = @import("apiweb.zig"); +const Window = @import("html/window.zig").Window; pub const Types = jsruntime.reflect(apiweb.Interfaces); @@ -16,17 +17,14 @@ fn execJS( alloc: std.mem.Allocator, js_env: *jsruntime.Env, ) anyerror!void { - // start JS env try js_env.start(alloc); defer js_env.stop(); // alias global as self and window - try js_env.attachObject(try js_env.getGlobal(), "self", null); - try js_env.attachObject(try js_env.getGlobal(), "window", null); - - // add document object - try js_env.addObject(doc, "document"); + var window = Window.create(null); + window.replaceDocument(parser.documentHTMLToDocument(doc)); + try js_env.bindGlobal(window); while (true) { diff --git a/src/main_get.zig b/src/main_get.zig index bb84b0d8..33a7d11e 100644 --- a/src/main_get.zig +++ b/src/main_get.zig @@ -3,6 +3,7 @@ const Browser = @import("browser/browser.zig").Browser; const jsruntime = @import("jsruntime"); const apiweb = @import("apiweb.zig"); + pub const Types = jsruntime.reflect(apiweb.Interfaces); pub const std_options = struct { diff --git a/src/main_shell.zig b/src/main_shell.zig index 920c77bf..c1971f9f 100644 --- a/src/main_shell.zig +++ b/src/main_shell.zig @@ -4,6 +4,7 @@ const jsruntime = @import("jsruntime"); const parser = @import("netsurf.zig"); const apiweb = @import("apiweb.zig"); +const Window = @import("html/window.zig").Window; const html_test = @import("html_test.zig").html; @@ -15,17 +16,14 @@ fn execJS( alloc: std.mem.Allocator, js_env: *jsruntime.Env, ) anyerror!void { - // start JS env try js_env.start(alloc); defer js_env.stop(); // alias global as self and window - try js_env.attachObject(try js_env.getGlobal(), "self", null); - try js_env.attachObject(try js_env.getGlobal(), "window", null); - - // add document object - try js_env.addObject(doc, "document"); + var window = Window.create(null); + window.replaceDocument(parser.documentHTMLToDocument(doc)); + try js_env.bindGlobal(window); // launch shellExec try jsruntime.shellExec(alloc, js_env); diff --git a/src/main_wpt.zig b/src/main_wpt.zig index 4d4dde57..15133e6e 100644 --- a/src/main_wpt.zig +++ b/src/main_wpt.zig @@ -30,6 +30,7 @@ const Out = enum { }; pub const Types = jsruntime.reflect(apiweb.Interfaces); +pub const GlobalType = apiweb.GlobalType; // TODO For now the WPT tests run is specific to WPT. // It manually load js framwork libs, and run the first script w/ js content in diff --git a/src/run_tests.zig b/src/run_tests.zig index db7baa52..9341b640 100644 --- a/src/run_tests.zig +++ b/src/run_tests.zig @@ -41,10 +41,6 @@ fn testExecFn( try js_env.start(alloc); defer js_env.stop(); - // alias global as self and window - try js_env.attachObject(try js_env.getGlobal(), "self", null); - try js_env.attachObject(try js_env.getGlobal(), "window", null); - // document const file = try std.fs.cwd().openFile("test.html", .{}); defer file.close(); @@ -54,8 +50,10 @@ fn testExecFn( std.debug.print("documentHTMLClose error: {s}\n", .{@errorName(err)}); }; - // add document object - try js_env.addObject(doc, "document"); + // alias global as self and window + var window = Window.create(null); + window.replaceDocument(parser.documentHTMLToDocument(doc)); + try js_env.bindGlobal(window); // run test try execFn(alloc, js_env); diff --git a/src/wpt/run.zig b/src/wpt/run.zig index ae7e18e2..09fdc1b9 100644 --- a/src/wpt/run.zig +++ b/src/wpt/run.zig @@ -8,6 +8,7 @@ const parser = @import("../netsurf.zig"); const jsruntime = @import("jsruntime"); const Loop = jsruntime.Loop; const Env = jsruntime.Env; +const Window = @import("../html/window.zig").Window; const Types = @import("../main_wpt.zig").Types; @@ -50,31 +51,14 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const } // setup global env vars. - try js_env.attachObject(try js_env.getGlobal(), "self", null); - try js_env.attachObject(try js_env.getGlobal(), "window", null); - try js_env.addObject(html_doc, "document"); + var window = Window.create(null); + window.replaceDocument(doc); + try js_env.bindGlobal(window); // thanks to the arena, we don't need to deinit res. var res: jsruntime.JSResult = undefined; const init = - \\window.listeners = []; - \\window.document = document; - \\window.parent = window; - \\window.addEventListener = function (type, listener, options) { - \\ window.listeners.push({type: type, listener: listener, options: options}); - \\}; - \\window.dispatchEvent = function (event) { - \\ len = window.listeners.length; - \\ for (var i = 0; i < len; i++) { - \\ if (window.listeners[i].type == event.target) { - \\ window.listeners[i].listener(event); - \\ } - \\ } - \\ return true; - \\}; - \\window.removeEventListener = function () {}; - \\ \\console = []; \\console.log = function () { \\ console.push(...arguments); @@ -116,7 +100,7 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const } // Mark tests as ready to run. - res = try evalJS(js_env, alloc, "window.dispatchEvent({target: 'load'});", "ready"); + res = try evalJS(js_env, alloc, "window.dispatchEvent(new Event('load'));", "ready"); if (!res.success) { return res; } diff --git a/vendor/jsruntime-lib b/vendor/jsruntime-lib index 1456575d..77a014c7 160000 --- a/vendor/jsruntime-lib +++ b/vendor/jsruntime-lib @@ -1 +1 @@ -Subproject commit 1456575dbfd074cf690b8beff6a8764118534174 +Subproject commit 77a014c7c26079c28258fe2dbcf3bbfc695c67bc From 500da5bfd89b002a734d3db2f32fb5a87962da3d Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Mar 2024 14:39:20 +0100 Subject: [PATCH 2/3] test: run JSRuntime test func directly Instead of calling the bultin test functions Indeed, it causes issue with type comparison. See https://github.com/lightpanda-io/browsercore/pull/184#issuecomment-1964369066 --- src/run_tests.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/run_tests.zig b/src/run_tests.zig index 9341b640..e2ca7f65 100644 --- a/src/run_tests.zig +++ b/src/run_tests.zig @@ -36,7 +36,6 @@ fn testExecFn( js_env: *jsruntime.Env, comptime execFn: jsruntime.ContextExecFn, ) anyerror!void { - // start JS env try js_env.start(alloc); defer js_env.stop(); @@ -89,6 +88,8 @@ fn testsAllExecFn( } pub fn main() !void { + try testJSRuntime(); + std.debug.print("\n", .{}); for (builtin.test_functions) |test_fn| { try test_fn.func(); @@ -104,7 +105,7 @@ test { std.testing.refAllDecls(DumpTest); } -test "jsruntime" { +fn testJSRuntime() !void { // generate tests try generate.tests(); From 886c9daa47c71799d33a9fd3272bf5fcf3e72e24 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Mar 2024 14:39:51 +0100 Subject: [PATCH 3/3] window: inject DocumentHTML instead of Document --- src/browser/browser.zig | 2 +- src/html/window.zig | 6 +++--- src/main.zig | 2 +- src/main_shell.zig | 2 +- src/run_tests.zig | 2 +- src/wpt/run.zig | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/browser/browser.zig b/src/browser/browser.zig index f901b2c3..d180ef27 100644 --- a/src/browser/browser.zig +++ b/src/browser/browser.zig @@ -229,7 +229,7 @@ pub const Page = struct { // TODO set the referrer to the document. - self.session.window.replaceDocument(doc); + self.session.window.replaceDocument(html_doc); // https://html.spec.whatwg.org/#read-html diff --git a/src/html/window.zig b/src/html/window.zig index e1080267..e7d1ca47 100644 --- a/src/html/window.zig +++ b/src/html/window.zig @@ -14,7 +14,7 @@ pub const Window = struct { // Extend libdom event target for pure zig struct. base: parser.EventTargetTBase = parser.EventTargetTBase{}, - document: ?*parser.Document = null, + document: ?*parser.DocumentHTML = null, target: []const u8, pub fn create(target: ?[]const u8) Window { @@ -23,7 +23,7 @@ pub const Window = struct { }; } - pub fn replaceDocument(self: *Window, doc: *parser.Document) void { + pub fn replaceDocument(self: *Window, doc: *parser.DocumentHTML) void { self.document = doc; } @@ -39,7 +39,7 @@ pub const Window = struct { return self; } - pub fn get_document(self: *Window) ?*parser.Document { + pub fn get_document(self: *Window) ?*parser.DocumentHTML { return self.document; } diff --git a/src/main.zig b/src/main.zig index 7bb1a24d..1dc34dc6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -23,7 +23,7 @@ fn execJS( // alias global as self and window var window = Window.create(null); - window.replaceDocument(parser.documentHTMLToDocument(doc)); + window.replaceDocument(doc); try js_env.bindGlobal(window); while (true) { diff --git a/src/main_shell.zig b/src/main_shell.zig index c1971f9f..965e7cf6 100644 --- a/src/main_shell.zig +++ b/src/main_shell.zig @@ -22,7 +22,7 @@ fn execJS( // alias global as self and window var window = Window.create(null); - window.replaceDocument(parser.documentHTMLToDocument(doc)); + window.replaceDocument(doc); try js_env.bindGlobal(window); // launch shellExec diff --git a/src/run_tests.zig b/src/run_tests.zig index e2ca7f65..2f5c8d6b 100644 --- a/src/run_tests.zig +++ b/src/run_tests.zig @@ -51,7 +51,7 @@ fn testExecFn( // alias global as self and window var window = Window.create(null); - window.replaceDocument(parser.documentHTMLToDocument(doc)); + window.replaceDocument(doc); try js_env.bindGlobal(window); // run test diff --git a/src/wpt/run.zig b/src/wpt/run.zig index 09fdc1b9..686363c0 100644 --- a/src/wpt/run.zig +++ b/src/wpt/run.zig @@ -23,7 +23,6 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const defer file.close(); const html_doc = try parser.documentHTMLParse(file.reader(), "UTF-8"); - const doc = parser.documentHTMLToDocument(html_doc); const dirname = fspath.dirname(f[dir.len..]) orelse unreachable; @@ -52,7 +51,7 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const // setup global env vars. var window = Window.create(null); - window.replaceDocument(doc); + window.replaceDocument(html_doc); try js_env.bindGlobal(window); // thanks to the arena, we don't need to deinit res. @@ -70,6 +69,7 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const } // loop hover the scripts. + const doc = parser.documentHTMLToDocument(html_doc); const scripts = try parser.documentGetElementsByTagName(doc, "script"); const slen = try parser.nodeListLength(scripts); for (0..slen) |i| {