aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bundler.zig505
-rw-r--r--src/feature_flags.zig2
-rw-r--r--src/fs.zig1
-rw-r--r--src/global.zig31
-rw-r--r--src/js_parser/imports.zig2
-rw-r--r--src/main.zig8
-rw-r--r--src/node_fallbacks.zig18
-rw-r--r--src/runtime.js91
8 files changed, 353 insertions, 305 deletions
diff --git a/src/bundler.zig b/src/bundler.zig
index 3614f4c53..4da491d26 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -580,6 +580,10 @@ pub fn NewBundler(cache_files: bool) type {
work_waiter: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0),
list_lock: Lock = Lock.init(),
+ dynamic_import_file_size_store: U32Map,
+ dynamic_import_file_size_store_lock: Lock,
+
+ const U32Map = std.AutoHashMap(u32, u32);
pub const current_version: u32 = 1;
const dist_index_js_string_pointer = Api.StringPointer{ .length = "dist/index.js".len };
const index_js_string_pointer = Api.StringPointer{ .length = "index.js".len, .offset = "dist/".len };
@@ -693,6 +697,8 @@ pub fn NewBundler(cache_files: bool) type {
// .resolve_queue = queue,
.bundler = bundler,
.tmpfile = tmpfile,
+ .dynamic_import_file_size_store = U32Map.init(allocator),
+ .dynamic_import_file_size_store_lock = Lock.init(),
.log = bundler.log,
.package_list_map = std.AutoHashMap(u64, u32).init(allocator),
.pool = undefined,
@@ -1105,6 +1111,24 @@ pub fn NewBundler(cache_files: bool) type {
}
};
+ fn writeEmptyModule(this: *GenerateNodeModuleBundle, package_relative_path: string, module_id: u32) !u32 {
+ this.write_lock.lock();
+ defer this.write_lock.unlock();
+ var code_offset = @truncate(u32, try this.tmpfile.getPos());
+ var writer = this.tmpfile.writer();
+ var buffered = std.io.bufferedWriter(writer);
+
+ var bufwriter = buffered.writer();
+ try bufwriter.writeAll("// ");
+ try bufwriter.writeAll(package_relative_path);
+ try bufwriter.writeAll(" (disabled/empty)\nexport var $");
+ std.fmt.formatInt(module_id, 16, .lower, .{}, bufwriter) catch unreachable;
+ try bufwriter.writeAll(" = () => { var obj = {}; Object.defineProperty(obj, 'default', { value: obj, enumerable: false, configurable: true }, obj); return obj; }; \n");
+ try buffered.flush();
+ this.tmpfile_byte_offset = @truncate(u32, try this.tmpfile.getPos());
+ return code_offset;
+ }
+
fn processImportRecord(this: *GenerateNodeModuleBundle, import_record: ImportRecord) !void {}
var json_ast_symbols = [_]js_ast.Symbol{
js_ast.Symbol{ .original_name = "$$m" },
@@ -1192,23 +1216,8 @@ pub fn NewBundler(cache_files: bool) type {
shared_buffer,
);
- var module_name = file_path.text["/bun-vfs/node_modules/".len..];
-
- if (module_name[0] == '@') {
- var end = strings.indexOfChar(module_name, '/').? + 1;
- end += strings.indexOfChar(module_name[end..], '/').?;
-
- module_name = module_name[0..end];
- } else {
- module_name = module_name[0..strings.indexOfChar(module_name, '/').?];
- }
-
- if (NodeFallbackModules.Map.get(module_name)) |mod| {
- break :brk CacheEntry{ .contents = mod.code.* };
- }
-
break :brk CacheEntry{
- .contents = "",
+ .contents = NodeFallbackModules.contentsFromPath(file_path.text) orelse "",
};
};
@@ -1217,20 +1226,7 @@ pub fn NewBundler(cache_files: bool) type {
// So we just say it's an empty object. Empty object mimicks what "browser": false does as well.
// TODO: optimize this so that all the exports for these are done in one line instead of writing repeatedly
if (entry.contents.len == 0 or (entry.contents.len < 33 and strings.trim(entry.contents, " \n\r").len == 0)) {
- this.write_lock.lock();
- defer this.write_lock.unlock();
- code_offset = @truncate(u32, try this.tmpfile.getPos());
- var writer = this.tmpfile.writer();
- var buffered = std.io.bufferedWriter(writer);
-
- var bufwriter = buffered.writer();
- try bufwriter.writeAll("// ");
- try bufwriter.writeAll(package_relative_path);
- try bufwriter.writeAll(" (disabled/empty file)\nexport var $");
- std.fmt.formatInt(module_id, 16, .lower, .{}, bufwriter) catch unreachable;
- try bufwriter.writeAll(" = () => { var obj = {}; Object.defineProperty(obj, 'default', { value: obj, enumerable: false, configurable: true }, obj); return obj; }; \n");
- try buffered.flush();
- this.tmpfile_byte_offset = @truncate(u32, try this.tmpfile.getPos());
+ code_offset = try this.writeEmptyModule(module_data.package_path, module_id);
} else {
var ast: js_ast.Ast = undefined;
@@ -1364,225 +1360,230 @@ pub fn NewBundler(cache_files: bool) type {
},
.json => {
var expr = json_parser.ParseJSON(&source, worker.data.log, worker.allocator) catch return;
- var stmt = js_ast.Stmt.alloc(worker.allocator, js_ast.S.ExportDefault{
- .value = js_ast.StmtOrExpr{ .expr = expr },
- .default_name = js_ast.LocRef{ .loc = logger.Loc{}, .ref = Ref{} },
- }, logger.Loc{ .start = 0 });
- var stmts = worker.allocator.alloc(js_ast.Stmt, 1) catch unreachable;
- stmts[0] = stmt;
- var parts = worker.allocator.alloc(js_ast.Part, 1) catch unreachable;
- parts[0] = js_ast.Part{ .stmts = stmts };
- ast = js_ast.Ast.initTest(parts);
-
- ast.runtime_imports = runtime.Runtime.Imports{};
- ast.runtime_imports.register = Ref{ .source_index = 0, .inner_index = 0 };
- ast.runtime_imports.__export = Ref{ .source_index = 0, .inner_index = 1 };
- ast.symbols = json_ast_symbols_list;
- ast.module_ref = Ref{ .source_index = 0, .inner_index = 2 };
- ast.exports_ref = ast.runtime_imports.__export;
- ast.bundle_export_ref = Ref{ .source_index = 0, .inner_index = 3 };
+ if (expr.data != .e_missing) {
+ var stmt = js_ast.Stmt.alloc(worker.allocator, js_ast.S.ExportDefault{
+ .value = js_ast.StmtOrExpr{ .expr = expr },
+ .default_name = js_ast.LocRef{ .loc = logger.Loc{}, .ref = Ref{} },
+ }, logger.Loc{ .start = 0 });
+ var stmts = worker.allocator.alloc(js_ast.Stmt, 1) catch unreachable;
+ stmts[0] = stmt;
+ var parts = worker.allocator.alloc(js_ast.Part, 1) catch unreachable;
+ parts[0] = js_ast.Part{ .stmts = stmts };
+ ast = js_ast.Ast.initTest(parts);
+
+ ast.runtime_imports = runtime.Runtime.Imports{};
+ ast.runtime_imports.register = Ref{ .source_index = 0, .inner_index = 0 };
+ ast.runtime_imports.__export = Ref{ .source_index = 0, .inner_index = 1 };
+ ast.symbols = json_ast_symbols_list;
+ ast.module_ref = Ref{ .source_index = 0, .inner_index = 2 };
+ ast.exports_ref = ast.runtime_imports.__export;
+ ast.bundle_export_ref = Ref{ .source_index = 0, .inner_index = 3 };
+ } else {
+ var parts = &[_]js_ast.Part{};
+ ast = js_ast.Ast.initTest(parts);
+ }
},
else => {
return;
},
}
- // const load_from_symbol_ref = ast.runtime_imports.$$r.?;
- // const reexport_ref = ast.runtime_imports.__reExport.?;
- const register_ref = ast.runtime_imports.register.?;
- const E = js_ast.E;
- const Expr = js_ast.Expr;
- const Stmt = js_ast.Stmt;
-
- var prepend_part: js_ast.Part = undefined;
- var needs_prepend_part = false;
- if (ast.parts.len > 1) {
- for (ast.parts) |part| {
- if (part.tag != .none and part.stmts.len > 0) {
- prepend_part = part;
- needs_prepend_part = true;
- break;
+ switch (ast.parts.len) {
+ // It can be empty after parsing too
+ // A file like this is an example:
+ // "//# sourceMappingURL=validator.js.map"
+ 0 => {
+ code_offset = try this.writeEmptyModule(module_data.package_path, module_id);
+ },
+ else => {
+ // const load_from_symbol_ref = ast.runtime_imports.$$r.?;
+ // const reexport_ref = ast.runtime_imports.__reExport.?;
+ const register_ref = ast.runtime_imports.register.?;
+ const E = js_ast.E;
+ const Expr = js_ast.Expr;
+ const Stmt = js_ast.Stmt;
+
+ var prepend_part: js_ast.Part = undefined;
+ var needs_prepend_part = false;
+ if (ast.parts.len > 1) {
+ for (ast.parts) |part| {
+ if (part.tag != .none and part.stmts.len > 0) {
+ prepend_part = part;
+ needs_prepend_part = true;
+ break;
+ }
+ }
}
- }
- }
-
- if (ast.parts.len == 0) {
- if (comptime isDebug) {
- Output.prettyErrorln("Missing AST for file: {s}", .{file_path.text});
- Output.flush();
- }
- }
-
- var package_path = js_ast.E.String{ .utf8 = module_data.package_path };
-
- var target_identifier = E.Identifier{ .ref = register_ref };
- var cjs_args: [2]js_ast.G.Arg = undefined;
- var module_binding = js_ast.B.Identifier{ .ref = ast.module_ref.? };
- var exports_binding = js_ast.B.Identifier{ .ref = ast.exports_ref.? };
- var part = &ast.parts[ast.parts.len - 1];
+ var package_path = js_ast.E.String{ .utf8 = module_data.package_path };
- var new_stmts: [1]Stmt = undefined;
- var register_args: [1]Expr = undefined;
- var closure = E.Arrow{
- .args = &cjs_args,
- .body = .{
- .loc = logger.Loc.Empty,
- .stmts = part.stmts,
- },
- };
+ var target_identifier = E.Identifier{ .ref = register_ref };
+ var cjs_args: [2]js_ast.G.Arg = undefined;
+ var module_binding = js_ast.B.Identifier{ .ref = ast.module_ref.? };
+ var exports_binding = js_ast.B.Identifier{ .ref = ast.exports_ref.? };
- cjs_args[0] = js_ast.G.Arg{
- .binding = js_ast.Binding{
- .loc = logger.Loc.Empty,
- .data = .{ .b_identifier = &module_binding },
- },
- };
- cjs_args[1] = js_ast.G.Arg{
- .binding = js_ast.Binding{
- .loc = logger.Loc.Empty,
- .data = .{ .b_identifier = &exports_binding },
- },
- };
+ var part = &ast.parts[ast.parts.len - 1];
- var properties: [1]js_ast.G.Property = undefined;
- var e_object = E.Object{
- .properties = &properties,
- };
- const module_path_str = js_ast.Expr{ .data = .{ .e_string = &package_path }, .loc = logger.Loc.Empty };
- properties[0] = js_ast.G.Property{
- .key = module_path_str,
- .value = Expr{ .loc = logger.Loc.Empty, .data = .{ .e_arrow = &closure } },
- };
+ var new_stmts: [1]Stmt = undefined;
+ var register_args: [1]Expr = undefined;
+ var closure = E.Arrow{
+ .args = &cjs_args,
+ .body = .{
+ .loc = logger.Loc.Empty,
+ .stmts = part.stmts,
+ },
+ };
- // if (!ast.uses_module_ref) {
- // var symbol = &ast.symbols[ast.module_ref.?.inner_index];
- // symbol.original_name = "_$$";
- // }
+ cjs_args[0] = js_ast.G.Arg{
+ .binding = js_ast.Binding{
+ .loc = logger.Loc.Empty,
+ .data = .{ .b_identifier = &module_binding },
+ },
+ };
+ cjs_args[1] = js_ast.G.Arg{
+ .binding = js_ast.Binding{
+ .loc = logger.Loc.Empty,
+ .data = .{ .b_identifier = &exports_binding },
+ },
+ };
- // $$m(12345, "react", "index.js", function(module, exports) {
+ var properties: [1]js_ast.G.Property = undefined;
+ var e_object = E.Object{
+ .properties = &properties,
+ };
+ const module_path_str = js_ast.Expr{ .data = .{ .e_string = &package_path }, .loc = logger.Loc.Empty };
+ properties[0] = js_ast.G.Property{
+ .key = module_path_str,
+ .value = Expr{ .loc = logger.Loc.Empty, .data = .{ .e_arrow = &closure } },
+ };
- // })
- var accessor = js_ast.E.Index{ .index = module_path_str, .target = js_ast.Expr{
- .data = .{ .e_object = &e_object },
- .loc = logger.Loc.Empty,
- } };
- register_args[0] = Expr{ .loc = logger.Loc.Empty, .data = .{ .e_index = &accessor } };
+ // if (!ast.uses_module_ref) {
+ // var symbol = &ast.symbols[ast.module_ref.?.inner_index];
+ // symbol.original_name = "_$$";
+ // }
+
+ // $$m(12345, "react", "index.js", function(module, exports) {
+
+ // })
+ var accessor = js_ast.E.Index{ .index = module_path_str, .target = js_ast.Expr{
+ .data = .{ .e_object = &e_object },
+ .loc = logger.Loc.Empty,
+ } };
+ register_args[0] = Expr{ .loc = logger.Loc.Empty, .data = .{ .e_index = &accessor } };
+
+ var call_register = E.Call{
+ .target = Expr{
+ .data = .{ .e_identifier = &target_identifier },
+ .loc = logger.Loc{ .start = 0 },
+ },
+ .args = &register_args,
+ };
+ var register_expr = Expr{ .loc = call_register.target.loc, .data = .{ .e_call = &call_register } };
+ var decls: [1]js_ast.G.Decl = undefined;
+ var bundle_export_binding = js_ast.B.Identifier{ .ref = ast.bundle_export_ref.? };
+ var binding = js_ast.Binding{
+ .loc = register_expr.loc,
+ .data = .{ .b_identifier = &bundle_export_binding },
+ };
+ decls[0] = js_ast.G.Decl{
+ .value = register_expr,
+ .binding = binding,
+ };
+ var export_var = js_ast.S.Local{
+ .decls = &decls,
+ .is_export = true,
+ };
+ new_stmts[0] = Stmt{ .loc = register_expr.loc, .data = .{ .s_local = &export_var } };
+ part.stmts = &new_stmts;
- var call_register = E.Call{
- .target = Expr{
- .data = .{ .e_identifier = &target_identifier },
- .loc = logger.Loc{ .start = 0 },
- },
- .args = &register_args,
- };
- var register_expr = Expr{ .loc = call_register.target.loc, .data = .{ .e_call = &call_register } };
- var decls: [1]js_ast.G.Decl = undefined;
- var bundle_export_binding = js_ast.B.Identifier{ .ref = ast.bundle_export_ref.? };
- var binding = js_ast.Binding{
- .loc = register_expr.loc,
- .data = .{ .b_identifier = &bundle_export_binding },
- };
- decls[0] = js_ast.G.Decl{
- .value = register_expr,
- .binding = binding,
- };
- var export_var = js_ast.S.Local{
- .decls = &decls,
- .is_export = true,
- };
- new_stmts[0] = Stmt{ .loc = register_expr.loc, .data = .{ .s_local = &export_var } };
- part.stmts = &new_stmts;
+ var writer = js_printer.NewFileWriter(this.tmpfile);
+ var symbols: [][]js_ast.Symbol = &([_][]js_ast.Symbol{ast.symbols});
- var writer = js_printer.NewFileWriter(this.tmpfile);
- var symbols: [][]js_ast.Symbol = &([_][]js_ast.Symbol{ast.symbols});
+ // It should only have one part.
+ ast.parts = ast.parts[ast.parts.len - 1 ..];
- // It should only have one part.
- ast.parts = ast.parts[ast.parts.len - 1 ..];
+ const write_result =
+ try js_printer.printCommonJSThreaded(
+ @TypeOf(writer),
+ writer,
+ ast,
+ js_ast.Symbol.Map.initList(symbols),
+ &source,
+ false,
+ js_printer.Options{
+ .to_module_ref = Ref.RuntimeRef,
+ .bundle_export_ref = ast.bundle_export_ref.?,
+ .source_path = file_path,
+ .externals = ast.externals,
+ .indent = 0,
+ .require_ref = ast.require_ref,
+ .module_hash = module_id,
+ .runtime_imports = ast.runtime_imports,
+ .prepend_part_value = &prepend_part,
+ .prepend_part_key = if (needs_prepend_part) closure.body.stmts.ptr else null,
+ },
+ Linker,
+ &bundler.linker,
+ &this.write_lock,
+ std.fs.File,
+ this.tmpfile,
+ std.fs.File.getPos,
+ );
- const write_result =
- try js_printer.printCommonJSThreaded(
- @TypeOf(writer),
- writer,
- ast,
- js_ast.Symbol.Map.initList(symbols),
- &source,
- false,
- js_printer.Options{
- .to_module_ref = Ref.RuntimeRef,
- .bundle_export_ref = ast.bundle_export_ref.?,
- .source_path = file_path,
- .externals = ast.externals,
- .indent = 0,
- .module_hash = module_id,
- .runtime_imports = ast.runtime_imports,
- .prepend_part_value = &prepend_part,
- .prepend_part_key = if (needs_prepend_part) closure.body.stmts.ptr else null,
+ code_offset = write_result.off;
+ this.tmpfile_byte_offset = write_result.end_off;
},
- Linker,
- &bundler.linker,
- &this.write_lock,
- std.fs.File,
- this.tmpfile,
- std.fs.File.getPos,
- );
-
- code_offset = write_result.off;
- written = write_result.len;
-
- // Faster to _not_ do the syscall
- // But there's some off-by-one error somewhere and more reliable to just do the lseek
- this.tmpfile_byte_offset = write_result.end_off;
-
- if (comptime isDebug) {
- Output.prettyln("{s}@{s}/{s} - {d}:{d} \n", .{ package.name, package.version, package_relative_path, package.hash, module_id });
- Output.flush();
- std.debug.assert(package_relative_path.len > 0);
}
+ }
- this.list_lock.lock();
- defer this.list_lock.unlock();
+ if (comptime isDebug) {
+ Output.prettyln("{s}@{s}/{s} - {d}:{d} \n", .{ package.name, package.version, package_relative_path, package.hash, module_id });
+ Output.flush();
+ std.debug.assert(package_relative_path.len > 0);
+ }
- const code_length = this.tmpfile_byte_offset - code_offset;
+ this.list_lock.lock();
+ defer this.list_lock.unlock();
- if (comptime isDebug) {
- std.debug.assert(code_length > 0);
- std.debug.assert(package.hash != 0);
- std.debug.assert(package.version.len > 0);
- std.debug.assert(package.name.len > 0);
- std.debug.assert(module_id > 0);
- }
+ const code_length = this.tmpfile_byte_offset - code_offset;
- var package_get_or_put_entry = try this.package_list_map.getOrPut(package.hash);
+ if (comptime isDebug) {
+ std.debug.assert(code_length > 0);
+ std.debug.assert(package.hash != 0);
+ std.debug.assert(package.version.len > 0);
+ std.debug.assert(package.name.len > 0);
+ std.debug.assert(module_id > 0);
+ }
- if (!package_get_or_put_entry.found_existing) {
- package_get_or_put_entry.value_ptr.* = @truncate(u32, this.package_list.items.len);
- try this.package_list.append(
- Api.JavascriptBundledPackage{
- .name = try this.appendHeaderString(package.name),
- .version = try this.appendHeaderString(package.version),
- .hash = package.hash,
- },
- );
- this.has_jsx = this.has_jsx or strings.eql(package.name, this.bundler.options.jsx.package_name);
- }
+ var package_get_or_put_entry = try this.package_list_map.getOrPut(package.hash);
- var path_extname_length = @truncate(u8, std.fs.path.extension(package_relative_path).len);
- try this.module_list.append(
- Api.JavascriptBundledModule{
- .path = try this.appendHeaderString(
- package_relative_path,
- ),
- .path_extname_length = path_extname_length,
- .package_id = package_get_or_put_entry.value_ptr.*,
- .id = module_id,
- .code = Api.StringPointer{
- .length = @truncate(u32, code_length),
- .offset = @truncate(u32, code_offset),
- },
+ if (!package_get_or_put_entry.found_existing) {
+ package_get_or_put_entry.value_ptr.* = @truncate(u32, this.package_list.items.len);
+ try this.package_list.append(
+ Api.JavascriptBundledPackage{
+ .name = try this.appendHeaderString(package.name),
+ .version = try this.appendHeaderString(package.version),
+ .hash = package.hash,
},
);
+ this.has_jsx = this.has_jsx or strings.eql(package.name, this.bundler.options.jsx.package_name);
}
+
+ var path_extname_length = @truncate(u8, std.fs.path.extension(package_relative_path).len);
+ try this.module_list.append(
+ Api.JavascriptBundledModule{
+ .path = try this.appendHeaderString(
+ package_relative_path,
+ ),
+ .path_extname_length = path_extname_length,
+ .package_id = package_get_or_put_entry.value_ptr.*,
+ .id = module_id,
+ .code = Api.StringPointer{
+ .length = @truncate(u32, code_length),
+ .offset = @truncate(u32, code_offset),
+ },
+ },
+ );
} else {
// If it's app code, scan but do not fully parse.
switch (loader) {
@@ -1630,9 +1631,73 @@ pub fn NewBundler(cache_files: bool) type {
const loader_ = this.bundler.options.loader(path.name.ext);
if (!loader_.isJavaScriptLikeOrJSON()) continue;
+
path.* = try path.dupeAlloc(this.allocator);
if (BundledModuleData.get(this, _resolved_import)) |mod| {
+ if (comptime !FeatureFlags.bundle_dynamic_import) {
+ if (import_record.kind == .dynamic)
+ continue;
+ } else {
+ // When app code dynamically imports a large file
+ // Don't bundle it. Leave it as a separate file.
+ // The main value from bundling in development is to minimize tiny, waterfall http requests
+ // If you're importing > 100 KB file dynamically, developer is probably explicitly trying to do that.
+ // There's a tradeoff between "I want to minimize page load time"
+ if (import_record.kind == .dynamic) {
+ this.dynamic_import_file_size_store_lock.lock();
+ defer this.dynamic_import_file_size_store_lock.unlock();
+ var dynamic_import_file_size = this.dynamic_import_file_size_store.getOrPut(mod.module_id) catch unreachable;
+ if (!dynamic_import_file_size.found_existing) {
+ var fd = _resolved_import.file_fd;
+ var can_close = false;
+ if (fd == 0) {
+ dynamic_import_file_size.value_ptr.* = 0;
+ fd = (std.fs.openFileAbsolute(path.textZ(), .{}) catch |err| {
+ this.log.addRangeWarningFmt(
+ &source,
+ import_record.range,
+ worker.allocator,
+ "{s} opening file: \"{s}\"",
+ .{ @errorName(err), path.text },
+ ) catch unreachable;
+ continue;
+ }).handle;
+ can_close = true;
+ Fs.FileSystem.setMaxFd(fd);
+ }
+
+ defer {
+ if (can_close and bundler.fs.fs.needToCloseFiles()) {
+ var _file = std.fs.File{ .handle = fd };
+ _file.close();
+ _resolved_import.file_fd = 0;
+ } else if (FeatureFlags.store_file_descriptors) {
+ _resolved_import.file_fd = fd;
+ }
+ }
+
+ var file = std.fs.File{ .handle = fd };
+ var stat = file.stat() catch |err| {
+ this.log.addRangeWarningFmt(
+ &source,
+ import_record.range,
+ worker.allocator,
+ "{s} stat'ing file: \"{s}\"",
+ .{ @errorName(err), path.text },
+ ) catch unreachable;
+ dynamic_import_file_size.value_ptr.* = 0;
+ continue;
+ };
+
+ dynamic_import_file_size.value_ptr.* = @truncate(u32, stat.size);
+ }
+
+ if (dynamic_import_file_size.value_ptr.* > 1024 * 100)
+ continue;
+ }
+ }
+
std.debug.assert(mod.module_id != 0);
try this.queue.upsert(
mod.module_id,
diff --git a/src/feature_flags.zig b/src/feature_flags.zig
index 33a4eaee1..b08bfbc0d 100644
--- a/src/feature_flags.zig
+++ b/src/feature_flags.zig
@@ -42,6 +42,8 @@ pub const watch_directories = true;
pub const tailwind_css_at_keyword = true;
+pub const bundle_dynamic_import = true;
+
// This feature flag exists so when you have defines inside package.json, you can use single quotes in nested strings.
pub const allow_json_single_quotes = true;
diff --git a/src/fs.zig b/src/fs.zig
index f1e572835..a64cb7555 100644
--- a/src/fs.zig
+++ b/src/fs.zig
@@ -903,6 +903,7 @@ pub const FileSystem = struct {
var _kind = stat.kind;
var cache = Entry.Cache{ .kind = Entry.Kind.file, .symlink = "" };
var symlink: []const u8 = "";
+
if (is_symlink) {
var file = if (existing_fd != 0) std.fs.File{ .handle = existing_fd } else try std.fs.openFileAbsoluteZ(absolute_path_c, .{ .read = true });
setMaxFd(file.handle);
diff --git a/src/global.zig b/src/global.zig
index dac2eebd5..38ceac916 100644
--- a/src/global.zig
+++ b/src/global.zig
@@ -168,7 +168,7 @@ pub const Output = struct {
if (comptime isWasm) {
source.stream.seekTo(0) catch return;
source.stream.writer().print(fmt, args) catch return;
-
+
root.console_log(root.Uint8Array.fromSlice(source.out_buffer[0..source.stream.pos]));
} else {
if (enable_buffering) {
@@ -437,32 +437,3 @@ pub const FileDescriptorType = if (isBrowser) u0 else std.os.fd_t;
// such is often the case with macOS
// As a useful optimization, we can store file descriptors and just keep them open...forever
pub const StoredFileDescriptorType = if (isWindows or isBrowser) u0 else std.os.fd_t;
-
-pub const PathBuilder = struct {
- const StringBuilderType = NewStringBuilder(std.fs.MAX_PATH_BYTES);
- builder: StringBuilderType = StringBuilderType.init(),
-
- pub fn init() PathBuilder {
- return PathBuilder{};
- }
-
- fn load(this: *PathBuilder) void {
- return @call(.{ .modifier = .always_inline }, StringBuilderType.load, .{&this.builder});
- }
-
- pub fn append(this: *PathBuilder, _str: string) void {
- return @call(.{ .modifier = .always_inline }, StringBuilderType.append, .{ &this.builder, _str });
- }
-
- pub fn pop(this: *PathBuilder, count: usize) void {
- return @call(.{ .modifier = .always_inline }, StringBuilderType.pop, .{ &this.builder, count });
- }
-
- pub fn str(this: *PathBuilder) string {
- return @call(.{ .modifier = .always_inline }, StringBuilderType.str, .{&this.builder});
- }
-
- pub fn reset(this: *PathBuilder) void {
- return @call(.{ .modifier = .always_inline }, StringBuilderType.reset, .{&this.builder});
- }
-};
diff --git a/src/js_parser/imports.zig b/src/js_parser/imports.zig
index b1ea18df2..80f162d88 100644
--- a/src/js_parser/imports.zig
+++ b/src/js_parser/imports.zig
@@ -17,7 +17,7 @@ pub usingnamespace @import("../global.zig");
pub usingnamespace @import("../ast/base.zig");
pub usingnamespace js_ast.G;
pub usingnamespace @import("../defines.zig");
-
+pub const isPackagePath = @import("../resolver/resolver.zig").isPackagePath;
pub const ImportKind = importRecord.ImportKind;
pub const BindingNodeIndex = js_ast.BindingNodeIndex;
diff --git a/src/main.zig b/src/main.zig
index 133e4f10f..7b86f7360 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -13,16 +13,12 @@ usingnamespace @import("defines.zig");
usingnamespace @import("global.zig");
const panicky = @import("panic_handler.zig");
const cli = @import("cli.zig");
-pub const MainPanicHandler = panicky.NewPanicHandler(panicky.default_panic);
+pub const MainPanicHandler = panicky.NewPanicHandler(std.builtin.default_panic);
const js = @import("javascript/jsc/bindings/bindings.zig");
usingnamespace @import("javascript/jsc/javascript.zig");
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn {
- if (MainPanicHandler.Singleton) |singleton| {
- MainPanicHandler.handle_panic(msg, error_return_trace);
- } else {
- panicky.default_panic(msg, error_return_trace);
- }
+ MainPanicHandler.handle_panic(msg, error_return_trace);
}
pub var start_time: i128 = 0;
pub fn main() anyerror!void {
diff --git a/src/node_fallbacks.zig b/src/node_fallbacks.zig
index def1d6126..63a005c27 100644
--- a/src/node_fallbacks.zig
+++ b/src/node_fallbacks.zig
@@ -479,3 +479,21 @@ pub const Map = std.ComptimeStringMap(FallbackModule, .{
&.{ "isomorphic-fetch", FallbackModule.@"isomorphic-fetch" },
&.{ "@vercel/fetch", FallbackModule.@"@vercel/fetch" },
});
+
+pub fn contentsFromPath(path: string) ?string {
+ var module_name = path["/bun-vfs/node_modules/".len..];
+
+ if (module_name[0] == '@') {
+ var end = std.mem.indexOfScalar(u8, module_name, '/').? + 1;
+ end += std.mem.indexOfScalar(u8, module_name[end..], '/').?;
+
+ module_name = module_name[0..end];
+ } else {
+ module_name = module_name[0..std.mem.indexOfScalar(u8, module_name, '/').?];
+ }
+
+ if (Map.get(module_name)) |mod| {
+ return mod.code.*;
+ }
+ return null;
+}
diff --git a/src/runtime.js b/src/runtime.js
index 52974144b..a90af7427 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -38,11 +38,12 @@ export var __toModule = (module) => {
};
var tagSymbol = Symbol("CommonJSTransformed");
+var cjsRequireSymbol = Symbol("CommonJS");
export var __commonJS = (cb, name) => {
var mod = {};
var has_run = false;
- return function require() {
+ const requireFunction = function load() {
if (has_run) {
return mod.exports;
}
@@ -97,12 +98,13 @@ export var __commonJS = (cb, name) => {
return mod.exports;
};
-};
-export var __cJS2eSM = (cb, name) => {
- return __commonJS(cb, name)();
+ requireFunction[cjsRequireSymbol] = true;
+ return requireFunction;
};
+export var __cJS2eSM = __commonJS;
+
var require_cache = new WeakMap();
export var __BUN_INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
@@ -119,51 +121,44 @@ export var __BUN_INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
// );
export var __require = (namespace) => {
- var entry = require_cache.get(namespace);
- if (typeof entry !== "undefined") {
- return entry;
- }
-
- var target =
- Object.prototype.hasOwnProperty.call(namespace, "default") &&
- Object.keys(namespace).length === 1
- ? namespace["default"]
- : namespace;
-
- if (typeof target !== "function") {
- throw new __BUN_INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.RequireFailedError(
- `Couldn't find module "${
- typeof namespace === "string"
- ? namespace
- : namespace.name || namespace.displayName || namespace.toString()
- }"`
- );
- }
-
- var exports = target();
- require_cache.set(namespace, exports);
- return exports;
-};
-
-if (
- !(
- "__BUN_INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED__MODULE_LOAD_CACHE" in
- globalThis
- )
-) {
- globalThis.__BUN_INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED__MODULE_LOAD_CACHE =
- new Map();
-}
-
-if (
- !(
- "__BUN_INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED__MODULE_REGISTRY" in
- globalThis
+ if (
+ typeof namespace === "object" &&
+ "default" in namespace &&
+ namespace.default[cjsRequireSymbol]
)
-) {
- globalThis.__BUN_INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED__MODULE_REGISTRY =
- new Map();
-}
+ return namespace.default();
+
+ return namespace;
+ // // is it an ESM module record?
+ // if (namespaceType === "object") return namespace;
+ // // is it a CommonJS module?
+
+ // // i have no idea what it is so i'm just going to try stuff and pray
+ // var entry = require_cache.get(namespace);
+ // if (typeof entry !== "undefined") {
+ // return entry;
+ // }
+
+ // var target =
+ // Object.prototype.hasOwnProperty.call(namespace, "default") &&
+ // Object.keys(namespace).length === 1
+ // ? namespace["default"]
+ // : namespace;
+
+ // if (typeof target !== "function") {
+ // throw new __BUN_INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.RequireFailedError(
+ // `Couldn't find module "${
+ // typeof namespace === "string"
+ // ? namespace
+ // : namespace.name || namespace.displayName || namespace.toString()
+ // }"`
+ // );
+ // }
+
+ // var exports = target();
+ // require_cache.set(namespace, exports);
+ // return exports;
+};
export var $$m = __commonJS;