Merge pull request #480 from lightpanda-io/zig-0.14

Zig 0.14
This commit is contained in:
Pierre Tachoire
2025-03-19 17:06:57 +01:00
committed by GitHub
28 changed files with 91 additions and 210 deletions

View File

@@ -5,7 +5,7 @@ inputs:
zig: zig:
description: 'Zig version to install' description: 'Zig version to install'
required: false required: false
default: '0.13.0' default: '0.14.0'
arch: arch:
description: 'CPU arch used to select the v8 lib' description: 'CPU arch used to select the v8 lib'
required: false required: false

View File

@@ -1,7 +1,7 @@
name: zig-fmt name: zig-fmt
env: env:
ZIG_VERSION: 0.13.0 ZIG_VERSION: 0.14.0
on: on:
pull_request: pull_request:

2
.gitmodules vendored
View File

@@ -1,6 +1,7 @@
[submodule "vendor/zig-js-runtime"] [submodule "vendor/zig-js-runtime"]
path = vendor/zig-js-runtime path = vendor/zig-js-runtime
url = https://github.com/lightpanda-io/zig-js-runtime.git/ url = https://github.com/lightpanda-io/zig-js-runtime.git/
branch = zig-0.14
[submodule "vendor/netsurf/libwapcaplet"] [submodule "vendor/netsurf/libwapcaplet"]
path = vendor/netsurf/libwapcaplet path = vendor/netsurf/libwapcaplet
url = https://github.com/lightpanda-io/libwapcaplet.git/ url = https://github.com/lightpanda-io/libwapcaplet.git/
@@ -28,3 +29,4 @@
[submodule "vendor/zig-async-io"] [submodule "vendor/zig-async-io"]
path = vendor/zig-async-io path = vendor/zig-async-io
url = https://github.com/lightpanda-io/zig-async-io.git/ url = https://github.com/lightpanda-io/zig-async-io.git/
branch = zig-0.14

View File

@@ -1,7 +1,7 @@
FROM ubuntu:24.04 FROM ubuntu:24.04
ARG MINISIG=0.12 ARG MINISIG=0.12
ARG ZIG=0.13.0 ARG ZIG=0.14.0
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
ARG ARCH=x86_64 ARG ARCH=x86_64
ARG V8=11.1.134 ARG V8=11.1.134

View File

@@ -140,7 +140,7 @@ You can also follow the progress of our Javascript support in our dedicated [zig
### Prerequisites ### Prerequisites
Lightpanda is written with [Zig](https://ziglang.org/) `0.13.0`. You have to Lightpanda is written with [Zig](https://ziglang.org/) `0.14.0`. You have to
install it with the right version in order to build the project. install it with the right version in order to build the project.
Lightpanda also depends on Lightpanda also depends on

View File

@@ -108,7 +108,7 @@ pub fn build(b: *std.Build) !void {
// compile // compile
const tests = b.addTest(.{ const tests = b.addTest(.{
.root_source_file = b.path("src/main_tests.zig"), .root_source_file = b.path("src/main_tests.zig"),
.test_runner = b.path("src/main_tests.zig"), .test_runner = .{ .path = b.path("src/main_tests.zig"), .mode = .simple },
.target = target, .target = target,
.optimize = mode, .optimize = mode,
}); });
@@ -134,7 +134,7 @@ pub fn build(b: *std.Build) !void {
// compile // compile
const unit_tests = b.addTest(.{ const unit_tests = b.addTest(.{
.root_source_file = b.path("src/unit_tests.zig"), .root_source_file = b.path("src/unit_tests.zig"),
.test_runner = b.path("src/unit_tests.zig"), .test_runner = .{ .path = b.path("src/unit_tests.zig"), .mode = .simple },
.target = target, .target = target,
.optimize = mode, .optimize = mode,
}); });
@@ -195,7 +195,7 @@ fn common(
step.root_module.addImport("asyncio", asyncio); step.root_module.addImport("asyncio", asyncio);
const tlsmod = b.addModule("tls", .{ const tlsmod = b.addModule("tls", .{
.root_source_file = b.path("vendor/tls.zig/src/main.zig"), .root_source_file = b.path("vendor/tls.zig/src/root.zig"),
}); });
step.root_module.addImport("tls", tlsmod); step.root_module.addImport("tls", tlsmod);
} }

View File

@@ -156,16 +156,16 @@ pub const Session = struct {
const ContextT = @TypeOf(ctx); const ContextT = @TypeOf(ctx);
const InspectorContainer = switch (@typeInfo(ContextT)) { const InspectorContainer = switch (@typeInfo(ContextT)) {
.Struct => ContextT, .@"struct" => ContextT,
.Pointer => |ptr| ptr.child, .pointer => |ptr| ptr.child,
.Void => NoopInspector, .void => NoopInspector,
else => @compileError("invalid context type"), else => @compileError("invalid context type"),
}; };
// const ctx_opaque = @as(*anyopaque, @ptrCast(ctx)); // const ctx_opaque = @as(*anyopaque, @ptrCast(ctx));
self.inspector = try jsruntime.Inspector.init( self.inspector = try jsruntime.Inspector.init(
arena, arena,
self.env, // TODO: change to 'env' when https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands &self.env,
if (@TypeOf(ctx) == void) @constCast(@ptrCast(&{})) else ctx, if (@TypeOf(ctx) == void) @constCast(@ptrCast(&{})) else ctx,
InspectorContainer.onInspectorResponse, InspectorContainer.onInspectorResponse,
InspectorContainer.onInspectorEvent, InspectorContainer.onInspectorEvent,
@@ -231,7 +231,7 @@ pub const Session = struct {
// load polyfills // load polyfills
// TODO: change to 'env' when https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands // TODO: change to 'env' when https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
try polyfill.load(self.arena.allocator(), self.env); try polyfill.load(self.arena.allocator(), &self.env);
// inspector // inspector
self.contextCreated(page, aux_data); self.contextCreated(page, aux_data);
@@ -264,7 +264,7 @@ pub const Session = struct {
fn contextCreated(self: *Session, page: *Page, aux_data: ?[]const u8) void { fn contextCreated(self: *Session, page: *Page, aux_data: ?[]const u8) void {
log.debug("inspector context created", .{}); log.debug("inspector context created", .{});
self.inspector.contextCreated(self.env, "", page.origin orelse "://", aux_data); self.inspector.contextCreated(&self.env, "", page.origin orelse "://", aux_data);
} }
}; };
@@ -316,7 +316,7 @@ pub const Page = struct {
pub fn wait(self: *Page) !void { pub fn wait(self: *Page) !void {
// try catch // try catch
var try_catch: jsruntime.TryCatch = undefined; var try_catch: jsruntime.TryCatch = undefined;
try_catch.init(self.session.env); try_catch.init(&self.session.env);
defer try_catch.deinit(); defer try_catch.deinit();
self.session.env.wait() catch |err| { self.session.env.wait() catch |err| {
@@ -324,7 +324,7 @@ pub const Page = struct {
if (err == error.EnvNotStarted) return; if (err == error.EnvNotStarted) return;
const arena = self.arena; const arena = self.arena;
if (try try_catch.err(arena, self.session.env)) |msg| { if (try try_catch.err(arena, &self.session.env)) |msg| {
defer arena.free(msg); defer arena.free(msg);
log.info("wait error: {s}", .{msg}); log.info("wait error: {s}", .{msg});
return; return;
@@ -591,9 +591,7 @@ pub const Page = struct {
// TODO handle charset attribute // TODO handle charset attribute
const opt_text = try parser.nodeTextContent(parser.elementToNode(s.element)); const opt_text = try parser.nodeTextContent(parser.elementToNode(s.element));
if (opt_text) |text| { if (opt_text) |text| {
// TODO: change to &self.session.env when try s.eval(self.arena, &self.session.env, text);
// https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
try s.eval(self.arena, self.session.env, text);
return; return;
} }
@@ -656,11 +654,8 @@ pub const Page = struct {
// received. // received.
fn fetchScript(self: *const Page, s: *const Script) !void { fn fetchScript(self: *const Page, s: *const Script) !void {
const arena = self.arena; const arena = self.arena;
const body = try self.fetchData(arena, s.src, null); const body = try self.fetchData(arena, s.src, null);
// TODO: change to &self.session.env when try s.eval(arena, &self.session.env, body);
// https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
try s.eval(arena, self.session.env, body);
} }
const Script = struct { const Script = struct {
@@ -683,9 +678,8 @@ pub const Page = struct {
return .{ return .{
.element = e, .element = e,
.kind = kind(try parser.elementGetAttribute(e, "type")), .kind = parseKind(try parser.elementGetAttribute(e, "type")),
.is_async = try parser.elementGetAttribute(e, "async") != null, .is_async = try parser.elementGetAttribute(e, "async") != null,
.src = try parser.elementGetAttribute(e, "src") orelse "inline", .src = try parser.elementGetAttribute(e, "src") orelse "inline",
}; };
} }
@@ -695,7 +689,7 @@ pub const Page = struct {
// > type indicates that the script is a "classic script", containing // > type indicates that the script is a "classic script", containing
// > JavaScript code. // > JavaScript code.
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attribute_is_not_set_default_an_empty_string_or_a_javascript_mime_type // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attribute_is_not_set_default_an_empty_string_or_a_javascript_mime_type
fn kind(stype: ?[]const u8) Kind { fn parseKind(stype: ?[]const u8) Kind {
if (stype == null or stype.?.len == 0) return .javascript; if (stype == null or stype.?.len == 0) return .javascript;
if (std.mem.eql(u8, stype.?, "application/javascript")) return .javascript; if (std.mem.eql(u8, stype.?, "application/javascript")) return .javascript;
if (std.mem.eql(u8, stype.?, "module")) return .module; if (std.mem.eql(u8, stype.?, "module")) return .module;
@@ -703,7 +697,7 @@ pub const Page = struct {
return .unknown; return .unknown;
} }
fn eval(self: Script, arena: Allocator, env: Env, body: []const u8) !void { fn eval(self: Script, arena: Allocator, env: *const Env, body: []const u8) !void {
var try_catch: jsruntime.TryCatch = undefined; var try_catch: jsruntime.TryCatch = undefined;
try_catch.init(env); try_catch.init(env);
defer try_catch.deinit(); defer try_catch.deinit();

View File

@@ -245,7 +245,7 @@ pub const Mime = struct {
const bit_len = @bitSizeOf(@TypeOf(target.*)) - 8; const bit_len = @bitSizeOf(@TypeOf(target.*)) - 8;
const byte_len = bit_len / 8; const byte_len = bit_len / 8;
const T = @Type(.{ .Int = .{ const T = @Type(.{ .int = .{
.bits = bit_len, .bits = bit_len,
.signedness = .unsigned, .signedness = .unsigned,
} }); } });

View File

@@ -454,7 +454,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
pub fn sendResult(self: *Self, result: anytype, opts: SendResultOpts) !void { pub fn sendResult(self: *Self, result: anytype, opts: SendResultOpts) !void {
return self.sender.sendJSON(.{ return self.sender.sendJSON(.{
.id = self.input.id, .id = self.input.id,
.result = if (comptime @typeInfo(@TypeOf(result)) == .Null) struct {}{} else result, .result = if (comptime @typeInfo(@TypeOf(result)) == .null) struct {}{} else result,
.sessionId = if (opts.include_session_id) self.input.session_id else null, .sessionId = if (opts.include_session_id) self.input.session_id else null,
}); });
} }
@@ -466,7 +466,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
// Events ALWAYS go to the client. self.sender should not be used // Events ALWAYS go to the client. self.sender should not be used
return self.cdp.sendJSON(.{ return self.cdp.sendJSON(.{
.method = method, .method = method,
.params = if (comptime @typeInfo(@TypeOf(p)) == .Null) struct {}{} else p, .params = if (comptime @typeInfo(@TypeOf(p)) == .null) struct {}{} else p,
.sessionId = opts.session_id, .sessionId = opts.session_id,
}); });
} }

View File

@@ -174,8 +174,8 @@ const TestContext = struct {
pub fn processMessage(self: *TestContext, msg: anytype) !void { pub fn processMessage(self: *TestContext, msg: anytype) !void {
var json_message: []const u8 = undefined; var json_message: []const u8 = undefined;
if (@typeInfo(@TypeOf(msg)) != .Pointer) { if (@typeInfo(@TypeOf(msg)) != .pointer) {
json_message = try json.stringifyAlloc(self.arena.allocator(), msg, .{}); json_message = try std.json.stringifyAlloc(self.arena.allocator(), msg, .{});
} else { } else {
// assume this is a string we want to send as-is, if it isn't, we'll // assume this is a string we want to send as-is, if it isn't, we'll
// get a compile error, so no big deal. // get a compile error, so no big deal.
@@ -196,7 +196,7 @@ const TestContext = struct {
pub fn expectSentResult(self: *TestContext, expected: anytype, opts: ExpectResultOpts) !void { pub fn expectSentResult(self: *TestContext, expected: anytype, opts: ExpectResultOpts) !void {
const expected_result = .{ const expected_result = .{
.id = opts.id, .id = opts.id,
.result = if (comptime @typeInfo(@TypeOf(expected)) == .Null) struct {}{} else expected, .result = if (comptime @typeInfo(@TypeOf(expected)) == .null) struct {}{} else expected,
.sessionId = opts.session_id, .sessionId = opts.session_id,
}; };
@@ -210,7 +210,7 @@ const TestContext = struct {
pub fn expectSentEvent(self: *TestContext, method: []const u8, params: anytype, opts: ExpectEventOpts) !void { pub fn expectSentEvent(self: *TestContext, method: []const u8, params: anytype, opts: ExpectEventOpts) !void {
const expected_event = .{ const expected_event = .{
.method = method, .method = method,
.params = if (comptime @typeInfo(@TypeOf(params)) == .Null) struct {}{} else params, .params = if (comptime @typeInfo(@TypeOf(params)) == .null) struct {}{} else params,
.sessionId = opts.session_id, .sessionId = opts.session_id,
}; };
@@ -323,96 +323,3 @@ fn compareJsonValues(a: std.json.Value, b: std.json.Value) bool {
}, },
} }
} }
// fn compareAnyToJsonValue(expected: anytype, actual: json.Value) bool {
// switch (@typeInfo(@TypeOf(expected))) {
// .Optional => {
// if (expected) |e| {
// return compareAnyToJsonValue(e, actual);
// }
// return actual == .null;
// },
// .Int, .ComptimeInt => {
// if (actual != .integer) {
// return false;
// }
// return expected == actual.integer;
// },
// .Float, .ComptimeFloat => {
// if (actual != .float) {
// return false;
// }
// return expected == actual.float;
// },
// .Bool => {
// if (actual != .bool) {
// return false;
// }
// return expected == actual.bool;
// },
// .Pointer => |ptr| switch (ptr.size) {
// .One => switch (@typeInfo(ptr.child)) {
// .Struct => return compareAnyToJsonValue(expected.*, actual),
// .Array => |arr| if (arr.child == u8) {
// if (actual != .string) {
// return false;
// }
// return std.mem.eql(u8, expected, actual.string);
// },
// else => {},
// },
// .Slice => switch (ptr.child) {
// u8 => {
// if (actual != .string) {
// return false;
// }
// return std.mem.eql(u8, expected, actual.string);
// },
// else => {},
// },
// else => {},
// },
// .Struct => |s| {
// if (s.is_tuple) {
// // how an array might look in an anytype
// if (actual != .array) {
// return false;
// }
// if (s.fields.len != actual.array.items.len) {
// return false;
// }
// inline for (s.fields, 0..) |f, i| {
// const e = @field(expected, f.name);
// if (compareAnyToJsonValue(e, actual.array.items[i]) == false) {
// return false;
// }
// }
// return true;
// }
// if (s.fields.len == 0) {
// return (actual == .array and actual.array.items.len == 0);
// }
// if (actual != .object) {
// return false;
// }
// inline for (s.fields) |f| {
// const e = @field(expected, f.name);
// if (actual.object.get(f.name)) |a| {
// if (compareAnyToJsonValue(e, a) == false) {
// return false;
// }
// } else if (@typeInfo(f.type) != .Optional or e != null) {
// // We don't JSON serialize nulls. So if we're expecting
// // a null, that should show up as a missing field.
// return false;
// }
// }
// return true;
// },
// else => {},
// }
// @compileError("Can't compare " ++ @typeName(@TypeOf(expected)));
// }

View File

@@ -63,7 +63,7 @@ pub fn Union(interfaces: anytype) type {
.decls = &.{}, .decls = &.{},
.is_exhaustive = true, .is_exhaustive = true,
}; };
const enum_T = @Type(.{ .Enum = enum_info }); const enum_T = @Type(.{ .@"enum" = enum_info });
// third iteration to generate union type // third iteration to generate union type
var union_fields: [fields.len]Type.UnionField = undefined; var union_fields: [fields.len]Type.UnionField = undefined;
@@ -79,7 +79,7 @@ pub fn Union(interfaces: anytype) type {
}; };
} }
return @Type(.{ .Union = .{ return @Type(.{ .@"union" = .{
.layout = .auto, .layout = .auto,
.tag_type = enum_T, .tag_type = enum_T,
.fields = &union_fields, .fields = &union_fields,
@@ -115,12 +115,12 @@ pub fn Tuple(args: anytype) type {
// has to be true in order to properly capture the default value // has to be true in order to properly capture the default value
.is_comptime = true, .is_comptime = true,
.alignment = @alignOf(type), .alignment = @alignOf(type),
.default_value = @ptrCast(&interfaces[i]), .default_value_ptr = @ptrCast(&interfaces[i]),
}; };
field_index += 1; field_index += 1;
} }
return @Type(.{ .Struct = .{ return @Type(.{ .@"struct" = .{
.layout = .auto, .layout = .auto,
.fields = &fields, .fields = &fields,
.decls = &.{}, .decls = &.{},
@@ -130,7 +130,7 @@ pub fn Tuple(args: anytype) type {
fn countInterfaces(args: anytype, count: usize) usize { fn countInterfaces(args: anytype, count: usize) usize {
var new_count = count; var new_count = count;
for (@typeInfo(@TypeOf(args)).Struct.fields) |f| { for (@typeInfo(@TypeOf(args)).@"struct".fields) |f| {
const member = @field(args, f.name); const member = @field(args, f.name);
if (@TypeOf(member) == type) { if (@TypeOf(member) == type) {
new_count += 1; new_count += 1;
@@ -143,7 +143,7 @@ fn countInterfaces(args: anytype, count: usize) usize {
fn flattenInterfaces(args: anytype, interfaces: []type, index: usize) usize { fn flattenInterfaces(args: anytype, interfaces: []type, index: usize) usize {
var new_index = index; var new_index = index;
for (@typeInfo(@TypeOf(args)).Struct.fields) |f| { for (@typeInfo(@TypeOf(args)).@"struct".fields) |f| {
const member = @field(args, f.name); const member = @field(args, f.name);
if (@TypeOf(member) == type) { if (@TypeOf(member) == type) {
interfaces[new_index] = member; interfaces[new_index] = member;
@@ -186,7 +186,7 @@ test "generate.Union" {
}; };
const value = Union(.{ Astruct, Bstruct, .{Cstruct} }); const value = Union(.{ Astruct, Bstruct, .{Cstruct} });
const ti = @typeInfo(value).Union; const ti = @typeInfo(value).@"union";
try std.testing.expectEqual(3, ti.fields.len); try std.testing.expectEqual(3, ti.fields.len);
try std.testing.expectEqualStrings("*generate.test.generate.Union.Astruct.Other", @typeName(ti.fields[0].type)); try std.testing.expectEqualStrings("*generate.test.generate.Union.Astruct.Other", @typeName(ti.fields[0].type));
try std.testing.expectEqualStrings(ti.fields[0].name, "Astruct"); try std.testing.expectEqualStrings(ti.fields[0].name, "Astruct");
@@ -209,7 +209,7 @@ test "generate.Tuple" {
{ {
const tuple = Tuple(.{ Astruct, Bstruct }){}; const tuple = Tuple(.{ Astruct, Bstruct }){};
const ti = @typeInfo(@TypeOf(tuple)).Struct; const ti = @typeInfo(@TypeOf(tuple)).@"struct";
try std.testing.expectEqual(true, ti.is_tuple); try std.testing.expectEqual(true, ti.is_tuple);
try std.testing.expectEqual(2, ti.fields.len); try std.testing.expectEqual(2, ti.fields.len);
try std.testing.expectEqual(Astruct, tuple.@"0"); try std.testing.expectEqual(Astruct, tuple.@"0");
@@ -219,7 +219,7 @@ test "generate.Tuple" {
{ {
// dedupe // dedupe
const tuple = Tuple(.{ Cstruct, Astruct, .{Astruct}, Bstruct, .{ Astruct, .{ Astruct, Bstruct } } }){}; const tuple = Tuple(.{ Cstruct, Astruct, .{Astruct}, Bstruct, .{ Astruct, .{ Astruct, Bstruct } } }){};
const ti = @typeInfo(@TypeOf(tuple)).Struct; const ti = @typeInfo(@TypeOf(tuple)).@"struct";
try std.testing.expectEqual(true, ti.is_tuple); try std.testing.expectEqual(true, ti.is_tuple);
try std.testing.expectEqual(3, ti.fields.len); try std.testing.expectEqual(3, ti.fields.len);
try std.testing.expectEqual(Cstruct, tuple.@"0"); try std.testing.expectEqual(Cstruct, tuple.@"0");

View File

@@ -1358,7 +1358,7 @@ pub fn connectTcp(client: *Client, host: []const u8, port: u16, protocol: Connec
conn.data.tls_client.* = tls23.client(stream, .{ conn.data.tls_client.* = tls23.client(stream, .{
.host = host, .host = host,
.root_ca = client.ca_bundle, .root_ca = .{ .bundle = client.ca_bundle },
}) catch return error.TlsInitializationFailed; }) catch return error.TlsInitializationFailed;
} }

View File

@@ -27,7 +27,7 @@ pub fn Incrementing(comptime T: type, comptime prefix: []const u8) type {
break :blk b; break :blk b;
}; };
const PrefixIntType = @Type(.{ .Int = .{ const PrefixIntType = @Type(.{ .int = .{
.bits = NUMERIC_START * 8, .bits = NUMERIC_START * 8,
.signedness = .unsigned, .signedness = .unsigned,
} }); } });

View File

@@ -151,7 +151,7 @@ fn LogT(comptime Out: type, comptime enhanced_readability: bool) type {
buffer.appendSliceAssumeCapacity(inject); buffer.appendSliceAssumeCapacity(inject);
} }
inline for (@typeInfo(@TypeOf(data)).Struct.fields) |f| { inline for (@typeInfo(@TypeOf(data)).@"struct".fields) |f| {
// + 2 for the leading space and the equal sign // + 2 for the leading space and the equal sign
// + 5 to save space for null/false/true common values // + 5 to save space for null/false/true common values
const key_len = f.name.len + 7; const key_len = f.name.len + 7;
@@ -179,30 +179,30 @@ fn LogT(comptime Out: type, comptime enhanced_readability: bool) type {
fn writeValue(allocator: Allocator, buffer: *std.ArrayListUnmanaged(u8), value: anytype) !void { fn writeValue(allocator: Allocator, buffer: *std.ArrayListUnmanaged(u8), value: anytype) !void {
const T = @TypeOf(value); const T = @TypeOf(value);
switch (@typeInfo(T)) { switch (@typeInfo(T)) {
.Optional => { .optional => {
if (value) |v| { if (value) |v| {
return writeValue(allocator, buffer, v); return writeValue(allocator, buffer, v);
} }
// in _log, we reserved space for a value of up to 5 bytes. // in _log, we reserved space for a value of up to 5 bytes.
return buffer.appendSliceAssumeCapacity("null"); return buffer.appendSliceAssumeCapacity("null");
}, },
.ComptimeInt, .Int, .ComptimeFloat, .Float => { .comptime_int, .int, .comptime_float, .float => {
return std.fmt.format(buffer.writer(allocator), "{d}", .{value}); return std.fmt.format(buffer.writer(allocator), "{d}", .{value});
}, },
.Bool => { .bool => {
// in _log, we reserved space for a value of up to 5 bytes. // in _log, we reserved space for a value of up to 5 bytes.
return buffer.appendSliceAssumeCapacity(if (value) "true" else "false"); return buffer.appendSliceAssumeCapacity(if (value) "true" else "false");
}, },
.ErrorSet => return buffer.appendSlice(allocator, @errorName(value)), .error_set => return buffer.appendSlice(allocator, @errorName(value)),
.Enum => return buffer.appendSlice(allocator, @tagName(value)), .@"enum" => return buffer.appendSlice(allocator, @tagName(value)),
.Array => return writeValue(allocator, buffer, &value), .array => return writeValue(allocator, buffer, &value),
.Pointer => |ptr| switch (ptr.size) { .pointer => |ptr| switch (ptr.size) {
.Slice => switch (ptr.child) { .slice => switch (ptr.child) {
u8 => return writeString(allocator, buffer, value), u8 => return writeString(allocator, buffer, value),
else => {}, else => {},
}, },
.One => switch (@typeInfo(ptr.child)) { .one => switch (@typeInfo(ptr.child)) {
.Array => |arr| if (arr.child == u8) { .array => |arr| if (arr.child == u8) {
return writeString(allocator, buffer, value); return writeString(allocator, buffer, value);
}, },
else => return false, else => return false,

View File

@@ -35,7 +35,7 @@ const version = @import("build_info").git_commit;
const log = std.log.scoped(.cli); const log = std.log.scoped(.cli);
pub const std_options = .{ pub const std_options = std.Options{
// Set the log level to info // Set the log level to info
.log_level = .debug, .log_level = .debug,
@@ -344,7 +344,7 @@ fn parseFetchArgs(
var verbose: bool = builtin.mode == .Debug; // In debug mode, force verbose. var verbose: bool = builtin.mode == .Debug; // In debug mode, force verbose.
fn logFn( fn logFn(
comptime level: std.log.Level, comptime level: std.log.Level,
comptime scope: @Type(.EnumLiteral), comptime scope: @Type(.enum_literal),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {

View File

@@ -260,7 +260,7 @@ pub const Tag = enum(u8) {
pub fn all() []Tag { pub fn all() []Tag {
comptime { comptime {
const info = @typeInfo(Tag).Enum; const info = @typeInfo(Tag).@"enum";
var l: [info.fields.len]Tag = undefined; var l: [info.fields.len]Tag = undefined;
for (info.fields, 0..) |field, i| { for (info.fields, 0..) |field, i| {
l[i] = @as(Tag, @enumFromInt(field.value)); l[i] = @as(Tag, @enumFromInt(field.value));
@@ -804,7 +804,7 @@ pub fn eventTargetDispatchEvent(et: *EventTarget, event: *Event) !bool {
pub fn eventTargetTBaseFieldName(comptime T: type) ?[]const u8 { pub fn eventTargetTBaseFieldName(comptime T: type) ?[]const u8 {
std.debug.assert(@inComptime()); std.debug.assert(@inComptime());
switch (@typeInfo(T)) { switch (@typeInfo(T)) {
.Struct => |ti| { .@"struct" => |ti| {
for (ti.fields) |f| { for (ti.fields) |f| {
if (f.type == EventTargetTBase) return f.name; if (f.type == EventTargetTBase) return f.name;
} }

View File

@@ -20,7 +20,7 @@ pub fn testExecFn(
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
js_env: *jsruntime.Env, js_env: *jsruntime.Env,
) anyerror!void { ) anyerror!void {
try @import("polyfill.zig").load(alloc, js_env.*); try @import("polyfill.zig").load(alloc, js_env);
var fetch = [_]Case{ var fetch = [_]Case{
.{ .{

View File

@@ -33,7 +33,7 @@ const modules = [_]struct {
.{ .name = "polyfill-fetch", .source = @import("fetch.zig").source }, .{ .name = "polyfill-fetch", .source = @import("fetch.zig").source },
}; };
pub fn load(alloc: std.mem.Allocator, env: Env) !void { pub fn load(alloc: std.mem.Allocator, env: *const Env) !void {
var try_catch: jsruntime.TryCatch = undefined; var try_catch: jsruntime.TryCatch = undefined;
try_catch.init(env); try_catch.init(env);
defer try_catch.deinit(); defer try_catch.deinit();

View File

@@ -57,13 +57,6 @@ const Server = struct {
listener: posix.socket_t, listener: posix.socket_t,
timeout: u64, timeout: u64,
// A memory poor for our Clients. Because we only allow 1 client to be
// connected at a time, and because of the way we accept, we don't need
// a lock for this, since the creation of a new client cannot happen at the
// same time as the destruction of a client.
client_pool: std.heap.MemoryPool(Client),
client_pool_lock: std.Thread.Mutex = .{},
// I/O fields // I/O fields
accept_completion: Completion, accept_completion: Completion,
@@ -71,7 +64,7 @@ const Server = struct {
json_version_response: []const u8, json_version_response: []const u8,
fn deinit(self: *Server) void { fn deinit(self: *Server) void {
self.client_pool.deinit(); _ = self;
} }
fn queueAccept(self: *Server) void { fn queueAccept(self: *Server) void {
@@ -102,28 +95,14 @@ const Server = struct {
result: AcceptError!posix.socket_t, result: AcceptError!posix.socket_t,
) !void { ) !void {
const socket = try result; const socket = try result;
const client = try self.allocator.create(Client);
const client = blk: {
self.client_pool_lock.lock();
defer self.client_pool_lock.unlock();
break :blk try self.client_pool.create();
};
errdefer {
self.client_pool_lock.lock();
self.client_pool.destroy(client);
self.client_pool_lock.unlock();
}
client.* = Client.init(socket, self); client.* = Client.init(socket, self);
client.start(); client.start();
log.info("client connected", .{}); log.info("client connected", .{});
} }
fn releaseClient(self: *Server, client: *Client) void { fn releaseClient(self: *Server, client: *Client) void {
self.client_pool_lock.lock(); self.allocator.destroy(client);
self.client_pool.destroy(client);
self.client_pool_lock.unlock();
} }
}; };
@@ -1053,7 +1032,6 @@ pub fn run(
.allocator = allocator, .allocator = allocator,
.accept_completion = undefined, .accept_completion = undefined,
.json_version_response = json_version_response, .json_version_response = json_version_response,
.client_pool = std.heap.MemoryPool(Client).init(allocator),
}; };
defer server.deinit(); defer server.deinit();
@@ -1488,8 +1466,8 @@ fn createTestClient() !TestClient {
const stream = try std.net.tcpConnectToAddress(address); const stream = try std.net.tcpConnectToAddress(address);
const timeout = std.mem.toBytes(posix.timeval{ const timeout = std.mem.toBytes(posix.timeval{
.tv_sec = 2, .sec = 2,
.tv_usec = 0, .usec = 0,
}); });
try posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.RCVTIMEO, &timeout); try posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.RCVTIMEO, &timeout);
try posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &timeout); try posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &timeout);

View File

@@ -922,7 +922,7 @@ fn expectAttribute(expected: anytype, url: ?[]const u8, set_cookie: []const u8)
var cookie = try Cookie.parse(testing.allocator, uri, set_cookie); var cookie = try Cookie.parse(testing.allocator, uri, set_cookie);
defer cookie.deinit(); defer cookie.deinit();
inline for (@typeInfo(@TypeOf(expected)).Struct.fields) |f| { inline for (@typeInfo(@TypeOf(expected)).@"struct".fields) |f| {
if (comptime std.mem.eql(u8, f.name, "expires")) { if (comptime std.mem.eql(u8, f.name, "expires")) {
try testing.expectDelta(expected.expires, cookie.expires, 1); try testing.expectDelta(expected.expires, cookie.expires, 1);
} else { } else {

View File

@@ -66,7 +66,7 @@ pub fn asUint(comptime string: anytype) AsUintReturn(string) {
fn AsUintReturn(comptime string: anytype) type { fn AsUintReturn(comptime string: anytype) type {
return @Type(.{ return @Type(.{
.Int = .{ .int = .{
.bits = @bitSizeOf(@TypeOf(string.*)) - 8, // (- 8) to exclude sentinel 0 .bits = @bitSizeOf(@TypeOf(string.*)) - 8, // (- 8) to exclude sentinel 0
.signedness = .unsigned, .signedness = .unsigned,
}, },

View File

@@ -137,12 +137,12 @@ const LightPandaEvent = struct {
try writer.objectField("event"); try writer.objectField("event");
try writer.write(@tagName(std.meta.activeTag(self.event))); try writer.write(@tagName(std.meta.activeTag(self.event)));
inline for (@typeInfo(telemetry.Event).Union.fields) |union_field| { inline for (@typeInfo(telemetry.Event).@"union".fields) |union_field| {
if (self.event == @field(telemetry.Event, union_field.name)) { if (self.event == @field(telemetry.Event, union_field.name)) {
const inner = @field(self.event, union_field.name); const inner = @field(self.event, union_field.name);
const TI = @typeInfo(@TypeOf(inner)); const TI = @typeInfo(@TypeOf(inner));
if (TI == .Struct) { if (TI == .@"struct") {
inline for (TI.Struct.fields) |field| { inline for (TI.@"struct".fields) |field| {
try writer.objectField(field.name); try writer.objectField(field.name);
try writer.write(@field(inner, field.name)); try writer.write(@field(inner, field.name));
} }

View File

@@ -11,10 +11,10 @@ const App = @import("app.zig").App;
// exactly how to assert equality // exactly how to assert equality
pub fn expectEqual(expected: anytype, actual: anytype) !void { pub fn expectEqual(expected: anytype, actual: anytype) !void {
switch (@typeInfo(@TypeOf(actual))) { switch (@typeInfo(@TypeOf(actual))) {
.Array => |arr| if (arr.child == u8) { .array => |arr| if (arr.child == u8) {
return std.testing.expectEqualStrings(expected, &actual); return std.testing.expectEqualStrings(expected, &actual);
}, },
.Pointer => |ptr| { .pointer => |ptr| {
if (ptr.child == u8) { if (ptr.child == u8) {
return std.testing.expectEqualStrings(expected, actual); return std.testing.expectEqualStrings(expected, actual);
} else if (comptime isStringArray(ptr.child)) { } else if (comptime isStringArray(ptr.child)) {
@@ -23,19 +23,19 @@ pub fn expectEqual(expected: anytype, actual: anytype) !void {
return expectString(expected, actual); return expectString(expected, actual);
} }
}, },
.Struct => |structType| { .@"struct" => |structType| {
inline for (structType.fields) |field| { inline for (structType.fields) |field| {
try expectEqual(@field(expected, field.name), @field(actual, field.name)); try expectEqual(@field(expected, field.name), @field(actual, field.name));
} }
return; return;
}, },
.Optional => { .optional => {
if (actual == null) { if (actual == null) {
return std.testing.expectEqual(null, expected); return std.testing.expectEqual(null, expected);
} }
return expectEqual(expected, actual.?); return expectEqual(expected, actual.?);
}, },
.Union => |union_info| { .@"union" => |union_info| {
if (union_info.tag_type == null) { if (union_info.tag_type == null) {
@compileError("Unable to compare untagged union values"); @compileError("Unable to compare untagged union values");
} }
@@ -59,12 +59,12 @@ pub fn expectEqual(expected: anytype, actual: anytype) !void {
} }
pub fn expectDelta(expected: anytype, actual: anytype, delta: anytype) !void { pub fn expectDelta(expected: anytype, actual: anytype, delta: anytype) !void {
if (@typeInfo(@TypeOf(expected)) == .Null) { if (@typeInfo(@TypeOf(expected)) == .null) {
return std.testing.expectEqual(null, actual); return std.testing.expectEqual(null, actual);
} }
switch (@typeInfo(@TypeOf(actual))) { switch (@typeInfo(@TypeOf(actual))) {
.Optional => { .optional => {
if (actual) |value| { if (actual) |value| {
return expectDelta(expected, value, delta); return expectDelta(expected, value, delta);
} }
@@ -74,7 +74,7 @@ pub fn expectDelta(expected: anytype, actual: anytype, delta: anytype) !void {
} }
switch (@typeInfo(@TypeOf(expected))) { switch (@typeInfo(@TypeOf(expected))) {
.Optional => { .optional => {
if (expected) |value| { if (expected) |value| {
return expectDelta(value, actual, delta); return expectDelta(value, actual, delta);
} }
@@ -96,7 +96,7 @@ pub fn expectDelta(expected: anytype, actual: anytype, delta: anytype) !void {
} }
fn isStringArray(comptime T: type) bool { fn isStringArray(comptime T: type) bool {
if (!is(.Array)(T) and !isPtrTo(.Array)(T)) { if (!is(.array)(T) and !isPtrTo(.array)(T)) {
return false; return false;
} }
return std.meta.Elem(T) == u8; return std.meta.Elem(T) == u8;
@@ -124,7 +124,7 @@ pub fn isPtrTo(comptime id: std.builtin.TypeId) TraitFn {
pub fn isSingleItemPtr(comptime T: type) bool { pub fn isSingleItemPtr(comptime T: type) bool {
if (comptime is(.pointer)(T)) { if (comptime is(.pointer)(T)) {
return @typeInfo(T).Pointer.size == .one; return @typeInfo(T).pointer.size == .one;
} }
return false; return false;
} }

View File

@@ -420,7 +420,7 @@ fn testParseQuery(expected: anytype, query: []const u8) !void {
defer values.deinit(); defer values.deinit();
var count: usize = 0; var count: usize = 0;
inline for (@typeInfo(@TypeOf(expected)).Struct.fields) |f| { inline for (@typeInfo(@TypeOf(expected)).@"struct".fields) |f| {
const actual = values.get(f.name); const actual = values.get(f.name);
const expect = @field(expected, f.name); const expect = @field(expected, f.name);
try testing.expectEqual(expect.len, actual.len); try testing.expectEqual(expect.len, actual.len);

View File

@@ -77,11 +77,11 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
defer js_env.stop(); defer js_env.stop();
// load polyfills // load polyfills
try polyfill.load(alloc, js_env); try polyfill.load(alloc, &js_env);
// display console logs // display console logs
defer { defer {
const res = evalJS(js_env, alloc, "console.join('\\n');", "console") catch unreachable; const res = evalJS(&js_env, alloc, "console.join('\\n');", "console") catch unreachable;
defer res.deinit(alloc); defer res.deinit(alloc);
if (res.msg != null and res.msg.?.len > 0) { if (res.msg != null and res.msg.?.len > 0) {
@@ -104,7 +104,7 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
\\ console.push("debug", ...arguments); \\ console.push("debug", ...arguments);
\\}; \\};
; ;
var res = try evalJS(js_env, alloc, init, "init"); var res = try evalJS(&js_env, alloc, init, "init");
if (!res.ok) return res; if (!res.ok) return res;
res.deinit(alloc); res.deinit(alloc);
@@ -123,14 +123,14 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
path = try fspath.join(alloc, &.{ "/", dirname, path }); path = try fspath.join(alloc, &.{ "/", dirname, path });
} }
res = try evalJS(js_env, alloc, try loader.get(path), src); res = try evalJS(&js_env, alloc, try loader.get(path), src);
if (!res.ok) return res; if (!res.ok) return res;
res.deinit(alloc); res.deinit(alloc);
} }
// If the script as a source text, execute it. // If the script as a source text, execute it.
const src = try parser.nodeTextContent(s) orelse continue; const src = try parser.nodeTextContent(s) orelse continue;
res = try evalJS(js_env, alloc, src, ""); res = try evalJS(&js_env, alloc, src, "");
if (!res.ok) return res; if (!res.ok) return res;
res.deinit(alloc); res.deinit(alloc);
} }
@@ -147,22 +147,22 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
// wait for all async executions // wait for all async executions
var try_catch: jsruntime.TryCatch = undefined; var try_catch: jsruntime.TryCatch = undefined;
try_catch.init(js_env); try_catch.init(&js_env);
defer try_catch.deinit(); defer try_catch.deinit();
js_env.wait() catch { js_env.wait() catch {
return .{ return .{
.ok = false, .ok = false,
.msg = try try_catch.err(alloc, js_env), .msg = try try_catch.err(alloc, &js_env),
}; };
}; };
// Check the final test status. // Check the final test status.
res = try evalJS(js_env, alloc, "report.status;", "teststatus"); res = try evalJS(&js_env, alloc, "report.status;", "teststatus");
if (!res.ok) return res; if (!res.ok) return res;
res.deinit(alloc); res.deinit(alloc);
// return the detailed result. // return the detailed result.
return try evalJS(js_env, alloc, "report.log", "teststatus"); return try evalJS(&js_env, alloc, "report.log", "teststatus");
} }
pub const Res = struct { pub const Res = struct {
@@ -176,7 +176,7 @@ pub const Res = struct {
} }
}; };
fn evalJS(env: jsruntime.Env, alloc: std.mem.Allocator, script: []const u8, name: ?[]const u8) !Res { fn evalJS(env: *const jsruntime.Env, alloc: std.mem.Allocator, script: []const u8, name: ?[]const u8) !Res {
var try_catch: jsruntime.TryCatch = undefined; var try_catch: jsruntime.TryCatch = undefined;
try_catch.init(env); try_catch.init(env);
defer try_catch.deinit(); defer try_catch.deinit();

2
vendor/tls.zig vendored