Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/browser/key_value.zig
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ pub const List = struct {
});
}

pub fn appendOwnedAssumeCapacity(self: *List, key: []const u8, value: []const u8) void {
self.entries.appendAssumeCapacity(.{
.key = key,
.value = value,
});
}

pub fn delete(self: *List, key: []const u8) void {
var i: usize = 0;
while (i < self.entries.items.len) {
Expand Down
24 changes: 24 additions & 0 deletions src/browser/url/url.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const std = @import("std");
const Allocator = std.mem.Allocator;

const parser = @import("../netsurf.zig");
const Env = @import("../env.zig").Env;
const Page = @import("../page.zig").Page;
const FormData = @import("../xhr/form_data.zig").FormData;
const HTMLElement = @import("../html/elements.zig").HTMLElement;
Expand Down Expand Up @@ -247,12 +248,31 @@ pub const URLSearchParams = struct {
const URLSearchParamsOpts = union(enum) {
qs: []const u8,
form_data: *const FormData,
js_obj: Env.JsObject,
};
pub fn constructor(opts_: ?URLSearchParamsOpts, page: *Page) !URLSearchParams {
const opts = opts_ orelse return .{ .entries = .{} };
return switch (opts) {
.qs => |qs| init(page.arena, qs),
.form_data => |fd| .{ .entries = try fd.entries.clone(page.arena) },
.js_obj => |js_obj| {
const arena = page.arena;
var it = js_obj.nameIterator();

var entries: kv.List = .{};
try entries.ensureTotalCapacity(arena, it.count);

while (try it.next()) |js_name| {
const name = try js_name.toString(arena);
const js_val = try js_obj.get(name);
entries.appendOwnedAssumeCapacity(
name,
try js_val.toString(arena),
);
}

return .{ .entries = entries };
},
};
}

Expand Down Expand Up @@ -613,5 +633,9 @@ test "Browser.URLSearchParams" {
.{ "ups.getAll('b')", "3" },
.{ "fd.delete('a')", null }, // the two aren't linked, it created a copy
.{ "ups.size", "3" },
.{ "ups = new URLSearchParams({over: 9000, spice: 'flow'})", null },
.{ "ups.size", "2" },
.{ "ups.getAll('over')", "9000" },
.{ "ups.getAll('spice')", "flow" },
}, .{});
}
40 changes: 40 additions & 0 deletions src/runtime/js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,13 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
}
}

pub fn get(self: JsObject, key: []const u8) !Value {
const scope = self.scope;
const js_key = v8.String.initUtf8(scope.isolate, key);
const js_val = try self.js_obj.getValue(scope.context, js_key);
return scope.createValue(js_val);
}

pub fn isTruthy(self: JsObject) bool {
const js_value = self.js_obj.toValue();
return js_value.toBool(self.scope.isolate);
Expand Down Expand Up @@ -1421,6 +1428,20 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
pub fn isNullOrUndefined(self: JsObject) bool {
return self.js_obj.toValue().isNullOrUndefined();
}

pub fn nameIterator(self: JsObject) ValueIterator {
const scope = self.scope;
const js_obj = self.js_obj;

const array = js_obj.getPropertyNames(scope.context);
const count = array.length();

return .{
.count = count,
.scope = scope,
.js_obj = array.castTo(v8.Object),
};
}
};

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

pub const ValueIterator = struct {
count: u32,
idx: u32 = 0,
js_obj: v8.Object,
scope: *const Scope,

pub fn next(self: *ValueIterator) !?Value {
const idx = self.idx;
if (idx == self.count) {
return null;
}
self.idx += 1;

const scope = self.scope;
const js_val = try self.js_obj.getAtIndex(scope.context, idx);
return scope.createValue(js_val);
}
};

fn compileModule(isolate: v8.Isolate, src: []const u8, name: []const u8) !v8.Module {
// compile
const script_name = v8.String.initUtf8(isolate, name);
Expand Down