mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
URLSearchParam constructor support for object initialization
This adds support for:
```
new URLSearchParams({over: 9000});
```
The spec says that any thing that produces/iterates a sequence of string pairs
is valid. By using the lower-level JsObject, this hopefully takes care of the
most common cases. But I don't think it's complete, and I don't think we
currently capture enough data to make this work. There's no way for the JS
runtime to know if a value (say, a netsurf instance, or even a Zig instance)
provides an string=>string iterator.
This commit is contained in:
@@ -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 {
|
pub fn delete(self: *List, key: []const u8) void {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < self.entries.items.len) {
|
while (i < self.entries.items.len) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ const std = @import("std");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
|
const Env = @import("../env.zig").Env;
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const FormData = @import("../xhr/form_data.zig").FormData;
|
const FormData = @import("../xhr/form_data.zig").FormData;
|
||||||
const HTMLElement = @import("../html/elements.zig").HTMLElement;
|
const HTMLElement = @import("../html/elements.zig").HTMLElement;
|
||||||
@@ -247,12 +248,31 @@ pub const URLSearchParams = struct {
|
|||||||
const URLSearchParamsOpts = union(enum) {
|
const URLSearchParamsOpts = union(enum) {
|
||||||
qs: []const u8,
|
qs: []const u8,
|
||||||
form_data: *const FormData,
|
form_data: *const FormData,
|
||||||
|
js_obj: Env.JsObject,
|
||||||
};
|
};
|
||||||
pub fn constructor(opts_: ?URLSearchParamsOpts, page: *Page) !URLSearchParams {
|
pub fn constructor(opts_: ?URLSearchParamsOpts, page: *Page) !URLSearchParams {
|
||||||
const opts = opts_ orelse return .{ .entries = .{} };
|
const opts = opts_ orelse return .{ .entries = .{} };
|
||||||
return switch (opts) {
|
return switch (opts) {
|
||||||
.qs => |qs| init(page.arena, qs),
|
.qs => |qs| init(page.arena, qs),
|
||||||
.form_data => |fd| .{ .entries = try fd.entries.clone(page.arena) },
|
.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 };
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,5 +633,9 @@ test "Browser.URLSearchParams" {
|
|||||||
.{ "ups.getAll('b')", "3" },
|
.{ "ups.getAll('b')", "3" },
|
||||||
.{ "fd.delete('a')", null }, // the two aren't linked, it created a copy
|
.{ "fd.delete('a')", null }, // the two aren't linked, it created a copy
|
||||||
.{ "ups.size", "3" },
|
.{ "ups.size", "3" },
|
||||||
|
.{ "ups = new URLSearchParams({over: 9000, spice: 'flow'})", null },
|
||||||
|
.{ "ups.size", "2" },
|
||||||
|
.{ "ups.getAll('over')", "9000" },
|
||||||
|
.{ "ups.getAll('spice')", "flow" },
|
||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
pub fn isTruthy(self: JsObject) bool {
|
||||||
const js_value = self.js_obj.toValue();
|
const js_value = self.js_obj.toValue();
|
||||||
return js_value.toBool(self.scope.isolate);
|
return js_value.toBool(self.scope.isolate);
|
||||||
@@ -1421,6 +1428,20 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
|||||||
pub fn isNullOrUndefined(self: JsObject) bool {
|
pub fn isNullOrUndefined(self: JsObject) bool {
|
||||||
return self.js_obj.toValue().isNullOrUndefined();
|
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
|
// 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 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 {
|
fn compileModule(isolate: v8.Isolate, src: []const u8, name: []const u8) !v8.Module {
|
||||||
// compile
|
// compile
|
||||||
const script_name = v8.String.initUtf8(isolate, name);
|
const script_name = v8.String.initUtf8(isolate, name);
|
||||||
|
|||||||
Reference in New Issue
Block a user