mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Bun.readFile() api
Former-commit-id: 4fd408537571b7b960d1f451ef774a067c125fce
This commit is contained in:
@@ -179,6 +179,69 @@ pub const Bun = struct {
|
||||
return ref;
|
||||
}
|
||||
|
||||
pub fn readFileAsString(
|
||||
this: void,
|
||||
ctx: js.JSContextRef,
|
||||
function: js.JSObjectRef,
|
||||
thisObject: js.JSObjectRef,
|
||||
arguments: []const js.JSValueRef,
|
||||
exception: js.ExceptionRef,
|
||||
) js.JSValueRef {
|
||||
if (arguments.len != 1 or !JSValue.isString(JSValue.fromRef(arguments[0]))) {
|
||||
JSError(getAllocator(ctx), "readFile expects a file path as a string. e.g. Bun.readFile(\"public/index.html\")", .{}, ctx, exception);
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
}
|
||||
var out = ZigString.Empty;
|
||||
JSValue.toZigString(JSValue.fromRef(arguments[0]), &out, VirtualMachine.vm.global);
|
||||
var out_slice = out.slice();
|
||||
|
||||
// The dots are kind of unnecessary. They'll be normalized.
|
||||
if (out.len == 0 or @ptrToInt(out.ptr) == 0 or std.mem.eql(u8, out_slice, ".") or std.mem.eql(u8, out_slice, "..") or std.mem.eql(u8, out_slice, "../")) {
|
||||
JSError(getAllocator(ctx), "readFile expects a valid file path. e.g. Bun.readFile(\"public/index.html\")", .{}, ctx, exception);
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
||||
|
||||
var parts = [_]string{out_slice};
|
||||
// This does the equivalent of Node's path.normalize(path.join(cwd, out_slice))
|
||||
var path = VirtualMachine.vm.bundler.fs.absBuf(&parts, &buf);
|
||||
buf[path.len] = 0;
|
||||
|
||||
const buf_z: [:0]const u8 = buf[0..path.len :0];
|
||||
var file = std.fs.cwd().openFileZ(buf_z, .{ .read = true, .write = false }) catch |err| {
|
||||
JSError(getAllocator(ctx), "Opening file {s} for path: \"{s}\"", .{ @errorName(err), path }, ctx, exception);
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
};
|
||||
|
||||
defer file.close();
|
||||
|
||||
const stat = file.stat() catch |err| {
|
||||
JSError(getAllocator(ctx), "Getting file size {s} for \"{s}\"", .{ @errorName(err), path }, ctx, exception);
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
};
|
||||
|
||||
if (stat.kind != .File) {
|
||||
JSError(getAllocator(ctx), "Can't read a {s} as a string (\"{s}\")", .{ @tagName(stat.kind), path }, ctx, exception);
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
}
|
||||
|
||||
var contents_buf = VirtualMachine.vm.allocator.alloc(u8, stat.size + 2) catch unreachable; // OOM
|
||||
defer VirtualMachine.vm.allocator.free(contents_buf);
|
||||
const contents_len = file.readAll(contents_buf) catch |err| {
|
||||
JSError(getAllocator(ctx), "{s} reading file (\"{s}\")", .{ @errorName(err), path }, ctx, exception);
|
||||
return js.JSValueMakeUndefined(ctx);
|
||||
};
|
||||
|
||||
contents_buf[contents_len] = 0;
|
||||
|
||||
// Very slow to do it this way. We're copying the string twice.
|
||||
// But it's important that this string is garbage collected instead of manually managed.
|
||||
// We can't really recycle this one.
|
||||
// TODO: use external string
|
||||
return js.JSValueMakeString(ctx, js.JSStringCreateWithUTF8CString(contents_buf.ptr));
|
||||
}
|
||||
|
||||
pub fn getPublicPath(to: string, comptime Writer: type, writer: Writer) void {
|
||||
const relative_path = VirtualMachine.vm.bundler.fs.relativeTo(to);
|
||||
if (VirtualMachine.vm.bundler.options.origin.isAbsolute()) {
|
||||
@@ -226,6 +289,13 @@ pub const Bun = struct {
|
||||
.@"return" = "string[]",
|
||||
},
|
||||
},
|
||||
.readFile = .{
|
||||
.rfn = Bun.readFileAsString,
|
||||
.ts = d.ts{
|
||||
.name = "readFile",
|
||||
.@"return" = "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
.Route = Router.Instance.GetClass(void){},
|
||||
|
||||
Reference in New Issue
Block a user