Skip to content

Commit 19b9ba8

Browse files
committed
add hash support to URL stitch
1 parent 92ddb56 commit 19b9ba8

File tree

4 files changed

+49
-27
lines changed

4 files changed

+49
-27
lines changed

src/browser/html/location.zig

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,12 @@ pub const Location = struct {
4444
}
4545

4646
pub fn set_hash(_: *const Location, hash: []const u8, page: *Page) !void {
47-
const current_url = page.url.raw;
48-
49-
const base_without_hash = if (std.mem.indexOfScalar(u8, current_url, '#')) |pos|
50-
current_url[0..pos]
47+
const normalized_hash = if (hash[0] == '#')
48+
hash
5149
else
52-
current_url;
53-
54-
const normalized_hash = std.mem.trimStart(u8, hash, "#");
55-
const new_url = try std.fmt.allocPrint(page.arena, "{s}#{s}", .{ base_without_hash, normalized_hash });
50+
try std.fmt.allocPrint(page.arena, "#{s}", .{hash});
5651

57-
return page.navigateFromWebAPI(new_url, .{ .reason = .script }, .replace);
52+
return page.navigateFromWebAPI(normalized_hash, .{ .reason = .script }, .replace);
5853
}
5954

6055
pub fn get_protocol(self: *Location) []const u8 {

src/browser/navigation/Navigation.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,9 @@ pub fn navigate(
228228
const committed = try page.js.createPromiseResolver(.page);
229229
const finished = try page.js.createPromiseResolver(.page);
230230

231-
const new_url = try URL.parse(url, null);
231+
const new_url_string = try URL.stitch(arena, url, page.url.raw, .{});
232+
const new_url = try URL.parse(new_url_string, null);
233+
232234
const is_same_document = try page.url.eqlDocument(&new_url, arena);
233235

234236
switch (kind) {

src/browser/page.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,6 @@ pub const Page = struct {
10841084
if (try self.url.eqlDocument(&new_url, session.transfer_arena)) {
10851085
self.url = new_url;
10861086
try self.window.changeLocation(self.url.raw, self);
1087-
10881087
try session.navigation.updateEntries(stitched_url, kind, self, true);
10891088
return;
10901089
}

src/url.zig

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,35 @@ pub const URL = struct {
8282
pub fn stitch(
8383
allocator: Allocator,
8484
raw_path: []const u8,
85-
base: []const u8,
85+
raw_base: []const u8,
8686
comptime opts: StitchOpts,
8787
) !StitchReturn(opts) {
88-
const path = std.mem.trim(u8, raw_path, &.{ '\n', '\r' });
88+
const trimmed_path = std.mem.trim(u8, raw_path, &.{ '\n', '\r' });
89+
90+
if (raw_base.len == 0 or isCompleteHTTPUrl(trimmed_path)) {
91+
return simpleStitch(allocator, trimmed_path, opts);
92+
}
8993

90-
if (base.len == 0 or isCompleteHTTPUrl(path)) {
91-
return simpleStitch(allocator, path, opts);
94+
if (trimmed_path.len == 0) {
95+
return simpleStitch(allocator, raw_base, opts);
9296
}
9397

98+
// base should get stripped of its hash whenever we are stitching.
99+
const base = if (std.mem.indexOfScalar(u8, raw_base, '#')) |hash_pos|
100+
raw_base[0..hash_pos]
101+
else
102+
raw_base;
103+
104+
const path_hash_start = std.mem.indexOfScalar(u8, trimmed_path, '#');
105+
const path = if (path_hash_start) |pos| trimmed_path[0..pos] else trimmed_path;
106+
const hash = if (path_hash_start) |pos| trimmed_path[pos..] else "";
107+
108+
// if path is just hash, we just append it to base.
94109
if (path.len == 0) {
95-
return simpleStitch(allocator, base, opts);
110+
if (comptime opts.null_terminated) {
111+
return std.fmt.allocPrintSentinel(allocator, "{s}{s}", .{ base, hash }, 0);
112+
}
113+
return std.fmt.allocPrint(allocator, "{s}{s}", .{ base, hash });
96114
}
97115

98116
if (std.mem.startsWith(u8, path, "//")) {
@@ -103,9 +121,9 @@ pub const URL = struct {
103121

104122
const protocol = base[0..index];
105123
if (comptime opts.null_terminated) {
106-
return std.fmt.allocPrintSentinel(allocator, "{s}:{s}", .{ protocol, path }, 0);
124+
return std.fmt.allocPrintSentinel(allocator, "{s}:{s}{s}", .{ protocol, path, hash }, 0);
107125
}
108-
return std.fmt.allocPrint(allocator, "{s}:{s}", .{ protocol, path });
126+
return std.fmt.allocPrint(allocator, "{s}:{s}{s}", .{ protocol, path, hash });
109127
}
110128

111129
// Quick hack because domains have to be at least 3 characters.
@@ -126,25 +144,28 @@ pub const URL = struct {
126144
return std.fmt.allocPrint(allocator, "{s}{s}", .{ root, path });
127145
}
128146

129-
var old_path = std.mem.trimStart(u8, base[root.len..], "/");
130-
if (std.mem.lastIndexOfScalar(u8, old_path, '/')) |pos| {
131-
old_path = old_path[0..pos];
147+
var oldraw_path = std.mem.trimStart(u8, base[root.len..], "/");
148+
if (std.mem.lastIndexOfScalar(u8, oldraw_path, '/')) |pos| {
149+
oldraw_path = oldraw_path[0..pos];
132150
} else {
133-
old_path = "";
151+
oldraw_path = "";
134152
}
135153

136154
// We preallocate all of the space possibly needed.
137-
// This is the root, old_path, new path, 3 slashes and perhaps a null terminated slot.
138-
var out = try allocator.alloc(u8, root.len + old_path.len + path.len + 3 + if (comptime opts.null_terminated) 1 else 0);
155+
// This is the root, oldraw_path, new path, 3 slashes and perhaps a null terminated slot.
156+
var out = try allocator.alloc(
157+
u8,
158+
root.len + oldraw_path.len + path.len + hash.len + 3 + if (comptime opts.null_terminated) 1 else 0,
159+
);
139160
var end: usize = 0;
140161
@memmove(out[0..root.len], root);
141162
end += root.len;
142163
out[root.len] = '/';
143164
end += 1;
144165
// If we don't have an old path, do nothing here.
145-
if (old_path.len > 0) {
146-
@memmove(out[end .. end + old_path.len], old_path);
147-
end += old_path.len;
166+
if (oldraw_path.len > 0) {
167+
@memmove(out[end .. end + oldraw_path.len], oldraw_path);
168+
end += oldraw_path.len;
148169
out[end] = '/';
149170
end += 1;
150171
}
@@ -182,6 +203,11 @@ pub const URL = struct {
182203
read += 1;
183204
}
184205

206+
if (hash.len > 0) {
207+
@memmove(out[write .. write + hash.len], hash);
208+
write += hash.len;
209+
}
210+
185211
if (comptime opts.null_terminated) {
186212
// we always have an extra space
187213
out[write] = 0;

0 commit comments

Comments
 (0)