diff --git a/src/browser/Page.zig b/src/browser/Page.zig
index eef70bbc..f8445447 100644
--- a/src/browser/Page.zig
+++ b/src/browser/Page.zig
@@ -587,13 +587,34 @@ pub fn scheduleNavigation(self: *Page, request_url: []const u8, opts: NavigateOp
// page that it's acting on.
fn scheduleNavigationWithArena(originator: *Page, arena: Allocator, request_url: []const u8, opts: NavigateOpts, nt: Navigation) !void {
const resolved_url, const is_about_blank = blk: {
+ if (URL.isCompleteHTTPUrl(request_url)) {
+ break :blk .{ try arena.dupeZ(u8, request_url), false };
+ }
+
if (std.mem.eql(u8, request_url, "about:blank")) {
// navigate will handle this special case
break :blk .{ "about:blank", true };
}
+
+ // request_url isn't a "complete" URL, so it has to be resolved with the
+ // originator's base. Unless, originator's base is "about:blank", in which
+ // case we have to walk up the parents and find a real base.
+ const page_base = base_blk: {
+ var maybe_not_blank_page = originator;
+ while (true) {
+ const maybe_base = maybe_not_blank_page.base();
+ if (std.mem.eql(u8, maybe_base, "about:blank") == false) {
+ break :base_blk maybe_base;
+ }
+ // The orelse here is probably an invalid case, but there isn't
+ // anything we can do about it. It should never happen?
+ maybe_not_blank_page = maybe_not_blank_page.parent orelse break :base_blk "";
+ }
+ };
+
const u = try URL.resolve(
arena,
- originator.base(),
+ page_base,
request_url,
.{ .always_dupe = true, .encode = true },
);
diff --git a/src/browser/tests/frames/frames.html b/src/browser/tests/frames/frames.html
index 90cb038e..c9443c80 100644
--- a/src/browser/tests/frames/frames.html
+++ b/src/browser/tests/frames/frames.html
@@ -139,8 +139,19 @@
});
+
+