authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-01 18:39:22-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-04 00:27:08-08:00
log1ccc87363a6436da293dbb1bc7bc8db2aa4d7bf7
treef6ae16ea94160a796e0a644afce1e8705bbf1cab
parent50e185b71822c180fccd07826a8dd5e3ec641cc1

std: fixes for WASI


5 files changed, 26 insertions(+), 17 deletions(-)

lib/std/Io/Threaded.zig+3-1
......@@ -12787,7 +12787,7 @@ const processSpawn = switch (native_os) {
1278712787fn processSpawnUnsupported(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child {
1278812788 _ = userdata;
1278912789 _ = options;
12790 return error.OperationUnsupported;
12790 return error.Unexpected;
1279112791}
1279212792
1279312793fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) process.SpawnError!process.Child {
......@@ -12995,6 +12995,7 @@ fn processSpawnPosix(userdata: ?*anyopaque, options: process.SpawnOptions) proce
1299512995}
1299612996
1299712997fn childWait(userdata: ?*anyopaque, child: *std.process.Child) process.Child.WaitError!process.Child.Term {
12998 if (native_os == .wasi) unreachable;
1299812999 const t: *Threaded = @ptrCast(@alignCast(userdata));
1299913000 switch (native_os) {
1300013001 .windows => return childWaitWindows(t, child),
......@@ -13003,6 +13004,7 @@ fn childWait(userdata: ?*anyopaque, child: *std.process.Child) process.Child.Wai
1300313004}
1300413005
1300513006fn childKill(userdata: ?*anyopaque, child: *std.process.Child) void {
13007 if (native_os == .wasi) unreachable;
1300613008 const t: *Threaded = @ptrCast(@alignCast(userdata));
1300713009 if (is_windows) {
1300813010 childKillWindows(t, child, 1) catch childCleanupWindows(child);
lib/std/posix/test.zig+2-2
......@@ -22,10 +22,10 @@ const tmpDir = std.testing.tmpDir;
2222
2323test "check WASI CWD" {
2424 if (native_os == .wasi) {
25 if (std.options.wasiCwd() != 3) {
25 const cwd: Dir = .cwd();
26 if (cwd.handle != 3) {
2627 @panic("WASI code that uses cwd (like this test) needs a preopen for cwd (add '--dir=.' to wasmtime)");
2728 }
28
2929 if (!builtin.link_libc) {
3030 // WASI without-libc hardcodes fd 3 as the FDCWD token so it can be passed directly to WASI calls
3131 try expectEqual(3, posix.AT.FDCWD);
lib/std/process/Args.zig+15-7
......@@ -10,8 +10,14 @@ const testing = std.testing;
1010
1111vector: Vector,
1212
13/// On WASI without libc, this is `void` because the environment has to be
14/// queried and heap-allocated at runtime.
1315pub const Vector = switch (native_os) {
1416 .windows => []const u16, // WTF-16 encoded
17 .wasi => switch (builtin.link_libc) {
18 false => void,
19 true => []const [*:0]const u8,
20 },
1521 .freestanding, .other => void,
1622 else => []const [*:0]const u8,
1723};
......@@ -457,6 +463,8 @@ pub fn iterateAllocator(a: Args, gpa: Allocator) Iterator.InitError!Iterator {
457463 return .initAllocator(a, gpa);
458464}
459465
466pub const ToSliceError = Iterator.Windows.InitError || Iterator.Wasi.InitError;
467
460468/// Returned value may reference several allocations; call `freeSlice` to
461469/// release.
462470///
......@@ -464,19 +472,19 @@ pub fn iterateAllocator(a: Args, gpa: Allocator) Iterator.InitError!Iterator {
464472/// [WTF-8](https://wtf-8.codeberg.page/).
465473/// * On other platforms, the result is an opaque sequence of bytes with no
466474/// particular encoding.
467pub fn toSlice(a: Args, gpa: Allocator) Allocator.Error![][:0]u8 {
475pub fn toSlice(a: Args, gpa: Allocator) ToSliceError![][:0]u8 {
468476 var it = try a.iterateAllocator(gpa);
469477 defer it.deinit();
470478
471 var contents = std.array_list.Managed(u8).init(gpa);
472 defer contents.deinit();
479 var contents: std.ArrayList(u8) = .empty;
480 defer contents.deinit(gpa);
473481
474 var slice_list = std.array_list.Managed(usize).init(gpa);
475 defer slice_list.deinit();
482 var slice_list: std.ArrayList(usize) = .empty;
483 defer slice_list.deinit(gpa);
476484
477485 while (it.next()) |arg| {
478 try contents.appendSlice(arg[0 .. arg.len + 1]);
479 try slice_list.append(arg.len);
486 try contents.appendSlice(gpa, arg[0 .. arg.len + 1]);
487 try slice_list.append(gpa, arg.len);
480488 }
481489
482490 const contents_slice = contents.items;
lib/std/process/Environ.zig+4-5
......@@ -757,6 +757,9 @@ test Map {
757757}
758758
759759test "convert from Environ to Map and back again" {
760 if (native_os == .windows) return;
761 if (native_os == .wasi and !builtin.link_libc) return;
762
760763 const gpa = testing.allocator;
761764
762765 var map: Map = .init(gpa);
......@@ -769,11 +772,7 @@ test "convert from Environ to Map and back again" {
769772 defer arena_allocator.deinit();
770773 const arena = arena_allocator.allocator();
771774
772 const environ: Environ = switch (native_os) {
773 .windows => return error.SkipZigTest,
774 .wasi => if (!builtin.libc) return error.SkipZigTest,
775 else => .{ .block = try map.createBlockPosix(arena, .{}) },
776 };
775 const environ: Environ = .{ .block = try map.createBlockPosix(arena, .{}) };
777776
778777 try testing.expectEqual(true, environ.contains(gpa, "FOO"));
779778 try testing.expectEqual(false, environ.contains(gpa, "BAR"));
lib/std/start.zig+2-2
......@@ -55,7 +55,7 @@ comptime {
5555 if (!@hasDecl(root, wasm_start_sym) and @hasDecl(root, "main")) {
5656 // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which
5757 // case it's not required to provide an entrypoint such as main.
58 @export(&wasi_start, .{ .name = wasm_start_sym });
58 @export(&startWasi, .{ .name = wasm_start_sym });
5959 }
6060 } else if (native_arch.isWasm() and native_os == .freestanding) {
6161 // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which
......@@ -90,7 +90,7 @@ fn wasm_freestanding_start() callconv(.c) void {
9090 _ = @call(.always_inline, callMain, .{ {}, {} });
9191}
9292
93fn wasi_start() callconv(.c) void {
93fn startWasi() callconv(.c) void {
9494 // The function call is marked inline because for some reason LLVM in
9595 // release mode fails to inline it, and we want fewer call frames in stack traces.
9696 switch (builtin.wasi_exec_model) {