From 5fcffbd66e0abfe133cc58da9401e8665db0d573 Mon Sep 17 00:00:00 2001 From: chloe caruso Date: Thu, 17 Apr 2025 15:35:44 -0700 Subject: [PATCH] this code fails to compile --- src/bun.js/api/bun/subprocess.zig | 22 +++--- src/bun.js/ipc.zig | 7 +- src/bun.js/webcore/streams.zig | 9 ++- src/deps/uws.zig | 7 +- src/io/PipeWriter.zig | 114 ++++++++++++++++-------------- src/shell/IOWriter.zig | 15 ++-- 6 files changed, 99 insertions(+), 75 deletions(-) diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 03a62d2752..f61dd815f5 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -913,6 +913,8 @@ pub const StaticPipeWriter = NewStaticPipeWriter(Subprocess); pub fn NewStaticPipeWriter(comptime ProcessType: type) type { return struct { + const This = @This(); + writer: IOWriter = .{}, stdio_result: StdioResult, source: Source = .{ .detached = {} }, @@ -922,20 +924,18 @@ pub fn NewStaticPipeWriter(comptime ProcessType: type) type { buffer: []const u8 = "", // It seems there is a bug in the Zig compiler. We'll get back to this one later - const WriterRefCount = bun.ptr.RefCount(This, "ref_count", _deinit, .{}); - pub usingnamespace bun.ptr.RefCount(This, "ref_count", _deinit, .{}); + const WriterRefCount = bun.ptr.RefCount(@This(), "ref_count", _deinit, .{}); + pub usingnamespace bun.ptr.RefCount(@This(), "ref_count", _deinit, .{}); - const This = @This(); const print = bun.Output.scoped(.StaticPipeWriter, false); - pub const IOWriter = bun.io.BufferedWriter( - This, - onWrite, - onError, - onClose, - getBuffer, - flush, - ); + pub const IOWriter = bun.io.BufferedWriter(@This(), .{ + .onWritable = null, + .getBuffer = getBuffer, + .onClose = onClose, + .onError = onError, + .onWrite = onWrite, + }); pub const Poll = IOWriter; pub fn updateRef(this: *This, add: bool) void { diff --git a/src/bun.js/ipc.zig b/src/bun.js/ipc.zig index 4e941ab733..f6cf1c2632 100644 --- a/src/bun.js/ipc.zig +++ b/src/bun.js/ipc.zig @@ -452,7 +452,12 @@ const NamedPipeIPCData = struct { mode: Mode, // we will use writer pipe as Duplex - writer: bun.io.StreamingWriter(NamedPipeIPCData, onWrite, onError, null, onPipeClose) = .{}, + writer: bun.io.StreamingWriter(@This(), .{ + .onWrite = onWrite, + .onError = onError, + .onWritable = null, + .onClose = onPipeClose, + }) = .{}, incoming: bun.ByteList = .{}, // Maybe we should use IPCBuffer here as well disconnected: bool = false, diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 78b48f71c0..4702f0388a 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -3429,15 +3429,20 @@ pub const FileSink = struct { const log = Output.scoped(.FileSink, false); // TODO: this usingnamespace is load-bearing, likely due to a compiler bug. + const RefCount = bun.ptr.RefCount(FileSink, "ref_count", deinit, .{}); pub usingnamespace brk: { - const RefCount = bun.ptr.RefCount(FileSink, "ref_count", deinit, .{}); break :brk struct { pub const ref = RefCount.ref; pub const deref = RefCount.deref; }; }; - pub const IOWriter = bun.io.StreamingWriter(@This(), onWrite, onError, onReady, onClose); + pub const IOWriter = bun.io.StreamingWriter(@This(), .{ + .onClose = onClose, + .onWritable = onReady, + .onError = onError, + .onWrite = onWrite, + }); pub const Poll = IOWriter; pub fn memoryCost(this: *const FileSink) usize { diff --git a/src/deps/uws.zig b/src/deps/uws.zig index 5285d6ace9..a8a2d0f2f7 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -558,7 +558,12 @@ pub const WindowsNamedPipe = if (Environment.isWindows) struct { pipe: if (Environment.isWindows) ?*uv.Pipe else void, // any duplex vm: *bun.JSC.VirtualMachine, //TODO: create a timeout version that dont need the JSC VM - writer: bun.io.StreamingWriter(WindowsNamedPipe, onWrite, onError, onWritable, onPipeClose) = .{}, + writer: bun.io.StreamingWriter(@This(), .{ + .onClose = onClose, + .onWritable = onWritable, + .onError = onError, + .onWrite = onWrite, + }) = .{}, incoming: bun.ByteList = .{}, // Maybe we should use IPCBuffer here as well ssl_error: CertError = .{}, diff --git a/src/io/PipeWriter.zig b/src/io/PipeWriter.zig index 57f6555963..164d5f69ac 100644 --- a/src/io/PipeWriter.zig +++ b/src/io/PipeWriter.zig @@ -31,18 +31,17 @@ pub fn PosixPipeWriter( comptime onWrite: fn (*This, written: usize, status: WriteStatus) void, comptime registerPoll: ?fn (*This) void, comptime onError: fn (*This, bun.sys.Error) void, - comptime onWritable: fn (*This) void, + comptime _: fn (*This) void, comptime getFileType: *const fn (*This) FileType, ) type { - _ = onWritable; // autofix return struct { - pub fn _tryWrite(this: *This, force_sync: bool, buf_: []const u8) WriteResult { + fn tryWrite(this: *This, force_sync: bool, buf_: []const u8) WriteResult { return switch (if (!force_sync) getFileType(this) else .file) { - inline else => |ft| return _tryWriteWithWriteFn(this, buf_, comptime writeToFileType(ft)), + inline else => |ft| return tryWriteWithWriteFn(this, buf_, comptime writeToFileType(ft)), }; } - fn _tryWriteWithWriteFn(this: *This, buf: []const u8, comptime write_fn: *const fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) WriteResult { + fn tryWriteWithWriteFn(this: *This, buf: []const u8, comptime write_fn: *const fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) WriteResult { const fd = getFd(this); var offset: usize = 0; @@ -147,7 +146,7 @@ pub fn PosixPipeWriter( var drained: usize = 0; while (drained < trimmed.len) { - const attempt = _tryWrite(parent, parent.getForceSync(), trimmed[drained..]); + const attempt = tryWrite(parent, parent.getForceSync(), trimmed[drained..]); switch (attempt) { .pending => |pending| { drained += pending; @@ -178,15 +177,18 @@ pub fn PosixPipeWriter( const PollOrFd = @import("./pipes.zig").PollOrFd; -pub fn PosixBufferedWriter( - comptime Parent: type, - comptime onWrite: *const fn (*Parent, amount: usize, status: WriteStatus) void, - comptime onError: *const fn (*Parent, bun.sys.Error) void, - comptime onClose: ?*const fn (*Parent) void, - comptime getBuffer: *const fn (*Parent) []const u8, - comptime onWritable: ?*const fn (*Parent) void, -) type { +/// See below for the expected signature of `function_table`. In many cases, the +/// function table can be the same as `Parent`. `anytype` is used because of a +/// dependency loop in Zig. +pub fn PosixBufferedWriter(Parent: type, function_table: anytype) type { return struct { + const PosixWriter = @This(); + const onWrite: *const fn (*Parent, amount: usize, status: WriteStatus) void = function_table.onWrite; + const onError: *const fn (*Parent, bun.sys.Error) void = function_table.onError; + const onClose: ?*const fn (*Parent) void = function_table.onClose; + const getBuffer: *const fn (*Parent) []const u8 = function_table.getBuffer; + const onWritable: ?*const fn (*Parent) void = function_table.onWritable; + handle: PollOrFd = .{ .closed = {} }, parent: *Parent = undefined, is_done: bool = false, @@ -194,12 +196,14 @@ pub fn PosixBufferedWriter( closed_without_reporting: bool = false, close_fd: bool = true, + const internals = PosixPipeWriter(@This(), getFd, getBufferInternal, _onWrite, registerPoll, _onError, _onWritable, getFileType); + pub const onPoll = internals.onPoll; + pub const drainBufferedData = internals.drainBufferedData; + pub fn memoryCost(_: *const @This()) usize { return @sizeOf(@This()); } - const PosixWriter = @This(); - pub const auto_poll = if (@hasDecl(Parent, "auto_poll")) Parent.auto_poll else true; pub fn createPoll(this: *@This(), fd: bun.FileDescriptor) *Async.FilePoll { @@ -294,8 +298,6 @@ pub fn PosixBufferedWriter( return getBuffer(this.parent); } - pub usingnamespace PosixPipeWriter(@This(), getFd, getBufferInternal, _onWrite, registerPoll, _onError, _onWritable, getFileType); - pub fn end(this: *PosixWriter) void { if (this.is_done) { return; @@ -375,22 +377,27 @@ pub fn PosixBufferedWriter( }; } -pub fn PosixStreamingWriter( - comptime Parent: type, - comptime onWrite: fn (*Parent, amount: usize, status: WriteStatus) void, - comptime onError: fn (*Parent, bun.sys.Error) void, - comptime onReady: ?fn (*Parent) void, - comptime onClose: fn (*Parent) void, -) type { +/// See below for the expected signature of `function_table`. In many cases, the +/// function table can be the same as `Parent`. `anytype` is used because of a +/// dependency loop in Zig. +pub fn PosixStreamingWriter(comptime Parent: type, comptime function_table: anytype) type { return struct { + const onWrite: fn (*Parent, amount: usize, status: WriteStatus) void = function_table.onWrite; + const onError: fn (*Parent, bun.sys.Error) void = function_table.onError; + const onReady: ?fn (*Parent) void = function_table.onReady; + const onClose: fn (*Parent) void = function_table.onClose; + outgoing: StreamBuffer = .{}, handle: PollOrFd = .{ .closed = {} }, parent: *Parent = undefined, is_done: bool = false, closed_without_reporting: bool = false, - force_sync: bool = false, + const internals = PosixPipeWriter(@This(), getFd, getBuffer, _onWrite, registerPoll, _onError, _onWritable, getFileType); + pub const onPoll = internals.onPoll; + pub const drainBufferedData = internals.drainBufferedData; + pub fn getForceSync(this: *const @This()) bool { return this.force_sync; } @@ -515,7 +522,7 @@ pub fn PosixStreamingWriter( const buf_len = this.outgoing.size() - before_len; - return this._maybeWriteNewlyBufferedData(buf_len); + return this.maybeWriteNewlyBufferedData(buf_len); } pub fn writeLatin1(this: *PosixWriter, buf: []const u8) WriteResult { @@ -536,10 +543,10 @@ pub fn PosixStreamingWriter( const buf_len = this.outgoing.size() - before_len; - return this._maybeWriteNewlyBufferedData(buf_len); + return this.maybeWriteNewlyBufferedData(buf_len); } - fn _maybeWriteNewlyBufferedData(this: *PosixWriter, buf_len: usize) WriteResult { + fn maybeWriteNewlyBufferedData(this: *PosixWriter, buf_len: usize) WriteResult { bun.assert(!this.is_done); if (this.shouldBuffer(0)) { @@ -549,13 +556,13 @@ pub fn PosixStreamingWriter( return .{ .wrote = buf_len }; } - return @This()._tryWriteNewlyBufferedData(this, this.outgoing.slice()); + return this.tryWriteNewlyBufferedData(this.outgoing.slice()); } - fn _tryWriteNewlyBufferedData(this: *PosixWriter, buf: []const u8) WriteResult { + fn tryWriteNewlyBufferedData(this: *PosixWriter, buf: []const u8) WriteResult { bun.assert(!this.is_done); - const rc = @This()._tryWrite(this, this.force_sync, buf); + const rc = internals.tryWrite(this, this.force_sync, buf); switch (rc) { .wrote => |amt| { @@ -614,10 +621,10 @@ pub fn PosixStreamingWriter( return .{ .err = bun.sys.Error.oom }; }; - return this._tryWriteNewlyBufferedData(this.outgoing.slice()); + return this.tryWriteNewlyBufferedData(this.outgoing.slice()); } - const rc = @This()._tryWrite(this, this.force_sync, buf); + const rc = internals.tryWrite(this, this.force_sync, buf); switch (rc) { .pending => |amt| { @@ -650,8 +657,6 @@ pub fn PosixStreamingWriter( return rc; } - pub usingnamespace PosixPipeWriter(@This(), getFd, getBuffer, _onWrite, registerPoll, _onError, _onWritable, getFileType); - pub fn flush(this: *PosixWriter) WriteResult { if (this.closed_without_reporting or this.is_done) { return .{ .done = 0 }; @@ -919,14 +924,10 @@ fn BaseWindowsPipeWriter( }; } -pub fn WindowsBufferedWriter( - comptime Parent: type, - comptime onWrite: *const fn (*Parent, amount: usize, status: WriteStatus) void, - comptime onError: *const fn (*Parent, bun.sys.Error) void, - comptime onClose: ?*const fn (*Parent) void, - comptime getBuffer: *const fn (*Parent) []const u8, - comptime onWritable: ?*const fn (*Parent) void, -) type { +/// See below for the expected signature of `function_table`. In many cases, the +/// function table can be the same as `Parent`. `anytype` is used because of a +/// dependency loop in Zig. +pub fn WindowsBufferedWriter(Parent: type, function_table: anytype) type { return struct { source: ?Source = null, owns_fd: bool = true, @@ -937,6 +938,12 @@ pub fn WindowsBufferedWriter( write_buffer: uv.uv_buf_t = uv.uv_buf_t.init(""), pending_payload_size: usize = 0, + const onWrite: *const fn (*Parent, amount: usize, status: WriteStatus) void = function_table.onWrite; + const onError: *const fn (*Parent, bun.sys.Error) void = function_table.onError; + const onClose: ?*const fn (*Parent) void = function_table.onClose; + const getBuffer: *const fn (*Parent) []const u8 = function_table.getBuffer; + const onWritable: ?*const fn (*Parent) void = function_table.onWritable; + const WindowsWriter = @This(); pub usingnamespace BaseWindowsPipeWriter(WindowsWriter, Parent); @@ -1179,15 +1186,18 @@ pub const StreamBuffer = struct { } }; -pub fn WindowsStreamingWriter( - comptime Parent: type, - /// reports the amount written and done means that we dont have any other pending data to send (but we may send more data) - comptime onWrite: fn (*Parent, amount: usize, status: WriteStatus) void, - comptime onError: fn (*Parent, bun.sys.Error) void, - comptime onWritable: ?fn (*Parent) void, - comptime onClose: fn (*Parent) void, -) type { +/// See below for the expected signature of `function_table`. In many cases, the +/// function table can be the same as `Parent`. `anytype` is used because of a +/// dependency loop in Zig. +pub fn WindowsStreamingWriter(comptime Parent: type, function_table: anytype) type { return struct { + /// reports the amount written and done means that we dont have any + /// other pending data to send (but we may send more data) + const onWrite: fn (*Parent, amount: usize, status: WriteStatus) void = function_table.onWrite; + const onError: fn (*Parent, bun.sys.Error) void = function_table.onError; + const onWritable: ?fn (*Parent) void = function_table.onWritable; + const onClose: fn (*Parent) void = function_table.onClose; + source: ?Source = null, /// if the source of this writer is a file descriptor, calling end() will not close it. /// if it is a path, then we claim ownership and the backing fd will be closed by end(). diff --git a/src/shell/IOWriter.zig b/src/shell/IOWriter.zig index 873fc19f85..f0e63dd96c 100644 --- a/src/shell/IOWriter.zig +++ b/src/shell/IOWriter.zig @@ -33,14 +33,13 @@ const SHRINK_THRESHOLD = 1024 * 128; pub const auto_poll = false; -pub const WriterImpl = bun.io.BufferedWriter( - IOWriter, - onWrite, - onError, - onClose, - getBuffer, - null, -); +pub const WriterImpl = bun.io.BufferedWriter(IOWriter, .{ + .onWrite = onWrite, + .onError = onError, + .onClose = onClose, + .getBuffer = getBuffer, + .onWritable = null, +}); pub const Poll = WriterImpl; // pub fn __onClose(_: *IOWriter) void {}