Skip to content

Commit c28d87d

Browse files
committed
Improve build and test speed
Test speed has been improved only slightly by tweaking a 2-second running tests. Build has been improved by: 1 - moving logFunctionCallError out of js.Caller and to a standalone function 2 - removing some non-generic code from the generic portions of the logger Caller.getter and Caller.setter have been removed in favor or calling Caller.method. This wasn't previously possible - prior to our v8 upgrade, they had different signatures. Also removed a largely unused parser/str.zig file.
1 parent faebabe commit c28d87d

File tree

7 files changed

+78
-254
lines changed

7 files changed

+78
-254
lines changed

src/browser/cssom/css_style_declaration.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub const CSSStyleDeclaration = struct {
8585
return self.order.items.len;
8686
}
8787

88-
pub fn get_parentRule() ?CSSRule {
88+
pub fn get_parentRule(_: *const CSSStyleDeclaration) ?CSSRule {
8989
return null;
9090
}
9191

src/browser/html/window.zig

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -337,20 +337,15 @@ test "Browser.HTML.Window" {
337337
// Note however that we in this test do not wait as the request is just send to the browser
338338
try runner.testCases(&.{
339339
.{
340-
\\ let start;
340+
\\ let start = 0;
341341
\\ function step(timestamp) {
342-
\\ if (start === undefined) {
343-
\\ start = timestamp;
344-
\\ }
345-
\\ const elapsed = timestamp - start;
346-
\\ if (elapsed < 2000) {
347-
\\ requestAnimationFrame(step);
348-
\\ }
342+
\\ start = timestamp;
349343
\\ }
350344
,
351345
null,
352346
},
353347
.{ "requestAnimationFrame(step);", null }, // returned id is checked in the next test
348+
.{ " start > 0", "true" },
354349
}, .{});
355350

356351
// cancelAnimationFrame should be able to cancel a request with the given id

src/cdp/cdp.zig

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ const json = std.json;
2323
const log = @import("../log.zig");
2424
const App = @import("../app.zig").App;
2525
const Env = @import("../browser/env.zig").Env;
26-
const asUint = @import("../str/parser.zig").asUint;
2726
const Browser = @import("../browser/browser.zig").Browser;
2827
const Session = @import("../browser/session.zig").Session;
2928
const Page = @import("../browser/page.zig").Page;
@@ -182,41 +181,41 @@ pub fn CDPT(comptime TypeProvider: type) type {
182181

183182
switch (domain.len) {
184183
3 => switch (@as(u24, @bitCast(domain[0..3].*))) {
185-
asUint("DOM") => return @import("domains/dom.zig").processMessage(command),
186-
asUint("Log") => return @import("domains/log.zig").processMessage(command),
187-
asUint("CSS") => return @import("domains/css.zig").processMessage(command),
184+
asUint(u24, "DOM") => return @import("domains/dom.zig").processMessage(command),
185+
asUint(u24, "Log") => return @import("domains/log.zig").processMessage(command),
186+
asUint(u24, "CSS") => return @import("domains/css.zig").processMessage(command),
188187
else => {},
189188
},
190189
4 => switch (@as(u32, @bitCast(domain[0..4].*))) {
191-
asUint("Page") => return @import("domains/page.zig").processMessage(command),
190+
asUint(u32, "Page") => return @import("domains/page.zig").processMessage(command),
192191
else => {},
193192
},
194193
5 => switch (@as(u40, @bitCast(domain[0..5].*))) {
195-
asUint("Fetch") => return @import("domains/fetch.zig").processMessage(command),
196-
asUint("Input") => return @import("domains/input.zig").processMessage(command),
194+
asUint(u40, "Fetch") => return @import("domains/fetch.zig").processMessage(command),
195+
asUint(u40, "Input") => return @import("domains/input.zig").processMessage(command),
197196
else => {},
198197
},
199198
6 => switch (@as(u48, @bitCast(domain[0..6].*))) {
200-
asUint("Target") => return @import("domains/target.zig").processMessage(command),
199+
asUint(u48, "Target") => return @import("domains/target.zig").processMessage(command),
201200
else => {},
202201
},
203202
7 => switch (@as(u56, @bitCast(domain[0..7].*))) {
204-
asUint("Browser") => return @import("domains/browser.zig").processMessage(command),
205-
asUint("Runtime") => return @import("domains/runtime.zig").processMessage(command),
206-
asUint("Network") => return @import("domains/network.zig").processMessage(command),
203+
asUint(u56, "Browser") => return @import("domains/browser.zig").processMessage(command),
204+
asUint(u56, "Runtime") => return @import("domains/runtime.zig").processMessage(command),
205+
asUint(u56, "Network") => return @import("domains/network.zig").processMessage(command),
207206
else => {},
208207
},
209208
8 => switch (@as(u64, @bitCast(domain[0..8].*))) {
210-
asUint("Security") => return @import("domains/security.zig").processMessage(command),
209+
asUint(u64, "Security") => return @import("domains/security.zig").processMessage(command),
211210
else => {},
212211
},
213212
9 => switch (@as(u72, @bitCast(domain[0..9].*))) {
214-
asUint("Emulation") => return @import("domains/emulation.zig").processMessage(command),
215-
asUint("Inspector") => return @import("domains/inspector.zig").processMessage(command),
213+
asUint(u72, "Emulation") => return @import("domains/emulation.zig").processMessage(command),
214+
asUint(u72, "Inspector") => return @import("domains/inspector.zig").processMessage(command),
216215
else => {},
217216
},
218217
11 => switch (@as(u88, @bitCast(domain[0..11].*))) {
219-
asUint("Performance") => return @import("domains/performance.zig").processMessage(command),
218+
asUint(u88, "Performance") => return @import("domains/performance.zig").processMessage(command),
220219
else => {},
221220
},
222221
else => {},
@@ -696,6 +695,10 @@ const InputParams = struct {
696695
}
697696
};
698697

698+
fn asUint(comptime T: type, comptime string: []const u8) T {
699+
return @bitCast(string[0..string.len].*);
700+
}
701+
699702
const testing = @import("testing.zig");
700703
test "cdp: invalid json" {
701704
var ctx = testing.context();

src/http/client.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3170,7 +3170,7 @@ test "HttpClient: async tls no body" {
31703170
}
31713171
}
31723172

3173-
test "HttpClient: async tls with body x" {
3173+
test "HttpClient: async tls with body" {
31743174
defer testing.reset();
31753175
for (0..5) |_| {
31763176
var client = try testClient();

src/log.zig

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,16 @@ fn logTo(comptime scope: Scope, level: Level, comptime msg: []const u8, data: an
146146
}
147147

148148
fn logLogfmt(comptime scope: Scope, level: Level, comptime msg: []const u8, data: anytype, writer: anytype) !void {
149+
try logLogFmtPrefix(scope, level, msg, writer);
150+
inline for (@typeInfo(@TypeOf(data)).@"struct".fields) |f| {
151+
const key = " " ++ f.name ++ "=";
152+
try writer.writeAll(key);
153+
try writeValue(.logfmt, @field(data, f.name), writer);
154+
}
155+
try writer.writeByte('\n');
156+
}
157+
158+
fn logLogFmtPrefix(comptime scope: Scope, level: Level, comptime msg: []const u8, writer: anytype) !void {
149159
try writer.writeAll("$time=");
150160
try writer.print("{d}", .{timestamp()});
151161

@@ -164,15 +174,20 @@ fn logLogfmt(comptime scope: Scope, level: Level, comptime msg: []const u8, data
164174
break :blk prefix ++ "\"" ++ msg ++ "\"";
165175
};
166176
try writer.writeAll(full_msg);
177+
}
178+
179+
fn logPretty(comptime scope: Scope, level: Level, comptime msg: []const u8, data: anytype, writer: anytype) !void {
180+
try logPrettyPrefix(scope, level, msg, writer);
167181
inline for (@typeInfo(@TypeOf(data)).@"struct".fields) |f| {
168-
const key = " " ++ f.name ++ "=";
182+
const key = " " ++ f.name ++ " = ";
169183
try writer.writeAll(key);
170-
try writeValue(.logfmt, @field(data, f.name), writer);
184+
try writeValue(.pretty, @field(data, f.name), writer);
185+
try writer.writeByte('\n');
171186
}
172187
try writer.writeByte('\n');
173188
}
174189

175-
fn logPretty(comptime scope: Scope, level: Level, comptime msg: []const u8, data: anytype, writer: anytype) !void {
190+
fn logPrettyPrefix(comptime scope: Scope, level: Level, comptime msg: []const u8, writer: anytype) !void {
176191
if (scope == .console and level == .fatal and comptime std.mem.eql(u8, msg, "lightpanda")) {
177192
try writer.writeAll("\x1b[0;104mWARN ");
178193
} else {
@@ -201,14 +216,6 @@ fn logPretty(comptime scope: Scope, level: Level, comptime msg: []const u8, data
201216
try writer.print(" \x1b[0m[+{d}ms]", .{elapsed()});
202217
try writer.writeByte('\n');
203218
}
204-
205-
inline for (@typeInfo(@TypeOf(data)).@"struct".fields) |f| {
206-
const key = " " ++ f.name ++ " = ";
207-
try writer.writeAll(key);
208-
try writeValue(.pretty, @field(data, f.name), writer);
209-
try writer.writeByte('\n');
210-
}
211-
try writer.writeByte('\n');
212219
}
213220

214221
pub fn writeValue(comptime format: Format, value: anytype, writer: anytype) !void {

src/runtime/js.zig

Lines changed: 37 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,7 +1876,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
18761876
defer caller.deinit();
18771877

18781878
const named_function = comptime NamedFunction.init(Struct, "get_" ++ name);
1879-
caller.getter(Struct, named_function, info) catch |err| {
1879+
caller.method(Struct, named_function, info) catch |err| {
18801880
caller.handleError(Struct, named_function, err, info);
18811881
};
18821882
}
@@ -1891,13 +1891,13 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
18911891
const setter_callback = v8.FunctionTemplate.initCallback(isolate, struct {
18921892
fn callback(raw_info: ?*const v8.C_FunctionCallbackInfo) callconv(.c) void {
18931893
const info = v8.FunctionCallbackInfo.initFromV8(raw_info);
1894+
std.debug.assert(info.length() == 1);
1895+
18941896
var caller = Caller(Self, State).init(info);
18951897
defer caller.deinit();
18961898

1897-
std.debug.assert(info.length() == 1);
1898-
const js_value = info.getArg(0);
18991899
const named_function = comptime NamedFunction.init(Struct, "set_" ++ name);
1900-
caller.setter(Struct, named_function, js_value, info) catch |err| {
1900+
caller.method(Struct, named_function, info) catch |err| {
19011901
caller.handleError(Struct, named_function, err, info);
19021902
};
19031903
}
@@ -2424,66 +2424,6 @@ fn Caller(comptime E: type, comptime State: type) type {
24242424
info.getReturnValue().set(try js_context.zigValueToJs(res));
24252425
}
24262426

2427-
fn getter(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, info: v8.FunctionCallbackInfo) !void {
2428-
const js_context = self.js_context;
2429-
const func = @field(Struct, named_function.name);
2430-
const Getter = @TypeOf(func);
2431-
if (@typeInfo(Getter).@"fn".return_type == null) {
2432-
@compileError(@typeName(Struct) ++ " has a getter without a return type: " ++ @typeName(Getter));
2433-
}
2434-
2435-
var args: ParamterTypes(Getter) = undefined;
2436-
const arg_fields = @typeInfo(@TypeOf(args)).@"struct".fields;
2437-
switch (arg_fields.len) {
2438-
0 => {}, // getters _can_ be parameterless
2439-
1, 2 => {
2440-
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(Struct), info.getThis());
2441-
comptime assertSelfReceiver(Struct, named_function);
2442-
@field(args, "0") = zig_instance;
2443-
if (comptime arg_fields.len == 2) {
2444-
comptime assertIsStateArg(Struct, named_function, 1);
2445-
@field(args, "1") = js_context.state;
2446-
}
2447-
},
2448-
else => @compileError(named_function.full_name + " has too many parmaters: " ++ @typeName(named_function.func)),
2449-
}
2450-
const res = @call(.auto, func, args);
2451-
info.getReturnValue().set(try js_context.zigValueToJs(res));
2452-
}
2453-
2454-
fn setter(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, js_value: v8.Value, info: v8.FunctionCallbackInfo) !void {
2455-
const js_context = self.js_context;
2456-
const func = @field(Struct, named_function.name);
2457-
comptime assertSelfReceiver(Struct, named_function);
2458-
2459-
const zig_instance = try E.typeTaggedAnyOpaque(named_function, *Receiver(Struct), info.getThis());
2460-
2461-
const Setter = @TypeOf(func);
2462-
var args: ParamterTypes(Setter) = undefined;
2463-
const arg_fields = @typeInfo(@TypeOf(args)).@"struct".fields;
2464-
switch (arg_fields.len) {
2465-
0 => unreachable, // assertSelfReceiver make sure of this
2466-
1 => @compileError(named_function.full_name ++ " only has 1 parameter"),
2467-
2, 3 => {
2468-
@field(args, "0") = zig_instance;
2469-
@field(args, "1") = try js_context.jsValueToZig(named_function, arg_fields[1].type, js_value);
2470-
if (comptime arg_fields.len == 3) {
2471-
comptime assertIsStateArg(Struct, named_function, 2);
2472-
@field(args, "2") = js_context.state;
2473-
}
2474-
},
2475-
else => @compileError(named_function.full_name ++ " setter with more than 3 parameters, why?"),
2476-
}
2477-
2478-
if (@typeInfo(Setter).@"fn".return_type) |return_type| {
2479-
if (@typeInfo(return_type) == .error_union) {
2480-
_ = try @call(.auto, func, args);
2481-
return;
2482-
}
2483-
}
2484-
_ = @call(.auto, func, args);
2485-
}
2486-
24872427
fn getIndex(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, idx: u32, info: v8.PropertyCallbackInfo) !u8 {
24882428
const js_context = self.js_context;
24892429
const func = @field(Struct, named_function.name);
@@ -2596,13 +2536,7 @@ fn Caller(comptime E: type, comptime State: type) type {
25962536

25972537
if (comptime builtin.mode == .Debug and @hasDecl(@TypeOf(info), "length")) {
25982538
if (log.enabled(.js, .warn)) {
2599-
const args_dump = self.serializeFunctionArgs(info) catch "failed to serialize args";
2600-
log.warn(.js, "function call error", .{
2601-
.name = named_function.full_name,
2602-
.err = err,
2603-
.args = args_dump,
2604-
.stack = stackForLogs(self.call_arena, isolate) catch |err1| @errorName(err1),
2605-
});
2539+
logFunctionCallError(self.call_arena, self.isolate, self.v8_context, err, named_function.full_name, info);
26062540
}
26072541
}
26082542

@@ -2670,6 +2604,7 @@ fn Caller(comptime E: type, comptime State: type) type {
26702604
// Does the error we want to return belong to the custom exeception's ErrorSet
26712605
fn isErrorSetException(comptime Exception: type, err: anytype) bool {
26722606
const Entry = std.meta.Tuple(&.{ []const u8, void });
2607+
26732608
const error_set = @typeInfo(Exception.ErrorSet).error_set.?;
26742609
const entries = comptime blk: {
26752610
var kv: [error_set.len]Entry = undefined;
@@ -2808,28 +2743,6 @@ fn Caller(comptime E: type, comptime State: type) type {
28082743
const Const_State = if (ti == .pointer) *const ti.pointer.child else State;
28092744
return T == State or T == Const_State;
28102745
}
2811-
2812-
fn serializeFunctionArgs(self: *const Self, info: anytype) ![]const u8 {
2813-
const isolate = self.isolate;
2814-
const v8_context = self.v8_context;
2815-
const arena = self.call_arena;
2816-
const separator = log.separator();
2817-
const js_parameter_count = info.length();
2818-
2819-
var arr: std.ArrayListUnmanaged(u8) = .{};
2820-
for (0..js_parameter_count) |i| {
2821-
const js_value = info.getArg(@intCast(i));
2822-
const value_string = try valueToDetailString(arena, js_value, isolate, v8_context);
2823-
const value_type = try jsStringToZig(arena, try js_value.typeOf(isolate), isolate);
2824-
try std.fmt.format(arr.writer(arena), "{s}{d}: {s} ({s})", .{
2825-
separator,
2826-
i + 1,
2827-
value_string,
2828-
value_type,
2829-
});
2830-
}
2831-
return arr.items;
2832-
}
28332746
};
28342747
}
28352748

@@ -3270,6 +3183,37 @@ const NamedFunction = struct {
32703183
}
32713184
};
32723185

3186+
// This is extracted to speed up compilation. When left inlined in handleError,
3187+
// this can add as much as 10 seconds of compilation time.
3188+
fn logFunctionCallError(arena: Allocator, isolate: v8.Isolate, context: v8.Context, err: anyerror, function_name: []const u8, info: v8.FunctionCallbackInfo) void {
3189+
const args_dump = serializeFunctionArgs(arena, isolate, context, info) catch "failed to serialize args";
3190+
log.warn(.js, "function call error", .{
3191+
.name = function_name,
3192+
.err = err,
3193+
.args = args_dump,
3194+
.stack = stackForLogs(arena, isolate) catch |err1| @errorName(err1),
3195+
});
3196+
}
3197+
3198+
fn serializeFunctionArgs(arena: Allocator, isolate: v8.Isolate, context: v8.Context, info: v8.FunctionCallbackInfo) ![]const u8 {
3199+
const separator = log.separator();
3200+
const js_parameter_count = info.length();
3201+
3202+
var arr: std.ArrayListUnmanaged(u8) = .{};
3203+
for (0..js_parameter_count) |i| {
3204+
const js_value = info.getArg(@intCast(i));
3205+
const value_string = try valueToDetailString(arena, js_value, isolate, context);
3206+
const value_type = try jsStringToZig(arena, try js_value.typeOf(isolate), isolate);
3207+
try std.fmt.format(arr.writer(arena), "{s}{d}: {s} ({s})", .{
3208+
separator,
3209+
i + 1,
3210+
value_string,
3211+
value_type,
3212+
});
3213+
}
3214+
return arr.items;
3215+
}
3216+
32733217
// This is called from V8. Whenever the v8 inspector has to describe a value
32743218
// it'll call this function to gets its [optional] subtype - which, from V8's
32753219
// point of view, is an arbitrary string.

0 commit comments

Comments
 (0)