Compare commits

...

6 Commits

Author SHA1 Message Date
Meghan Denny
3b99d0a84d convert chown and fchown 2024-08-14 16:58:47 -07:00
Meghan Denny
61cb52b946 convert chmod and fchmod 2024-08-14 16:58:34 -07:00
Meghan Denny
2e7c40482b convert access and exists 2024-08-14 16:57:49 -07:00
Meghan Denny
0e50590b10 convert stat + fstat 2024-08-14 16:57:08 -07:00
Meghan Denny
b27ee7ab46 add an earlyResolve method 2024-08-14 16:56:30 -07:00
Meghan Denny
6c5961db5f organize node:fs uv calls better 2024-08-14 15:42:21 -07:00

View File

@@ -61,17 +61,17 @@ const ArrayBuffer = JSC.MarkedArrayBuffer;
const Buffer = JSC.Buffer;
const FileSystemFlags = JSC.Node.FileSystemFlags;
pub const Async = struct {
pub const access = NewAsyncFSTask(Return.Access, Arguments.Access, NodeFS.access);
pub const access = NewUVFSRequest(Return.Access, Arguments.Access, .access);
pub const appendFile = NewAsyncFSTask(Return.AppendFile, Arguments.AppendFile, NodeFS.appendFile);
pub const chmod = NewAsyncFSTask(Return.Chmod, Arguments.Chmod, NodeFS.chmod);
pub const chown = NewAsyncFSTask(Return.Chown, Arguments.Chown, NodeFS.chown);
pub const chmod = NewUVFSRequest(Return.Chmod, Arguments.Chmod, .chmod);
pub const chown = NewUVFSRequest(Return.Chown, Arguments.Chown, .chown);
pub const close = NewUVFSRequest(Return.Close, Arguments.Close, .close);
pub const copyFile = NewAsyncFSTask(Return.CopyFile, Arguments.CopyFile, NodeFS.copyFile);
pub const exists = NewAsyncFSTask(Return.Exists, Arguments.Exists, NodeFS.exists);
pub const fchmod = NewAsyncFSTask(Return.Fchmod, Arguments.FChmod, NodeFS.fchmod);
pub const fchown = NewAsyncFSTask(Return.Fchown, Arguments.Fchown, NodeFS.fchown);
pub const exists = NewUVFSRequest(Return.Exists, Arguments.Exists, .exists);
pub const fchmod = NewUVFSRequest(Return.Fchmod, Arguments.FChmod, .fchmod);
pub const fchown = NewUVFSRequest(Return.Fchown, Arguments.Fchown, .fchown);
pub const fdatasync = NewAsyncFSTask(Return.Fdatasync, Arguments.FdataSync, NodeFS.fdatasync);
pub const fstat = NewAsyncFSTask(Return.Fstat, Arguments.Fstat, NodeFS.fstat);
pub const fstat = NewUVFSRequest(Return.Fstat, Arguments.Fstat, .fstat);
pub const fsync = NewAsyncFSTask(Return.Fsync, Arguments.Fsync, NodeFS.fsync);
pub const ftruncate = NewAsyncFSTask(Return.Ftruncate, Arguments.FTruncate, NodeFS.ftruncate);
pub const futimes = NewAsyncFSTask(Return.Futimes, Arguments.Futimes, NodeFS.futimes);
@@ -92,7 +92,7 @@ pub const Async = struct {
pub const rename = NewAsyncFSTask(Return.Rename, Arguments.Rename, NodeFS.rename);
pub const rm = NewAsyncFSTask(Return.Rm, Arguments.Rm, NodeFS.rm);
pub const rmdir = NewAsyncFSTask(Return.Rmdir, Arguments.RmDir, NodeFS.rmdir);
pub const stat = NewAsyncFSTask(Return.Stat, Arguments.Stat, NodeFS.stat);
pub const stat = NewUVFSRequest(Return.Stat, Arguments.Stat, .stat);
pub const symlink = NewAsyncFSTask(Return.Symlink, Arguments.Symlink, NodeFS.symlink);
pub const truncate = NewAsyncFSTask(Return.Truncate, Arguments.Truncate, NodeFS.truncate);
pub const unlink = NewAsyncFSTask(Return.Unlink, Arguments.Unlink, NodeFS.unlink);
@@ -154,6 +154,14 @@ pub const Async = struct {
.write,
.readv,
.writev,
.stat,
.fstat,
.access,
.exists,
.chmod,
.fchmod,
.chown,
.fchown,
=> {},
else => return NewAsyncFSTask(ReturnType, ArgumentType, @field(NodeFS, @tagName(FunctionEnum))),
}
@@ -211,9 +219,7 @@ pub const Async = struct {
if (fd == 1 or fd == 2) {
log("uv close({}) SKIPPED", .{fd});
task.result = Maybe(Return.Close).success;
task.globalObject.bunVM().eventLoop().enqueueTask(JSC.Task.init(task));
return task.promise.value();
return task.earlyResolve(Maybe(Return.Close).success);
}
const rc = uv.uv_fs_close(loop, &task.req, fd, &uv_callback);
@@ -264,17 +270,119 @@ pub const Async = struct {
bun.debugAssert(rc == .zero);
log("uv writev({d}, {*}, {d}, {d}, {d} total bytes) = ~~", .{ fd, bufs.ptr, bufs.len, pos, sum });
},
else => comptime unreachable,
.stat => {
const args_: Arguments.Stat = task.args;
const path = args_.path.sliceZ(&this.node_fs.sync_error_buf);
const rc = uv.uv_fs_stat(loop, &task.req, path.ptr, &uv_callback);
bun.debugAssert(rc == .zero);
log("uv stat({s}) = ~~", .{path});
},
.fstat => {
const args_: Arguments.Fstat = task.args;
const fd = args_.fd.impl().uv();
const rc = uv.uv_fs_fstat(loop, &task.req, fd, &uv_callback);
bun.debugAssert(rc == .zero);
log("uv fstat({d}) = ~~", .{fd});
},
.access => {
const args_: Arguments.Access = task.args;
const path = args_.path.sliceZ(&this.node_fs.sync_error_buf);
const mode = args_.mode;
const rc = uv.uv_fs_access(loop, &task.req, path.ptr, @intFromEnum(mode), &uv_callback);
bun.debugAssert(rc == .zero);
log("uv stat({s}, {d}) = ~~", .{ path, mode });
},
.exists => {
const args_: Arguments.Exists = task.args;
const path = args_.path orelse return task.earlyResolve(.{ .result = false });
const slice = path.sliceZ(&this.node_fs.sync_error_buf);
const rc = uv.uv_fs_access(loop, &task.req, slice.ptr, std.posix.F_OK, &uv_callback);
bun.debugAssert(rc == .zero);
log("uv exists({s}) = ~~", .{slice});
},
.chmod => {
const args_: Arguments.Chmod = task.args;
const path = args_.path.sliceZ(&this.node_fs.sync_error_buf);
const mode = args_.mode;
const rc = uv.uv_fs_chmod(loop, &task.req, path.ptr, mode, &uv_callback);
bun.debugAssert(rc == .zero);
log("uv chmod({s}, {d}) = ~~", .{ path, mode });
},
.fchmod => {
const args_: Arguments.FChmod = task.args;
const fd = args_.fd.impl().uv();
const mode = args_.mode;
const rc = uv.uv_fs_fchmod(loop, &task.req, fd, mode, &uv_callback);
bun.debugAssert(rc == .zero);
log("uv fchmod({d}, {d}) = ~~", .{ fd, mode });
},
.chown => {
const args_: Arguments.Chown = task.args;
const path = args_.path.sliceZ(&this.node_fs.sync_error_buf);
const uid = args_.uid;
const gid = args_.gid;
const rc = uv.uv_fs_chown(loop, &task.req, path.ptr, uid, gid, &uv_callback);
bun.debugAssert(rc == .zero);
log("uv chown({s}, {d}, {d}) = ~~", .{ path, uid, gid });
},
.fchown => {
const args_: Arguments.Fchown = task.args;
const fd = args_.fd.impl().uv();
const uid = args_.uid;
const gid = args_.gid;
const rc = uv.uv_fs_fchown(loop, &task.req, fd, uid, gid, &uv_callback);
bun.debugAssert(rc == .zero);
log("uv chown({d}, {d}, {d}) = ~~", .{ fd, uid, gid });
},
else => @compileError("unimplemented fire uv_" ++ @tagName(FunctionEnum)),
}
return task.promise.value();
}
fn uv_callback(req: *uv.fs_t) callconv(.C) void {
defer uv.uv_fs_req_cleanup(req);
const this: *Task = @ptrCast(@alignCast(req.data.?));
var node_fs = NodeFS{};
this.result = @field(NodeFS, "uv_" ++ @tagName(FunctionEnum))(&node_fs, this.args, @intFromEnum(req.result));
const args = &this.args;
const rc = @intFromEnum(req.result);
this.result = if (rc < 0) switch (comptime FunctionEnum) {
.open => Maybe(Return.Open){ .err = .{ .errno = @intCast(-rc), .syscall = .open, .path = args.path.slice() } },
.close => Maybe(Return.Close){ .err = .{ .errno = @intCast(-rc), .syscall = .close, .fd = args.fd } },
.read => Maybe(Return.Read){ .err = .{ .errno = @intCast(-rc), .syscall = .read, .fd = args.fd } },
.write => Maybe(Return.Write){ .err = .{ .errno = @intCast(-rc), .syscall = .write, .fd = args.fd } },
.readv => Maybe(Return.Readv){ .err = .{ .errno = @intCast(-rc), .syscall = .readv, .fd = args.fd } },
.writev => Maybe(Return.Writev){ .err = .{ .errno = @intCast(-rc), .syscall = .writev, .fd = args.fd } },
.stat => if (!args.throw_if_no_entry and rc == uv.UV_ENOENT) .{ .result = .not_found } else .{ .err = .{ .errno = @intCast(-rc), .syscall = .stat, .path = args.path.slice() } },
.fstat => .{ .err = .{ .errno = @intCast(-rc), .syscall = .writev, .fd = args.fd } },
.access => .{ .err = .{ .errno = @intCast(-rc), .syscall = .access, .path = args.path.slice() } },
.exists => .{ .result = false },
.chmod => .{ .err = .{ .errno = @intCast(-rc), .syscall = .chmod, .path = args.path.slice() } },
.fchmod => .{ .err = .{ .errno = @intCast(-rc), .syscall = .fchmod, .fd = args.fd } },
.chown => .{ .err = .{ .errno = @intCast(-rc), .syscall = .chown, .path = args.path.slice() } },
.fchown => .{ .err = .{ .errno = @intCast(-rc), .syscall = .fchown, .fd = args.fd } },
else => @compileError("unimplemented callback uv_" ++ @tagName(FunctionEnum)),
} else switch (comptime FunctionEnum) {
.open => Maybe(Return.Open).initResult(FDImpl.decode(bun.toFD(@as(u32, @intCast(rc))))),
.close => Maybe(Return.Close).success,
.read => Maybe(Return.Read).initResult(.{ .bytes_read = @intCast(rc) }),
.write => Maybe(Return.Write).initResult(.{ .bytes_written = @intCast(rc) }),
.readv => Maybe(Return.Readv).initResult(.{ .bytes_read = @intCast(rc) }),
.writev => Maybe(Return.Writev).initResult(.{ .bytes_written = @intCast(rc) }),
.stat => Maybe(Return.Stat).initResult(.{ .stats = Stats.init(req.statbuf, args.big_int) }),
.fstat => Maybe(Return.Fstat).initResult(Stats.init(req.statbuf, false)),
.access => Maybe(Return.Access).success,
.exists => Maybe(Return.Exists).initResult(true),
.chmod => Maybe(Return.Chmod).success,
.fchmod => Maybe(Return.Fchmod).success,
.chown => Maybe(Return.Chown).success,
.fchown => Maybe(Return.Fchown).success,
else => @compileError("unimplemented callback uv_" ++ @tagName(FunctionEnum)),
};
if (this.result == .err) {
this.result.err.path = bun.default_allocator.dupe(u8, this.result.err.path) catch "";
@@ -284,6 +392,12 @@ pub const Async = struct {
this.globalObject.bunVM().eventLoop().enqueueTask(JSC.Task.init(this));
}
fn earlyResolve(this: *Task, value: Maybe(ReturnType)) JSC.JSValue {
this.result = value;
this.globalObject.bunVM().eventLoop().enqueueTask(JSC.Task.init(this));
return this.promise.value();
}
pub fn runFromJSThread(this: *Task) void {
const globalObject = this.globalObject;
var success = @as(JSC.Maybe(ReturnType).Tag, this.result) == .result;
@@ -327,6 +441,7 @@ pub const Async = struct {
this.args.deinit();
}
this.promise.deinit();
this.req.deinit();
this.destroy();
}
};
@@ -4325,17 +4440,6 @@ pub const NodeFS = struct {
return if (Syscall.close(args.fd)) |err| .{ .err = err } else Maybe(Return.Close).success;
}
pub fn uv_close(_: *NodeFS, args: Arguments.Close, rc: i64) Maybe(Return.Close) {
if (rc < 0) {
return Maybe(Return.Close){ .err = .{
.errno = @intCast(-rc),
.syscall = .close,
.fd = args.fd,
} };
}
return Maybe(Return.Close).success;
}
// since we use a 64 KB stack buffer, we should not let this function get inlined
pub noinline fn copyFileUsingReadWriteLoop(src: [:0]const u8, dest: [:0]const u8, src_fd: FileDescriptor, dest_fd: FileDescriptor, stat_size: usize, wrote: *u64) Maybe(Return.CopyFile) {
var stack_buf: [64 * 1024]u8 = undefined;
@@ -5087,18 +5191,6 @@ pub const NodeFS = struct {
};
}
pub fn uv_open(this: *NodeFS, args: Arguments.Open, rc: i64) Maybe(Return.Open) {
_ = this;
if (rc < 0) {
return Maybe(Return.Open){ .err = .{
.errno = @intCast(-rc),
.syscall = .open,
.path = args.path.slice(),
} };
}
return Maybe(Return.Open).initResult(FDImpl.decode(bun.toFD(@as(u32, @intCast(rc)))));
}
pub fn openDir(_: *NodeFS, _: Arguments.OpenDir, comptime _: Flavor) Maybe(Return.OpenDir) {
return Maybe(Return.OpenDir).todo();
}
@@ -5152,30 +5244,6 @@ pub const NodeFS = struct {
);
}
pub fn uv_read(this: *NodeFS, args: Arguments.Read, rc: i64) Maybe(Return.Read) {
_ = this;
if (rc < 0) {
return Maybe(Return.Read){ .err = .{
.errno = @intCast(-rc),
.syscall = .read,
.fd = args.fd,
} };
}
return Maybe(Return.Read).initResult(.{ .bytes_read = @intCast(rc) });
}
pub fn uv_readv(this: *NodeFS, args: Arguments.Readv, rc: i64) Maybe(Return.Readv) {
_ = this;
if (rc < 0) {
return Maybe(Return.Readv){ .err = .{
.errno = @intCast(-rc),
.syscall = .readv,
.fd = args.fd,
} };
}
return Maybe(Return.Readv).initResult(.{ .bytes_read = @intCast(rc) });
}
pub fn readv(this: *NodeFS, args: Arguments.Readv, comptime flavor: Flavor) Maybe(Return.Readv) {
return if (args.position != null) _preadv(this, args, flavor) else _readv(this, args, flavor);
}
@@ -5188,30 +5256,6 @@ pub const NodeFS = struct {
return if (args.position != null) _pwrite(this, args, flavor) else _write(this, args, flavor);
}
pub fn uv_write(this: *NodeFS, args: Arguments.Write, rc: i64) Maybe(Return.Write) {
_ = this;
if (rc < 0) {
return Maybe(Return.Write){ .err = .{
.errno = @intCast(-rc),
.syscall = .write,
.fd = args.fd,
} };
}
return Maybe(Return.Write).initResult(.{ .bytes_written = @intCast(rc) });
}
pub fn uv_writev(this: *NodeFS, args: Arguments.Writev, rc: i64) Maybe(Return.Writev) {
_ = this;
if (rc < 0) {
return Maybe(Return.Writev){ .err = .{
.errno = @intCast(-rc),
.syscall = .writev,
.fd = args.fd,
} };
}
return Maybe(Return.Writev).initResult(.{ .bytes_written = @intCast(rc) });
}
fn _write(_: *NodeFS, args: Arguments.Write, comptime flavor: Flavor) Maybe(Return.Write) {
_ = flavor;