From dcde306de7424b49135ea72f40c07f3e0e545cd0 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 3 Dec 2025 16:50:51 +0300 Subject: [PATCH 1/3] support overloads of `Performance#measure` --- src/browser/webapi/Performance.zig | 116 +++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 22 deletions(-) diff --git a/src/browser/webapi/Performance.zig b/src/browser/webapi/Performance.zig index dbd2c4f84..b259b3e0e 100644 --- a/src/browser/webapi/Performance.zig +++ b/src/browser/webapi/Performance.zig @@ -48,8 +48,82 @@ pub fn mark(self: *Performance, name: []const u8, _options: ?Mark.Options, page: return m; } -pub fn measure(self: *Performance, name: []const u8, _options: ?Measure.Options, page: *Page) !*Measure { - const m = try Measure.init(name, _options, page); +const MeasureOptionsOrStartMark = union(enum) { + measure_options: Measure.Options, + start_mark: []const u8, +}; + +pub fn measure( + self: *Performance, + name: []const u8, + maybe_options_or_start: ?MeasureOptionsOrStartMark, + maybe_end_mark: ?[]const u8, + page: *Page, +) !*Measure { + const perf = &page.window._performance; + if (maybe_options_or_start) |options_or_start| switch (options_or_start) { + .measure_options => |options| { + // Get start timestamp. + const start_timestamp = blk: { + if (options.start) |timestamp_or_mark| { + break :blk switch (timestamp_or_mark) { + .timestamp => |timestamp| timestamp, + .mark => |mark_name| try self.getMarkTime(mark_name), + }; + } + + break :blk 0.0; + }; + + // Get end timestamp. + const end_timestamp = blk: { + if (options.end) |timestamp_or_mark| { + break :blk switch (timestamp_or_mark) { + .timestamp => |timestamp| timestamp, + .mark => |mark_name| try self.getMarkTime(mark_name), + }; + } + + break :blk perf.now(); + }; + + const m = try Measure.init1( + name, + options.detail, + start_timestamp, + end_timestamp, + options.duration, + page, + ); + try self._entries.append(page.arena, m._proto); + return m; + }, + .start_mark => |start_mark| { + // Get start timestamp. + const start_timestamp = try self.getMarkTime(start_mark); + // Get end timestamp. + const end_timestamp = blk: { + if (maybe_end_mark) |mark_name| { + break :blk try self.getMarkTime(mark_name); + } + + break :blk perf.now(); + }; + + const m = try Measure.init1( + name, + null, + start_timestamp, + end_timestamp, + null, + page, + ); + try self._entries.append(page.arena, m._proto); + return m; + }, + }; + + const m = try Measure.init1(name, null, 0.0, perf.now(), null, page); try self._entries.append(page.arena, m._proto); return m; } @@ -259,39 +333,37 @@ pub const Measure = struct { const Options = struct { detail: ?js.Object = null, - start: ?[]const u8 = null, - end: ?[]const u8 = null, + start: ?TimestampOrMark, + end: ?TimestampOrMark, duration: ?f64 = null, - }; - - pub fn init(name: []const u8, _opts: ?Options, page: *Page) !*Measure { - const opts = _opts orelse Options{}; - const perf = &page.window._performance; - const start_time = if (opts.start) |start_mark| - try perf.getMarkTime(start_mark) - else - 0.0; - - const end_time = if (opts.end) |end_mark| - try perf.getMarkTime(end_mark) - else - perf.now(); - - const duration = opts.duration orelse (end_time - start_time); + const TimestampOrMark = union(enum) { + timestamp: f64, + mark: []const u8, + }; + }; + pub fn init( + name: []const u8, + maybe_detail: ?js.Object, + start_timestamp: f64, + end_timestamp: f64, + maybe_duration: ?f64, + page: *Page, + ) !*Measure { + const duration = maybe_duration orelse (end_timestamp - start_timestamp); if (duration < 0.0) { return error.TypeError; } - const detail = if (opts.detail) |d| try d.persist() else null; + const detail = if (maybe_detail) |d| try d.persist() else null; const m = try page._factory.create(Measure{ ._proto = undefined, ._detail = detail, }); const entry = try page._factory.create(Entry{ - ._start_time = start_time, + ._start_time = start_timestamp, ._duration = duration, ._name = try page.dupeString(name), ._type = .{ .measure = m }, From 51d147746803011f29037dcd59f5adc04368af0d Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 3 Dec 2025 16:53:30 +0300 Subject: [PATCH 2/3] `init1` => `init` --- src/browser/webapi/Performance.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/browser/webapi/Performance.zig b/src/browser/webapi/Performance.zig index b259b3e0e..1d7ba3de9 100644 --- a/src/browser/webapi/Performance.zig +++ b/src/browser/webapi/Performance.zig @@ -87,7 +87,7 @@ pub fn measure( break :blk perf.now(); }; - const m = try Measure.init1( + const m = try Measure.init( name, options.detail, start_timestamp, @@ -110,7 +110,7 @@ pub fn measure( break :blk perf.now(); }; - const m = try Measure.init1( + const m = try Measure.init( name, null, start_timestamp, @@ -123,7 +123,7 @@ pub fn measure( }, }; - const m = try Measure.init1(name, null, 0.0, perf.now(), null, page); + const m = try Measure.init(name, null, 0.0, perf.now(), null, page); try self._entries.append(page.arena, m._proto); return m; } From c2218d776edfc883e902d809c76a3bdc0fa25b3b Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Thu, 4 Dec 2025 18:11:31 +0300 Subject: [PATCH 3/3] support `navigationStart` in `getMarkTime` Turns out this is just an alias to 0. --- src/browser/webapi/Performance.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/browser/webapi/Performance.zig b/src/browser/webapi/Performance.zig index 1d7ba3de9..f3823372d 100644 --- a/src/browser/webapi/Performance.zig +++ b/src/browser/webapi/Performance.zig @@ -195,6 +195,13 @@ fn getMarkTime(self: *const Performance, mark_name: []const u8) !f64 { return entry._start_time; } } + + // Recognized mark names by browsers. `navigationStart` is an equivalent + // to 0. Others are dependant to request arrival, end of request etc. + if (std.mem.eql(u8, "navigationStart", mark_name)) { + return 0; + } + return error.SyntaxError; // Mark not found }