mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +00:00
refactor HTMLAnchorElement
Prefer new URL implementation with separate store for object data.
This commit is contained in:
@@ -221,9 +221,29 @@ pub const HTMLAnchorElement = struct {
|
|||||||
return parser.anchorGetHref(self);
|
return parser.anchorGetHref(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_href(self: *parser.Anchor, href: []const u8, page: *const Page) !void {
|
pub fn set_href(self: *parser.Anchor, href: []const u8, page: *Page) !void {
|
||||||
const full = try urlStitch(page.call_arena, href, page.url.getHref(), .{});
|
const full = try urlStitch(page.call_arena, href, page.url.getHref(), .{});
|
||||||
return parser.anchorSetHref(self, full);
|
|
||||||
|
// Get the stored internal URL if we had one.
|
||||||
|
if (page.getObjectData(self)) |internal_url| {
|
||||||
|
const u = NativeURL.fromInternal(internal_url);
|
||||||
|
// Reparse with the new href.
|
||||||
|
_ = try u.reparse(full);
|
||||||
|
errdefer u.deinit();
|
||||||
|
|
||||||
|
// TODO: Remove the entry from the map on an error situation.
|
||||||
|
|
||||||
|
return parser.anchorSetHref(self, u.getHref());
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't have internal URL stored in object_data yet.
|
||||||
|
// Create one for this anchor element.
|
||||||
|
const u = try NativeURL.parse(full, null);
|
||||||
|
errdefer u.deinit();
|
||||||
|
// Save to map.
|
||||||
|
try page.putObjectData(self, u.internal.?);
|
||||||
|
|
||||||
|
return parser.anchorSetHref(self, u.getHref());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_hreflang(self: *parser.Anchor) ![]const u8 {
|
pub fn get_hreflang(self: *parser.Anchor) ![]const u8 {
|
||||||
@@ -258,170 +278,188 @@ pub const HTMLAnchorElement = struct {
|
|||||||
return try parser.nodeSetTextContent(parser.anchorToNode(self), v);
|
return try parser.nodeSetTextContent(parser.anchorToNode(self), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn url(self: *parser.Anchor, page: *Page) !URL {
|
fn getHref(self: *parser.Anchor) !?[]const u8 {
|
||||||
// Although the URL.constructor union accepts an .{.element = X}, we
|
return parser.elementGetAttribute(@ptrCast(@alignCast(self)), "href");
|
||||||
// can't use this here because the behavior is different.
|
}
|
||||||
// URL.constructor(document.createElement('a')
|
|
||||||
// should fail (a.href isn't a valid URL)
|
/// Returns the URL associated with given anchor element.
|
||||||
// But
|
/// Creates a new URL object if not created before.
|
||||||
// document.createElement('a').host
|
fn getURL(self: *parser.Anchor, page: *Page) !NativeURL {
|
||||||
// should not fail, it should return an empty string
|
if (page.getObjectData(self)) |internal_url| {
|
||||||
if (try parser.elementGetAttribute(@ptrCast(@alignCast(self)), "href")) |href| {
|
return NativeURL.fromInternal(internal_url);
|
||||||
return URL.constructor(.{ .string = href }, null, page); // TODO inject base url
|
|
||||||
}
|
}
|
||||||
return .empty;
|
|
||||||
|
// Try to get href string.
|
||||||
|
const maybe_anchor_href = try getHref(self);
|
||||||
|
if (maybe_anchor_href) |anchor_href| {
|
||||||
|
// Allocate a URL for this anchor element.
|
||||||
|
const u = try NativeURL.parse(anchor_href, null);
|
||||||
|
// Save in map.
|
||||||
|
try page.putObjectData(self, u.internal.?);
|
||||||
|
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No anchor href string found; let's just return an error.
|
||||||
|
return error.HrefAttributeNotGiven;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO return a disposable string
|
// TODO return a disposable string
|
||||||
pub fn get_origin(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_origin(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = getURL(self, page) catch return "";
|
||||||
return u.get_origin(page);
|
// Though we store the URL in object data map, we still have to allocate
|
||||||
|
// for origin string sadly.
|
||||||
|
return u.getOrigin(page.arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO return a disposable string
|
// TODO return a disposable string
|
||||||
pub fn get_protocol(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_protocol(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = getURL(self, page) catch return "";
|
||||||
return u.get_protocol();
|
return u.getProtocol();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_protocol(self: *parser.Anchor, v: []const u8, page: *Page) !void {
|
pub fn set_protocol(self: *parser.Anchor, v: []const u8, page: *Page) !void {
|
||||||
const arena = page.arena;
|
const u = try getURL(self, page);
|
||||||
_ = arena;
|
try u.setProtocol(v);
|
||||||
var u = try url(self, page);
|
return parser.anchorSetHref(self, u.getHref());
|
||||||
|
|
||||||
u.set_protocol(v);
|
|
||||||
const href = try u.get_href(page);
|
|
||||||
try parser.anchorSetHref(self, href);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NativeURL = @import("../../url.zig").URL;
|
||||||
|
|
||||||
|
// TODO: Return a disposable string.
|
||||||
pub fn get_host(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_host(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = getURL(self, page) catch return "";
|
||||||
return u.get_host();
|
return u.host();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_host(self: *parser.Anchor, v: []const u8, page: *Page) !void {
|
pub fn set_host(self: *parser.Anchor, host_str: []const u8, page: *Page) !void {
|
||||||
// search : separator
|
const u = blk: {
|
||||||
var p: ?[]const u8 = null;
|
if (page.getObjectData(self)) |internal_url| {
|
||||||
var h: []const u8 = undefined;
|
break :blk NativeURL.fromInternal(internal_url);
|
||||||
for (v, 0..) |c, i| {
|
|
||||||
if (c == ':') {
|
|
||||||
h = v[0..i];
|
|
||||||
//p = try std.fmt.parseInt(u16, v[i + 1 ..], 10);
|
|
||||||
p = v[i + 1 ..];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var u = try url(self, page);
|
const maybe_anchor_href = try getHref(self);
|
||||||
|
if (maybe_anchor_href) |anchor_href| {
|
||||||
|
const new_u = try NativeURL.parse(anchor_href, null);
|
||||||
|
try page.putObjectData(self, new_u.internal.?);
|
||||||
|
break :blk new_u;
|
||||||
|
}
|
||||||
|
|
||||||
if (p) |port| {
|
// Last resort; try to create URL object out of host_str.
|
||||||
u.set_host(h);
|
const new_u = try NativeURL.parse(host_str, null);
|
||||||
u.set_port(port);
|
// We can just return here since host is updated.
|
||||||
} else {
|
return page.putObjectData(self, new_u.internal.?);
|
||||||
u.set_host(v);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const href = try u.get_href(page);
|
try u.setHost(host_str);
|
||||||
try parser.anchorSetHref(self, href);
|
return parser.anchorSetHref(self, u.getHref());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_hostname(self: *parser.Anchor, page: *Page) ![]const u8 {
|
//pub fn get_hostname(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
// const maybe_href_str = try getAnchorHref(self);
|
||||||
return u.get_hostname();
|
// const href_str = maybe_href_str orelse return "";
|
||||||
}
|
//
|
||||||
|
// const u = try NativeURL.parse(href_str, null);
|
||||||
|
// defer u.deinit();
|
||||||
|
//
|
||||||
|
// return page.arena.dupe(u8, u.getHostname());
|
||||||
|
//}
|
||||||
|
|
||||||
pub fn set_hostname(self: *parser.Anchor, v: []const u8, page: *Page) !void {
|
//pub fn set_hostname(self: *parser.Anchor, v: []const u8) !void {
|
||||||
var u = try url(self, page);
|
// const maybe_href_str = try getAnchorHref(self);
|
||||||
u.set_host(v);
|
//
|
||||||
const href = try u.get_href(page);
|
// if (maybe_href_str) |href_str| {
|
||||||
try parser.anchorSetHref(self, href);
|
// const u = try NativeURL.parse(href_str, null);
|
||||||
}
|
// defer u.deinit();
|
||||||
|
//
|
||||||
|
// try u.setHostname(v);
|
||||||
|
//
|
||||||
|
// return parser.anchorSetHref(self, u.getHref());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // No href string there; use the given value as href.
|
||||||
|
// const u = try NativeURL.parse(v, null);
|
||||||
|
// defer u.deinit();
|
||||||
|
//
|
||||||
|
// return parser.anchorSetHref(self, u.getHref());
|
||||||
|
//}
|
||||||
|
|
||||||
// TODO return a disposable string
|
// TODO return a disposable string
|
||||||
pub fn get_port(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_port(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = getURL(self, page) catch return "";
|
||||||
return u.get_port();
|
return u.getPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_port(self: *parser.Anchor, v: ?[]const u8, page: *Page) !void {
|
pub fn set_port(self: *parser.Anchor, maybe_port: ?[]const u8, page: *Page) !void {
|
||||||
var u = try url(self, page);
|
// TODO: Check for valid port (u16 integer).
|
||||||
|
if (maybe_port) |port| {
|
||||||
|
const u = try getURL(self, page);
|
||||||
|
try u.setPort(port);
|
||||||
|
|
||||||
if (v != null and v.?.len > 0) {
|
return parser.anchorSetHref(self, u.getHref());
|
||||||
u.set_host(v.?);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const href = try u.get_href(page);
|
|
||||||
try parser.anchorSetHref(self, href);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO return a disposable string
|
// TODO return a disposable string
|
||||||
pub fn get_username(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_username(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
return u.get_username();
|
return u.getUsername() orelse "";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_username(self: *parser.Anchor, v: ?[]const u8, page: *Page) !void {
|
pub fn set_username(self: *parser.Anchor, maybe_username: ?[]const u8, page: *Page) !void {
|
||||||
if (v) |username| {
|
if (maybe_username) |username| {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
u.set_username(username);
|
try u.setUsername(username);
|
||||||
|
try parser.anchorSetHref(self, u.getHref());
|
||||||
const href = try u.get_href(page);
|
|
||||||
try parser.anchorSetHref(self, href);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_password(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_password(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
return u.get_password();
|
return u.getPassword() orelse "";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_password(self: *parser.Anchor, v: ?[]const u8, page: *Page) !void {
|
pub fn set_password(self: *parser.Anchor, maybe_password: ?[]const u8, page: *Page) !void {
|
||||||
if (v) |password| {
|
if (maybe_password) |password| {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
u.set_password(password);
|
try u.setPassword(password);
|
||||||
|
try parser.anchorSetHref(self, u.getHref());
|
||||||
const href = try u.get_href(page);
|
|
||||||
try parser.anchorSetHref(self, href);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO return a disposable string
|
// TODO return a disposable string
|
||||||
pub fn get_pathname(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_pathname(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
return u.get_pathname();
|
return u.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pathname(self: *parser.Anchor, v: []const u8, page: *Page) !void {
|
pub fn set_pathname(self: *parser.Anchor, pathname: []const u8, page: *Page) !void {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
u.set_pathname(v);
|
try u.setPath(pathname);
|
||||||
const href = try u.get_href(page);
|
return parser.anchorSetHref(self, u.getHref());
|
||||||
try parser.anchorSetHref(self, href);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_search(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_search(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
return u.get_search(page);
|
return u.getSearch() orelse "";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_search(self: *parser.Anchor, v: []const u8, page: *Page) !void {
|
pub fn set_search(self: *parser.Anchor, search: []const u8, page: *Page) !void {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
try u.set_search(v, page);
|
u.setSearch(search);
|
||||||
|
return parser.anchorSetHref(self, u.getHref());
|
||||||
const href = try u.get_href(page);
|
|
||||||
try parser.anchorSetHref(self, href);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO return a disposable string
|
// TODO return a disposable string
|
||||||
pub fn get_hash(self: *parser.Anchor, page: *Page) ![]const u8 {
|
pub fn get_hash(self: *parser.Anchor, page: *Page) ![]const u8 {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
return u.get_hash();
|
return u.getHash() orelse "";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_hash(self: *parser.Anchor, v: []const u8, page: *Page) !void {
|
pub fn set_hash(self: *parser.Anchor, hash: []const u8, page: *Page) !void {
|
||||||
var u = try url(self, page);
|
const u = try getURL(self, page);
|
||||||
u.set_hash(v);
|
u.setHash(hash);
|
||||||
const href = try u.get_href(page);
|
return parser.anchorSetHref(self, u.getHref());
|
||||||
try parser.anchorSetHref(self, href);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ pub const Page = struct {
|
|||||||
|
|
||||||
polyfill_loader: polyfill.Loader = .{},
|
polyfill_loader: polyfill.Loader = .{},
|
||||||
|
|
||||||
|
/// KV map for various object data; use pointers as unsigned integer keys
|
||||||
|
/// and store any `*anyopaque` as values. If a key or value will be
|
||||||
|
/// deinitialized (freed), it should be removed from the map too.
|
||||||
|
object_data: ObjectDataMap = .{},
|
||||||
|
|
||||||
scheduler: Scheduler,
|
scheduler: Scheduler,
|
||||||
http_client: *Http.Client,
|
http_client: *Http.Client,
|
||||||
script_manager: ScriptManager,
|
script_manager: ScriptManager,
|
||||||
@@ -122,6 +127,21 @@ pub const Page = struct {
|
|||||||
complete,
|
complete,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ObjectDataMap = std.HashMapUnmanaged(
|
||||||
|
usize,
|
||||||
|
*anyopaque,
|
||||||
|
struct {
|
||||||
|
pub fn hash(_: @This(), key: usize) usize {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eql(_: @This(), a: usize, b: usize) bool {
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
std.hash_map.default_max_load_percentage,
|
||||||
|
);
|
||||||
|
|
||||||
pub fn init(self: *Page, arena: Allocator, call_arena: Allocator, session: *Session) !void {
|
pub fn init(self: *Page, arena: Allocator, call_arena: Allocator, session: *Session) !void {
|
||||||
const browser = session.browser;
|
const browser = session.browser;
|
||||||
const script_manager = ScriptManager.init(browser, self);
|
const script_manager = ScriptManager.init(browser, self);
|
||||||
@@ -160,6 +180,7 @@ pub const Page = struct {
|
|||||||
self.http_client.abort();
|
self.http_client.abort();
|
||||||
self.script_manager.deinit();
|
self.script_manager.deinit();
|
||||||
self.url.deinit();
|
self.url.deinit();
|
||||||
|
self.object_data.deinit(self.arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(self: *Page) !void {
|
fn reset(self: *Page) !void {
|
||||||
@@ -170,6 +191,12 @@ pub const Page = struct {
|
|||||||
self.http_client.abort();
|
self.http_client.abort();
|
||||||
self.script_manager.reset();
|
self.script_manager.reset();
|
||||||
|
|
||||||
|
_ = try self.url.reparse("about:blank");
|
||||||
|
errdefer self.url.deinit();
|
||||||
|
|
||||||
|
self.object_data.deinit(self.arena);
|
||||||
|
self.object_data = .{};
|
||||||
|
|
||||||
self.load_state = .parsing;
|
self.load_state = .parsing;
|
||||||
self.mode = .{ .pre = {} };
|
self.mode = .{ .pre = {} };
|
||||||
_ = self.session.browser.page_arena.reset(.{ .retain_with_limit = 1 * 1024 * 1024 });
|
_ = self.session.browser.page_arena.reset(.{ .retain_with_limit = 1 * 1024 * 1024 });
|
||||||
@@ -200,6 +227,21 @@ pub const Page = struct {
|
|||||||
}.runMessageLoop, 5, .{ .name = "page.messageLoop" });
|
}.runMessageLoop, 5, .{ .name = "page.messageLoop" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the object data by given key.
|
||||||
|
/// `key` must be a pointer type.
|
||||||
|
/// Type of value is unknown to map; so the caller must do the type casting.
|
||||||
|
pub fn getObjectData(self: *Page, key: anytype) ?*anyopaque {
|
||||||
|
std.debug.assert(@typeInfo(@TypeOf(key)) == .pointer);
|
||||||
|
return self.object_data.get(@intFromPtr(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Puts the object data by given key.
|
||||||
|
/// `key` must be a pointer type.
|
||||||
|
pub fn putObjectData(self: *Page, key: anytype, value: *anyopaque) Allocator.Error!void {
|
||||||
|
std.debug.assert(@typeInfo(@TypeOf(key)) == .pointer);
|
||||||
|
return self.object_data.put(self.arena, @intFromPtr(key), value);
|
||||||
|
}
|
||||||
|
|
||||||
pub const DumpOpts = struct {
|
pub const DumpOpts = struct {
|
||||||
// set to include element shadowroots in the dump
|
// set to include element shadowroots in the dump
|
||||||
page: ?*const Page = null,
|
page: ?*const Page = null,
|
||||||
|
|||||||
52
src/url.zig
52
src/url.zig
@@ -44,6 +44,11 @@ pub const URL = struct {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Forms a `URL` from given `internal`. Memory is not copied.
|
||||||
|
pub fn fromInternal(internal: ada.URL) URL {
|
||||||
|
return .{ .internal = internal };
|
||||||
|
}
|
||||||
|
|
||||||
/// Deinitializes internal url.
|
/// Deinitializes internal url.
|
||||||
pub fn deinit(self: URL) void {
|
pub fn deinit(self: URL) void {
|
||||||
std.debug.assert(self.internal != null);
|
std.debug.assert(self.internal != null);
|
||||||
@@ -100,6 +105,28 @@ pub const URL = struct {
|
|||||||
if (!is_set) return error.InvalidHostname;
|
if (!is_set) return error.InvalidHostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getUsername(self: URL) ?[]const u8 {
|
||||||
|
const username = ada.getUsernameNullable(self.internal);
|
||||||
|
if (username.data == null) return null;
|
||||||
|
return username.data[0..username.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setUsername(self: URL, username: []const u8) error{InvalidUsername}!void {
|
||||||
|
const is_set = ada.setUsername(self.internal, username);
|
||||||
|
if (!is_set) return error.InvalidUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getPassword(self: URL) ?[]const u8 {
|
||||||
|
const password = ada.getPasswordNullable(self.internal);
|
||||||
|
if (password.data == null) return null;
|
||||||
|
return password.data[0..password.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setPassword(self: URL, password: []const u8) error{InvalidPassword}!void {
|
||||||
|
const is_set = ada.setPassword(self.internal, password);
|
||||||
|
if (!is_set) return error.InvalidPassword;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getFragment(self: URL) ?[]const u8 {
|
pub fn getFragment(self: URL) ?[]const u8 {
|
||||||
// Ada calls it "hash" instead of "fragment".
|
// Ada calls it "hash" instead of "fragment".
|
||||||
const hash = ada.getHashNullable(self.internal);
|
const hash = ada.getHashNullable(self.internal);
|
||||||
@@ -108,6 +135,26 @@ pub const URL = struct {
|
|||||||
return hash.data[0..hash.length];
|
return hash.data[0..hash.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getSearch(self: URL) ?[]const u8 {
|
||||||
|
const search = ada.getSearchNullable(self.internal);
|
||||||
|
if (search.data == null) return null;
|
||||||
|
return search.data[0..search.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setSearch(self: URL, search: []const u8) void {
|
||||||
|
return ada.setSearch(self.internal, search);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getHash(self: URL) ?[]const u8 {
|
||||||
|
const hash = ada.getHashNullable(self.internal);
|
||||||
|
if (hash.data == null) return null;
|
||||||
|
return hash.data[0..hash.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setHash(self: URL, hash: []const u8) void {
|
||||||
|
return ada.setHash(self.internal, hash);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getProtocol(self: URL) []const u8 {
|
pub fn getProtocol(self: URL) []const u8 {
|
||||||
return ada.getProtocol(self.internal);
|
return ada.getProtocol(self.internal);
|
||||||
}
|
}
|
||||||
@@ -135,6 +182,11 @@ pub const URL = struct {
|
|||||||
return pathname.data[0..pathname.length];
|
return pathname.data[0..pathname.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setPath(self: URL, path: []const u8) error{InvalidPath}!void {
|
||||||
|
const is_set = ada.setPathname(self.internal, path);
|
||||||
|
if (!is_set) return error.InvalidPath;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the URL's protocol is secure.
|
/// Returns true if the URL's protocol is secure.
|
||||||
pub fn isSecure(self: URL) bool {
|
pub fn isSecure(self: URL) bool {
|
||||||
const scheme = ada.getSchemeType(self.internal);
|
const scheme = ada.getSchemeType(self.internal);
|
||||||
|
|||||||
12
vendor/ada/root.zig
vendored
12
vendor/ada/root.zig
vendored
@@ -71,12 +71,24 @@ pub inline fn getHrefNullable(url: URL) String {
|
|||||||
return c.ada_get_href(url);
|
return c.ada_get_href(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn getUsernameNullable(url: URL) String {
|
||||||
|
return c.ada_get_username(url);
|
||||||
|
}
|
||||||
|
|
||||||
/// Can return an empty string.
|
/// Can return an empty string.
|
||||||
pub inline fn getUsername(url: URL) []const u8 {
|
pub inline fn getUsername(url: URL) []const u8 {
|
||||||
const username = c.ada_get_username(url);
|
const username = c.ada_get_username(url);
|
||||||
return username.data[0..username.length];
|
return username.data[0..username.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub inline fn getPasswordNullable(url: URL) String {
|
||||||
|
return c.ada_get_password(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn getSearchNullable(url: URL) String {
|
||||||
|
return c.ada_get_search(url);
|
||||||
|
}
|
||||||
|
|
||||||
/// Can return an empty string.
|
/// Can return an empty string.
|
||||||
pub inline fn getPassword(url: URL) []const u8 {
|
pub inline fn getPassword(url: URL) []const u8 {
|
||||||
const password = c.ada_get_password(url);
|
const password = c.ada_get_password(url);
|
||||||
|
|||||||
Reference in New Issue
Block a user