Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/browser/dom/dom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const IntersectionObserver = @import("intersection_observer.zig");
const DOMParser = @import("dom_parser.zig").DOMParser;
const TreeWalker = @import("tree_walker.zig").TreeWalker;
const NodeFilter = @import("node_filter.zig").NodeFilter;
const Performance = @import("performance.zig").Performance;
const PerformanceObserver = @import("performance_observer.zig").PerformanceObserver;

pub const Interfaces = .{
Expand All @@ -46,6 +45,6 @@ pub const Interfaces = .{
DOMParser,
TreeWalker,
NodeFilter,
Performance,
@import("performance.zig").Interfaces,
PerformanceObserver,
};
116 changes: 116 additions & 0 deletions src/browser/dom/performance.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ const std = @import("std");

const parser = @import("../netsurf.zig");
const EventTarget = @import("../dom/event_target.zig").EventTarget;
const Env = @import("../env.zig").Env;
const Page = @import("../page.zig").Page;

pub const Interfaces = .{
Performance,
PerformanceEntry,
PerformanceMark,
};

const MarkOptions = struct {
detail: ?Env.JsObject = null,
start_time: ?f64 = null,
};

// https://developer.mozilla.org/en-US/docs/Web/API/Performance
pub const Performance = struct {
Expand Down Expand Up @@ -52,6 +65,93 @@ pub const Performance = struct {
pub fn _now(self: *Performance) f64 {
return limitedResolutionMs(self.time_origin.read());
}

pub fn _mark(_: *Performance, name: []const u8, _options: ?MarkOptions, page: *Page) !PerformanceMark {
const mark: PerformanceMark = try .constructor(name, _options, page);
// TODO: Should store this in an entries list
return mark;
}
};

// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry
pub const PerformanceEntry = struct {
const PerformanceEntryType = enum {
element,
event,
first_input,
largest_contentful_paint,
layout_shift,
long_animation_frame,
longtask,
mark,
measure,
navigation,
paint,
resource,
taskattribution,
visibility_state,

pub fn toString(self: PerformanceEntryType) []const u8 {
return switch (self) {
.first_input => "first-input",
.largest_contentful_paint => "largest-contentful-paint",
.layout_shift => "layout-shift",
.long_animation_frame => "long-animation-frame",
.visibility_state => "visibility-state",
else => @tagName(self),
};
}
};

duration: f64 = 0.0,
entry_type: PerformanceEntryType,
name: []const u8,
start_time: f64 = 0.0,

pub fn get_duration(self: *const PerformanceEntry) f64 {
return self.duration;
}

pub fn get_entryType(self: *const PerformanceEntry) PerformanceEntryType {
return self.entry_type;
}

pub fn get_name(self: *const PerformanceEntry) []const u8 {
return self.name;
}

pub fn get_startTime(self: *const PerformanceEntry) f64 {
return self.start_time;
}
};

// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMark
pub const PerformanceMark = struct {
pub const prototype = *PerformanceEntry;

proto: PerformanceEntry,
detail: ?Env.JsObject,

pub fn constructor(name: []const u8, _options: ?MarkOptions, page: *Page) !PerformanceMark {
const perf = &page.window.performance;

const options = _options orelse MarkOptions{};
const start_time = options.start_time orelse perf._now();
const detail = if (options.detail) |d| try d.persist() else null;

if (start_time < 0.0) {
return error.TypeError;
}

const duped_name = try page.arena.dupe(u8, name);
const proto = PerformanceEntry{ .name = duped_name, .entry_type = .mark, .start_time = start_time };

return .{ .proto = proto, .detail = detail };
}

pub fn get_detail(self: *const PerformanceMark) ?Env.JsObject {
return self.detail;
}
};

const testing = @import("./../../testing.zig");
Expand Down Expand Up @@ -85,3 +185,19 @@ test "Performance: now" {
// Check resolution
try testing.expectDelta(@rem(after * std.time.us_per_ms, 100.0), 0.0, 0.1);
}

test "Browser.Performance.Mark" {
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
defer runner.deinit();

try runner.testCases(&.{
.{ "let performance = window.performance", "undefined" },
.{ "performance instanceof Performance", "true" },
.{ "let mark = performance.mark(\"start\")", "undefined" },
.{ "mark instanceof PerformanceMark", "true" },
.{ "mark.name", "start" },
.{ "mark.entryType", "mark" },
.{ "mark.duration", "0" },
.{ "mark.detail", "null" },
}, .{});
}
8 changes: 7 additions & 1 deletion src/runtime/js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2201,7 +2201,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {

const T = @TypeOf(value);
switch (@typeInfo(T)) {
.void, .bool, .int, .comptime_int, .float, .comptime_float => {
.void, .bool, .int, .comptime_int, .float, .comptime_float, .@"enum" => {
// Need to do this to keep the compiler happy
// simpleZigValueToJs handles all of these cases.
unreachable;
Expand Down Expand Up @@ -3084,6 +3084,12 @@ fn simpleZigValueToJs(isolate: v8.Isolate, value: anytype, comptime fail: bool)
}
},
.@"union" => return simpleZigValueToJs(isolate, std.meta.activeTag(value), fail),
.@"enum" => {
const T = @TypeOf(value);
if (@hasDecl(T, "toString")) {
return simpleZigValueToJs(isolate, value.toString(), fail);
}
},
else => {},
}
if (fail) {
Expand Down