diff options
-rw-r--r-- | src/bun_js.zig | 93 | ||||
-rw-r--r-- | src/bundler.zig | 2 | ||||
-rw-r--r-- | src/cli/run_command.zig | 172 |
3 files changed, 211 insertions, 56 deletions
diff --git a/src/bun_js.zig b/src/bun_js.zig new file mode 100644 index 000000000..e0af9d273 --- /dev/null +++ b/src/bun_js.zig @@ -0,0 +1,93 @@ +usingnamespace @import("global.zig"); +const std = @import("std"); + +const lex = @import("js_lexer.zig"); +const logger = @import("logger.zig"); +const alloc = @import("alloc.zig"); +const options = @import("options.zig"); +const js_parser = @import("js_parser.zig"); +const json_parser = @import("json_parser.zig"); +const js_printer = @import("js_printer.zig"); +const js_ast = @import("js_ast.zig"); +const linker = @import("linker.zig"); +usingnamespace @import("ast/base.zig"); +usingnamespace @import("defines.zig"); +const panicky = @import("panic_handler.zig"); +const sync = @import("./sync.zig"); +const Api = @import("api/schema.zig").Api; +const resolve_path = @import("./resolver/resolve_path.zig"); +const configureTransformOptionsForBun = @import("./javascript/jsc/config.zig").configureTransformOptionsForBun; +const Command = @import("cli.zig").Command; +const bundler = @import("bundler.zig"); +const NodeModuleBundle = @import("node_module_bundle.zig").NodeModuleBundle; +const DotEnv = @import("env_loader.zig"); +const which = @import("which.zig").which; +const VirtualMachine = @import("./javascript/jsc/javascript.zig").VirtualMachine; + +pub const Run = struct { + file: std.fs.File, + ctx: Command.Context, + vm: *VirtualMachine, + entry_path: string, + pub fn boot(ctx: Command.Context, file: std.fs.File, entry_path: string) !void { + js_ast.Expr.Data.Store.create(default_allocator); + js_ast.Stmt.Data.Store.create(default_allocator); + + var run = Run{ + .vm = try VirtualMachine.init(ctx.allocator, ctx.args, null, ctx.log, null), + .file = file, + .ctx = ctx, + .entry_path = entry_path, + }; + + run.vm.bundler.configureRouter(false) catch |err| { + if (Output.enable_ansi_colors) { + run.vm.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true) catch {}; + } else { + run.vm.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {}; + } + + std.os.exit(1); + }; + run.vm.bundler.configureDefines() catch |err| { + if (Output.enable_ansi_colors) { + run.vm.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true) catch {}; + } else { + run.vm.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {}; + } + + std.os.exit(1); + }; + + try run.start(); + } + + pub fn start(this: *Run) !void { + var promise = try this.vm.loadEntryPoint(this.entry_path); + + this.vm.global.vm().drainMicrotasks(); + + while (promise.status(this.vm.global.vm()) == .Pending) { + this.vm.global.vm().drainMicrotasks(); + } + + if (promise.status(this.vm.global.vm()) == .Rejected) { + this.vm.defaultErrorHandler(promise.result(this.vm.global.vm()), null); + std.os.exit(1); + } + + _ = promise.result(this.vm.global.vm()); + + if (this.vm.log.msgs.items.len > 0) { + if (Output.enable_ansi_colors) { + this.vm.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true) catch {}; + } else { + this.vm.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {}; + } + } + + Output.flush(); + + std.os.exit(0); + } +}; diff --git a/src/bundler.zig b/src/bundler.zig index 9967369d3..35c078759 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -2597,6 +2597,8 @@ pub const Bundler = struct { bundler.macro_context = js_ast.Macro.MacroContext.init(bundler); } + opts.features.top_level_await = bundler.options.platform.isBun(); + opts.macro_context = &bundler.macro_context.?; opts.macro_context.remap = this_parse.macro_remappings; opts.features.is_macro_runtime = bundler.options.platform == .bun_macro; diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index 93b8f80c6..fba8296a8 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -22,7 +22,7 @@ const bundler = @import("../bundler.zig"); const NodeModuleBundle = @import("../node_module_bundle.zig").NodeModuleBundle; const DotEnv = @import("../env_loader.zig"); const which = @import("../which.zig").which; - +const Run = @import("../bun_js.zig").Run; var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; var path_buf2: [std.fs.MAX_PATH_BYTES]u8 = undefined; const NpmArgs = struct { @@ -268,6 +268,121 @@ pub const RunCommand = struct { } pub fn exec(ctx: Command.Context, comptime bin_dirs_only: bool, comptime log_errors: bool) !bool { + // Step 1. Figure out what we're trying to run + var positionals = ctx.positionals; + if (positionals.len > 0 and strings.eqlComptime(positionals[0], "run") or strings.eqlComptime(positionals[0], "r")) { + positionals = positionals[1..]; + } + + var script_name_to_search: string = ""; + + if (positionals.len > 0) { + script_name_to_search = positionals[0]; + } + + var passthrough: []const string = &[_]string{}; + + var passthrough_list = std.ArrayList(string).init(ctx.allocator); + if (script_name_to_search.len > 0) { + get_passthrough: { + + // If they explicitly pass "--", that means they want everything after that to be passed through. + for (std.os.argv) |argv, i| { + if (strings.eqlComptime(std.mem.span(argv), "--")) { + if (std.os.argv.len > i + 1) { + var count: usize = 0; + for (std.os.argv[i + 1 ..]) |arg| { + count += 1; + } + try passthrough_list.ensureTotalCapacity(count); + + for (std.os.argv[i + 1 ..]) |arg| { + passthrough_list.appendAssumeCapacity(std.mem.span(arg)); + } + + passthrough = passthrough_list.toOwnedSlice(); + break :get_passthrough; + } + } + } + + // If they do not pass "--", assume they want everything after the script name to be passed through. + for (std.os.argv) |argv, i| { + if (strings.eql(std.mem.span(argv), script_name_to_search)) { + if (std.os.argv.len > i + 1) { + try passthrough_list.ensureTotalCapacity(std.os.argv[i + 1 ..].len); + + for (std.os.argv[i + 1 ..]) |arg| { + passthrough_list.appendAssumeCapacity(std.mem.span(arg)); + } + + passthrough = passthrough_list.toOwnedSlice(); + break :get_passthrough; + } + } + } + } + } + + if (comptime log_errors) { + if (script_name_to_search.len > 0) { + possibly_open_with_bun_js: { + if (options.defaultLoaders.get(std.fs.path.extension(script_name_to_search))) |loader| { + if (loader.isJavaScriptLike()) { + const cwd = std.os.getcwd(&path_buf) catch break :possibly_open_with_bun_js; + path_buf[cwd.len] = std.fs.path.sep; + var parts = [_]string{script_name_to_search}; + var file_path = resolve_path.joinAbsStringBuf( + path_buf[0 .. cwd.len + 1], + &path_buf2, + &parts, + .auto, + ); + if (file_path.len == 0) break :possibly_open_with_bun_js; + path_buf2[file_path.len] = 0; + var file_pathZ = path_buf2[0..file_path.len :0]; + + var file = std.fs.openFileAbsoluteZ(file_pathZ, .{ .read = true }) catch break :possibly_open_with_bun_js; + // "White space after #! is optional." + var shebang_buf: [64]u8 = undefined; + const shebang_size = file.pread(&shebang_buf, 0) catch |err| { + Output.prettyErrorln("<r><red>error<r>: Failed to read file <b>{s}<r> due to error <b>{s}<r>", .{ file_path, @errorName(err) }); + Output.flush(); + std.os.exit(1); + }; + + var shebang: string = shebang_buf[0..shebang_size]; + shebang = std.mem.trim(u8, shebang, " \r\n\t"); + if (shebang.len == 0) break :possibly_open_with_bun_js; + + if (shebang.len > 2 and strings.eqlComptimeIgnoreLen(shebang[0..2], "#!")) { + break :possibly_open_with_bun_js; + } + + Run.boot(ctx, file, ctx.allocator.dupe(u8, file_path) catch unreachable) catch |err| { + if (Output.enable_ansi_colors) { + ctx.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), true) catch {}; + } else { + ctx.log.printForLogLevelWithEnableAnsiColors(Output.errorWriter(), false) catch {}; + } + + Output.prettyErrorln("<r><red>error<r>: Failed to run <b>{s}<r> due to error <b>{s}<r>", .{ + std.fs.path.basename(file_path), + @errorName(err), + }); + Output.flush(); + std.os.exit(1); + }; + + return true; + + // If we get here, then we run it with Bun.js + + } + } + } + } + } var args = ctx.args; args.node_modules_bundle_path = null; args.node_modules_bundle_path_server = null; @@ -286,11 +401,6 @@ pub const RunCommand = struct { } this_bundler.configureLinker(); - var positionals = ctx.positionals; - if (positionals.len > 0 and strings.eqlComptime(positionals[0], "run") or strings.eqlComptime(positionals[0], "r")) { - positionals = positionals[1..]; - } - var root_dir_info = this_bundler.resolver.readDirInfo(this_bundler.fs.top_level_dir) catch |err| { if (!log_errors) return false; if (Output.enable_ansi_colors) { @@ -394,56 +504,6 @@ pub const RunCommand = struct { PATH = new_path.items; } - var script_name_to_search: string = ""; - - if (positionals.len > 0) { - script_name_to_search = positionals[0]; - } - - var passthrough: []const string = &[_]string{}; - - var passthrough_list = std.ArrayList(string).init(ctx.allocator); - if (script_name_to_search.len > 0) { - get_passthrough: { - - // If they explicitly pass "--", that means they want everything after that to be passed through. - for (std.os.argv) |argv, i| { - if (strings.eqlComptime(std.mem.span(argv), "--")) { - if (std.os.argv.len > i + 1) { - var count: usize = 0; - for (std.os.argv[i + 1 ..]) |arg| { - count += 1; - } - try passthrough_list.ensureTotalCapacity(count); - - for (std.os.argv[i + 1 ..]) |arg| { - passthrough_list.appendAssumeCapacity(std.mem.span(arg)); - } - - passthrough = passthrough_list.toOwnedSlice(); - break :get_passthrough; - } - } - } - - // If they do not pass "--", assume they want everything after the script name to be passed through. - for (std.os.argv) |argv, i| { - if (strings.eql(std.mem.span(argv), script_name_to_search)) { - if (std.os.argv.len > i + 1) { - try passthrough_list.ensureTotalCapacity(std.os.argv[i + 1 ..].len); - - for (std.os.argv[i + 1 ..]) |arg| { - passthrough_list.appendAssumeCapacity(std.mem.span(arg)); - } - - passthrough = passthrough_list.toOwnedSlice(); - break :get_passthrough; - } - } - } - } - } - var did_print = false; if (root_dir_info.enclosing_package_json) |package_json| { if (package_json.name.len > 0) { |