Merge pull request #1490 from lightpanda-io/missing_properties

Add a number of [simple] missing properties
This commit is contained in:
Pierre Tachoire
2026-02-08 10:36:28 +01:00
committed by GitHub
5 changed files with 94 additions and 0 deletions

View File

@@ -437,11 +437,21 @@ pub fn unknownWindowPropertyCallback(c_name: ?*const v8.Name, handle: ?*const v8
}
if (comptime IS_DEBUG) {
if (std.mem.startsWith(u8, property, "__")) {
// some frameworks will extend built-in types using a __ prefix
// these should always be safe to ignore.
return 0;
}
const ignored = std.StaticStringMap(void).initComptime(.{
.{ "Deno", {} },
.{ "process", {} },
.{ "ShadyDOM", {} },
.{ "ShadyCSS", {} },
// a lot of sites seem to like having their own window.config.
.{ "config", {} },
.{ "litNonce", {} },
.{ "litHtmlVersions", {} },
.{ "litElementVersions", {} },
@@ -457,6 +467,8 @@ pub fn unknownWindowPropertyCallback(c_name: ?*const v8.Name, handle: ?*const v8
.{ "__google_recaptcha_client", {} },
.{ "CLOSURE_FLAGS", {} },
.{ "__REACT_DEVTOOLS_GLOBAL_HOOK__", {} },
.{ "ApplePaySession", {} },
});
if (!ignored.has(property)) {
log.debug(.unknown_prop, "unknown global property", .{
@@ -512,6 +524,17 @@ pub fn unknownObjectPropertyCallback(comptime JsApi: type) *const fn (?*const v8
}
}
if (JsApi == @import("../webapi/element/Html.zig") or JsApi == @import("../webapi/Element.zig") or JsApi == @import("../webapi/element/html/Custom.zig")) {
// react ?
if (std.mem.eql(u8, property, "props")) return 0;
if (std.mem.eql(u8, property, "hydrated")) return 0;
if (std.mem.eql(u8, property, "isHydrated")) return 0;
}
if (JsApi == @import("../webapi/Console.zig")) {
if (std.mem.eql(u8, property, "firebug")) return 0;
}
const ignored = std.StaticStringMap(void).initComptime(.{});
if (!ignored.has(property)) {
log.debug(.unknown_prop, "unknown object property", .{

View File

@@ -102,6 +102,14 @@ pub fn getPlugins(self: *Navigator) *PluginArray {
return &self._plugins;
}
pub fn getDoNotTrack(_: *const Navigator) ?[]const u8 {
return null;
}
pub fn getGlobalPrivacyControl(_: *const Navigator) bool {
return true;
}
pub fn registerProtocolHandler(_: *const Navigator, scheme: []const u8, url: [:0]const u8, page: *const Page) !void {
try validateProtocolHandlerScheme(scheme);
try validateProtocolHandlerURL(url, page);
@@ -196,6 +204,8 @@ pub const JsApi = struct {
pub const product = bridge.accessor(Navigator.getProduct, null, .{});
pub const webdriver = bridge.accessor(Navigator.getWebdriver, null, .{});
pub const plugins = bridge.accessor(Navigator.getPlugins, null, .{});
pub const doNotTrack = bridge.accessor(Navigator.getDoNotTrack, null, .{});
pub const globalPrivacyControl = bridge.accessor(Navigator.getGlobalPrivacyControl, null, .{});
pub const registerProtocolHandler = bridge.function(Navigator.registerProtocolHandler, .{ .dom_exception = true });
pub const unregisterProtocolHandler = bridge.function(Navigator.unregisterProtocolHandler, .{ .dom_exception = true });

View File

@@ -100,6 +100,18 @@ pub fn setLoading(self: *Image, value: []const u8, page: *Page) !void {
try self.asElement().setAttributeSafe(comptime .wrap("loading"), .wrap(value), page);
}
pub fn getNaturalWidth(_: *const Image) u32 {
// this is a valid response under a number of normal conditions, but could
// be used to detect the nature of Browser.
return 0;
}
pub fn getNaturalHeight(_: *const Image) u32 {
// this is a valid response under a number of normal conditions, but could
// be used to detect the nature of Browser.
return 0;
}
pub const JsApi = struct {
pub const bridge = js.Bridge(Image);
@@ -117,6 +129,8 @@ pub const JsApi = struct {
pub const height = bridge.accessor(Image.getHeight, Image.setHeight, .{});
pub const crossOrigin = bridge.accessor(Image.getCrossOrigin, Image.setCrossOrigin, .{});
pub const loading = bridge.accessor(Image.getLoading, Image.setLoading, .{});
pub const naturalWidth = bridge.accessor(Image.getNaturalWidth, null, .{});
pub const naturalHeight = bridge.accessor(Image.getNaturalHeight, null, .{});
};
pub const Build = struct {

View File

@@ -30,6 +30,9 @@ _proto: *HtmlElement,
pub fn asElement(self: *Link) *Element {
return self._proto._proto;
}
pub fn asConstElement(self: *const Link) *const Element {
return self._proto._proto;
}
pub fn asNode(self: *Link) *Node {
return self.asElement().asNode();
}
@@ -57,6 +60,14 @@ pub fn setRel(self: *Link, value: []const u8, page: *Page) !void {
try self.asElement().setAttributeSafe(comptime .wrap("rel"), .wrap(value), page);
}
pub fn getAs(self: *const Link) []const u8 {
return self.asConstElement().getAttributeSafe(comptime .wrap("as")) orelse "";
}
pub fn setAs(self: *Link, value: []const u8, page: *Page) !void {
return self.asElement().setAttributeSafe(comptime .wrap("as"), .wrap(value), page);
}
pub const JsApi = struct {
pub const bridge = js.Bridge(Link);
@@ -66,6 +77,7 @@ pub const JsApi = struct {
pub var class_id: bridge.ClassId = undefined;
};
pub const as = bridge.accessor(Link.getAs, Link.setAs, .{});
pub const rel = bridge.accessor(Link.getRel, Link.setRel, .{});
pub const href = bridge.accessor(Link.getHref, Link.setHref, .{});
pub const relList = bridge.accessor(_getRelList, null, .{ .null_as_undefined = true });

View File

@@ -76,6 +76,38 @@ pub fn setNonce(self: *Script, value: []const u8, page: *Page) !void {
return self.asElement().setAttributeSafe(comptime .wrap("nonce"), .wrap(value), page);
}
pub fn getCharset(self: *const Script) []const u8 {
return self.asConstElement().getAttributeSafe(comptime .wrap("charset")) orelse "";
}
pub fn setCharset(self: *Script, value: []const u8, page: *Page) !void {
return self.asElement().setAttributeSafe(comptime .wrap("charset"), .wrap(value), page);
}
pub fn getAsync(self: *const Script) bool {
return self.asConstElement().getAttributeSafe(comptime .wrap("async")) != null;
}
pub fn setAsync(self: *Script, value: bool, page: *Page) !void {
if (value) {
try self.asElement().setAttributeSafe(comptime .wrap("async"), .wrap(""), page);
} else {
try self.asElement().removeAttribute(comptime .wrap("async"), page);
}
}
pub fn getDefer(self: *const Script) bool {
return self.asConstElement().getAttributeSafe(comptime .wrap("defer")) != null;
}
pub fn setDefer(self: *Script, value: bool, page: *Page) !void {
if (value) {
try self.asElement().setAttributeSafe(comptime .wrap("defer"), .wrap(""), page);
} else {
try self.asElement().removeAttribute(comptime .wrap("defer"), page);
}
}
pub fn getOnLoad(self: *const Script) ?js.Function.Global {
return self._on_load;
}
@@ -110,8 +142,11 @@ pub const JsApi = struct {
};
pub const src = bridge.accessor(Script.getSrc, Script.setSrc, .{});
pub const @"defer" = bridge.accessor(Script.getDefer, Script.setDefer, .{});
pub const async = bridge.accessor(Script.getAsync, Script.setAsync, .{});
pub const @"type" = bridge.accessor(Script.getType, Script.setType, .{});
pub const nonce = bridge.accessor(Script.getNonce, Script.setNonce, .{});
pub const charset = bridge.accessor(Script.getCharset, Script.setCharset, .{});
pub const onload = bridge.accessor(Script.getOnLoad, Script.setOnLoad, .{});
pub const onerror = bridge.accessor(Script.getOnError, Script.setOnError, .{});
pub const noModule = bridge.accessor(Script.getNoModule, null, .{});