Skip to content

Commit 5dcc3db

Browse files
authored
Merge pull request #795 from lightpanda-io/performance_observer
Add dummy PerformanceObserver
2 parents ef9f828 + c5d49a9 commit 5dcc3db

File tree

6 files changed

+90
-6
lines changed

6 files changed

+90
-6
lines changed

src/browser/dom/dom.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ const IntersectionObserver = @import("intersection_observer.zig");
2828
const DOMParser = @import("dom_parser.zig").DOMParser;
2929
const TreeWalker = @import("tree_walker.zig").TreeWalker;
3030
const NodeFilter = @import("node_filter.zig").NodeFilter;
31+
const Performance = @import("performance.zig").Performance;
32+
const PerformanceObserver = @import("performance_observer.zig").PerformanceObserver;
3133

3234
pub const Interfaces = .{
3335
DOMException,
@@ -44,4 +46,6 @@ pub const Interfaces = .{
4446
DOMParser,
4547
TreeWalker,
4648
NodeFilter,
49+
Performance,
50+
PerformanceObserver,
4751
};
File renamed without changes.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <francis@lightpanda.io>
4+
// Pierre Tachoire <pierre@lightpanda.io>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
21+
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver
22+
pub const PerformanceObserver = struct {
23+
pub const _supportedEntryTypes = [0][]const u8{};
24+
};
25+
26+
const testing = @import("../../testing.zig");
27+
test "Browser.DOM.PerformanceObserver" {
28+
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
29+
defer runner.deinit();
30+
31+
try runner.testCases(&.{
32+
.{ "PerformanceObserver.supportedEntryTypes.length", "0" },
33+
}, .{});
34+
}

src/browser/html/html.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ const Navigator = @import("navigator.zig").Navigator;
2424
const History = @import("history.zig").History;
2525
const Location = @import("location.zig").Location;
2626
const MediaQueryList = @import("media_query_list.zig").MediaQueryList;
27-
const Performance = @import("performance.zig").Performance;
2827

2928
pub const Interfaces = .{
3029
HTMLDocument,
@@ -37,6 +36,5 @@ pub const Interfaces = .{
3736
History,
3837
Location,
3938
MediaQueryList,
40-
Performance,
4139
@import("screen.zig").Interfaces,
4240
};

src/browser/html/window.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const Crypto = @import("../crypto/crypto.zig").Crypto;
3131
const Console = @import("../console/console.zig").Console;
3232
const EventTarget = @import("../dom/event_target.zig").EventTarget;
3333
const MediaQueryList = @import("media_query_list.zig").MediaQueryList;
34-
const Performance = @import("performance.zig").Performance;
34+
const Performance = @import("../dom/performance.zig").Performance;
3535
const CSSStyleDeclaration = @import("../cssom/css_style_declaration.zig").CSSStyleDeclaration;
3636
const CustomElementRegistry = @import("../webcomponents/custom_element_registry.zig").CustomElementRegistry;
3737
const Screen = @import("screen.zig").Screen;

src/runtime/js.zig

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
337337
const env = self.env;
338338
const isolate = env.isolate;
339339
const Global = @TypeOf(global.*);
340+
const templates = &self.env.templates;
340341

341342
var v8_context: v8.Context = blk: {
342343
var temp_scope: v8.HandleScope = undefined;
@@ -351,7 +352,6 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
351352

352353
// All the FunctionTemplates that we created and setup in Env.init
353354
// are now going to get associated with our global instance.
354-
const templates = &self.env.templates;
355355
inline for (Types, 0..) |s, i| {
356356
const Struct = s.defaultValue().?;
357357
const class_name = v8.String.initUtf8(isolate, comptime classNameForStruct(Struct));
@@ -463,6 +463,38 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
463463
}
464464
}
465465

466+
// Primitive attributes are set directly on the FunctionTemplate
467+
// when we setup the environment. But we cannot set more complex
468+
// types (v8 will crash).
469+
//
470+
// Plus, just to create more complex types, we always need a
471+
// context, i.e. an Array has to have a Context to exist.
472+
//
473+
// As far as I can tell, getting the FunctionTemplate's object
474+
// and setting values directly on it, for each context, is the
475+
// way to do this.
476+
inline for (Types, 0..) |s, i| {
477+
const Struct = s.defaultValue().?;
478+
inline for (@typeInfo(Struct).@"struct".decls) |declaration| {
479+
const name = declaration.name;
480+
if (comptime name[0] == '_') {
481+
const value = @field(Struct, name);
482+
483+
if (comptime isComplexAttributeType(@typeInfo(@TypeOf(value)))) {
484+
const js_obj = templates[i].getFunction(v8_context).toObject();
485+
const js_name = v8.String.initUtf8(isolate, name[1..]).toName();
486+
const js_val = try js_context.zigValueToJs(value);
487+
if (!js_obj.setValue(v8_context, js_name, js_val)) {
488+
log.fatal(.app, "set class attribute", .{
489+
.@"struct" = @typeName(Struct),
490+
.name = name,
491+
});
492+
}
493+
}
494+
}
495+
}
496+
}
497+
466498
_ = try js_context._mapZigInstanceToJs(v8_context.getGlobal(), global);
467499
return js_context;
468500
}
@@ -1809,7 +1841,9 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
18091841
if (comptime name[0] == '_') {
18101842
switch (@typeInfo(@TypeOf(@field(Struct, name)))) {
18111843
.@"fn" => generateMethod(Struct, name, isolate, template_proto),
1812-
else => generateAttribute(Struct, name, isolate, template, template_proto),
1844+
else => |ti| if (!comptime isComplexAttributeType(ti)) {
1845+
generateAttribute(Struct, name, isolate, template, template_proto);
1846+
},
18131847
}
18141848
} else if (comptime std.mem.startsWith(u8, name, "get_")) {
18151849
generateProperty(Struct, name[4..], isolate, template_proto);
@@ -1930,7 +1964,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
19301964
// apply it both to the type itself
19311965
template.set(js_name, js_value, v8.PropertyAttribute.ReadOnly + v8.PropertyAttribute.DontDelete);
19321966

1933-
// andto instances of the type
1967+
// and to instances of the type
19341968
template_proto.set(js_name, js_value, v8.PropertyAttribute.ReadOnly + v8.PropertyAttribute.DontDelete);
19351969
}
19361970

@@ -2396,6 +2430,20 @@ fn isEmpty(comptime T: type) bool {
23962430
return @typeInfo(T) != .@"opaque" and @sizeOf(T) == 0 and @hasDecl(T, "js_legacy_factory") == false;
23972431
}
23982432

2433+
// Attributes that return a primitive type are setup directly on the
2434+
// FunctionTemplate when the Env is setup. More complex types need a v8.Context
2435+
// and cannot be set directly on the FunctionTemplate.
2436+
// We default to saying types are primitives because that's mostly what
2437+
// we have. If we add a new complex type that isn't explictly handled here,
2438+
// we'll get a compiler error in simpleZigValueToJs, and can then explicitly
2439+
// add the type here.
2440+
fn isComplexAttributeType(ti: std.builtin.Type) bool {
2441+
return switch (ti) {
2442+
.array => true,
2443+
else => false,
2444+
};
2445+
}
2446+
23992447
// Responsible for calling Zig functions from JS invokations. This could
24002448
// probably just contained in ExecutionWorld, but having this specific logic, which
24012449
// is somewhat repetitive between constructors, functions, getters, etc contained

0 commit comments

Comments
 (0)