diff options
author | 2021-09-12 00:39:57 -0700 | |
---|---|---|
committer | 2021-09-12 00:39:57 -0700 | |
commit | 350569655bcf4348d521f20cec4da7aee55ae102 (patch) | |
tree | aa278040f04d477739a16aef25991ca1ce7cd4ed /src | |
parent | 092f9ac766ff532cb34587b5d93c401070cc79cf (diff) | |
download | bun-350569655bcf4348d521f20cec4da7aee55ae102.tar.gz bun-350569655bcf4348d521f20cec4da7aee55ae102.tar.zst bun-350569655bcf4348d521f20cec4da7aee55ae102.zip |
Support bundling dynamically imported modules.
Diffstat (limited to 'src')
-rw-r--r-- | src/bundler.zig | 505 | ||||
-rw-r--r-- | src/feature_flags.zig | 2 | ||||
-rw-r--r-- | src/fs.zig | 1 | ||||
-rw-r--r-- | src/global.zig | 31 | ||||
-rw-r--r-- | src/js_parser/imports.zig | 2 | ||||
-rw-r--r-- | src/main.zig | 8 | ||||
-rw-r--r-- | src/node_fallbacks.zig | 18 | ||||
-rw-r--r-- | src/runtime.js | 91 |
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 = ®ister_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 = ®ister_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; |