From 7afecf0f85d0cea0c0b547dd26c93b8d35d232ff Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 9 Oct 2025 11:23:19 +0200 Subject: [PATCH] move mod specifier resolution js/context => script manager --- src/browser/ScriptManager.zig | 10 ++++++++++ src/browser/html/elements.zig | 1 + src/browser/js/Context.zig | 9 +++------ src/tests/html/script/importmap.html | 24 ++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 src/tests/html/script/importmap.html diff --git a/src/browser/ScriptManager.zig b/src/browser/ScriptManager.zig index 06b6ca1d..3ee86be6 100644 --- a/src/browser/ScriptManager.zig +++ b/src/browser/ScriptManager.zig @@ -248,6 +248,16 @@ pub fn addFromElement(self: *ScriptManager, element: *parser.Element, comptime c }); } +// Resolve a module specifier to an valid URL. +pub fn resolveSpecifier(_: *ScriptManager, arena: Allocator, specifier: []const u8, base: []const u8) ![:0]const u8 { + return URL.stitch( + arena, + specifier, + base, + .{ .alloc = .if_needed, .null_terminated = true }, + ); +} + pub fn getModule(self: *ScriptManager, url: [:0]const u8, referrer: []const u8) !void { const gop = try self.sync_modules.getOrPut(self.allocator, url); if (gop.found_existing) { diff --git a/src/browser/html/elements.zig b/src/browser/html/elements.zig index 0fc5502f..e9e95fdf 100644 --- a/src/browser/html/elements.zig +++ b/src/browser/html/elements.zig @@ -1353,6 +1353,7 @@ test "Browser: HTML.HtmlScriptElement" { try testing.htmlRunner("html/script/inline_defer.html"); try testing.htmlRunner("html/script/import.html"); try testing.htmlRunner("html/script/dynamic_import.html"); + try testing.htmlRunner("html/script/importmap.html"); } test "Browser: HTML.HtmlSlotElement" { diff --git a/src/browser/js/Context.zig b/src/browser/js/Context.zig index 8d298f0d..46c6261f 100644 --- a/src/browser/js/Context.zig +++ b/src/browser/js/Context.zig @@ -251,11 +251,10 @@ pub fn module(self: *Context, comptime want_result: bool, src: []const u8, url: for (0..requests.length()) |i| { const req = requests.get(v8_context, @intCast(i)).castTo(v8.ModuleRequest); const specifier = try self.jsStringToZig(req.getSpecifier(), .{}); - const normalized_specifier = try @import("../../url.zig").stitch( + const normalized_specifier = try self.script_manager.?.resolveSpecifier( self.call_arena, specifier, owned_url, - .{ .alloc = .if_needed, .null_terminated = true }, ); const gop = try self.module_cache.getOrPut(self.arena, normalized_specifier); if (!gop.found_existing) { @@ -1127,11 +1126,10 @@ pub fn dynamicModuleCallback( return @constCast(self.rejectPromise("Out of memory").handle); }; - const normalized_specifier = @import("../../url.zig").stitch( + const normalized_specifier = self.script_manager.?.resolveSpecifier( self.arena, // might need to survive until the module is loaded specifier, resource, - .{ .alloc = .if_needed, .null_terminated = true }, ) catch |err| { log.err(.app, "OOM", .{ .err = err, .src = "dynamicModuleCallback3" }); return @constCast(self.rejectPromise("Out of memory").handle); @@ -1171,11 +1169,10 @@ fn _resolveModuleCallback(self: *Context, referrer: v8.Module, specifier: []cons return error.UnknownModuleReferrer; }; - const normalized_specifier = try @import("../../url.zig").stitch( + const normalized_specifier = try self.script_manager.?.resolveSpecifier( self.call_arena, specifier, referrer_path, - .{ .alloc = .if_needed, .null_terminated = true }, ); const gop = try self.module_cache.getOrPut(self.arena, normalized_specifier); diff --git a/src/tests/html/script/importmap.html b/src/tests/html/script/importmap.html new file mode 100644 index 00000000..d3f457a9 --- /dev/null +++ b/src/tests/html/script/importmap.html @@ -0,0 +1,24 @@ + + + + + + + + + +