diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/base64/bun-base64.c | 2 | ||||
| -rw-r--r-- | src/base64/fastavxbase64.c | 2 | ||||
| -rw-r--r-- | src/base64/fastavxbase64.h | 3 | ||||
| m--------- | src/bun.js/WebKit | 0 | ||||
| -rw-r--r-- | src/bun.js/node/syscall.zig | 8 | ||||
| -rw-r--r-- | src/bun.js/node/types.zig | 51 | ||||
| -rw-r--r-- | src/cli.zig | 2 | ||||
| -rw-r--r-- | src/cli/upgrade_command.zig | 172 | ||||
| -rw-r--r-- | src/env.zig | 2 | ||||
| -rw-r--r-- | src/http.zig | 6 | ||||
| -rw-r--r-- | src/http_client_async.zig | 2 | ||||
| -rw-r--r-- | src/install/install.zig | 56 | ||||
| -rw-r--r-- | src/runtime.footer.bun.js | 1 | ||||
| -rw-r--r-- | src/string_immutable.zig | 2 |
14 files changed, 267 insertions, 42 deletions
diff --git a/src/base64/bun-base64.c b/src/base64/bun-base64.c index e11f88da5..6cf11bbe7 100644 --- a/src/base64/bun-base64.c +++ b/src/base64/bun-base64.c @@ -22,7 +22,7 @@ size_t bun_base64_encode(char *dest, const char *src, size_t len) { return chromium_base64_encode(dest, src, len); } -#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) +#elif defined(__GNUC__) && (defined(__x86_64__) && defined(__AVX2__)) size_t bun_base64_decode(char *dest, const char *src, size_t len, size_t *outlen) { diff --git a/src/base64/fastavxbase64.c b/src/base64/fastavxbase64.c index 47be824b4..305288fde 100644 --- a/src/base64/fastavxbase64.c +++ b/src/base64/fastavxbase64.c @@ -1,4 +1,4 @@ -#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) +#if defined(__GNUC__) && defined(__x86_64__) && defined(__AVX2__) #include "fastavxbase64.h" #include <stdbool.h> diff --git a/src/base64/fastavxbase64.h b/src/base64/fastavxbase64.h index d1064a5d1..80f097ae8 100644 --- a/src/base64/fastavxbase64.h +++ b/src/base64/fastavxbase64.h @@ -1,4 +1,5 @@ -#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) + +#if defined(__GNUC__) && defined(__x86_64__) && defined(__AVX2__) #ifndef EXPAVX_B64 #define EXPAVX_B64 diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit -Subproject 7e7774dabf1c2d94fe3604defb3c54a4c989c3b +Subproject 6dd3cae7c03f061b30e09cce5da17b2e7b108ad diff --git a/src/bun.js/node/syscall.zig b/src/bun.js/node/syscall.zig index b931e9c0e..4378a4762 100644 --- a/src/bun.js/node/syscall.zig +++ b/src/bun.js/node/syscall.zig @@ -16,27 +16,29 @@ const C = @import("../../global.zig").C; const linux = os.linux; const Maybe = JSC.Maybe; +// On Linux AARCh64, zig is missing stat & lstat syscalls +const use_libc = (Environment.isLinux and Environment.isAarch64) or Environment.isMac; pub const system = if (Environment.isLinux) linux else @import("io").darwin; pub const S = struct { pub usingnamespace if (Environment.isLinux) linux.S else std.os.S; }; const sys = std.os.system; -const statSym = if (Environment.isMac) +const statSym = if (use_libc) C.stat else if (Environment.isLinux) linux.stat else @compileError("STAT"); -const fstatSym = if (Environment.isMac) +const fstatSym = if (use_libc) C.fstat else if (Environment.isLinux) linux.fstat else @compileError("STAT"); -const lstat64 = if (Environment.isMac) +const lstat64 = if (use_libc) C.lstat else if (Environment.isLinux) linux.lstat diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 2e704037e..18d437d76 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -797,7 +797,7 @@ pub const FileSystemFlags = enum(Mode) { } }; -/// Milliseconds precision +/// Milliseconds precision pub const Date = enum(u64) { _, @@ -818,12 +818,27 @@ fn StatsLike(comptime name: [:0]const u8, comptime T: type) type { This, .{ .name = name }, .{ - .isFile = .{ - .rfn = JSC.wrap(This, "isFile", false), + .isBlockDevice = .{ + .rfn = JSC.wrap(This, "isBlockDevice", false), + }, + .isCharacterDevice = .{ + .rfn = JSC.wrap(This, "isCharacterDevice", false), }, .isDirectory = .{ .rfn = JSC.wrap(This, "isDirectory", false), }, + .isFIFO = .{ + .rfn = JSC.wrap(This, "isFIFO", false), + }, + .isFile = .{ + .rfn = JSC.wrap(This, "isFile", false), + }, + .isSocket = .{ + .rfn = JSC.wrap(This, "isSocket", false), + }, + .isSymbolicLink = .{ + .rfn = JSC.wrap(This, "isSymbolicLink", false), + }, .finalize = finalize, }, .{ @@ -957,13 +972,39 @@ fn StatsLike(comptime name: [:0]const u8, comptime T: type) type { }; } - pub fn isFile(this: *Stats) JSC.JSValue { - return JSC.JSValue.jsBoolean(os.S.ISREG(@intCast(Mode, this.mode))); + pub fn isBlockDevice(this: *Stats) JSC.JSValue { + return JSC.JSValue.jsBoolean(os.S.ISBLK(@intCast(Mode, this.mode))); + } + + pub fn isCharacterDevice(this: *Stats) JSC.JSValue { + return JSC.JSValue.jsBoolean(os.S.ISCHR(@intCast(Mode, this.mode))); } + pub fn isDirectory(this: *Stats) JSC.JSValue { return JSC.JSValue.jsBoolean(os.S.ISDIR(@intCast(Mode, this.mode))); } + pub fn isFIFO(this: *Stats) JSC.JSValue { + return JSC.JSValue.jsBoolean(os.S.ISFIFO(@intCast(Mode, this.mode))); + } + + pub fn isFile(this: *Stats) JSC.JSValue { + return JSC.JSValue.jsBoolean(os.S.ISREG(@intCast(Mode, this.mode))); + } + + pub fn isSocket(this: *Stats) JSC.JSValue { + return JSC.JSValue.jsBoolean(os.S.ISSOCK(@intCast(Mode, this.mode))); + } + + // Node.js says this method is only valid on the result of lstat() + // so it's fine if we just include it on stat() because it would + // still just return false. + // + // See https://nodejs.org/api/fs.html#statsissymboliclink + pub fn isSymbolicLink(this: *Stats) JSC.JSValue { + return JSC.JSValue.jsBoolean(os.S.ISLNK(@intCast(Mode, this.mode))); + } + pub fn toJS(this: Stats, ctx: JSC.C.JSContextRef, _: JSC.C.ExceptionRef) JSC.C.JSValueRef { var _this = bun.default_allocator.create(Stats) catch unreachable; _this.* = this; diff --git a/src/cli.zig b/src/cli.zig index 7bdf75dbb..e849d258f 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -55,7 +55,7 @@ const UpgradeCommand = @import("./cli/upgrade_command.zig").UpgradeCommand; const MacroMap = @import("./resolver/package_json.zig").MacroMap; const Reporter = @import("./report.zig"); -var start_time: i128 = undefined; +pub var start_time: i128 = undefined; const Bunfig = @import("./bunfig.zig").Bunfig; pub const Cli = struct { diff --git a/src/cli/upgrade_command.zig b/src/cli/upgrade_command.zig index a64985bbb..fd101d775 100644 --- a/src/cli/upgrade_command.zig +++ b/src/cli/upgrade_command.zig @@ -56,17 +56,35 @@ pub const Version = struct { size: u32 = 0, pub fn name(this: Version) ?string { - if (this.tag.len > "bun-v".len and strings.eqlComptime(this.tag[0.."bun-v".len], "bun-v")) { - return this.tag[("bun-v".len)..]; - } else { - return null; + if (this.tag.len <= "bun-v".len or !strings.hasPrefixComptime(this.tag, "bun-v")) { + if (strings.eqlComptime(this.tag, "canary")) { + const Cli = @import("../cli.zig"); + + return std.fmt.allocPrint( + bun.default_allocator, + "bun-canary-timestamp-{any}", + .{ + std.fmt.fmtSliceHexLower( + std.mem.asBytes( + &bun.hash( + std.mem.asBytes(&Cli.start_time), + ), + ), + ), + }, + ) catch unreachable; + } + return this.tag; } + + return this.tag["bun-v".len..]; } pub const platform_label = if (Environment.isMac) "darwin" else "linux"; pub const arch_label = if (Environment.isAarch64) "aarch64" else "x64"; pub const triplet = platform_label ++ "-" ++ arch_label; - pub const folder_name = "bun-" ++ triplet; + const suffix = if (Environment.baseline) "-baseline" else ""; + pub const folder_name = "bun-" ++ triplet ++ suffix; pub const zip_filename = folder_name ++ ".zip"; const current_version: string = "bun-v" ++ Global.package_json_version; @@ -79,7 +97,10 @@ pub const Version = struct { pub const UpgradeCheckerThread = struct { var update_checker_thread: std.Thread = undefined; pub fn spawn(env_loader: *DotEnv.Loader) void { - if (env_loader.map.get("BUN_DISABLE_UPGRADE_CHECK") != null or env_loader.map.get("CI") != null) return; + if (env_loader.map.get("BUN_DISABLE_UPGRADE_CHECK") != null or + env_loader.map.get("CI") != null or + strings.eqlComptime(env_loader.get("BUN_CANARY") orelse "0", "1")) + return; update_checker_thread = std.Thread.spawn(.{}, run, .{env_loader}) catch return; update_checker_thread.detach(); } @@ -352,12 +373,14 @@ pub const UpgradeCommand = struct { break :brk DotEnv.Loader.init(map, ctx.allocator); }; - env_loader.loadProcess(); var version: Version = undefined; + const use_canary = strings.eqlComptime(env_loader.map.get("BUN_CANARY") orelse "0", "1") or + // TODO: add separate args just for "bun upgrade"? + strings.containsAny(bun.span(std.os.argv), "--canary"); - { + if (!use_canary) { var refresher = std.Progress{}; var progress = refresher.start("Fetching version tags", 0); @@ -383,12 +406,19 @@ pub const UpgradeCommand = struct { ); Global.exit(1); } - } - { Output.prettyErrorln("<r><b>bun <cyan>v{s}<r> is out<r>! You're on <blue>{s}<r>\n", .{ version.name().?, Global.package_json_version }); Output.flush(); + } else { + version = Version{ + .tag = "canary", + .zip_url = "https://github.com/oven-sh/bun/releases/download/canary/" ++ Version.zip_filename, + .size = 0, + .buf = MutableString.initEmpty(bun.default_allocator), + }; + } + { var refresher = std.Progress{}; var progress = refresher.start("Downloading", version.size); refresher.refresh(); @@ -412,7 +442,22 @@ pub const UpgradeCommand = struct { const response = try async_http.sendSync(true); switch (response.status_code) { - 404 => return error.HTTP404, + 404 => { + if (use_canary) { + Output.prettyErrorln( + \\<r><red>error:<r> Canary builds are not available for this platform yet + \\ + \\ Release: <cyan>https://github.com/oven-sh/bun/releases/tag/canary<r> + \\ Filename: <b>{s}<r> + \\ + , .{ + Version.zip_filename, + }); + Global.exit(1); + } + + return error.HTTP404; + }, 403 => return error.HTTPForbidden, 429 => return error.HTTPTooManyRequests, 499...599 => return error.GitHubIsDown, @@ -502,7 +547,6 @@ pub const UpgradeCommand = struct { Global.exit(1); } } - { var verify_argv = [_]string{ exe_subpath, @@ -526,17 +570,21 @@ pub const UpgradeCommand = struct { Global.exit(1); } - if (!strings.eql(std.mem.trim(u8, result.stdout, " \n\r\t"), version_name)) { - save_dir_.deleteTree(version_name) catch {}; - - Output.prettyErrorln( - "<r><red>error<r>: The downloaded version of bun (<red>{s}<r>) doesn't match the expected version (<b>{s}<r>)<r>. Cancelled upgrade", - .{ - result.stdout[0..@minimum(result.stdout.len, 128)], - version_name, - }, - ); - Global.exit(1); + // It should run successfully + // but we don't care about the version number if we're doing a canary build + if (!use_canary) { + if (!strings.eql(std.mem.trim(u8, result.stdout, " \n\r\t"), version_name)) { + save_dir_.deleteTree(version_name) catch {}; + + Output.prettyErrorln( + "<r><red>error<r>: The downloaded version of bun (<red>{s}<r>) doesn't match the expected version (<b>{s}<r>)<r>. Cancelled upgrade", + .{ + result.stdout[0..@minimum(result.stdout.len, 128)], + version_name, + }, + ); + Global.exit(1); + } } } @@ -555,6 +603,47 @@ pub const UpgradeCommand = struct { Global.exit(1); }; + if (use_canary) { + + // Check if the versions are the same + const target_stat = target_dir.statFile(target_filename) catch |err| { + save_dir_.deleteTree(version_name) catch {}; + Output.prettyErrorln("<r><red>error:<r> Failed to stat target bun {s}", .{@errorName(err)}); + Global.exit(1); + }; + + const dest_stat = save_dir.statFile(exe_subpath) catch |err| { + save_dir_.deleteTree(version_name) catch {}; + Output.prettyErrorln("<r><red>error:<r> Failed to stat source bun {s}", .{@errorName(err)}); + Global.exit(1); + }; + + if (target_stat.size == dest_stat.size and target_stat.size > 0) { + var input_buf = try ctx.allocator.alloc(u8, target_stat.size); + + const target_hash = std.hash.Wyhash.hash(0, target_dir.readFile(target_filename, input_buf) catch |err| { + save_dir_.deleteTree(version_name) catch {}; + Output.prettyErrorln("<r><red>error:<r> Failed to read target bun {s}", .{@errorName(err)}); + Global.exit(1); + }); + + const source_hash = std.hash.Wyhash.hash(0, save_dir.readFile(exe_subpath, input_buf) catch |err| { + save_dir_.deleteTree(version_name) catch {}; + Output.prettyErrorln("<r><red>error:<r> Failed to read source bun {s}", .{@errorName(err)}); + Global.exit(1); + }); + + if (target_hash == source_hash) { + save_dir_.deleteTree(version_name) catch {}; + Output.prettyErrorln( + "<r><green>Congrats!<r> You're already on the latest canary build of bun", + .{}, + ); + Global.exit(0); + } + } + } + if (env_loader.map.get("BUN_DRY_RUN") == null) { C.moveFileZ(save_dir.fd, exe_subpath, target_dir.fd, target_filename) catch |err| { save_dir_.deleteTree(version_name) catch {}; @@ -583,7 +672,42 @@ pub const UpgradeCommand = struct { Output.printStartEnd(ctx.start_time, std.time.nanoTimestamp()); - Output.prettyErrorln("<r> Upgraded.\n\n<b><green>Welcome to bun v{s}!<r>\n\n Report any bugs:\n https://github.com/oven-sh/bun/issues\n\n What's new:\n https://github.com/oven-sh/bun/releases/tag/{s}<r>", .{ version_name, version.tag }); + if (use_canary) { + Output.prettyErrorln( + \\<r> Upgraded. + \\ + \\<b><green>Welcome to bun's latest canary build!<r> + \\ + \\Report any bugs: + \\ + \\ https://github.com/oven-sh/bun/issues + \\ + \\What's new: + \\ + \\ <cyan>https://github.com/oven-sh/bun/releases/tag/{s}<r> + \\ + , + .{version.tag}, + ); + } else { + Output.prettyErrorln( + \\<r> Upgraded. + \\ + \\<b><green>Welcome to bun v{s}!<r> + \\ + \\Report any bugs: + \\ + \\ https://github.com/oven-sh/bun/issues + \\ + \\What's new: + \\ + \\ <cyan>https://github.com/oven-sh/bun/releases/tag/{s}<r> + \\ + , + .{ version_name, version.tag }, + ); + } + Output.flush(); return; } diff --git a/src/env.zig b/src/env.zig index 0e4cbc414..aa0a6de86 100644 --- a/src/env.zig +++ b/src/env.zig @@ -25,4 +25,4 @@ pub const isX86 = @import("builtin").target.cpu.arch.isX86(); pub const isX64 = @import("builtin").target.cpu.arch == .x86_64; pub const allow_assert = isDebug or isTest; pub const analytics_url = if (isDebug) "http://localhost:4000/events" else "http://i.bun.sh/events"; -pub const simd = isX86 or isAarch64; +pub const baseline = @import("build_options").baseline; diff --git a/src/http.zig b/src/http.zig index 1515f976f..605bd1840 100644 --- a/src/http.zig +++ b/src/http.zig @@ -1881,9 +1881,9 @@ pub const RequestContext = struct { var reloader = Api.Reloader.disable; if (ctx.bundler.options.hot_module_reloading) { reloader = Api.Reloader.live; - // if (ctx.bundler.options.jsx.supports_fast_refresh) { - // reloader = Api.Reloader.fast_refresh; - // } + if (ctx.bundler.options.jsx.supports_fast_refresh and ctx.bundler.env.get("BUN_FORCE_HMR") != null) { + reloader = Api.Reloader.fast_refresh; + } } const welcome_message = Api.WebsocketMessageWelcome{ diff --git a/src/http_client_async.zig b/src/http_client_async.zig index 2da75b652..7b376c986 100644 --- a/src/http_client_async.zig +++ b/src/http_client_async.zig @@ -56,6 +56,8 @@ pub fn onThreadStart(_: ?*anyopaque) ?*anyopaque { \\ <cyan>wsl --update<r> \\ <cyan>wsl --shutdown<r> \\ + \\ Please make sure you're using WSL version 2 (not WSL 1). + \\ \\If that doesn't work (and you're on a Windows machine), try this: \\ 1. Open Windows Update \\ 2. Download any updates to Windows Subsystem for Linux diff --git a/src/install/install.zig b/src/install/install.zig index 8ae032022..7373cf90d 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -199,7 +199,61 @@ const NetworkTask = struct { scope: *const Npm.Registry.Scope, loaded_manifest: ?Npm.PackageManifest, ) !void { - this.url_buf = try std.fmt.allocPrint(allocator, "{s}://{s}/{s}/{s}", .{ scope.url.displayProtocol(), scope.url.displayHostname(), strings.trim(scope.url.path, "/"), name }); + const pathname: string = if (!strings.eqlComptime(scope.url.pathname, "/")) + scope.url.pathname + else + @as(string, ""); + + if (pathname.len > 0) { + if (scope.url.getPort()) |port_number| { + this.url_buf = try std.fmt.allocPrint( + allocator, + "{s}://{s}:{d}/{s}/{s}", + .{ + scope.url.displayProtocol(), + scope.url.displayHostname(), + port_number, + pathname, + name, + }, + ); + } else { + this.url_buf = try std.fmt.allocPrint( + allocator, + "{s}://{s}/{s}/{s}", + .{ + scope.url.displayProtocol(), + scope.url.displayHostname(), + pathname, + name, + }, + ); + } + } else { + if (scope.url.getPort()) |port_number| { + this.url_buf = try std.fmt.allocPrint( + allocator, + "{s}://{s}:{d}/{s}", + .{ + scope.url.displayProtocol(), + scope.url.displayHostname(), + port_number, + name, + }, + ); + } else { + this.url_buf = try std.fmt.allocPrint( + allocator, + "{s}://{s}/{s}", + .{ + scope.url.displayProtocol(), + scope.url.displayHostname(), + name, + }, + ); + } + } + var last_modified: string = ""; var etag: string = ""; if (loaded_manifest) |manifest| { diff --git a/src/runtime.footer.bun.js b/src/runtime.footer.bun.js index 72a2703e9..a5466f53a 100644 --- a/src/runtime.footer.bun.js +++ b/src/runtime.footer.bun.js @@ -22,5 +22,6 @@ export var __require = (globalThis.require ||= function (moduleId) { return BUN_RUNTIME.__require(moduleId); }); +__require.d ||= BUN_RUNTIME.__require.d; globalThis.__internalIsCommonJSNamespace ||= BUN_RUNTIME.__internalIsCommonJSNamespace; diff --git a/src/string_immutable.zig b/src/string_immutable.zig index ec3a2ecbe..801eacd51 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -78,7 +78,7 @@ pub inline fn containsComptime(self: string, comptime str: string) bool { pub const includes = contains; pub inline fn containsAny(in: anytype, target: string) bool { - for (in) |str| if (contains(str, target)) return true; + for (in) |str| if (contains(bun.span(str), target)) return true; return false; } |
