diff options
author | 2023-07-27 16:55:49 -0700 | |
---|---|---|
committer | 2023-07-27 16:55:49 -0700 | |
commit | 007f357495d02ccccc4a75f6f04a7e127d022a72 (patch) | |
tree | 3103a41b1fa8fb350cbeabb34e31536705e744e4 /src | |
parent | 16a7224ce5de519afa4765594d45350c95a87adc (diff) | |
download | bun-007f357495d02ccccc4a75f6f04a7e127d022a72.tar.gz bun-007f357495d02ccccc4a75f6f04a7e127d022a72.tar.zst bun-007f357495d02ccccc4a75f6f04a7e127d022a72.zip |
Make readFile() async (#3850)
* less leaky
* async readfile
* Update types.zig
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/bun.js/node/node_fs.zig | 426 | ||||
-rw-r--r-- | src/bun.js/node/node_fs_binding.zig | 13 | ||||
-rw-r--r-- | src/bun.js/node/types.zig | 28 | ||||
-rw-r--r-- | src/js/node/fs.js | 8 | ||||
-rw-r--r-- | src/js/node/fs.promises.ts | 2 | ||||
-rw-r--r-- | src/js/out/modules/node/fs.js | 5 | ||||
-rw-r--r-- | src/js/out/modules/node/fs.promises.js | 2 |
7 files changed, 310 insertions, 174 deletions
diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index 6d2ec4120..2068cca3f 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -62,14 +62,16 @@ pub const AsyncReaddirTask = struct { task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, result: JSC.Maybe(Return.Readdir), ref: JSC.PollRef = .{}, + arena: bun.ArenaAllocator, - pub fn create(globalObject: *JSC.JSGlobalObject, readdir_args: Arguments.Readdir, vm: *JSC.VirtualMachine) JSC.JSValue { + pub fn create(globalObject: *JSC.JSGlobalObject, readdir_args: Arguments.Readdir, vm: *JSC.VirtualMachine, arena: bun.ArenaAllocator) JSC.JSValue { var task = bun.default_allocator.create(AsyncReaddirTask) catch @panic("out of memory"); task.* = AsyncReaddirTask{ .promise = JSC.JSPromise.Strong.init(globalObject), .args = readdir_args, .result = undefined, .globalObject = globalObject, + .arena = arena, }; task.ref.ref(vm); @@ -120,8 +122,9 @@ pub const AsyncReaddirTask = struct { } pub fn deinit(this: *AsyncReaddirTask) void { + this.arena.deinit(); this.ref.unref(this.globalObject.bunVM()); - this.args.deinit(); + this.args.deinitAndUnprotect(); this.promise.strong.deinit(); bun.default_allocator.destroy(this); } @@ -135,12 +138,14 @@ pub const AsyncStatTask = struct { result: JSC.Maybe(Return.Stat), ref: JSC.PollRef = .{}, is_lstat: bool = false, + arena: bun.ArenaAllocator, pub fn create( globalObject: *JSC.JSGlobalObject, readdir_args: Arguments.Stat, vm: *JSC.VirtualMachine, is_lstat: bool, + arena: bun.ArenaAllocator, ) JSC.JSValue { var task = bun.default_allocator.create(AsyncStatTask) catch @panic("out of memory"); task.* = AsyncStatTask{ @@ -149,6 +154,7 @@ pub const AsyncStatTask = struct { .result = undefined, .globalObject = globalObject, .is_lstat = is_lstat, + .arena = arena, }; task.ref.ref(vm); @@ -202,13 +208,94 @@ pub const AsyncStatTask = struct { } pub fn deinit(this: *AsyncStatTask) void { + this.arena.deinit(); this.ref.unref(this.globalObject.bunVM()); - this.args.deinit(); + this.args.deinitAndUnprotect(); this.promise.strong.deinit(); bun.default_allocator.destroy(this); } }; +pub const AsyncReadFileTask = struct { + promise: JSC.JSPromise.Strong, + args: Arguments.ReadFile, + globalObject: *JSC.JSGlobalObject, + task: JSC.WorkPoolTask = .{ .callback = &workPoolCallback }, + result: JSC.Maybe(Return.ReadFile), + ref: JSC.PollRef = .{}, + arena: bun.ArenaAllocator, + + pub fn create( + globalObject: *JSC.JSGlobalObject, + args: Arguments.ReadFile, + vm: *JSC.VirtualMachine, + arena: bun.ArenaAllocator, + ) JSC.JSValue { + var task = bun.default_allocator.create(AsyncReadFileTask) catch @panic("out of memory"); + task.* = AsyncReadFileTask{ + .promise = JSC.JSPromise.Strong.init(globalObject), + .args = args, + .result = undefined, + .globalObject = globalObject, + .arena = arena, + }; + task.ref.ref(vm); + + JSC.WorkPool.schedule(&task.task); + + return task.promise.value(); + } + + fn workPoolCallback(task: *JSC.WorkPoolTask) void { + var this: *AsyncReadFileTask = @fieldParentPtr(AsyncReadFileTask, "task", task); + + var node_fs = NodeFS{}; + this.result = node_fs.readFile(this.args, .promise); + + this.globalObject.bunVMConcurrently().eventLoop().enqueueTaskConcurrent(JSC.ConcurrentTask.fromCallback(this, runFromJSThread)); + } + + fn runFromJSThread(this: *AsyncReadFileTask) void { + var globalObject = this.globalObject; + var success = @as(JSC.Maybe(Return.ReadFile).Tag, this.result) == .result; + const result = switch (this.result) { + .err => |err| err.toJSC(globalObject), + .result => |res| brk: { + var exceptionref: JSC.C.JSValueRef = null; + const out = JSC.JSValue.c(JSC.To.JS.withType(Return.ReadFile, res, globalObject, &exceptionref)); + const exception = JSC.JSValue.c(exceptionref); + if (exception != .zero) { + success = false; + break :brk exception; + } + + break :brk out; + }, + }; + var promise_value = this.promise.value(); + var promise = this.promise.get(); + promise_value.ensureStillAlive(); + + this.deinit(); + switch (success) { + false => { + promise.reject(globalObject, result); + }, + true => { + promise.resolve(globalObject, result); + }, + } + } + + pub fn deinit(this: *AsyncReadFileTask) void { + this.ref.unref(this.globalObject.bunVM()); + this.args.deinitAndUnprotect(); + this.promise.strong.deinit(); + this.arena.deinit(); + bun.default_allocator.destroy(this); + } +}; + // TODO: to improve performance for all of these // The tagged unions for each type should become regular unions // and the tags should be passed in as comptime arguments to the functions performing the syscalls @@ -812,6 +899,10 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn deinitAndUnprotect(this: Stat) void { + this.path.deinitAndUnprotect(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Stat { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1309,6 +1400,10 @@ pub const Arguments = struct { this.path.deinit(); } + pub fn deinitAndUnprotect(this: Readdir) void { + this.path.deinitAndUnprotect(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?Readdir { const path = PathLike.fromJS(ctx, arguments, exception) orelse { if (exception.* == null) { @@ -1872,6 +1967,10 @@ pub const Arguments = struct { self.path.deinit(); } + pub fn deinitAndUnprotect(self: ReadFile) void { + self.path.deinitAndUnprotect(); + } + pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice, exception: JSC.C.ExceptionRef) ?ReadFile { const path = PathOrFileDescriptor.fromJS(ctx, arguments, arguments.arena.allocator(), exception) orelse { if (exception.* == null) { @@ -3857,193 +3956,186 @@ pub const NodeFS = struct { }; } - pub fn readFileWithOptions(this: *NodeFS, args: Arguments.ReadFile, comptime flavor: Flavor, comptime string_type: StringType) Maybe(Return.ReadFileWithOptions) { + pub fn readFileWithOptions(this: *NodeFS, args: Arguments.ReadFile, comptime _: Flavor, comptime string_type: StringType) Maybe(Return.ReadFileWithOptions) { var path: [:0]const u8 = undefined; - switch (comptime flavor) { - .sync => { - const fd = switch (args.path) { - .path => brk: { - path = args.path.path.sliceZ(&this.sync_error_buf); - if (this.vm) |vm| { - if (vm.standalone_module_graph) |graph| { - if (graph.find(path)) |file| { - if (args.encoding == .buffer) { - return .{ - .result = .{ - .buffer = Buffer.fromBytes( - bun.default_allocator.dupe(u8, file.contents) catch @panic("out of memory"), - bun.default_allocator, - .Uint8Array, - ), - }, - }; - } else if (comptime string_type == .default) - return .{ - .result = .{ - .string = bun.default_allocator.dupe(u8, file.contents) catch @panic("out of memory"), - }, - } - else - return .{ - .result = .{ - .null_terminated = bun.default_allocator.dupeZ(u8, file.contents) catch @panic("out of memory"), - }, - }; + const fd = switch (args.path) { + .path => brk: { + path = args.path.path.sliceZ(&this.sync_error_buf); + if (this.vm) |vm| { + if (vm.standalone_module_graph) |graph| { + if (graph.find(path)) |file| { + if (args.encoding == .buffer) { + return .{ + .result = .{ + .buffer = Buffer.fromBytes( + bun.default_allocator.dupe(u8, file.contents) catch @panic("out of memory"), + bun.default_allocator, + .Uint8Array, + ), + }, + }; + } else if (comptime string_type == .default) + return .{ + .result = .{ + .string = bun.default_allocator.dupe(u8, file.contents) catch @panic("out of memory"), + }, } - } + else + return .{ + .result = .{ + .null_terminated = bun.default_allocator.dupeZ(u8, file.contents) catch @panic("out of memory"), + }, + }; } - - break :brk switch (Syscall.open( - path, - os.O.RDONLY | os.O.NOCTTY, - 0, - )) { - .err => |err| return .{ - .err = err.withPath(if (args.path == .path) args.path.path.slice() else ""), - }, - .result => |fd_| fd_, - }; - }, - .fd => |_fd| _fd, - }; - - defer { - if (args.path == .path) - _ = Syscall.close(fd); + } } - const stat_ = switch (Syscall.fstat(fd)) { + break :brk switch (Syscall.open( + path, + os.O.RDONLY | os.O.NOCTTY, + 0, + )) { .err => |err| return .{ - .err = err, + .err = err.withPath(if (args.path == .path) args.path.path.slice() else ""), }, - .result => |stat_| stat_, + .result => |fd_| fd_, }; + }, + .fd => |_fd| _fd, + }; - // Only used in DOMFormData - if (args.offset > 0) { - std.os.lseek_SET(fd, args.offset) catch {}; - } + defer { + if (args.path == .path) + _ = Syscall.close(fd); + } - // For certain files, the size might be 0 but the file might still have contents. - const size = @as( - u64, - @intCast(@max( - @min( - stat_.size, - @as( - @TypeOf(stat_.size), - // Only used in DOMFormData - @intCast(args.max_size orelse std.math.maxInt( - JSC.WebCore.Blob.SizeType, - )), - ), - ), - 0, - )), - ) + if (comptime string_type == .null_terminated) 1 else 0; - - var buf = std.ArrayList(u8).init(bun.default_allocator); - buf.ensureTotalCapacityPrecise(size + 16) catch unreachable; - buf.expandToCapacity(); - var total: usize = 0; - - while (total < size) { - switch (Syscall.read(fd, buf.items.ptr[total..buf.capacity])) { - .err => |err| return .{ - .err = err, - }, - .result => |amt| { - total += amt; - // There are cases where stat()'s size is wrong or out of date - if (total > size and amt != 0) { - buf.ensureUnusedCapacity(8096) catch unreachable; - buf.expandToCapacity(); - continue; - } + const stat_ = switch (Syscall.fstat(fd)) { + .err => |err| return .{ + .err = err, + }, + .result => |stat_| stat_, + }; - if (amt == 0) { - break; - } - }, + // Only used in DOMFormData + if (args.offset > 0) { + std.os.lseek_SET(fd, args.offset) catch {}; + } + + // For certain files, the size might be 0 but the file might still have contents. + const size = @as( + u64, + @intCast(@max( + @min( + stat_.size, + @as( + @TypeOf(stat_.size), + // Only used in DOMFormData + @intCast(args.max_size orelse std.math.maxInt( + JSC.WebCore.Blob.SizeType, + )), + ), + ), + 0, + )), + ) + if (comptime string_type == .null_terminated) 1 else 0; + + var buf = std.ArrayList(u8).init(bun.default_allocator); + buf.ensureTotalCapacityPrecise(size + 16) catch unreachable; + buf.expandToCapacity(); + var total: usize = 0; + + while (total < size) { + switch (Syscall.read(fd, buf.items.ptr[total..buf.capacity])) { + .err => |err| return .{ + .err = err, + }, + .result => |amt| { + total += amt; + // There are cases where stat()'s size is wrong or out of date + if (total > size and amt != 0) { + buf.ensureUnusedCapacity(8096) catch unreachable; + buf.expandToCapacity(); + continue; } - } else { - // https://github.com/oven-sh/bun/issues/1220 - while (true) { - switch (Syscall.read(fd, buf.items.ptr[total..buf.capacity])) { - .err => |err| return .{ - .err = err, - }, - .result => |amt| { - total += amt; - // There are cases where stat()'s size is wrong or out of date - if (total > size and amt != 0) { - buf.ensureUnusedCapacity(8096) catch unreachable; - buf.expandToCapacity(); - continue; - } - if (amt == 0) { - break; - } - }, - } + if (amt == 0) { + break; } + }, + } + } else { + // https://github.com/oven-sh/bun/issues/1220 + while (true) { + switch (Syscall.read(fd, buf.items.ptr[total..buf.capacity])) { + .err => |err| return .{ + .err = err, + }, + .result => |amt| { + total += amt; + // There are cases where stat()'s size is wrong or out of date + if (total > size and amt != 0) { + buf.ensureUnusedCapacity(8096) catch unreachable; + buf.expandToCapacity(); + continue; + } + + if (amt == 0) { + break; + } + }, } + } + } - buf.items.len = if (comptime string_type == .null_terminated) total + 1 else total; - if (total == 0) { - buf.deinit(); - return switch (args.encoding) { - .buffer => .{ + buf.items.len = if (comptime string_type == .null_terminated) total + 1 else total; + if (total == 0) { + buf.deinit(); + return switch (args.encoding) { + .buffer => .{ + .result = .{ + .buffer = Buffer.empty, + }, + }, + else => brk: { + if (comptime string_type == .default) { + break :brk .{ .result = .{ - .buffer = Buffer.empty, + .string = "", }, - }, - else => brk: { - if (comptime string_type == .default) { - break :brk .{ - .result = .{ - .string = "", - }, - }; - } else { - break :brk .{ - .result = .{ - .null_terminated = "", - }, - }; - } + }; + } else { + break :brk .{ + .result = .{ + .null_terminated = "", + }, + }; + } + }, + }; + } + + return switch (args.encoding) { + .buffer => .{ + .result = .{ + .buffer = Buffer.fromBytes(buf.items, bun.default_allocator, .Uint8Array), + }, + }, + else => brk: { + if (comptime string_type == .default) { + break :brk .{ + .result = .{ + .string = buf.items, }, }; - } - - return switch (args.encoding) { - .buffer => .{ + } else { + break :brk .{ .result = .{ - .buffer = Buffer.fromBytes(buf.items, bun.default_allocator, .Uint8Array), + .null_terminated = buf.toOwnedSliceSentinel(0) catch unreachable, }, - }, - else => brk: { - if (comptime string_type == .default) { - break :brk .{ - .result = .{ - .string = buf.items, - }, - }; - } else { - break :brk .{ - .result = .{ - .null_terminated = buf.toOwnedSliceSentinel(0) catch unreachable, - }, - }; - } - }, - }; + }; + } }, - else => {}, - } - - return Maybe(Return.ReadFile).todo; + }; } pub fn writeFileWithPathBuffer(pathbuf: *[bun.MAX_PATH_BYTES]u8, args: Arguments.WriteFile) Maybe(Return.WriteFile) { diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index 88e0b30e2..b7ce9996c 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -108,7 +108,7 @@ fn call(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction { globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame, ) callconv(.C) JSC.JSValue { - if (comptime FunctionEnum != .readdir and FunctionEnum != .lstat and FunctionEnum != .stat) { + if (comptime FunctionEnum != .readdir and FunctionEnum != .lstat and FunctionEnum != .stat and FunctionEnum != .readFile) { globalObject.throw("Not implemented yet", .{}); return .zero; } @@ -122,6 +122,7 @@ fn call(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction { // we might've already thrown if (exceptionref != null) globalObject.throwValue(JSC.JSValue.c(exceptionref)); + slice.deinit(); return .zero; }) else @@ -131,17 +132,23 @@ fn call(comptime FunctionEnum: NodeFSFunctionEnum) NodeFSFunction { if (exception1 != .zero) { globalObject.throwValue(exception1); + + slice.deinit(); return .zero; } // TODO: handle globalObject.throwValue if (comptime FunctionEnum == .readdir) { - return JSC.Node.AsyncReaddirTask.create(globalObject, args, slice.vm); + return JSC.Node.AsyncReaddirTask.create(globalObject, args, slice.vm, slice.arena); + } + + if (comptime FunctionEnum == .readFile) { + return JSC.Node.AsyncReadFileTask.create(globalObject, args, slice.vm, slice.arena); } if (comptime FunctionEnum == .stat or FunctionEnum == .lstat) { - return JSC.Node.AsyncStatTask.create(globalObject, args, slice.vm, FunctionEnum == .lstat); + return JSC.Node.AsyncStatTask.create(globalObject, args, slice.vm, FunctionEnum == .lstat, slice.arena); } // defer { diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index dadf28629..e472f370f 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -629,6 +629,18 @@ pub const PathLike = union(Tag) { } } + pub fn deinitAndUnprotect(this: *const PathLike) void { + switch (this.*) { + .slice_with_underlying_string => |val| { + val.deinit(); + }, + .buffer => |val| { + val.buffer.value.unprotect(); + }, + else => {}, + } + } + pub inline fn slice(this: PathLike) string { return switch (this) { .string => this.string.slice(), @@ -917,6 +929,15 @@ pub const ArgumentsSlice = struct { }; } + pub fn initAsync(vm: *JSC.VirtualMachine, arguments: []const JSC.JSValue) ArgumentsSlice { + return ArgumentsSlice{ + .remaining = bun.default_allocator.dupe(JSC.JSValue, arguments), + .vm = vm, + .all = arguments, + .arena = bun.ArenaAllocator.init(bun.default_allocator), + }; + } + pub inline fn len(this: *const ArgumentsSlice) u16 { return @as(u16, @truncate(this.remaining.len)); } @@ -1029,6 +1050,12 @@ pub const PathOrFileDescriptor = union(Tag) { } } + pub fn deinitAndUnprotect(this: PathOrFileDescriptor) void { + if (this == .path) { + this.path.deinitAndUnprotect(); + } + } + pub fn hash(this: JSC.Node.PathOrFileDescriptor) u64 { return switch (this) { .path => bun.hash(this.path.slice()), @@ -1962,6 +1989,7 @@ pub const Path = struct { defer str.deref(); return str.toJS(globalThis); } + pub fn normalize(globalThis: *JSC.JSGlobalObject, isWindows: bool, args_ptr: [*]JSC.JSValue, args_len: u16) callconv(.C) JSC.JSValue { if (comptime is_bindgen) return JSC.JSValue.jsUndefined(); if (args_len == 0) return JSC.ZigString.init("").toValue(globalThis); diff --git a/src/js/node/fs.js b/src/js/node/fs.js index f847cf179..aa03ffc5c 100644 --- a/src/js/node/fs.js +++ b/src/js/node/fs.js @@ -147,7 +147,13 @@ export var access = function access(...args) { fs.readdir(...args).then(result => callback(null, result), callback); }, readFile = function readFile(...args) { - callbackify(fs.readFileSync, args); + const callback = args[args.length - 1]; + if (typeof callback !== "function") { + // TODO: set code + throw new TypeError("Callback must be a function"); + } + + fs.readFile(...args).then(result => callback(null, result), callback); }, writeFile = function writeFile(...args) { callbackify(fs.writeFileSync, args); diff --git a/src/js/node/fs.promises.ts b/src/js/node/fs.promises.ts index 1826586ae..0bf6eb9b2 100644 --- a/src/js/node/fs.promises.ts +++ b/src/js/node/fs.promises.ts @@ -90,7 +90,7 @@ export var access = promisify(fs.accessSync), read = promisify(fs.readSync), write = promisify(fs.writeSync), readdir = fs.readdir.bind(fs), - readFile = promisify(fs.readFileSync), + readFile = fs.readFile.bind(fs), writeFile = promisify(fs.writeFileSync), readlink = promisify(fs.readlinkSync), realpath = promisify(fs.realpathSync), diff --git a/src/js/out/modules/node/fs.js b/src/js/out/modules/node/fs.js index 947eaf826..720d03134 100644 --- a/src/js/out/modules/node/fs.js +++ b/src/js/out/modules/node/fs.js @@ -113,7 +113,10 @@ var access = function access2(...args) { throw new TypeError("Callback must be a function"); fs.readdir(...args).then((result) => callback(null, result), callback); }, readFile = function readFile2(...args) { - callbackify(fs.readFileSync, args); + const callback = args[args.length - 1]; + if (typeof callback !== "function") + throw new TypeError("Callback must be a function"); + fs.readFile(...args).then((result) => callback(null, result), callback); }, writeFile = function writeFile2(...args) { callbackify(fs.writeFileSync, args); }, readlink = function readlink2(...args) { diff --git a/src/js/out/modules/node/fs.promises.js b/src/js/out/modules/node/fs.promises.js index 185955dd5..852836098 100644 --- a/src/js/out/modules/node/fs.promises.js +++ b/src/js/out/modules/node/fs.promises.js @@ -1 +1 @@ -var o=(g)=>{return import.meta.require(g)};function H(g,q={}){const C=[];if(g instanceof URL)throw new TypeError("Watch URLs are not supported yet");else if(Buffer.isBuffer(g))g=g.toString();else if(typeof g!=="string")throw new TypeError("Expected path to be a string or Buffer");let B=null;if(typeof q==="string")q={encoding:q};return P.watch(g,q||{},(A,z)=>{if(C.push({eventType:A,filename:z}),B){const D=B;B=null,D()}}),{async*[Symbol.asyncIterator](){let A=!1;while(!A){while(C.length){let z=C.shift();if(z.eventType==="close"){A=!0;break}if(z.eventType==="error")throw A=!0,z.filename;yield z}await new Promise((z)=>B=z)}}}}var P=Bun.fs(),G="::bunternal::",U={[G]:(g)=>{return async function(...q){return await 1,g.apply(P,q)}}}[G],I=U(P.accessSync),J=U(P.appendFileSync),K=U(P.closeSync),L=U(P.copyFileSync),M=U(P.existsSync),N=U(P.chownSync),O=U(P.chmodSync),Q=U(P.fchmodSync),S=U(P.fchownSync),V=U(P.fstatSync),X=U(P.fsyncSync),Y=U(P.ftruncateSync),Z=U(P.futimesSync),_=U(P.lchmodSync),$=U(P.lchownSync),T=U(P.linkSync),W=P.lstat.bind(P),j=U(P.mkdirSync),x=U(P.mkdtempSync),E=U(P.openSync),F=U(P.readSync),w=U(P.writeSync),k=P.readdir.bind(P),R=U(P.readFileSync),h=U(P.writeFileSync),b=U(P.readlinkSync),u=U(P.realpathSync),c=U(P.renameSync),d=P.stat.bind(P),v=U(P.symlinkSync),a=U(P.truncateSync),l=U(P.unlinkSync),y=U(P.utimesSync),p=U(P.lutimesSync),m=U(P.rmSync),n=U(P.rmdirSync),t=(g,q,C)=>{return new Promise((B,A)=>{try{var z=P.writevSync(g,q,C)}catch(D){A(D);return}B({bytesWritten:z,buffers:q})})},r=(g,q,C)=>{return new Promise((B,A)=>{try{var z=P.readvSync(g,q,C)}catch(D){A(D);return}B({bytesRead:z,buffers:q})})},f={access:I,appendFile:J,close:K,copyFile:L,exists:M,chown:N,chmod:O,fchmod:Q,fchown:S,fstat:V,fsync:X,ftruncate:Y,futimes:Z,lchmod:_,lchown:$,link:T,lstat:W,mkdir:j,mkdtemp:x,open:E,read:F,write:w,readdir:k,readFile:R,writeFile:h,readlink:b,realpath:u,rename:c,stat:d,symlink:v,truncate:a,unlink:l,utimes:y,lutimes:p,rm:m,rmdir:n,watch:H,writev:t,readv:r,constants,[Symbol.for("CommonJS")]:0};export{t as writev,h as writeFile,w as write,H as watch,y as utimes,l as unlink,a as truncate,v as symlink,d as stat,n as rmdir,m as rm,c as rename,u as realpath,r as readv,b as readlink,k as readdir,R as readFile,F as read,E as open,x as mkdtemp,j as mkdir,p as lutimes,W as lstat,T as link,$ as lchown,_ as lchmod,Z as futimes,Y as ftruncate,X as fsync,V as fstat,S as fchown,Q as fchmod,M as exists,f as default,L as copyFile,K as close,N as chown,O as chmod,J as appendFile,I as access}; +var o=(S)=>{return import.meta.require(S)};function G(S,U={}){const A=[];if(S instanceof URL)throw new TypeError("Watch URLs are not supported yet");else if(Buffer.isBuffer(S))S=S.toString();else if(typeof S!=="string")throw new TypeError("Expected path to be a string or Buffer");let z=null;if(typeof U==="string")U={encoding:U};return C.watch(S,U||{},(q,g)=>{if(A.push({eventType:q,filename:g}),z){const B=z;z=null,B()}}),{async*[Symbol.asyncIterator](){let q=!1;while(!q){while(A.length){let g=A.shift();if(g.eventType==="close"){q=!0;break}if(g.eventType==="error")throw q=!0,g.filename;yield g}await new Promise((g)=>z=g)}}}}var C=Bun.fs(),D="::bunternal::",J={[D]:(S)=>{return async function(...U){return await 1,S.apply(C,U)}}}[D],H=J(C.accessSync),I=J(C.appendFileSync),K=J(C.closeSync),L=J(C.copyFileSync),M=J(C.existsSync),N=J(C.chownSync),O=J(C.chmodSync),P=J(C.fchmodSync),Q=J(C.fchownSync),V=J(C.fstatSync),X=J(C.fsyncSync),Y=J(C.ftruncateSync),Z=J(C.futimesSync),_=J(C.lchmodSync),$=J(C.lchownSync),T=J(C.linkSync),W=C.lstat.bind(C),j=J(C.mkdirSync),x=J(C.mkdtempSync),E=J(C.openSync),F=J(C.readSync),k=J(C.writeSync),R=C.readdir.bind(C),w=C.readFile.bind(C),h=J(C.writeFileSync),b=J(C.readlinkSync),u=J(C.realpathSync),d=J(C.renameSync),c=C.stat.bind(C),v=J(C.symlinkSync),a=J(C.truncateSync),l=J(C.unlinkSync),y=J(C.utimesSync),p=J(C.lutimesSync),m=J(C.rmSync),n=J(C.rmdirSync),t=(S,U,A)=>{return new Promise((z,q)=>{try{var g=C.writevSync(S,U,A)}catch(B){q(B);return}z({bytesWritten:g,buffers:U})})},r=(S,U,A)=>{return new Promise((z,q)=>{try{var g=C.readvSync(S,U,A)}catch(B){q(B);return}z({bytesRead:g,buffers:U})})},i={access:H,appendFile:I,close:K,copyFile:L,exists:M,chown:N,chmod:O,fchmod:P,fchown:Q,fstat:V,fsync:X,ftruncate:Y,futimes:Z,lchmod:_,lchown:$,link:T,lstat:W,mkdir:j,mkdtemp:x,open:E,read:F,write:k,readdir:R,readFile:w,writeFile:h,readlink:b,realpath:u,rename:d,stat:c,symlink:v,truncate:a,unlink:l,utimes:y,lutimes:p,rm:m,rmdir:n,watch:G,writev:t,readv:r,constants,[Symbol.for("CommonJS")]:0};export{t as writev,h as writeFile,k as write,G as watch,y as utimes,l as unlink,a as truncate,v as symlink,c as stat,n as rmdir,m as rm,d as rename,u as realpath,r as readv,b as readlink,R as readdir,w as readFile,F as read,E as open,x as mkdtemp,j as mkdir,p as lutimes,W as lstat,T as link,$ as lchown,_ as lchmod,Z as futimes,Y as ftruncate,X as fsync,V as fstat,Q as fchown,P as fchmod,M as exists,i as default,L as copyFile,K as close,N as chown,O as chmod,I as appendFile,H as access}; |