mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 06:23:45 +00:00
Re-enable cached property support
The idea is that frequently accessed properties, e.g. window.document, can be cached directly as data properties on the underlying v8::Object, removing the need for the access call into Zig. This is only used on a handful of properties, almost all of which are on the Window. It is important that the property be read-only. For example, window.location cannot be cached this way because window.location is writable (e.g. window.location.hash = '#blah'). This existed briefly before Zigdom, but was removed as part of the migration. The implementation has changed. This previously relied on a "postAttach" feature which no longer exists. It is not integrated in the bridge/callback directly and lazily applied after the first access.
This commit is contained in:
@@ -82,6 +82,7 @@ pub fn deinit(self: *Caller) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const CallOpts = struct {
|
pub const CallOpts = struct {
|
||||||
|
cache: ?[]const u8 = null,
|
||||||
dom_exception: bool = false,
|
dom_exception: bool = false,
|
||||||
null_as_undefined: bool = false,
|
null_as_undefined: bool = false,
|
||||||
as_typed_array: bool = false,
|
as_typed_array: bool = false,
|
||||||
@@ -150,9 +151,27 @@ pub fn method(self: *Caller, comptime T: type, func: anytype, handle: *const v8.
|
|||||||
fn _method(self: *Caller, comptime T: type, func: anytype, info: FunctionCallbackInfo, comptime opts: CallOpts) !void {
|
fn _method(self: *Caller, comptime T: type, func: anytype, info: FunctionCallbackInfo, comptime opts: CallOpts) !void {
|
||||||
const F = @TypeOf(func);
|
const F = @TypeOf(func);
|
||||||
var args = try self.getArgs(F, 1, info);
|
var args = try self.getArgs(F, 1, info);
|
||||||
@field(args, "0") = try TaggedOpaque.fromJS(*T, info.getThis());
|
|
||||||
|
const js_this = info.getThis();
|
||||||
|
@field(args, "0") = try TaggedOpaque.fromJS(*T, js_this);
|
||||||
|
|
||||||
const res = @call(.auto, func, args);
|
const res = @call(.auto, func, args);
|
||||||
info.getReturnValue().set(try self.local.zigValueToJs(res, opts));
|
|
||||||
|
const mapped = try self.local.zigValueToJs(res, opts);
|
||||||
|
const return_value = info.getReturnValue();
|
||||||
|
return_value.set(mapped);
|
||||||
|
|
||||||
|
if (comptime opts.cache != null) {
|
||||||
|
// store the return value directly in the JS object for faster subsequent
|
||||||
|
// calls. We only do this for a few frequently used properties (e.g. window.document)
|
||||||
|
const local = self.local;
|
||||||
|
const key_handle = local.isolate.initStringHandle(opts.cache.?);
|
||||||
|
var out: v8.MaybeBool = undefined;
|
||||||
|
v8.v8__Object__DefineOwnProperty(js_this, local.handle, key_handle, mapped.handle, 0, &out);
|
||||||
|
if (comptime IS_DEBUG) {
|
||||||
|
std.debug.assert(out.has_value and out.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function(self: *Caller, comptime T: type, func: anytype, handle: *const v8.FunctionCallbackInfo, comptime opts: CallOpts) void {
|
pub fn function(self: *Caller, comptime T: type, func: anytype, handle: *const v8.FunctionCallbackInfo, comptime opts: CallOpts) void {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
|
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||||
//
|
//
|
||||||
// Francis Bouvier <francis@lightpanda.io>
|
// Francis Bouvier <francis@lightpanda.io>
|
||||||
// Pierre Tachoire <pierre@lightpanda.io>
|
// Pierre Tachoire <pierre@lightpanda.io>
|
||||||
@@ -164,7 +164,7 @@ pub const Accessor = struct {
|
|||||||
|
|
||||||
const Opts = struct {
|
const Opts = struct {
|
||||||
static: bool = false,
|
static: bool = false,
|
||||||
cache: ?[]const u8 = null, // @ZIGDOM
|
cache: ?[]const u8 = null,
|
||||||
as_typed_array: bool = false,
|
as_typed_array: bool = false,
|
||||||
null_as_undefined: bool = false,
|
null_as_undefined: bool = false,
|
||||||
};
|
};
|
||||||
@@ -184,11 +184,13 @@ pub const Accessor = struct {
|
|||||||
|
|
||||||
if (comptime opts.static) {
|
if (comptime opts.static) {
|
||||||
caller.function(T, getter, handle.?, .{
|
caller.function(T, getter, handle.?, .{
|
||||||
|
.cache = opts.cache,
|
||||||
.as_typed_array = opts.as_typed_array,
|
.as_typed_array = opts.as_typed_array,
|
||||||
.null_as_undefined = opts.null_as_undefined,
|
.null_as_undefined = opts.null_as_undefined,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
caller.method(T, getter, handle.?, .{
|
caller.method(T, getter, handle.?, .{
|
||||||
|
.cache = opts.cache,
|
||||||
.as_typed_array = opts.as_typed_array,
|
.as_typed_array = opts.as_typed_array,
|
||||||
.null_as_undefined = opts.null_as_undefined,
|
.null_as_undefined = opts.null_as_undefined,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ pub const JsApi = struct {
|
|||||||
pub const applets = bridge.accessor(HTMLDocument.getApplets, null, .{});
|
pub const applets = bridge.accessor(HTMLDocument.getApplets, null, .{});
|
||||||
pub const plugins = bridge.accessor(HTMLDocument.getEmbeds, null, .{});
|
pub const plugins = bridge.accessor(HTMLDocument.getEmbeds, null, .{});
|
||||||
pub const currentScript = bridge.accessor(HTMLDocument.getCurrentScript, null, .{});
|
pub const currentScript = bridge.accessor(HTMLDocument.getCurrentScript, null, .{});
|
||||||
pub const location = bridge.accessor(HTMLDocument.getLocation, HTMLDocument.setLocation, .{ .cache = "location" });
|
pub const location = bridge.accessor(HTMLDocument.getLocation, HTMLDocument.setLocation, .{});
|
||||||
pub const all = bridge.accessor(HTMLDocument.getAll, null, .{});
|
pub const all = bridge.accessor(HTMLDocument.getAll, null, .{});
|
||||||
pub const cookie = bridge.accessor(HTMLDocument.getCookie, HTMLDocument.setCookie, .{});
|
pub const cookie = bridge.accessor(HTMLDocument.getCookie, HTMLDocument.setCookie, .{});
|
||||||
pub const doctype = bridge.accessor(HTMLDocument.getDocType, null, .{});
|
pub const doctype = bridge.accessor(HTMLDocument.getDocType, null, .{});
|
||||||
|
|||||||
@@ -651,7 +651,7 @@ pub const JsApi = struct {
|
|||||||
pub const localStorage = bridge.accessor(Window.getLocalStorage, null, .{ .cache = "localStorage" });
|
pub const localStorage = bridge.accessor(Window.getLocalStorage, null, .{ .cache = "localStorage" });
|
||||||
pub const sessionStorage = bridge.accessor(Window.getSessionStorage, null, .{ .cache = "sessionStorage" });
|
pub const sessionStorage = bridge.accessor(Window.getSessionStorage, null, .{ .cache = "sessionStorage" });
|
||||||
pub const document = bridge.accessor(Window.getDocument, null, .{ .cache = "document" });
|
pub const document = bridge.accessor(Window.getDocument, null, .{ .cache = "document" });
|
||||||
pub const location = bridge.accessor(Window.getLocation, Window.setLocation, .{ .cache = "location" });
|
pub const location = bridge.accessor(Window.getLocation, Window.setLocation, .{});
|
||||||
pub const history = bridge.accessor(Window.getHistory, null, .{});
|
pub const history = bridge.accessor(Window.getHistory, null, .{});
|
||||||
pub const navigation = bridge.accessor(Window.getNavigation, null, .{});
|
pub const navigation = bridge.accessor(Window.getNavigation, null, .{});
|
||||||
pub const crypto = bridge.accessor(Window.getCrypto, null, .{ .cache = "crypto" });
|
pub const crypto = bridge.accessor(Window.getCrypto, null, .{ .cache = "crypto" });
|
||||||
|
|||||||
Reference in New Issue
Block a user