Convert more comptime-getters to fast getters

Follow up to https://github.com/lightpanda-io/browser/pull/1495 which introduced
the concept of a fast getter. This commit expands the new behavior to all
comptime-known scalar getters.

It also leverages the new `v8__FunctionTemplate__New__Config` to
1 - flag fast getters as having no side effect
2 - set the length (arity) on all functions
This commit is contained in:
Karl Seguin
2026-02-09 11:35:27 +08:00
parent 0a410a5544
commit 8d49515a3c
18 changed files with 108 additions and 211 deletions

View File

@@ -13,7 +13,7 @@ inputs:
zig-v8: zig-v8:
description: 'zig v8 version to install' description: 'zig v8 version to install'
required: false required: false
default: 'v0.2.7' default: 'v0.2.8'
v8: v8:
description: 'v8 version to install' description: 'v8 version to install'
required: false required: false

View File

@@ -3,7 +3,7 @@ FROM debian:stable-slim
ARG MINISIG=0.12 ARG MINISIG=0.12
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
ARG V8=14.0.365.4 ARG V8=14.0.365.4
ARG ZIG_V8=v0.2.7 ARG ZIG_V8=v0.2.8
ARG TARGETPLATFORM ARG TARGETPLATFORM
RUN apt-get update -yq && \ RUN apt-get update -yq && \

View File

@@ -6,8 +6,8 @@
.minimum_zig_version = "0.15.2", .minimum_zig_version = "0.15.2",
.dependencies = .{ .dependencies = .{
.v8 = .{ .v8 = .{
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/refs/tags/0.2.7.tar.gz", .url = "https://github.com/lightpanda-io/zig-v8-fork/archive/refs/tags/v0.2.8.tar.gz",
.hash = "v8-0.0.0-xddH62VUBADeNHR3Go37RmFrODPARC-f5vjxkpJtxQsZ", .hash = "v8-0.0.0-xddH63lfBADJ7UE2zAJ8nJIBnxoSiimXSaX6Q_M_7DS3",
}, },
//.v8 = .{ .path = "../zig-v8-fork" }, //.v8 = .{ .path = "../zig-v8-fork" },
.@"boringssl-zig" = .{ .@"boringssl-zig" = .{

View File

@@ -455,7 +455,7 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
switch (definition) { switch (definition) {
bridge.Accessor => { bridge.Accessor => {
const js_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len)); const js_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len));
const getter_callback = @constCast(v8.v8__FunctionTemplate__New__DEFAULT2(isolate, value.getter).?); const getter_callback = @constCast(v8.v8__FunctionTemplate__New__Config(isolate, &.{ .callback = value.getter }).?);
if (value.setter == null) { if (value.setter == null) {
if (value.static) { if (value.static) {
v8.v8__Template__SetAccessorProperty__DEFAULT(@ptrCast(template), js_name, getter_callback); v8.v8__Template__SetAccessorProperty__DEFAULT(@ptrCast(template), js_name, getter_callback);
@@ -466,12 +466,12 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
if (comptime IS_DEBUG) { if (comptime IS_DEBUG) {
std.debug.assert(value.static == false); std.debug.assert(value.static == false);
} }
const setter_callback = @constCast(v8.v8__FunctionTemplate__New__DEFAULT2(isolate, value.setter.?).?); const setter_callback = @constCast(v8.v8__FunctionTemplate__New__Config(isolate, &.{ .callback = value.setter.? }).?);
v8.v8__ObjectTemplate__SetAccessorProperty__DEFAULT2(target, js_name, getter_callback, setter_callback); v8.v8__ObjectTemplate__SetAccessorProperty__DEFAULT2(target, js_name, getter_callback, setter_callback);
} }
}, },
bridge.Function => { bridge.Function => {
const function_template = @constCast(v8.v8__FunctionTemplate__New__DEFAULT2(isolate, value.func).?); const function_template = @constCast(v8.v8__FunctionTemplate__New__Config(isolate, &.{ .callback = value.func, .length = value.arity }).?);
const js_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len)); const js_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len));
if (value.static) { if (value.static) {
v8.v8__Template__Set(@ptrCast(template), js_name, @ptrCast(function_template), v8.None); v8.v8__Template__Set(@ptrCast(template), js_name, @ptrCast(function_template), v8.None);
@@ -509,7 +509,7 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
has_named_index_getter = true; has_named_index_getter = true;
}, },
bridge.Iterator => { bridge.Iterator => {
const function_template = @constCast(v8.v8__FunctionTemplate__New__DEFAULT2(isolate, value.func).?); const function_template = @constCast(v8.v8__FunctionTemplate__New__Config(isolate, &.{ .callback = value.func }).?);
const js_name = if (value.async) const js_name = if (value.async)
v8.v8__Symbol__GetAsyncIterator(isolate) v8.v8__Symbol__GetAsyncIterator(isolate)
else else
@@ -518,7 +518,8 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
}, },
bridge.Property => { bridge.Property => {
const js_value = switch (value.value) { const js_value = switch (value.value) {
inline .bool, .int => |v| js.simpleZigValueToJs(.{ .handle = isolate }, v, true, false), .null => js.simpleZigValueToJs(.{ .handle = isolate }, null, true, false),
inline .bool, .int, .float, .string => |v| js.simpleZigValueToJs(.{ .handle = isolate }, v, true, false),
}; };
const js_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len)); const js_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len));
@@ -527,7 +528,11 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
// is like an Accessor, but because the value is known at // is like an Accessor, but because the value is known at
// compile time, we skip _a lot_ of code and quickly return // compile time, we skip _a lot_ of code and quickly return
// the hard-coded value // the hard-coded value
const getter_callback = @constCast(v8.v8__FunctionTemplate__New__DEFAULT3(isolate, bridge.Property.getter, js_value)); const getter_callback = @constCast(v8.v8__FunctionTemplate__New__Config(isolate, &.{
.callback = bridge.Property.getter,
.data = js_value,
.side_effect_type = v8.kSideEffectType_HasSideEffectToReceiver,
}));
v8.v8__ObjectTemplate__SetAccessorProperty__DEFAULT(target, js_name, getter_callback); v8.v8__ObjectTemplate__SetAccessorProperty__DEFAULT(target, js_name, getter_callback);
} else { } else {
// apply it both to the type itself // apply it both to the type itself

View File

@@ -63,12 +63,23 @@ pub fn Builder(comptime T: type) type {
} }
pub fn property(value: anytype, opts: Property.Opts) Property { pub fn property(value: anytype, opts: Property.Opts) Property {
// If you add strings to this, they might need to be internalized! switch (@typeInfo(@TypeOf(value))) {
return switch (@typeInfo(@TypeOf(value))) { .bool => return Property.init(.{ .bool = value }, opts),
.bool => Property.init(.{ .bool = value }, opts), .null => return Property.init(.null, opts),
.comptime_int, .int => Property.init(.{ .int = value }, opts), .comptime_int, .int => return Property.init(.{ .int = value }, opts),
else => @compileError("Property for " ++ @typeName(@TypeOf(value)) ++ " hasn't been defined yet"), .comptime_float, .float => return Property.init(.{ .float = value }, opts),
}; .pointer => |ptr| switch (ptr.size) {
.one => {
const one_info = @typeInfo(ptr.child);
if (one_info == .array and one_info.array.child == u8) {
return Property.init(.{ .string = value }, opts);
}
},
else => {},
},
else => {},
}
@compileError("Property for " ++ @typeName(@TypeOf(value)) ++ " hasn't been defined yet");
} }
const PrototypeChainEntry = @import("TaggedOpaque.zig").PrototypeChainEntry; const PrototypeChainEntry = @import("TaggedOpaque.zig").PrototypeChainEntry;
@@ -150,6 +161,7 @@ pub const Constructor = struct {
pub const Function = struct { pub const Function = struct {
static: bool, static: bool,
arity: usize,
func: *const fn (?*const v8.FunctionCallbackInfo) callconv(.c) void, func: *const fn (?*const v8.FunctionCallbackInfo) callconv(.c) void,
const Opts = struct { const Opts = struct {
@@ -162,6 +174,7 @@ pub const Function = struct {
fn init(comptime T: type, comptime func: anytype, comptime opts: Opts) Function { fn init(comptime T: type, comptime func: anytype, comptime opts: Opts) Function {
return .{ return .{
.static = opts.static, .static = opts.static,
.arity = getArity(@TypeOf(func)),
.func = struct { .func = struct {
fn wrap(handle: ?*const v8.FunctionCallbackInfo) callconv(.c) void { fn wrap(handle: ?*const v8.FunctionCallbackInfo) callconv(.c) void {
const v8_isolate = v8.v8__FunctionCallbackInfo__GetIsolate(handle).?; const v8_isolate = v8.v8__FunctionCallbackInfo__GetIsolate(handle).?;
@@ -186,6 +199,22 @@ pub const Function = struct {
}.wrap, }.wrap,
}; };
} }
fn getArity(comptime T: type) usize {
var count: usize = 0;
var params = @typeInfo(T).@"fn".params;
for (params[1..]) |p| { // start at 1, skip self
const PT = p.type.?;
if (PT == *Page or PT == *const Page) {
break;
}
if (@typeInfo(PT) == .optional) {
break;
}
count += 1;
}
return count;
}
}; };
pub const Accessor = struct { pub const Accessor = struct {
@@ -403,10 +432,12 @@ pub const Property = struct {
value: Value, value: Value,
template: bool, template: bool,
// If you add strings to this, they might need to be internalized!
const Value = union(enum) { const Value = union(enum) {
null,
int: i64, int: i64,
float: f64,
bool: bool, bool: bool,
string: []const u8,
}; };
const Opts = struct { const Opts = struct {

View File

@@ -2,6 +2,8 @@
<body></body> <body></body>
<script src="../testing.js"></script> <script src="../testing.js"></script>
<script id=createElement> <script id=createElement>
testing.expectEqual(1, document.createElement.length);
const div1 = document.createElement('div'); const div1 = document.createElement('div');
testing.expectEqual(true, div1 instanceof HTMLDivElement); testing.expectEqual(true, div1 instanceof HTMLDivElement);
testing.expectEqual("DIV", div1.tagName); testing.expectEqual("DIV", div1.tagName);

View File

@@ -23,6 +23,7 @@
<main>Main content</main> <main>Main content</main>
<script id=byId name="test1"> <script id=byId name="test1">
testing.expectEqual(1, document.querySelector.length);
testing.expectError("SyntaxError: Syntax Error", () => document.querySelector('')); testing.expectError("SyntaxError: Syntax Error", () => document.querySelector(''));
testing.withError((err) => { testing.withError((err) => {
testing.expectEqual(12, err.code); testing.expectEqual(12, err.code);

View File

@@ -25,6 +25,7 @@
<script id=setTimeout> <script id=setTimeout>
testing.expectEqual(1, window.setTimeout.length);
let wst2 = 1; let wst2 = 1;
window.setTimeout((a, b) => { window.setTimeout((a, b) => {
wst2 = a + b; wst2 = a + b;

View File

@@ -103,18 +103,6 @@ pub fn getContentType(self: *const Document) []const u8 {
}; };
} }
pub fn getCharacterSet(_: *const Document) []const u8 {
return "UTF-8";
}
pub fn getCompatMode(_: *const Document) []const u8 {
return "CSS1Compat";
}
pub fn getReferrer(_: *const Document) []const u8 {
return "";
}
pub fn getDomain(_: *const Document, page: *const Page) []const u8 { pub fn getDomain(_: *const Document, page: *const Page) []const u8 {
return URL.getHostname(page.url); return URL.getHostname(page.url);
} }
@@ -951,11 +939,6 @@ pub const JsApi = struct {
pub const activeElement = bridge.accessor(Document.getActiveElement, null, .{}); pub const activeElement = bridge.accessor(Document.getActiveElement, null, .{});
pub const styleSheets = bridge.accessor(Document.getStyleSheets, null, .{}); pub const styleSheets = bridge.accessor(Document.getStyleSheets, null, .{});
pub const contentType = bridge.accessor(Document.getContentType, null, .{}); pub const contentType = bridge.accessor(Document.getContentType, null, .{});
pub const characterSet = bridge.accessor(Document.getCharacterSet, null, .{});
pub const charset = bridge.accessor(Document.getCharacterSet, null, .{});
pub const inputEncoding = bridge.accessor(Document.getCharacterSet, null, .{});
pub const compatMode = bridge.accessor(Document.getCompatMode, null, .{});
pub const referrer = bridge.accessor(Document.getReferrer, null, .{});
pub const domain = bridge.accessor(Document.getDomain, null, .{}); pub const domain = bridge.accessor(Document.getDomain, null, .{});
pub const createElement = bridge.function(Document.createElement, .{ .dom_exception = true }); pub const createElement = bridge.function(Document.createElement, .{ .dom_exception = true });
pub const createElementNS = bridge.function(Document.createElementNS, .{ .dom_exception = true }); pub const createElementNS = bridge.function(Document.createElementNS, .{ .dom_exception = true });
@@ -1004,14 +987,19 @@ pub const JsApi = struct {
pub const adoptedStyleSheets = bridge.accessor(Document.getAdoptedStyleSheets, Document.setAdoptedStyleSheets, .{}); pub const adoptedStyleSheets = bridge.accessor(Document.getAdoptedStyleSheets, Document.setAdoptedStyleSheets, .{});
pub const hidden = bridge.accessor(Document.getHidden, null, .{}); pub const hidden = bridge.accessor(Document.getHidden, null, .{});
pub const visibilityState = bridge.accessor(Document.getVisibilityState, null, .{}); pub const visibilityState = bridge.accessor(Document.getVisibilityState, null, .{});
pub const prerendering = bridge.property(false, .{ .template = false });
pub const defaultView = bridge.accessor(struct { pub const defaultView = bridge.accessor(struct {
fn defaultView(_: *const Document, page: *Page) *@import("Window.zig") { fn defaultView(_: *const Document, page: *Page) *@import("Window.zig") {
return page.window; return page.window;
} }
}.defaultView, null, .{ .cache = "defaultView" }); }.defaultView, null, .{ .cache = "defaultView" });
pub const hasFocus = bridge.function(Document.hasFocus, .{}); pub const hasFocus = bridge.function(Document.hasFocus, .{});
pub const prerendering = bridge.property(false, .{ .template = false });
pub const characterSet = bridge.property("UTF-8", .{ .template = false });
pub const charset = bridge.property("UTF-8", .{ .template = false });
pub const inputEncoding = bridge.property("UTF-8", .{ .template = false });
pub const compatMode = bridge.property("CSS1Compat", .{ .template = false });
pub const referrer = bridge.property("", .{ .template = false });
}; };
const testing = @import("../../testing.zig"); const testing = @import("../../testing.zig");

View File

@@ -24,10 +24,6 @@ pub fn init() IdleDeadline {
return .{}; return .{};
} }
pub fn getDidTimeout(_: *const IdleDeadline) bool {
return false;
}
pub fn timeRemaining(_: *const IdleDeadline) f64 { pub fn timeRemaining(_: *const IdleDeadline) f64 {
// Return a fixed 50ms. // Return a fixed 50ms.
// This allows idle callbacks to perform work without complex // This allows idle callbacks to perform work without complex
@@ -47,5 +43,5 @@ pub const JsApi = struct {
}; };
pub const timeRemaining = bridge.function(IdleDeadline.timeRemaining, .{}); pub const timeRemaining = bridge.function(IdleDeadline.timeRemaining, .{});
pub const didTimeout = bridge.accessor(IdleDeadline.getDidTimeout, null, .{}); pub const didTimeout = bridge.property(false, .{ .template = false });
}; };

View File

@@ -32,16 +32,8 @@ pub fn getUserAgent(_: *const Navigator, page: *Page) []const u8 {
return page._session.browser.app.config.http_headers.user_agent; return page._session.browser.app.config.http_headers.user_agent;
} }
pub fn getAppName(_: *const Navigator) []const u8 { pub fn getLanguages(_: *const Navigator) [1][]const u8 {
return "Netscape"; return .{"en-US"};
}
pub fn getAppCodeName(_: *const Navigator) []const u8 {
return "Netscape";
}
pub fn getAppVersion(_: *const Navigator) []const u8 {
return "1.0";
} }
pub fn getPlatform(_: *const Navigator) []const u8 { pub fn getPlatform(_: *const Navigator) []const u8 {
@@ -54,62 +46,15 @@ pub fn getPlatform(_: *const Navigator) []const u8 {
}; };
} }
pub fn getLanguage(_: *const Navigator) []const u8 {
return "en-US";
}
pub fn getLanguages(_: *const Navigator) [1][]const u8 {
return .{"en-US"};
}
pub fn getOnLine(_: *const Navigator) bool {
return true;
}
pub fn getCookieEnabled(_: *const Navigator) bool {
return true;
}
pub fn getHardwareConcurrency(_: *const Navigator) u32 {
return 4;
}
pub fn getMaxTouchPoints(_: *const Navigator) u32 {
return 0;
}
/// Returns the vendor name
pub fn getVendor(_: *const Navigator) []const u8 {
return "";
}
/// Returns the product name (typically "Gecko" for compatibility)
pub fn getProduct(_: *const Navigator) []const u8 {
return "Gecko";
}
/// Returns whether Java is enabled (always false) /// Returns whether Java is enabled (always false)
pub fn javaEnabled(_: *const Navigator) bool { pub fn javaEnabled(_: *const Navigator) bool {
return false; return false;
} }
/// Returns whether the browser is controlled by automation (always false)
pub fn getWebdriver(_: *const Navigator) bool {
return false;
}
pub fn getPlugins(self: *Navigator) *PluginArray { pub fn getPlugins(self: *Navigator) *PluginArray {
return &self._plugins; 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 { pub fn registerProtocolHandler(_: *const Navigator, scheme: []const u8, url: [:0]const u8, page: *const Page) !void {
try validateProtocolHandlerScheme(scheme); try validateProtocolHandlerScheme(scheme);
try validateProtocolHandlerURL(url, page); try validateProtocolHandlerURL(url, page);
@@ -190,22 +135,22 @@ pub const JsApi = struct {
// Read-only properties // Read-only properties
pub const userAgent = bridge.accessor(Navigator.getUserAgent, null, .{}); pub const userAgent = bridge.accessor(Navigator.getUserAgent, null, .{});
pub const appName = bridge.accessor(Navigator.getAppName, null, .{}); pub const appName = bridge.property("Netscape", .{ .template = false });
pub const appCodeName = bridge.accessor(Navigator.getAppCodeName, null, .{}); pub const appCodeName = bridge.property("Netscape", .{ .template = false });
pub const appVersion = bridge.accessor(Navigator.getAppVersion, null, .{}); pub const appVersion = bridge.property("1.0", .{ .template = false });
pub const platform = bridge.accessor(Navigator.getPlatform, null, .{}); pub const platform = bridge.accessor(Navigator.getPlatform, null, .{});
pub const language = bridge.accessor(Navigator.getLanguage, null, .{}); pub const language = bridge.property("en-US", .{ .template = false });
pub const languages = bridge.accessor(Navigator.getLanguages, null, .{}); pub const languages = bridge.accessor(Navigator.getLanguages, null, .{});
pub const onLine = bridge.accessor(Navigator.getOnLine, null, .{}); pub const onLine = bridge.property(true, .{ .template = false });
pub const cookieEnabled = bridge.accessor(Navigator.getCookieEnabled, null, .{}); pub const cookieEnabled = bridge.property(true, .{ .template = false });
pub const hardwareConcurrency = bridge.accessor(Navigator.getHardwareConcurrency, null, .{}); pub const hardwareConcurrency = bridge.property(4, .{ .template = false });
pub const maxTouchPoints = bridge.accessor(Navigator.getMaxTouchPoints, null, .{}); pub const maxTouchPoints = bridge.property(0, .{ .template = false });
pub const vendor = bridge.accessor(Navigator.getVendor, null, .{}); pub const vendor = bridge.property("", .{ .template = false });
pub const product = bridge.accessor(Navigator.getProduct, null, .{}); pub const product = bridge.property("Gecko", .{ .template = false });
pub const webdriver = bridge.accessor(Navigator.getWebdriver, null, .{}); pub const webdriver = bridge.property(false, .{ .template = false });
pub const plugins = bridge.accessor(Navigator.getPlugins, null, .{}); pub const plugins = bridge.accessor(Navigator.getPlugins, null, .{});
pub const doNotTrack = bridge.accessor(Navigator.getDoNotTrack, null, .{}); pub const doNotTrack = bridge.property(null, .{ .template = false });
pub const globalPrivacyControl = bridge.accessor(Navigator.getGlobalPrivacyControl, null, .{}); pub const globalPrivacyControl = bridge.property(true, .{ .template = false });
pub const registerProtocolHandler = bridge.function(Navigator.registerProtocolHandler, .{ .dom_exception = true }); pub const registerProtocolHandler = bridge.function(Navigator.registerProtocolHandler, .{ .dom_exception = true });
pub const unregisterProtocolHandler = bridge.function(Navigator.unregisterProtocolHandler, .{ .dom_exception = true }); pub const unregisterProtocolHandler = bridge.function(Navigator.unregisterProtocolHandler, .{ .dom_exception = true });

View File

@@ -26,9 +26,6 @@ const PluginArray = @This();
_pad: bool = false, _pad: bool = false,
pub fn getLength(_: *const PluginArray) u32 {
return 0;
}
pub fn refresh(_: *const PluginArray) void {} pub fn refresh(_: *const PluginArray) void {}
pub fn getAtIndex(_: *const PluginArray, index: usize) ?*Plugin { pub fn getAtIndex(_: *const PluginArray, index: usize) ?*Plugin {
_ = index; _ = index;
@@ -64,7 +61,7 @@ pub const JsApi = struct {
pub const empty_with_no_proto = true; pub const empty_with_no_proto = true;
}; };
pub const length = bridge.accessor(PluginArray.getLength, null, .{}); pub const length = bridge.property(0, .{ .template = false });
pub const refresh = bridge.function(PluginArray.refresh, .{}); pub const refresh = bridge.function(PluginArray.refresh, .{});
pub const @"[int]" = bridge.indexed(PluginArray.getAtIndex, .{ .null_as_undefined = true }); pub const @"[int]" = bridge.indexed(PluginArray.getAtIndex, .{ .null_as_undefined = true });
pub const @"[str]" = bridge.namedIndexed(PluginArray.getByName, null, null, .{ .null_as_undefined = true }); pub const @"[str]" = bridge.namedIndexed(PluginArray.getByName, null, null, .{ .null_as_undefined = true });

View File

@@ -43,30 +43,6 @@ pub fn asEventTarget(self: *Screen) *EventTarget {
return self._proto; return self._proto;
} }
pub fn getWidth(_: *const Screen) u32 {
return 1920;
}
pub fn getHeight(_: *const Screen) u32 {
return 1080;
}
pub fn getAvailWidth(_: *const Screen) u32 {
return 1920;
}
pub fn getAvailHeight(_: *const Screen) u32 {
return 1040; // 40px reserved for taskbar/dock
}
pub fn getColorDepth(_: *const Screen) u32 {
return 24;
}
pub fn getPixelDepth(_: *const Screen) u32 {
return 24;
}
pub fn getOrientation(self: *Screen, page: *Page) !*Orientation { pub fn getOrientation(self: *Screen, page: *Page) !*Orientation {
if (self._orientation) |orientation| { if (self._orientation) |orientation| {
return orientation; return orientation;
@@ -85,12 +61,12 @@ pub const JsApi = struct {
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
}; };
pub const width = bridge.accessor(Screen.getWidth, null, .{}); pub const width = bridge.property(1920, .{ .template = false });
pub const height = bridge.accessor(Screen.getHeight, null, .{}); pub const height = bridge.property(1080, .{ .template = false });
pub const availWidth = bridge.accessor(Screen.getAvailWidth, null, .{}); pub const availWidth = bridge.property(1920, .{ .template = false });
pub const availHeight = bridge.accessor(Screen.getAvailHeight, null, .{}); pub const availHeight = bridge.property(1040, .{ .template = false });
pub const colorDepth = bridge.accessor(Screen.getColorDepth, null, .{}); pub const colorDepth = bridge.property(24, .{ .template = false });
pub const pixelDepth = bridge.accessor(Screen.getPixelDepth, null, .{}); pub const pixelDepth = bridge.property(24, .{ .template = false });
pub const orientation = bridge.accessor(Screen.getOrientation, null, .{}); pub const orientation = bridge.accessor(Screen.getOrientation, null, .{});
}; };
@@ -107,14 +83,6 @@ pub const Orientation = struct {
return self._proto; return self._proto;
} }
pub fn getAngle(_: *const Orientation) u32 {
return 0;
}
pub fn getType(_: *const Orientation) []const u8 {
return "landscape-primary";
}
pub const JsApi = struct { pub const JsApi = struct {
pub const bridge = js.Bridge(Orientation); pub const bridge = js.Bridge(Orientation);
@@ -124,7 +92,7 @@ pub const Orientation = struct {
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
}; };
pub const angle = bridge.accessor(Orientation.getAngle, null, .{}); pub const angle = bridge.property(0, .{ .template = false });
pub const @"type" = bridge.accessor(Orientation.getType, null, .{}); pub const @"type" = bridge.property("landscape-primary", .{ .template = false });
}; };
}; };

View File

@@ -341,14 +341,6 @@ pub fn getComputedStyle(_: *const Window, element: *Element, pseudo_element: ?[]
return CSSStyleProperties.init(element, true, page); return CSSStyleProperties.init(element, true, page);
} }
pub fn getIsSecureContext(_: *const Window) bool {
// Return false since we don't have secure-context-only APIs implemented
// (webcam, geolocation, clipboard, etc.)
// This is safer and could help avoid processing errors by hinting at
// sites not to try to access those features
return false;
}
pub fn postMessage(self: *Window, message: js.Value.Global, target_origin: ?[]const u8, page: *Page) !void { pub fn postMessage(self: *Window, message: js.Value.Global, target_origin: ?[]const u8, page: *Page) !void {
// For now, we ignore targetOrigin checking and just dispatch the message // For now, we ignore targetOrigin checking and just dispatch the message
// In a full implementation, we would validate the origin // In a full implementation, we would validate the origin
@@ -405,14 +397,6 @@ pub fn getFramesLength(self: *const Window) u32 {
return ln; return ln;
} }
pub fn getInnerWidth(_: *const Window) u32 {
return 1920;
}
pub fn getInnerHeight(_: *const Window) u32 {
return 1080;
}
pub fn getScrollX(self: *const Window) u32 { pub fn getScrollX(self: *const Window) u32 {
return self._scroll_pos.x; return self._scroll_pos.x;
} }
@@ -421,12 +405,6 @@ pub fn getScrollY(self: *const Window) u32 {
return self._scroll_pos.y; return self._scroll_pos.y;
} }
pub fn getOpener(_: *const Window) ?*Window {
// This should return a window-like object in specific conditions. Would be
// pretty complicated to properly support I think.
return null;
}
const ScrollToOpts = union(enum) { const ScrollToOpts = union(enum) {
x: i32, x: i32,
opts: Opts, opts: Opts,
@@ -743,19 +721,28 @@ pub const JsApi = struct {
pub const reportError = bridge.function(Window.reportError, .{}); pub const reportError = bridge.function(Window.reportError, .{});
pub const getComputedStyle = bridge.function(Window.getComputedStyle, .{}); pub const getComputedStyle = bridge.function(Window.getComputedStyle, .{});
pub const getSelection = bridge.function(Window.getSelection, .{}); pub const getSelection = bridge.function(Window.getSelection, .{});
pub const isSecureContext = bridge.accessor(Window.getIsSecureContext, null, .{});
pub const frames = bridge.accessor(Window.getWindow, null, .{ .cache = "frames" }); pub const frames = bridge.accessor(Window.getWindow, null, .{ .cache = "frames" });
pub const index = bridge.indexed(Window.getFrame, .{ .null_as_undefined = true }); pub const index = bridge.indexed(Window.getFrame, .{ .null_as_undefined = true });
pub const length = bridge.accessor(Window.getFramesLength, null, .{ .cache = "length" }); pub const length = bridge.accessor(Window.getFramesLength, null, .{ .cache = "length" });
pub const innerWidth = bridge.accessor(Window.getInnerWidth, null, .{ .cache = "innerWidth" });
pub const innerHeight = bridge.accessor(Window.getInnerHeight, null, .{ .cache = "innerHeight" });
pub const scrollX = bridge.accessor(Window.getScrollX, null, .{ .cache = "scrollX" }); pub const scrollX = bridge.accessor(Window.getScrollX, null, .{ .cache = "scrollX" });
pub const scrollY = bridge.accessor(Window.getScrollY, null, .{ .cache = "scrollY" }); pub const scrollY = bridge.accessor(Window.getScrollY, null, .{ .cache = "scrollY" });
pub const pageXOffset = bridge.accessor(Window.getScrollX, null, .{ .cache = "pageXOffset" }); pub const pageXOffset = bridge.accessor(Window.getScrollX, null, .{ .cache = "pageXOffset" });
pub const pageYOffset = bridge.accessor(Window.getScrollY, null, .{ .cache = "pageYOffset" }); pub const pageYOffset = bridge.accessor(Window.getScrollY, null, .{ .cache = "pageYOffset" });
pub const scrollTo = bridge.function(Window.scrollTo, .{}); pub const scrollTo = bridge.function(Window.scrollTo, .{});
pub const scroll = bridge.function(Window.scrollTo, .{}); pub const scroll = bridge.function(Window.scrollTo, .{});
pub const opener = bridge.accessor(Window.getOpener, null, .{});
// Return false since we don't have secure-context-only APIs implemented
// (webcam, geolocation, clipboard, etc.)
// This is safer and could help avoid processing errors by hinting at
// sites not to try to access those features
pub const isSecureContext = bridge.property(false, .{ .template = false });
pub const innerWidth = bridge.property(1920, .{ .template = false });
pub const innerHeight = bridge.property(1080, .{ .template = false });
// This should return a window-like object in specific conditions. Would be
// pretty complicated to properly support I think.
pub const opener = bridge.property(null, .{ .template = false });
}; };
const testing = @import("../../testing.zig"); const testing = @import("../../testing.zig");

View File

@@ -36,14 +36,6 @@ pub fn cancel(_: *Animation) void {}
pub fn finish(_: *Animation) void {} pub fn finish(_: *Animation) void {}
pub fn reverse(_: *Animation) void {} pub fn reverse(_: *Animation) void {}
pub fn getPlayState(_: *const Animation) []const u8 {
return "finished";
}
pub fn getPending(_: *const Animation) bool {
return false;
}
pub fn getFinished(self: *Animation, page: *Page) !js.Promise { pub fn getFinished(self: *Animation, page: *Page) !js.Promise {
if (self._finished_resolver == null) { if (self._finished_resolver == null) {
const resolver = page.js.local.?.createPromiseResolver(); const resolver = page.js.local.?.createPromiseResolver();
@@ -94,8 +86,8 @@ pub const JsApi = struct {
pub const cancel = bridge.function(Animation.cancel, .{}); pub const cancel = bridge.function(Animation.cancel, .{});
pub const finish = bridge.function(Animation.finish, .{}); pub const finish = bridge.function(Animation.finish, .{});
pub const reverse = bridge.function(Animation.reverse, .{}); pub const reverse = bridge.function(Animation.reverse, .{});
pub const playState = bridge.accessor(Animation.getPlayState, null, .{}); pub const playState = bridge.property("finished", .{ .template = false });
pub const pending = bridge.accessor(Animation.getPending, null, .{}); pub const pending = bridge.property(false, .{ .template = false });
pub const finished = bridge.accessor(Animation.getFinished, null, .{}); pub const finished = bridge.accessor(Animation.getFinished, null, .{});
pub const ready = bridge.accessor(Animation.getReady, null, .{}); pub const ready = bridge.accessor(Animation.getReady, null, .{});
pub const effect = bridge.accessor(Animation.getEffect, Animation.setEffect, .{}); pub const effect = bridge.accessor(Animation.getEffect, Animation.setEffect, .{});

View File

@@ -65,10 +65,6 @@ pub fn deinit(self: *TextDecoder, _: bool) void {
self._page.releaseArena(self._arena); self._page.releaseArena(self._arena);
} }
pub fn getEncoding(_: *const TextDecoder) []const u8 {
return "utf-8";
}
pub fn getIgnoreBOM(self: *const TextDecoder) bool { pub fn getIgnoreBOM(self: *const TextDecoder) bool {
return self._ignore_bom; return self._ignore_bom;
} }
@@ -120,7 +116,7 @@ pub const JsApi = struct {
pub const constructor = bridge.constructor(TextDecoder.init, .{}); pub const constructor = bridge.constructor(TextDecoder.init, .{});
pub const decode = bridge.function(TextDecoder.decode, .{}); pub const decode = bridge.function(TextDecoder.decode, .{});
pub const encoding = bridge.accessor(TextDecoder.getEncoding, null, .{}); pub const encoding = bridge.property("utf-8", .{ .template = false });
pub const fatal = bridge.accessor(TextDecoder.getFatal, null, .{}); pub const fatal = bridge.accessor(TextDecoder.getFatal, null, .{});
pub const ignoreBOM = bridge.accessor(TextDecoder.getIgnoreBOM, null, .{}); pub const ignoreBOM = bridge.accessor(TextDecoder.getIgnoreBOM, null, .{});
}; };

View File

@@ -26,10 +26,6 @@ pub fn init() TextEncoder {
return .{}; return .{};
} }
pub fn getEncoding(_: *const TextEncoder) []const u8 {
return "utf-8";
}
pub fn encode(_: *const TextEncoder, v: []const u8) !js.TypedArray(u8) { pub fn encode(_: *const TextEncoder, v: []const u8) !js.TypedArray(u8) {
if (!std.unicode.utf8ValidateSlice(v)) { if (!std.unicode.utf8ValidateSlice(v)) {
return error.InvalidUtf8; return error.InvalidUtf8;
@@ -50,7 +46,7 @@ pub const JsApi = struct {
pub const constructor = bridge.constructor(TextEncoder.init, .{}); pub const constructor = bridge.constructor(TextEncoder.init, .{});
pub const encode = bridge.function(TextEncoder.encode, .{ .as_typed_array = true }); pub const encode = bridge.function(TextEncoder.encode, .{ .as_typed_array = true });
pub const encoding = bridge.accessor(TextEncoder.getEncoding, null, .{}); pub const encoding = bridge.property("utf-8", .{ .template = false });
}; };
const testing = @import("../../../testing.zig"); const testing = @import("../../../testing.zig");

View File

@@ -139,14 +139,6 @@ pub fn getMetaKey(self: *const MouseEvent) bool {
return self._meta_key; return self._meta_key;
} }
pub fn getOffsetX(_: *const MouseEvent) f64 {
return 0.0;
}
pub fn getOffsetY(_: *const MouseEvent) f64 {
return 0.0;
}
pub fn getPageX(self: *const MouseEvent) f64 { pub fn getPageX(self: *const MouseEvent) f64 {
// this should be clientX + window.scrollX // this should be clientX + window.scrollX
return self._client_x; return self._client_x;
@@ -189,8 +181,8 @@ pub const JsApi = struct {
pub const clientY = bridge.accessor(getClientY, null, .{}); pub const clientY = bridge.accessor(getClientY, null, .{});
pub const ctrlKey = bridge.accessor(getCtrlKey, null, .{}); pub const ctrlKey = bridge.accessor(getCtrlKey, null, .{});
pub const metaKey = bridge.accessor(getMetaKey, null, .{}); pub const metaKey = bridge.accessor(getMetaKey, null, .{});
pub const offsetX = bridge.accessor(getOffsetX, null, .{}); pub const offsetX = bridge.property(0.0, .{ .template = false });
pub const offsetY = bridge.accessor(getOffsetY, null, .{}); pub const offsetY = bridge.property(0.0, .{ .template = false });
pub const pageX = bridge.accessor(getPageX, null, .{}); pub const pageX = bridge.accessor(getPageX, null, .{});
pub const pageY = bridge.accessor(getPageY, null, .{}); pub const pageY = bridge.accessor(getPageY, null, .{});
pub const relatedTarget = bridge.accessor(getRelatedTarget, null, .{}); pub const relatedTarget = bridge.accessor(getRelatedTarget, null, .{});