aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bun.js/api/bun.zig3
-rw-r--r--src/bun.js/api/server.zig22
-rw-r--r--src/bun.js/javascript.zig5
-rw-r--r--src/bun.js/node/node_fs.zig30
-rw-r--r--src/bun.js/webcore/blob.zig36
-rw-r--r--src/cli/build_command.zig1
-rw-r--r--src/standalone_bun.zig44
7 files changed, 124 insertions, 17 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 034aaa81f..2e6381c74 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -896,6 +896,9 @@ pub fn createNodeFS(
) js.JSValueRef {
var module = ctx.allocator().create(JSC.Node.NodeJSFS) catch unreachable;
module.* = .{};
+ var vm = ctx.bunVM();
+ if (vm.standalone_module_graph != null)
+ module.node_fs.vm = vm;
return module.toJS(ctx).asObjectRef();
}
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index a56ff971f..ebfacdcc9 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -2744,19 +2744,15 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
// 1. Bun.file("foo")
// 2. The content-disposition header is not present
if (!has_content_disposition and content_type.category.autosetFilename()) {
- if (this.blob.store()) |store| {
- if (store.data == .file) {
- if (store.data.file.pathlike == .path) {
- const basename = std.fs.path.basename(store.data.file.pathlike.path.slice());
- if (basename.len > 0) {
- var filename_buf: [1024]u8 = undefined;
-
- resp.writeHeader(
- "content-disposition",
- std.fmt.bufPrint(&filename_buf, "filename=\"{s}\"", .{basename[0..@min(basename.len, 1024 - 32)]}) catch "",
- );
- }
- }
+ if (this.blob.getFileName()) |filename| {
+ const basename = std.fs.path.basename(filename);
+ if (basename.len > 0) {
+ var filename_buf: [1024]u8 = undefined;
+
+ resp.writeHeader(
+ "content-disposition",
+ std.fmt.bufPrint(&filename_buf, "filename=\"{s}\"", .{basename[0..@min(basename.len, 1024 - 32)]}) catch "",
+ );
}
}
}
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index 3baa25e22..cb1a50f1d 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -593,7 +593,10 @@ pub const VirtualMachine = struct {
pub inline fn nodeFS(this: *VirtualMachine) *Node.NodeFS {
return this.node_fs orelse brk: {
this.node_fs = bun.default_allocator.create(Node.NodeFS) catch unreachable;
- this.node_fs.?.* = Node.NodeFS{};
+ this.node_fs.?.* = Node.NodeFS{
+ // only used when standalone module graph is enabled
+ .vm = if (this.standalone_module_graph != null) this else null,
+ };
break :brk this.node_fs.?;
};
}
diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig
index 21a65251a..35c616a89 100644
--- a/src/bun.js/node/node_fs.zig
+++ b/src/bun.js/node/node_fs.zig
@@ -2492,6 +2492,7 @@ pub const NodeFS = struct {
/// That means a stack-allocated buffer won't suffice. Instead, we re-use
/// the heap allocated buffer on the NodefS struct
sync_error_buf: [bun.MAX_PATH_BYTES]u8 = undefined,
+ vm: ?*JSC.VirtualMachine = null,
pub const ReturnType = Return;
@@ -3442,6 +3443,35 @@ pub const NodeFS = struct {
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)
+ .{
+ .result = .{
+ .string = bun.default_allocator.dupe(u8, file.contents) catch @panic("out of memory"),
+ },
+ }
+ else
+ .{
+ .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,
diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig
index 1e63ea3a2..868acbb80 100644
--- a/src/bun.js/webcore/blob.zig
+++ b/src/bun.js/webcore/blob.zig
@@ -952,6 +952,13 @@ pub const Blob = struct {
switch (path_) {
.path => {
const slice = path_.path.slice();
+
+ if (vm.standalone_module_graph) |graph| {
+ if (graph.find(slice)) |file| {
+ return file.blob(globalThis).dupe();
+ }
+ }
+
var cloned = (allocator.dupeZ(u8, slice) catch unreachable)[0..slice.len];
break :brk .{
@@ -2195,6 +2202,9 @@ pub const Blob = struct {
cap: SizeType = 0,
allocator: std.mem.Allocator,
+ /// Used by standalone module graph
+ stored_name: bun.PathString = bun.PathString.empty,
+
pub fn init(bytes: []u8, allocator: std.mem.Allocator) ByteStore {
return .{
.ptr = bytes.ptr,
@@ -2528,17 +2538,31 @@ pub const Blob = struct {
this: *Blob,
globalThis: *JSC.JSGlobalObject,
) callconv(.C) JSValue {
+ if (this.getFileName()) |path| {
+ var str = bun.String.create(path);
+ return str.toJS(globalThis);
+ }
+
+ return JSValue.undefined;
+ }
+
+ pub fn getFileName(
+ this: *const Blob,
+ ) ?[]const u8 {
if (this.store) |store| {
if (store.data == .file) {
if (store.data.file.pathlike == .path) {
- return ZigString.fromUTF8(store.data.file.pathlike.path.slice()).toValueGC(globalThis);
+ return store.data.file.pathlike.path.slice();
}
// we shouldn't return Number here.
+ } else if (store.data == .bytes) {
+ if (store.data.bytes.stored_name.slice().len > 0)
+ return store.data.bytes.stored_name.slice();
}
}
- return JSC.JSValue.jsUndefined();
+ return null;
}
// TODO: Move this to a separate `File` object or BunFile
@@ -3469,6 +3493,14 @@ pub const AnyBlob = union(enum) {
InternalBlob: InternalBlob,
WTFStringImpl: bun.WTF.StringImpl,
+ pub fn getFileName(this: *const AnyBlob) ?[]const u8 {
+ return switch (this.*) {
+ .Blob => this.Blob.getFileName(),
+ .WTFStringImpl => null,
+ .InternalBlob => null,
+ };
+ }
+
pub inline fn fastSize(this: *const AnyBlob) Blob.SizeType {
return switch (this.*) {
.Blob => this.Blob.size,
diff --git a/src/cli/build_command.zig b/src/cli/build_command.zig
index 44e512996..ef99f7765 100644
--- a/src/cli/build_command.zig
+++ b/src/cli/build_command.zig
@@ -107,6 +107,7 @@ pub const BuildCommand = struct {
// We never want to hit the filesystem for these files
// This "compiled" protocol is specially handled by the module resolver.
this_bundler.options.public_path = "compiled://root/";
+ this_bundler.resolver.opts.public_path = "compiled://root/";
if (outfile.len == 0) {
outfile = std.fs.path.basename(this_bundler.options.entry_points[0]);
diff --git a/src/standalone_bun.zig b/src/standalone_bun.zig
index e7363fb58..b18fe384e 100644
--- a/src/standalone_bun.zig
+++ b/src/standalone_bun.zig
@@ -18,6 +18,14 @@ pub const StandaloneModuleGraph = struct {
return &this.files.values()[this.entry_point_id];
}
+ pub fn find(this: *const StandaloneModuleGraph, name: []const u8) ?*File {
+ if (!bun.strings.hasPrefixComptime(name, "compiled://root/")) {
+ return null;
+ }
+
+ return this.files.getPtr(name);
+ }
+
pub const CompiledModuleGraphFile = struct {
name: Schema.StringPointer = .{},
loader: bun.options.Loader = .file,
@@ -30,6 +38,32 @@ pub const StandaloneModuleGraph = struct {
loader: bun.options.Loader,
contents: []const u8 = "",
sourcemap: LazySourceMap,
+ blob_: ?*bun.JSC.WebCore.Blob = null,
+
+ pub fn blob(this: *File, globalObject: *bun.JSC.JSGlobalObject) *bun.JSC.WebCore.Blob {
+ if (this.blob_ == null) {
+ var store = bun.JSC.WebCore.Blob.Store.init(@constCast(this.contents), bun.default_allocator) catch @panic("out of memory");
+ // make it never free
+ store.ref();
+
+ var blob_ = bun.default_allocator.create(bun.JSC.WebCore.Blob) catch @panic("out of memory");
+ blob_.* = bun.JSC.WebCore.Blob.initWithStore(store, globalObject);
+ blob_.allocator = bun.default_allocator;
+
+ if (bun.HTTP.MimeType.byExtensionNoDefault(bun.strings.trimLeadingChar(std.fs.path.extension(this.name), '.'))) |mime| {
+ store.mime_type = mime;
+ blob_.content_type = mime.value;
+ blob_.content_type_was_set = true;
+ blob_.content_type_allocated = false;
+ }
+
+ store.data.bytes.stored_name = bun.PathString.init(this.name);
+
+ this.blob_ = blob_;
+ }
+
+ return this.blob_.?;
+ }
};
pub const LazySourceMap = union(enum) {
@@ -152,8 +186,16 @@ pub const StandaloneModuleGraph = struct {
continue;
}
+ var dest_path = output_file.dest_path;
+ if (bun.strings.hasPrefixComptime(dest_path, "./")) {
+ dest_path = dest_path[2..];
+ }
+
var module = CompiledModuleGraphFile{
- .name = string_builder.fmtAppendCount("{s}{s}", .{ prefix, output_file.dest_path }),
+ .name = string_builder.fmtAppendCount("{s}{s}", .{
+ prefix,
+ dest_path,
+ }),
.loader = output_file.loader,
.contents = string_builder.appendCount(output_file.value.buffer.bytes),
};