Skip to content

Commit 09466a2

Browse files
authored
Merge pull request #764 from lightpanda-io/url_search_parmas_from_object
URLSearchParam constructor support for object initialization
2 parents e77d888 + c758054 commit 09466a2

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

src/browser/key_value.zig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ pub const List = struct {
102102
});
103103
}
104104

105+
pub fn appendOwnedAssumeCapacity(self: *List, key: []const u8, value: []const u8) void {
106+
self.entries.appendAssumeCapacity(.{
107+
.key = key,
108+
.value = value,
109+
});
110+
}
111+
105112
pub fn delete(self: *List, key: []const u8) void {
106113
var i: usize = 0;
107114
while (i < self.entries.items.len) {

src/browser/url/url.zig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const std = @import("std");
2020
const Allocator = std.mem.Allocator;
2121

2222
const parser = @import("../netsurf.zig");
23+
const Env = @import("../env.zig").Env;
2324
const Page = @import("../page.zig").Page;
2425
const FormData = @import("../xhr/form_data.zig").FormData;
2526
const HTMLElement = @import("../html/elements.zig").HTMLElement;
@@ -247,12 +248,31 @@ pub const URLSearchParams = struct {
247248
const URLSearchParamsOpts = union(enum) {
248249
qs: []const u8,
249250
form_data: *const FormData,
251+
js_obj: Env.JsObject,
250252
};
251253
pub fn constructor(opts_: ?URLSearchParamsOpts, page: *Page) !URLSearchParams {
252254
const opts = opts_ orelse return .{ .entries = .{} };
253255
return switch (opts) {
254256
.qs => |qs| init(page.arena, qs),
255257
.form_data => |fd| .{ .entries = try fd.entries.clone(page.arena) },
258+
.js_obj => |js_obj| {
259+
const arena = page.arena;
260+
var it = js_obj.nameIterator();
261+
262+
var entries: kv.List = .{};
263+
try entries.ensureTotalCapacity(arena, it.count);
264+
265+
while (try it.next()) |js_name| {
266+
const name = try js_name.toString(arena);
267+
const js_val = try js_obj.get(name);
268+
entries.appendOwnedAssumeCapacity(
269+
name,
270+
try js_val.toString(arena),
271+
);
272+
}
273+
274+
return .{ .entries = entries };
275+
},
256276
};
257277
}
258278

@@ -613,5 +633,9 @@ test "Browser.URLSearchParams" {
613633
.{ "ups.getAll('b')", "3" },
614634
.{ "fd.delete('a')", null }, // the two aren't linked, it created a copy
615635
.{ "ups.size", "3" },
636+
.{ "ups = new URLSearchParams({over: 9000, spice: 'flow'})", null },
637+
.{ "ups.size", "2" },
638+
.{ "ups.getAll('over')", "9000" },
639+
.{ "ups.getAll('spice')", "flow" },
616640
}, .{});
617641
}

src/runtime/js.zig

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,13 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
13661366
}
13671367
}
13681368

1369+
pub fn get(self: JsObject, key: []const u8) !Value {
1370+
const scope = self.scope;
1371+
const js_key = v8.String.initUtf8(scope.isolate, key);
1372+
const js_val = try self.js_obj.getValue(scope.context, js_key);
1373+
return scope.createValue(js_val);
1374+
}
1375+
13691376
pub fn isTruthy(self: JsObject) bool {
13701377
const js_value = self.js_obj.toValue();
13711378
return js_value.toBool(self.scope.isolate);
@@ -1421,6 +1428,20 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
14211428
pub fn isNullOrUndefined(self: JsObject) bool {
14221429
return self.js_obj.toValue().isNullOrUndefined();
14231430
}
1431+
1432+
pub fn nameIterator(self: JsObject) ValueIterator {
1433+
const scope = self.scope;
1434+
const js_obj = self.js_obj;
1435+
1436+
const array = js_obj.getPropertyNames(scope.context);
1437+
const count = array.length();
1438+
1439+
return .{
1440+
.count = count,
1441+
.scope = scope,
1442+
.js_obj = array.castTo(v8.Object),
1443+
};
1444+
}
14241445
};
14251446

14261447
// This only exists so that we know whether a function wants the opaque
@@ -1626,6 +1647,25 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
16261647
}
16271648
};
16281649

1650+
pub const ValueIterator = struct {
1651+
count: u32,
1652+
idx: u32 = 0,
1653+
js_obj: v8.Object,
1654+
scope: *const Scope,
1655+
1656+
pub fn next(self: *ValueIterator) !?Value {
1657+
const idx = self.idx;
1658+
if (idx == self.count) {
1659+
return null;
1660+
}
1661+
self.idx += 1;
1662+
1663+
const scope = self.scope;
1664+
const js_val = try self.js_obj.getAtIndex(scope.context, idx);
1665+
return scope.createValue(js_val);
1666+
}
1667+
};
1668+
16291669
fn compileModule(isolate: v8.Isolate, src: []const u8, name: []const u8) !v8.Module {
16301670
// compile
16311671
const script_name = v8.String.initUtf8(isolate, name);

0 commit comments

Comments
 (0)