aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/javascript/jsc/JavascriptCore.zig2
-rw-r--r--src/javascript/jsc/base.zig40
-rw-r--r--src/javascript/jsc/javascript.zig72
3 files changed, 113 insertions, 1 deletions
diff --git a/src/javascript/jsc/JavascriptCore.zig b/src/javascript/jsc/JavascriptCore.zig
index 612009a1f..f443799c1 100644
--- a/src/javascript/jsc/JavascriptCore.zig
+++ b/src/javascript/jsc/JavascriptCore.zig
@@ -18,7 +18,7 @@ pub const struct_OpaqueJSPropertyNameArray = generic;
pub const JSPropertyNameArrayRef = ?*struct_OpaqueJSPropertyNameArray;
pub const struct_OpaqueJSPropertyNameAccumulator = generic;
pub const JSPropertyNameAccumulatorRef = ?*struct_OpaqueJSPropertyNameAccumulator;
-pub const JSTypedArrayBytesDeallocator = ?fn (?*c_void, ?*c_void) callconv(.C) void;
+pub const JSTypedArrayBytesDeallocator = ?fn (*c_void, *c_void) callconv(.C) void;
pub const OpaqueJSValue = generic;
pub const JSValueRef = ?*OpaqueJSValue;
pub const JSObjectRef = ?*OpaqueJSValue;
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig
index 4acd688c1..65300f07c 100644
--- a/src/javascript/jsc/base.zig
+++ b/src/javascript/jsc/base.zig
@@ -1494,8 +1494,48 @@ pub const ArrayBuffer = struct {
byte_len: u32,
typed_array_type: js.JSTypedArrayType,
+
+ pub inline fn slice(this: *const ArrayBuffer) []u8 {
+ return this.ptr[this.offset .. this.offset + this.byte_len];
+ }
};
+pub const MarkedArrayBuffer = struct {
+ buffer: ArrayBuffer,
+ allocator: *std.mem.Allocator,
+
+ pub fn fromBytes(bytes: []u8, allocator: *std.mem.Allocator, typed_array_type: js.JSTypedArrayType) MarkedArrayBuffer {
+ return MarkedArrayBuffer{
+ .buffer = ArrayBuffer{ .offset = 0, .len = @intCast(u32, bytes.len), .byte_len = @intCast(u32, bytes.len), .typed_array_type = typed_array_type, .ptr = bytes.ptr },
+ .allocator = allocator,
+ };
+ }
+
+ pub fn destroy(this: *MarkedArrayBuffer) void {
+ const content = this.*;
+ content.allocator.free(content.buffer.slice());
+ content.allocator.destroy(this);
+ }
+
+ pub fn init(allocator: *std.mem.Allocator, size: u32, typed_array_type: js.JSTypedArrayType) !*MarkedArrayBuffer {
+ const bytes = try allocator.alloc(u8, size);
+ var container = try allocator.create(MarkedArrayBuffer);
+ container.* = MarkedArrayBuffer.fromBytes(bytes, allocator, typed_array_type);
+ return container;
+ }
+
+ pub fn toJSObjectRef(this: *MarkedArrayBuffer, ctx: js.JSContextRef, exception: js.ExceptionRef) js.JSObjectRef {
+ return js.JSObjectMakeTypedArrayWithBytesNoCopy(ctx, this.buffer.typed_array_type, this.buffer.ptr, this.buffer.byte_len, MarkedArrayBuffer_deallocator, this, exception);
+ }
+};
+
+export fn MarkedArrayBuffer_deallocator(bytes_: *c_void, ctx_: *c_void) void {
+ var ctx = @ptrCast(*MarkedArrayBuffer, @alignCast(@alignOf(*MarkedArrayBuffer), ctx_));
+
+ if (comptime isDebug) std.debug.assert(ctx.buffer.ptr == @ptrCast([*]u8, bytes_));
+ ctx.destroy();
+}
+
pub fn castObj(obj: js.JSObjectRef, comptime Type: type) *Type {
return JSPrivateDataPtr.from(js.JSObjectGetPrivate(obj)).as(Type);
}
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index e4ccd62e5..50585bf91 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -181,6 +181,71 @@ pub const Bun = struct {
return ref;
}
+ pub fn readFileAsBytes(
+ 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), "readFileBytes 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), "readFileBytes 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
+ errdefer 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;
+
+ var marked_array_buffer = VirtualMachine.vm.allocator.create(MarkedArrayBuffer) catch unreachable;
+ marked_array_buffer.* = MarkedArrayBuffer.fromBytes(
+ contents_buf[0..contents_len],
+ VirtualMachine.vm.allocator,
+ js.JSTypedArrayType.kJSTypedArrayTypeUint8Array,
+ );
+
+ return marked_array_buffer.toJSObjectRef(ctx, exception);
+ }
pub fn readFileAsString(
this: void,
@@ -324,6 +389,13 @@ pub const Bun = struct {
.@"return" = "string",
},
},
+ .readFileBytes = .{
+ .rfn = Bun.readFileAsBytes,
+ .ts = d.ts{
+ .name = "readFile",
+ .@"return" = "Uint8Array",
+ },
+ },
.getPublicPath = .{
.rfn = Bun.getPublicPathJS,
.ts = d.ts{