diff --git a/src/browser/tools.zig b/src/browser/tools.zig index 5650d0bcb..be65b06ab 100644 --- a/src/browser/tools.zig +++ b/src/browser/tools.zig @@ -2375,7 +2375,10 @@ fn renderJson(arena: std.mem.Allocator, value: anytype) ToolError![]const u8 { fn ensurePage(session: *lp.Session, registry: *NodeRegistry, url: ?[:0]const u8, timeout: ?u32) ToolError!*lp.Frame { if (url) |u| { if (session.currentFrame()) |frame| { - if (std.mem.eql(u8, frame.url, u)) return frame; + const is_loaded = frame._parse_state != .pre and frame._last_navigate_error == null; + if (is_loaded and std.mem.eql(u8, frame.url, u)) { + return frame; + } } _ = try performGoto(session, registry, u, .{ .timeout = timeout }); } @@ -3023,3 +3026,18 @@ test "isPathSafe: absolute paths and traversal are rejected" { try std.testing.expect(!isPathSafe("sub/..")); try std.testing.expect(!isPathSafe("..")); } + +test "markdown: a same-url page whose navigation failed is navigated again" { + var registry: NodeRegistry = .init(std.testing.allocator); + defer registry.deinit(); + + const session = testing.test_session; + defer if (session.primaryPage()) |page| page.close(); + + const aa = testing.arena_allocator; + const args = try std.json.parseFromSliceLeaky(std.json.Value, aa, + \\{"url":"http://localhost:1/"} + , .{}); + try std.testing.expect((try call(aa, session, ®istry, "goto", args, .{})).is_error); + try std.testing.expect((try call(aa, session, ®istry, "markdown", args, .{})).is_error); +}