diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..62e969a32f --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,8 @@ +# Add commits to ignore in `git blame`. This allows large stylistic refactors to +# avoid mucking up blames. +# +# To configure git to use this, run: +# +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# +4ec410e0d7c5f6a712c323444edbf56b48d432d8 # make @import("bun") work in zig (#19096) \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8793467f69..0ee2a8534b 100644 --- a/.gitignore +++ b/.gitignore @@ -153,6 +153,7 @@ test/cli/install/registry/packages/publish-pkg-* test/cli/install/registry/packages/@secret/publish-pkg-8 test/js/third_party/prisma/prisma/sqlite/dev.db-journal tmp +codegen-for-zig-team.tar.gz # Dependencies /vendor diff --git a/build.zig b/build.zig index bc5c4fcc28..f3a61aef29 100644 --- a/build.zig +++ b/build.zig @@ -4,7 +4,7 @@ const builtin = @import("builtin"); const Build = std.Build; const Step = Build.Step; const Compile = Step.Compile; -const LazyPath = Step.LazyPath; +const LazyPath = Build.LazyPath; const Target = std.Target; const ResolvedTarget = std.Build.ResolvedTarget; const CrossTarget = std.zig.CrossTarget; @@ -21,18 +21,18 @@ const pathRel = fs.path.relative; /// When updating this, make sure to adjust SetupZig.cmake const recommended_zig_version = "0.14.0"; -comptime { - if (!std.mem.eql(u8, builtin.zig_version_string, recommended_zig_version)) { - @compileError( - "" ++ - "Bun requires Zig version " ++ recommended_zig_version ++ ", but you have " ++ - builtin.zig_version_string ++ ". This is automatically configured via Bun's " ++ - "CMake setup. You likely meant to run `bun run build`. If you are trying to " ++ - "upgrade the Zig compiler, edit ZIG_COMMIT in cmake/tools/SetupZig.cmake or " ++ - "comment this error out.", - ); - } -} +// comptime { +// if (!std.mem.eql(u8, builtin.zig_version_string, recommended_zig_version)) { +// @compileError( +// "" ++ +// "Bun requires Zig version " ++ recommended_zig_version ++ ", but you have " ++ +// builtin.zig_version_string ++ ". This is automatically configured via Bun's " ++ +// "CMake setup. You likely meant to run `bun run build`. If you are trying to " ++ +// "upgrade the Zig compiler, edit ZIG_COMMIT in cmake/tools/SetupZig.cmake or " ++ +// "comment this error out.", +// ); +// } +// } const zero_sha = "0000000000000000000000000000000000000000"; @@ -93,6 +93,7 @@ const BunBuildOptions = struct { opts.addOption(bool, "baseline", this.isBaseline()); opts.addOption(bool, "enable_logs", this.enable_logs); opts.addOption([]const u8, "reported_nodejs_version", b.fmt("{}", .{this.reported_nodejs_version})); + opts.addOption(bool, "zig_self_hosted_backend", this.no_llvm); const mod = opts.createModule(); this.cached_options_module = mod; @@ -198,10 +199,7 @@ pub fn build(b: *Build) !void { const bun_version = b.option([]const u8, "version", "Value of `Bun.version`") orelse "0.0.0"; - b.reference_trace = ref_trace: { - const trace = b.option(u32, "reference-trace", "Set the reference trace") orelse 24; - break :ref_trace if (trace == 0) null else trace; - }; + b.reference_trace = b.reference_trace orelse 32; const obj_format = b.option(ObjectFormat, "obj_format", "Output file for object files") orelse .obj; @@ -388,7 +386,22 @@ pub fn build(b: *Build) !void { // zig build translate-c-headers { const step = b.step("translate-c", "Copy generated translated-c-headers.zig to zig-out"); - step.dependOn(&b.addInstallFile(getTranslateC(b, b.graph.host, .Debug).getOutput(), "translated-c-headers.zig").step); + for ([_]TargetDescription{ + .{ .os = .windows, .arch = .x86_64 }, + .{ .os = .mac, .arch = .x86_64 }, + .{ .os = .mac, .arch = .aarch64 }, + .{ .os = .linux, .arch = .x86_64 }, + .{ .os = .linux, .arch = .aarch64 }, + .{ .os = .linux, .arch = .x86_64, .musl = true }, + .{ .os = .linux, .arch = .aarch64, .musl = true }, + }) |t| { + const resolved = t.resolveTarget(b); + step.dependOn( + &b.addInstallFile(getTranslateC(b, resolved, .Debug), b.fmt("translated-c-headers/{s}.zig", .{ + resolved.result.zigTriple(b.allocator) catch @panic("OOM"), + })).step, + ); + } } // zig build enum-extractor @@ -405,23 +418,32 @@ pub fn build(b: *Build) !void { } } -pub fn addMultiCheck( +const TargetDescription = struct { + os: OperatingSystem, + arch: Arch, + musl: bool = false, + + fn resolveTarget(desc: TargetDescription, b: *Build) std.Build.ResolvedTarget { + return b.resolveTargetQuery(.{ + .os_tag = OperatingSystem.stdOSTag(desc.os), + .cpu_arch = desc.arch, + .cpu_model = getCpuModel(desc.os, desc.arch) orelse .determined_by_arch_os, + .os_version_min = getOSVersionMin(desc.os), + .glibc_version = if (desc.musl) null else getOSGlibCVersion(desc.os), + }); + } +}; + +fn addMultiCheck( b: *Build, parent_step: *Step, root_build_options: BunBuildOptions, - to_check: []const struct { os: OperatingSystem, arch: Arch, musl: bool = false }, + to_check: []const TargetDescription, optimize: []const std.builtin.OptimizeMode, ) void { for (to_check) |check| { for (optimize) |mode| { - const check_target = b.resolveTargetQuery(.{ - .os_tag = OperatingSystem.stdOSTag(check.os), - .cpu_arch = check.arch, - .cpu_model = getCpuModel(check.os, check.arch) orelse .determined_by_arch_os, - .os_version_min = getOSVersionMin(check.os), - .glibc_version = if (check.musl) null else getOSGlibCVersion(check.os), - }); - + const check_target = check.resolveTarget(b); var options: BunBuildOptions = .{ .target = check_target, .os = check.os, @@ -445,7 +467,13 @@ pub fn addMultiCheck( } } -fn getTranslateC(b: *Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *Step.TranslateC { +fn getTranslateC(b: *Build, initial_target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) LazyPath { + const target = b.resolveTargetQuery(q: { + var query = initial_target.query; + if (query.os_tag == .windows) + query.abi = .gnu; + break :q query; + }); const translate_c = b.addTranslateC(.{ .root_source_file = b.path("src/c-headers-for-zig.h"), .target = target, @@ -461,7 +489,35 @@ fn getTranslateC(b: *Build, target: std.Build.ResolvedTarget, optimize: std.buil const str, const value = entry; translate_c.defineCMacroRaw(b.fmt("{s}={d}", .{ str, @intFromBool(value) })); } - return translate_c; + + if (target.result.os.tag == .windows) { + // translate-c is unable to translate the unsuffixed windows functions + // like `SetCurrentDirectory` since they are defined with an odd macro + // that translate-c doesn't handle. + // + // #define SetCurrentDirectory __MINGW_NAME_AW(SetCurrentDirectory) + // + // In these cases, it's better to just reference the underlying function + // directly: SetCurrentDirectoryW. To make the error better, a post + // processing step is applied to the translate-c file. + // + // Additionally, this step makes it so that decls like NTSTATUS and + // HANDLE point to the standard library structures. + const helper_exe = b.addExecutable(.{ + .name = "process_windows_translate_c", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/codegen/process_windows_translate_c.zig"), + .target = b.graph.host, + .optimize = .Debug, + }), + }); + const in = translate_c.getOutput(); + const run = b.addRunArtifact(helper_exe); + run.addFileArg(in); + const out = run.addOutputFileArg("c-headers-for-zig.zig"); + return out; + } + return translate_c.getOutput(); } pub fn addBunObject(b: *Build, opts: *BunBuildOptions) *Compile { @@ -580,7 +636,7 @@ fn addInternalImports(b: *Build, mod: *Module, opts: *BunBuildOptions) void { mod.addImport("build_options", opts.buildOptionsModule(b)); const translate_c = getTranslateC(b, opts.target, opts.optimize); - mod.addImport("translated-c-headers", translate_c.createModule()); + mod.addImport("translated-c-headers", b.createModule(.{ .root_source_file = translate_c })); const zlib_internal_path = switch (os) { .windows => "src/deps/zlib.win32.zig", diff --git a/misctools/lldb/lldb_pretty_printers.py b/misctools/lldb/lldb_pretty_printers.py index 0ed2e6667e..4b0993ca43 100644 --- a/misctools/lldb/lldb_pretty_printers.py +++ b/misctools/lldb/lldb_pretty_printers.py @@ -61,7 +61,6 @@ zig_keywords = { 'try', 'union', 'unreachable', - 'usingnamespace', 'var', 'volatile', 'while', diff --git a/package.json b/package.json index a0161a693f..7ae7d3612e 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ }, "scripts": { "build": "bun run build:debug", + "watch": "bun zig build check --watch", "bd": "(bun run --silent build:debug &> /tmp/bun.debug.build.log || (cat /tmp/bun.debug.build.log && rm -rf /tmp/bun.debug.build.log && exit 1)) && rm -f /tmp/bun.debug.build.log && ./build/debug/bun-debug", "build:debug": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Debug -B build/debug", "build:valgrind": "bun ./scripts/build.mjs -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_BASELINE=ON -ENABLE_VALGRIND=ON -B build/debug-valgrind", diff --git a/scripts/pack-codegen-for-zig-team.sh b/scripts/pack-codegen-for-zig-team.sh new file mode 100644 index 0000000000..2d7ccbade7 --- /dev/null +++ b/scripts/pack-codegen-for-zig-team.sh @@ -0,0 +1,12 @@ +#!/bin/sh +if ! test -d build/debug/codegen; then + echo "Missing codegen" + exit 1 +fi + +out="codegen-for-zig-team.tar.gz" +tar -cf "$out" \ + build/debug/codegen \ + src/bun.js/bindings/GeneratedBindings.zig \ + src/bun.js/bindings/GeneratedJS2Native.zig +echo "-> $out" \ No newline at end of file diff --git a/src/StaticHashMap.zig b/src/StaticHashMap.zig index 31f6700ab8..e1288adb53 100644 --- a/src/StaticHashMap.zig +++ b/src/StaticHashMap.zig @@ -57,7 +57,20 @@ pub fn StaticHashMap(comptime K: type, comptime V: type, comptime Context: type, // get_probe_count: usize = 0, // del_probe_count: usize = 0, - pub usingnamespace HashMapMixin(Self, K, V, Context); + const impl = HashMapMixin(Self, K, V, Context); + pub const putAssumeCapacity = impl.putAssumeCapacity; + pub const slice = impl.slice; + pub const clearRetainingCapacity = impl.clearRetainingCapacity; + pub const putAssumeCapacityContext = impl.putAssumeCapacityContext; + pub const getOrPutAssumeCapacity = impl.getOrPutAssumeCapacity; + pub const getOrPutAssumeCapacityContext = impl.getOrPutAssumeCapacityContext; + pub const get = impl.get; + pub const getContext = impl.getContext; + pub const has = impl.has; + pub const hasWithHash = impl.hasWithHash; + pub const hasContext = impl.hasContext; + pub const delete = impl.delete; + pub const deleteContext = impl.deleteContext; }; } @@ -96,7 +109,20 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime Context: type, compt // get_probe_count: usize = 0, // del_probe_count: usize = 0, - pub usingnamespace HashMapMixin(Self, K, V, Context); + const impl = HashMapMixin(Self, K, V, Context); + pub const putAssumeCapacity = impl.putAssumeCapacity; + pub const slice = impl.slice; + pub const clearRetainingCapacity = impl.clearRetainingCapacity; + pub const putAssumeCapacityContext = impl.putAssumeCapacityContext; + pub const getOrPutAssumeCapacity = impl.getOrPutAssumeCapacity; + pub const getOrPutAssumeCapacityContext = impl.getOrPutAssumeCapacityContext; + pub const get = impl.get; + pub const getContext = impl.getContext; + pub const has = impl.has; + pub const hasWithHash = impl.hasWithHash; + pub const hasContext = impl.hasContext; + pub const delete = impl.delete; + pub const deleteContext = impl.deleteContext; pub fn initCapacity(gpa: mem.Allocator, capacity: u64) !Self { assert(math.isPowerOfTwo(capacity)); diff --git a/src/boringssl.zig b/src/boringssl.zig index d74cacad3f..893b1b3551 100644 --- a/src/boringssl.zig +++ b/src/boringssl.zig @@ -222,8 +222,8 @@ pub fn ERR_toJS(globalThis: *JSC.JSGlobalObject, err_code: u32) JSC.JSValue { const error_message: []const u8 = bun.sliceTo(outbuf[0..], 0); if (error_message.len == "BoringSSL ".len) { - return globalThis.ERR_BORINGSSL("An unknown BoringSSL error occurred: {d}", .{err_code}).toJS(); + return globalThis.ERR(.BORINGSSL, "An unknown BoringSSL error occurred: {d}", .{err_code}).toJS(); } - return globalThis.ERR_BORINGSSL("{s}", .{error_message}).toJS(); + return globalThis.ERR(.BORINGSSL, "{s}", .{error_message}).toJS(); } diff --git a/src/brotli.zig b/src/brotli.zig index f6bf49b7a4..9dcbe00271 100644 --- a/src/brotli.zig +++ b/src/brotli.zig @@ -1,9 +1,6 @@ const bun = @import("bun"); const std = @import("std"); -pub const c = struct { - pub usingnamespace @import("./deps/brotli_decoder.zig"); - pub usingnamespace @import("./deps/brotli_encoder.zig"); -}; +pub const c = @import("./deps/brotli_c.zig"); const BrotliDecoder = c.BrotliDecoder; const BrotliEncoder = c.BrotliEncoder; diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 427f5c994b..dd13b27c32 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -892,7 +892,7 @@ export fn Bun__resolveSync(global: *JSGlobalObject, specifier: JSValue, source: defer specifier_str.deref(); if (specifier_str.length() == 0) { - return global.ERR_INVALID_ARG_VALUE("The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; + return global.ERR(.INVALID_ARG_VALUE, "The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; } const source_str = source.toBunString(global) catch return .zero; @@ -916,7 +916,7 @@ export fn Bun__resolveSyncWithPaths( defer specifier_str.deref(); if (specifier_str.length() == 0) { - return global.ERR_INVALID_ARG_VALUE("The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; + return global.ERR(.INVALID_ARG_VALUE, "The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; } const source_str = source.toBunString(global) catch return .zero; @@ -939,7 +939,7 @@ export fn Bun__resolveSyncWithSource(global: *JSGlobalObject, specifier: JSValue const specifier_str = specifier.toBunString(global) catch return .zero; defer specifier_str.deref(); if (specifier_str.length() == 0) { - return global.ERR_INVALID_ARG_VALUE("The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; + return global.ERR(.INVALID_ARG_VALUE, "The argument 'id' must be a non-empty string. Received ''", .{}).throw() catch .zero; } return JSC.toJSHostValue(global, doResolveWithArgs(global, specifier_str, source.*, is_esm, true, is_user_require_resolve)); } @@ -1082,7 +1082,7 @@ pub fn serve(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.J } const obj = server.toJS(globalObject); if (route_list_object != .zero) { - ServerType.routeListSetCached(obj, globalObject, route_list_object); + ServerType.js.routeListSetCached(obj, globalObject, route_list_object); } server.js_value.set(globalObject, obj); diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig index dca95ee845..aaa344430f 100644 --- a/src/bun.js/api/bun/dns_resolver.zig +++ b/src/bun.js/api/bun/dns_resolver.zig @@ -3241,13 +3241,13 @@ pub const DNSResolver = struct { return c_ares.AF.INET6; } - return JSC.Error.ERR_INVALID_IP_ADDRESS.throw(globalThis, "Invalid IP address: \"{s}\"", .{slice}); + return JSC.Error.INVALID_IP_ADDRESS.throw(globalThis, "Invalid IP address: \"{s}\"", .{slice}); } fn setChannelServers(channel: *c_ares.Channel, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { // It's okay to call dns.setServers with active queries, but not dns.Resolver.setServers if (channel != try getChannelFromVM(globalThis) and c_ares.ares_queue_active_queries(channel) != 0) { - return globalThis.ERR_DNS_SET_SERVERS_FAILED("Failed to set servers: there are pending queries", .{}).throw(); + return globalThis.ERR(.DNS_SET_SERVERS_FAILED, "Failed to set servers: there are pending queries", .{}).throw(); } const arguments = callframe.arguments(); @@ -3313,7 +3313,7 @@ pub const DNSResolver = struct { }; if (c_ares.ares_inet_pton(af, addressBuffer.ptr, &entries[i].addr) != 1) { - return JSC.Error.ERR_INVALID_IP_ADDRESS.throw(globalThis, "Invalid IP address: \"{s}\"", .{addressSlice}); + return JSC.Error.INVALID_IP_ADDRESS.throw(globalThis, "Invalid IP address: \"{s}\"", .{addressSlice}); } if (i > 0) { diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index c1882820bb..b7735b06b0 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -2674,7 +2674,7 @@ pub const H2FrameParser = struct { } if (this.outStandingPings >= this.maxOutstandingPings) { - const exception = JSC.toTypeError(.ERR_HTTP2_PING_CANCEL, "HTTP2 ping cancelled", .{}, globalObject); + const exception = JSC.toTypeError(.HTTP2_PING_CANCEL, "HTTP2 ping cancelled", .{}, globalObject); return globalObject.throwValue(exception); } @@ -2714,7 +2714,7 @@ pub const H2FrameParser = struct { defer origin_string.deinit(); const slice = origin_string.slice(); if (slice.len + 2 > 16384) { - const exception = JSC.toTypeError(.ERR_HTTP2_ORIGIN_LENGTH, "HTTP/2 ORIGIN frames are limited to 16382 bytes", .{}, globalObject); + const exception = JSC.toTypeError(.HTTP2_ORIGIN_LENGTH, "HTTP/2 ORIGIN frames are limited to 16382 bytes", .{}, globalObject); return globalObject.throwValue(exception); } @@ -2752,12 +2752,12 @@ pub const H2FrameParser = struct { defer origin_string.deinit(); const slice = origin_string.slice(); _ = writer.writeInt(u16, @intCast(slice.len), .big) catch { - const exception = JSC.toTypeError(.ERR_HTTP2_ORIGIN_LENGTH, "HTTP/2 ORIGIN frames are limited to 16382 bytes", .{}, globalObject); + const exception = JSC.toTypeError(.HTTP2_ORIGIN_LENGTH, "HTTP/2 ORIGIN frames are limited to 16382 bytes", .{}, globalObject); return globalObject.throwValue(exception); }; _ = writer.write(slice) catch { - const exception = JSC.toTypeError(.ERR_HTTP2_ORIGIN_LENGTH, "HTTP/2 ORIGIN frames are limited to 16382 bytes", .{}, globalObject); + const exception = JSC.toTypeError(.HTTP2_ORIGIN_LENGTH, "HTTP/2 ORIGIN frames are limited to 16382 bytes", .{}, globalObject); return globalObject.throwValue(exception); }; } @@ -3288,16 +3288,16 @@ pub const H2FrameParser = struct { const name = name_slice.slice(); if (header_name.charAt(0) == ':') { - const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_PSEUDOHEADER, "\"{s}\" is an invalid pseudoheader or is used incorrectly", .{name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_INVALID_PSEUDOHEADER, "\"{s}\" is an invalid pseudoheader or is used incorrectly", .{name}, globalObject); return globalObject.throwValue(exception); } var js_value = try headers_arg.getTruthy(globalObject, name) orelse { - const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{name}, globalObject); return globalObject.throwValue(exception); }; const validated_name = toValidHeaderName(name, name_buffer[0..name.len]) catch { - const exception = JSC.toTypeError(.ERR_INVALID_HTTP_TOKEN, "The arguments Header name is invalid. Received {s}", .{name}, globalObject); + const exception = JSC.toTypeError(.INVALID_HTTP_TOKEN, "The arguments Header name is invalid. Received {s}", .{name}, globalObject); return globalObject.throwValue(exception); }; @@ -3307,7 +3307,7 @@ pub const H2FrameParser = struct { if (SingleValueHeaders.indexOf(validated_name)) |idx| { if (value_iter.len > 1 or single_value_headers[idx]) { - const exception = JSC.toTypeError(.ERR_HTTP2_HEADER_SINGLE_VALUE, "Header field \"{s}\" must only have a single value", .{validated_name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_HEADER_SINGLE_VALUE, "Header field \"{s}\" must only have a single value", .{validated_name}, globalObject); return globalObject.throwValue(exception); } single_value_headers[idx] = true; @@ -3315,12 +3315,12 @@ pub const H2FrameParser = struct { while (value_iter.next()) |item| { if (item.isEmptyOrUndefinedOrNull()) { - const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}, globalObject); return globalObject.throwValue(exception); } const value_str = item.toStringOrNull(globalObject) orelse { - const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}, globalObject); return globalObject.throwValue(exception); }; @@ -3344,13 +3344,13 @@ pub const H2FrameParser = struct { } else { if (SingleValueHeaders.indexOf(validated_name)) |idx| { if (single_value_headers[idx]) { - const exception = JSC.toTypeError(.ERR_HTTP2_HEADER_SINGLE_VALUE, "Header field \"{s}\" must only have a single value", .{validated_name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_HEADER_SINGLE_VALUE, "Header field \"{s}\" must only have a single value", .{validated_name}, globalObject); return globalObject.throwValue(exception); } single_value_headers[idx] = true; } const value_str = js_value.toStringOrNull(globalObject) orelse { - const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}, globalObject); return globalObject.throwValue(exception); }; @@ -3659,7 +3659,7 @@ pub const H2FrameParser = struct { return JSC.JSValue.jsNumber(stream_id); } const validated_name = toValidHeaderName(name, name_buffer[0..name.len]) catch { - const exception = JSC.toTypeError(.ERR_INVALID_HTTP_TOKEN, "The arguments Header name is invalid. Received \"{s}\"", .{name}, globalObject); + const exception = JSC.toTypeError(.INVALID_HTTP_TOKEN, "The arguments Header name is invalid. Received \"{s}\"", .{name}, globalObject); return globalObject.throwValue(exception); }; @@ -3669,14 +3669,14 @@ pub const H2FrameParser = struct { if (this.isServer) { if (!ValidResponsePseudoHeaders.has(validated_name)) { if (!globalObject.hasException()) { - return globalObject.ERR_HTTP2_INVALID_PSEUDOHEADER("\"{s}\" is an invalid pseudoheader or is used incorrectly", .{name}).throw(); + return globalObject.ERR(.HTTP2_INVALID_PSEUDOHEADER, "\"{s}\" is an invalid pseudoheader or is used incorrectly", .{name}).throw(); } return .zero; } } else { if (!ValidRequestPseudoHeaders.has(validated_name)) { if (!globalObject.hasException()) { - return globalObject.ERR_HTTP2_INVALID_PSEUDOHEADER("\"{s}\" is an invalid pseudoheader or is used incorrectly", .{name}).throw(); + return globalObject.ERR(.HTTP2_INVALID_PSEUDOHEADER, "\"{s}\" is an invalid pseudoheader or is used incorrectly", .{name}).throw(); } return .zero; } @@ -3687,7 +3687,7 @@ pub const H2FrameParser = struct { const js_value: JSC.JSValue = try headers_arg.get(globalObject, name) orelse { if (!globalObject.hasException()) { - return globalObject.ERR_HTTP2_INVALID_HEADER_VALUE("Invalid value for header \"{s}\"", .{name}).throw(); + return globalObject.ERR(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{name}).throw(); } return .zero; }; @@ -3700,7 +3700,7 @@ pub const H2FrameParser = struct { if (SingleValueHeaders.indexOf(validated_name)) |idx| { if (value_iter.len > 1 or single_value_headers[idx]) { if (!globalObject.hasException()) { - const exception = JSC.toTypeError(.ERR_HTTP2_HEADER_SINGLE_VALUE, "Header field \"{s}\" must only have a single value", .{validated_name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_HEADER_SINGLE_VALUE, "Header field \"{s}\" must only have a single value", .{validated_name}, globalObject); return globalObject.throwValue(exception); } return .zero; @@ -3711,14 +3711,14 @@ pub const H2FrameParser = struct { while (value_iter.next()) |item| { if (item.isEmptyOrUndefinedOrNull()) { if (!globalObject.hasException()) { - return globalObject.ERR_HTTP2_INVALID_HEADER_VALUE("Invalid value for header \"{s}\"", .{validated_name}).throw(); + return globalObject.ERR(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}).throw(); } return .zero; } const value_str = item.toStringOrNull(globalObject) orelse { if (!globalObject.hasException()) { - return globalObject.ERR_HTTP2_INVALID_HEADER_VALUE("Invalid value for header \"{s}\"", .{validated_name}).throw(); + return globalObject.ERR(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{validated_name}).throw(); } return .zero; }; @@ -3747,14 +3747,14 @@ pub const H2FrameParser = struct { log("single header {s}", .{name}); if (SingleValueHeaders.indexOf(validated_name)) |idx| { if (single_value_headers[idx]) { - const exception = JSC.toTypeError(.ERR_HTTP2_HEADER_SINGLE_VALUE, "Header field \"{s}\" must only have a single value", .{validated_name}, globalObject); + const exception = JSC.toTypeError(.HTTP2_HEADER_SINGLE_VALUE, "Header field \"{s}\" must only have a single value", .{validated_name}, globalObject); return globalObject.throwValue(exception); } single_value_headers[idx] = true; } const value_str = js_value.toStringOrNull(globalObject) orelse { if (!globalObject.hasException()) { - return globalObject.ERR_HTTP2_INVALID_HEADER_VALUE("Invalid value for header \"{s}\"", .{name}).throw(); + return globalObject.ERR(.HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{name}).throw(); } return .zero; }; diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index fbb32fc90c..82b5602534 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -875,7 +875,7 @@ pub const Listener = struct { this_socket.ref(); if (listener.strong_data.get()) |default_data| { const globalObject = listener.handlers.globalObject; - Socket.dataSetCached(this_socket.getThisValue(globalObject), globalObject, default_data); + Socket.js.dataSetCached(this_socket.getThisValue(globalObject), globalObject, default_data); } return this_socket; } @@ -901,7 +901,7 @@ pub const Listener = struct { this_socket.ref(); if (listener.strong_data.get()) |default_data| { const globalObject = listener.handlers.globalObject; - Socket.dataSetCached(this_socket.getThisValue(globalObject), globalObject, default_data); + Socket.js.dataSetCached(this_socket.getThisValue(globalObject), globalObject, default_data); } if (socket.ext(**anyopaque)) |ctx| { ctx.* = bun.cast(**anyopaque, this_socket); @@ -1150,7 +1150,7 @@ pub const Listener = struct { .server_name = server_name, .socket_context = null, }); - TLSSocket.dataSetCached(tls.getThisValue(globalObject), globalObject, default_data); + TLSSocket.js.dataSetCached(tls.getThisValue(globalObject), globalObject, default_data); tls.poll_ref.ref(handlers.vm); tls.ref(); if (connection == .unix) { @@ -1177,7 +1177,7 @@ pub const Listener = struct { .socket_context = null, }); tcp.ref(); - TCPSocket.dataSetCached(tcp.getThisValue(globalObject), globalObject, default_data); + TCPSocket.js.dataSetCached(tcp.getThisValue(globalObject), globalObject, default_data); tcp.poll_ref.ref(handlers.vm); if (connection == .unix) { @@ -1250,7 +1250,7 @@ pub const Listener = struct { .socket_context = socket_context, // owns the socket context }); - SocketType.dataSetCached(socket.getThisValue(globalObject), globalObject, default_data); + SocketType.js.dataSetCached(socket.getThisValue(globalObject), globalObject, default_data); socket.flags.allow_half_open = socket_config.allowHalfOpen; socket.doConnect(connection) catch { socket.handleConnectError(@intFromEnum(if (port == null) bun.C.SystemErrno.ENOENT else bun.C.SystemErrno.ECONNREFUSED)); @@ -1331,7 +1331,16 @@ fn selectALPNCallback( fn NewSocket(comptime ssl: bool) type { return struct { const This = @This(); + pub const js = if (!ssl) + JSC.Codegen.JSTCPSocket + else + JSC.Codegen.JSTLSSocket; + pub const toJS = js.toJS; + pub const fromJS = js.fromJS; + pub const fromJSDirect = js.fromjsDirect; + pub const new = bun.TrivialNew(@This()); + const RefCount = bun.ptr.RefCount(@This(), "ref_count", deinit, .{}); pub const ref = RefCount.ref; pub const deref = RefCount.deref; @@ -1406,11 +1415,6 @@ fn NewSocket(comptime ssl: bool) type { _: u7 = 0, }; - pub usingnamespace if (!ssl) - JSC.Codegen.JSTCPSocket - else - JSC.Codegen.JSTLSSocket; - pub fn hasPendingActivity(this: *This) callconv(.C) bool { return this.has_pending_activity.load(.acquire); } @@ -2013,7 +2017,7 @@ fn NewSocket(comptime ssl: bool) type { value: JSC.JSValue, ) callconv(.C) bool { log("setData()", .{}); - This.dataSetCached(this.this_value, globalObject, value); + This.js.dataSetCached(this.this_value, globalObject, value); return true; } @@ -3610,7 +3614,7 @@ fn NewSocket(comptime ssl: bool) type { // Do not create the JS Wrapper object until _after_ we've validated the TLS config. // Otherwise, JSC will GC it and the lifetime gets very complicated. const tls_js_value = tls.getThisValue(globalObject); - TLSSocket.dataSetCached(tls_js_value, globalObject, default_data); + TLSSocket.js.dataSetCached(tls_js_value, globalObject, default_data); tls.socket = new_socket; const new_context = new_socket.context().?; @@ -3652,7 +3656,7 @@ fn NewSocket(comptime ssl: bool) type { const raw_js_value = raw.getThisValue(globalObject); if (JSSocketType(ssl).dataGetCached(this_js)) |raw_default_data| { raw_default_data.ensureStillAlive(); - TLSSocket.dataSetCached(raw_js_value, globalObject, raw_default_data); + TLSSocket.js.dataSetCached(raw_js_value, globalObject, raw_default_data); } // marks both as active @@ -4425,7 +4429,7 @@ pub fn jsUpgradeDuplexToTLS(globalObject: *JSC.JSGlobalObject, callframe: *JSC.C .socket_context = null, // only set after the wrapTLS }); const tls_js_value = tls.getThisValue(globalObject); - TLSSocket.dataSetCached(tls_js_value, globalObject, default_data); + TLSSocket.js.dataSetCached(tls_js_value, globalObject, default_data); var duplexContext = DuplexUpgradeContext.new(.{ .upgrade = undefined, diff --git a/src/bun.js/api/bun/socket/SocketAddress.zig b/src/bun.js/api/bun/socket/SocketAddress.zig index 3ff29a9485..cd299ff39f 100644 --- a/src/bun.js/api/bun/socket/SocketAddress.zig +++ b/src/bun.js/api/bun/socket/SocketAddress.zig @@ -115,9 +115,9 @@ pub const Options = struct { } inline fn throwBadPort(global: *JSC.JSGlobalObject, port_: JSC.JSValue) bun.JSError { const ty = global.determineSpecificType(port_) catch { - return global.ERR_SOCKET_BAD_PORT("The \"options.port\" argument must be a valid IP port number.", .{}).throw(); + return global.ERR(.SOCKET_BAD_PORT, "The \"options.port\" argument must be a valid IP port number.", .{}).throw(); }; - return global.ERR_SOCKET_BAD_PORT("The \"options.port\" argument must be a valid IP port number. Got {s}.", .{ty}).throw(); + return global.ERR(.SOCKET_BAD_PORT, "The \"options.port\" argument must be a valid IP port number. Got {s}.", .{ty}).throw(); } }; diff --git a/src/bun.js/api/bun/spawn.zig b/src/bun.js/api/bun/spawn.zig index 4b4bacdb8b..8733e05e43 100644 --- a/src/bun.js/api/bun/spawn.zig +++ b/src/bun.js/api/bun/spawn.zig @@ -429,6 +429,17 @@ pub const PosixSpawn = struct { } } - pub usingnamespace @import("./process.zig"); - pub usingnamespace @import("./spawn/stdio.zig"); + pub const process = @import("process.zig"); + pub const Process = process.Process; + pub const SpawnOptions = process.SpawnOptions; + pub const Status = process.Status; + pub const sync = process.sync; + pub const spawnProcess = process.spawnProcess; + pub const WindowsSpawnResult = process.WindowsSpawnResult; + pub const PosixSpawnResult = process.PosixSpawnResult; + pub const SpawnProcessResult = process.SpawnProcessResult; + pub const WindowsSpawnOptions = process.WindowsSpawnOptions; + pub const Rusage = process.Rusage; + + pub const Stdio = @import("spawn/stdio.zig").Stdio; }; diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index c4b093734b..a90f727dca 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -232,7 +232,7 @@ pub fn createResourceUsageObject(this: *Subprocess, globalObject: *JSGlobalObjec const pid_rusage = this.pid_rusage orelse brk: { if (Environment.isWindows) { if (this.process.poller == .uv) { - this.pid_rusage = PosixSpawn.uv_getrusage(&this.process.poller.uv); + this.pid_rusage = PosixSpawn.process.uv_getrusage(&this.process.poller.uv); break :brk this.pid_rusage.?; } } @@ -775,7 +775,7 @@ pub fn doSend(this: *Subprocess, global: *JSC.JSGlobalObject, callFrame: *JSC.Ca const ipc_data = &(this.ipc_data orelse { if (this.hasExited()) { - return global.ERR_IPC_CHANNEL_CLOSED("Subprocess.send() cannot be used after the process has exited.", .{}).throw(); + return global.ERR(.IPC_CHANNEL_CLOSED, "Subprocess.send() cannot be used after the process has exited.", .{}).throw(); } else { return global.throw("Subprocess.send() can only be used if an IPC channel is open.", .{}); } @@ -913,29 +913,30 @@ pub const StaticPipeWriter = NewStaticPipeWriter(Subprocess); pub fn NewStaticPipeWriter(comptime ProcessType: type) type { return struct { + const This = @This(); + + ref_count: WriterRefCount, writer: IOWriter = .{}, stdio_result: StdioResult, source: Source = .{ .detached = {} }, process: *ProcessType = undefined, event_loop: JSC.EventLoopHandle, - ref_count: WriterRefCount, buffer: []const u8 = "", // It seems there is a bug in the Zig compiler. We'll get back to this one later - const WriterRefCount = bun.ptr.RefCount(This, "ref_count", _deinit, .{}); - pub usingnamespace bun.ptr.RefCount(This, "ref_count", _deinit, .{}); + const WriterRefCount = bun.ptr.RefCount(@This(), "ref_count", _deinit, .{}); + pub const ref = WriterRefCount.ref; + pub const deref = WriterRefCount.deref; - const This = @This(); const print = bun.Output.scoped(.StaticPipeWriter, false); - pub const IOWriter = bun.io.BufferedWriter( - This, - onWrite, - onError, - onClose, - getBuffer, - flush, - ); + pub const IOWriter = bun.io.BufferedWriter(@This(), struct { + pub const onWritable = null; + pub const getBuffer = This.getBuffer; + pub const onClose = This.onClose; + pub const onError = This.onError; + pub const onWrite = This.onWrite; + }); pub const Poll = IOWriter; pub fn updateRef(this: *This, add: bool) void { @@ -2706,10 +2707,10 @@ const LifecycleScriptSubprocess = bun.install.LifecycleScriptSubprocess; const Body = JSC.WebCore.Body; const IPClog = Output.scoped(.IPC, false); -const PosixSpawn = bun.posix.spawn; -const Rusage = bun.posix.spawn.Rusage; -const Process = bun.posix.spawn.Process; -const WaiterThread = bun.posix.spawn.WaiterThread; +const PosixSpawn = bun.spawn; +const Rusage = bun.spawn.Rusage; +const Process = bun.spawn.Process; +const WaiterThread = bun.spawn.WaiterThread; const Stdio = bun.spawn.Stdio; const StdioResult = if (Environment.isWindows) bun.spawn.WindowsSpawnResult.StdioResult else ?bun.FileDescriptor; diff --git a/src/bun.js/api/crypto/CryptoHasher.zig b/src/bun.js/api/crypto/CryptoHasher.zig index eec9906f6e..959fbc1e1d 100644 --- a/src/bun.js/api/crypto/CryptoHasher.zig +++ b/src/bun.js/api/crypto/CryptoHasher.zig @@ -228,7 +228,7 @@ pub const CryptoHasher = union(enum) { inline else => |*str| { defer str.deinit(); const encoding = JSC.Node.Encoding.from(str.slice()) orelse { - return globalThis.ERR_INVALID_ARG_VALUE("Unknown encoding: {s}", .{str.slice()}).throw(); + return globalThis.ERR(.INVALID_ARG_VALUE, "Unknown encoding: {s}", .{str.slice()}).throw(); }; return hashToEncoding(globalThis, &evp, input, encoding); @@ -393,7 +393,7 @@ pub const CryptoHasher = union(enum) { inline else => |*str| { defer str.deinit(); const encoding = JSC.Node.Encoding.from(str.slice()) orelse { - return globalThis.ERR_INVALID_ARG_VALUE("Unknown encoding: {s}", .{str.slice()}).throw(); + return globalThis.ERR(.INVALID_ARG_VALUE, "Unknown encoding: {s}", .{str.slice()}).throw(); }; return this.digestToEncoding(globalThis, encoding); @@ -517,7 +517,7 @@ const CryptoHasherZig = struct { inline else => |*str| { defer str.deinit(); const encoding = JSC.Node.Encoding.from(str.slice()) orelse { - return globalThis.ERR_INVALID_ARG_VALUE("Unknown encoding: {s}", .{str.slice()}).throw(); + return globalThis.ERR(.INVALID_ARG_VALUE, "Unknown encoding: {s}", .{str.slice()}).throw(); }; if (encoding == .buffer) { @@ -664,7 +664,10 @@ fn StaticCryptoHasher(comptime Hasher: type, comptime name: [:0]const u8) type { const ThisHasher = @This(); - pub usingnamespace @field(JSC.Codegen, "JS" ++ name); + pub const js = @field(JSC.Codegen, "JS" ++ name); + pub const toJS = js.toJS; + pub const fromJS = js.fromJS; + pub const fromJSDirect = js.fromJSDirect; pub const digest = JSC.wrapInstanceMethod(ThisHasher, "digest_", false); pub const hash = JSC.wrapStaticMethod(ThisHasher, "hash_", false); @@ -741,7 +744,7 @@ fn StaticCryptoHasher(comptime Hasher: type, comptime name: [:0]const u8) type { inline else => |*str| { defer str.deinit(); const encoding = JSC.Node.Encoding.from(str.slice()) orelse { - return globalThis.ERR_INVALID_ARG_VALUE("Unknown encoding: {s}", .{str.slice()}).throw(); + return globalThis.ERR(.INVALID_ARG_VALUE, "Unknown encoding: {s}", .{str.slice()}).throw(); }; return hashToEncoding(globalThis, input, encoding); @@ -765,12 +768,12 @@ fn StaticCryptoHasher(comptime Hasher: type, comptime name: [:0]const u8) type { globalObject: *JSC.JSGlobalObject, _: *JSC.JSObject, ) JSC.JSValue { - return ThisHasher.getConstructor(globalObject); + return ThisHasher.js.getConstructor(globalObject); } pub fn update(this: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { if (this.digested) { - return globalThis.ERR_INVALID_STATE(name ++ " hasher already digested, create a new instance to update", .{}).throw(); + return globalThis.ERR(.INVALID_STATE, name ++ " hasher already digested, create a new instance to update", .{}).throw(); } const thisValue = callframe.this(); const input = callframe.argument(0); @@ -792,14 +795,14 @@ fn StaticCryptoHasher(comptime Hasher: type, comptime name: [:0]const u8) type { output: ?JSC.Node.StringOrBuffer, ) bun.JSError!JSC.JSValue { if (this.digested) { - return globalThis.ERR_INVALID_STATE(name ++ " hasher already digested, create a new instance to digest again", .{}).throw(); + return globalThis.ERR(.INVALID_STATE, name ++ " hasher already digested, create a new instance to digest again", .{}).throw(); } if (output) |*string_or_buffer| { switch (string_or_buffer.*) { inline else => |*str| { defer str.deinit(); const encoding = JSC.Node.Encoding.from(str.slice()) orelse { - return globalThis.ERR_INVALID_ARG_VALUE("Unknown encoding: {s}", .{str.slice()}).throw(); + return globalThis.ERR(.INVALID_ARG_VALUE, "Unknown encoding: {s}", .{str.slice()}).throw(); }; return this.digestToEncoding(globalThis, encoding); diff --git a/src/bun.js/api/crypto/PBKDF2.zig b/src/bun.js/api/crypto/PBKDF2.zig index bbcf83f52f..2708940369 100644 --- a/src/bun.js/api/crypto/PBKDF2.zig +++ b/src/bun.js/api/crypto/PBKDF2.zig @@ -175,7 +175,7 @@ pub fn fromJS(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame, is_asy const slice = try arg4.toSlice(globalThis, bun.default_allocator); defer slice.deinit(); const name = slice.slice(); - return globalThis.ERR_CRYPTO_INVALID_DIGEST("Invalid digest: {s}", .{name}).throw(); + return globalThis.ERR(.CRYPTO_INVALID_DIGEST, "Invalid digest: {s}", .{name}).throw(); } return error.JSError; }; diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index b1290ef750..a9c158c4df 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -1290,7 +1290,7 @@ pub const FFI = struct { defer type_name.deinit(); abi_types.appendAssumeCapacity(ABIType.label.get(type_name.slice()) orelse { abi_types.clearAndFree(allocator); - return JSC.toTypeError(.ERR_INVALID_ARG_VALUE, "Unknown type {s}", .{type_name.slice()}, global); + return JSC.toTypeError(.INVALID_ARG_VALUE, "Unknown type {s}", .{type_name.slice()}, global); }); } } @@ -1322,7 +1322,7 @@ pub const FFI = struct { defer ret_slice.deinit(); return_type = ABIType.label.get(ret_slice.slice()) orelse { abi_types.clearAndFree(allocator); - return JSC.toTypeError(.ERR_INVALID_ARG_VALUE, "Unknown return type {s}", .{ret_slice.slice()}, global); + return JSC.toTypeError(.INVALID_ARG_VALUE, "Unknown return type {s}", .{ret_slice.slice()}, global); }; } @@ -1381,7 +1381,7 @@ pub const FFI = struct { const value = symbols_iter.value; if (value.isEmptyOrUndefinedOrNull()) { - return JSC.toTypeError(.ERR_INVALID_ARG_VALUE, "Expected an object for key \"{any}\"", .{prop}, global); + return JSC.toTypeError(.INVALID_ARG_VALUE, "Expected an object for key \"{any}\"", .{prop}, global); } var function: Function = .{ .allocator = allocator }; diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 59df543db9..3f3891009e 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -5154,13 +5154,26 @@ const PluginsResult = union(enum) { err, }; -pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { +pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { debug, production }) type { return struct { - pub usingnamespace NamespaceType; + pub const js = switch (protocol_enum) { + .http => switch (development_kind) { + .debug => bun.JSC.Codegen.JSDebugHTTPServer, + .production => bun.JSC.Codegen.JSHTTPServer, + }, + .https => switch (development_kind) { + .debug => bun.JSC.Codegen.JSDebugHTTPSServer, + .production => bun.JSC.Codegen.JSHTTPSServer, + }, + }; + pub const fromJS = js.fromJS; + pub const toJS = js.toJS; + pub const toJSDirect = js.toJSDirect; + pub const new = bun.TrivialNew(@This()); - pub const ssl_enabled = ssl_enabled_; - pub const debug_mode = debug_mode_; + pub const ssl_enabled = protocol_enum == .https; + pub const debug_mode = development_kind == .debug; const ThisServer = @This(); pub const RequestContext = NewRequestContext(ssl_enabled, debug_mode, @This()); @@ -5685,7 +5698,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp const route_list_value = this.setRoutes(); if (new_config.had_routes_object) { if (this.js_value.get()) |server_js_value| { - NamespaceType.routeListSetCached(server_js_value, this.globalThis, route_list_value); + js.routeListSetCached(server_js_value, this.globalThis, route_list_value); } } } @@ -5700,7 +5713,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp const route_list_value = this.setRoutes(); if (route_list_value != .zero) { if (this.js_value.get()) |server_js_value| { - NamespaceType.routeListSetCached(server_js_value, this.globalThis, route_list_value); + js.routeListSetCached(server_js_value, this.globalThis, route_list_value); } } return true; @@ -5820,7 +5833,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp ); } else { const fetch_error = JSC.WebCore.Fetch.fetch_type_error_strings.get(bun.JSC.C.JSValueGetType(ctx, first_arg.asRef())); - const err = JSC.toTypeError(.ERR_INVALID_ARG_TYPE, "{s}", .{fetch_error}, ctx); + const err = JSC.toTypeError(.INVALID_ARG_TYPE, "{s}", .{fetch_error}, ctx); return JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(ctx, err); } @@ -5961,7 +5974,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp port = @intCast(listener.getLocalPort()); } break :blk bun.fmt.URLFormatter{ - .proto = if (comptime ssl_enabled_) .https else .http, + .proto = if (comptime ssl_enabled) .https else .http, .hostname = if (tcp.hostname) |hostname| bun.sliceTo(@constCast(hostname), 0) else null, .port = port, }; @@ -6130,7 +6143,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp this.listener = null; this.unref(); - if (!ssl_enabled_) + if (!ssl_enabled) this.vm.removeListeningSocketForWatchMode(listener.socket().fd()); if (!abrupt) { @@ -6241,7 +6254,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp server.request_pool_allocator = RequestContext.pool.?; - if (comptime ssl_enabled_) { + if (comptime ssl_enabled) { Analytics.Features.https_server += 1; } else { Analytics.Features.http_server += 1; @@ -6364,7 +6377,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp this.listener = socket; this.vm.event_loop_handle = Async.Loop.get(); - if (!ssl_enabled_) + if (!ssl_enabled) this.vm.addListeningSocketForWatchMode(socket.?.socket().fd()); } @@ -6612,7 +6625,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp var should_deinit_context = false; var prepared = server.prepareJsRequestContext(req, resp, &should_deinit_context, false) orelse return; - const server_request_list = NamespaceType.routeListGetCached(server.jsValueAssertAlive()).?; + const server_request_list = js.routeListGetCached(server.jsValueAssertAlive()).?; var response_value = Bun__ServerRouteList__callRoute(server.globalThis, index, prepared.request_object, server.jsValueAssertAlive(), server_request_list, &prepared.js_request, req); if (server.globalThis.tryTakeException()) |exception| { @@ -6859,7 +6872,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp var should_deinit_context = false; var prepared = server.prepareJsRequestContext(req, resp, &should_deinit_context, false) orelse return; prepared.ctx.upgrade_context = upgrade_ctx; // set the upgrade context - const server_request_list = NamespaceType.routeListGetCached(server.jsValueAssertAlive()).?; + const server_request_list = js.routeListGetCached(server.jsValueAssertAlive()).?; var response_value = Bun__ServerRouteList__callRoute(server.globalThis, index, prepared.request_object, server.jsValueAssertAlive(), server_request_list, &prepared.js_request, req); if (server.globalThis.tryTakeException()) |exception| { @@ -7368,10 +7381,10 @@ pub const ServerAllConnectionsClosedTask = struct { } }; -pub const HTTPServer = NewServer(JSC.Codegen.JSHTTPServer, false, false); -pub const HTTPSServer = NewServer(JSC.Codegen.JSHTTPSServer, true, false); -pub const DebugHTTPServer = NewServer(JSC.Codegen.JSDebugHTTPServer, false, true); -pub const DebugHTTPSServer = NewServer(JSC.Codegen.JSDebugHTTPSServer, true, true); +pub const HTTPServer = NewServer(.http, .production); +pub const HTTPSServer = NewServer(.https, .production); +pub const DebugHTTPServer = NewServer(.http, .debug); +pub const DebugHTTPSServer = NewServer(.https, .debug); pub const AnyServer = struct { ptr: Ptr, diff --git a/src/bun.js/api/server/NodeHTTPResponse.zig b/src/bun.js/api/server/NodeHTTPResponse.zig index c3cfbc4839..a12a50de1f 100644 --- a/src/bun.js/api/server/NodeHTTPResponse.zig +++ b/src/bun.js/api/server/NodeHTTPResponse.zig @@ -404,7 +404,7 @@ pub fn jsUnref(this: *NodeHTTPResponse, globalObject: *JSC.JSGlobalObject, _: *J fn handleEndedIfNecessary(state: uws.State, globalObject: *JSC.JSGlobalObject) bun.JSError!void { if (!state.isResponsePending()) { - return globalObject.ERR_HTTP_HEADERS_SENT("Stream is already ended", .{}).throw(); + return globalObject.ERR(.HTTP_HEADERS_SENT, "Stream is already ended", .{}).throw(); } } @@ -428,7 +428,7 @@ pub fn writeHead(this: *NodeHTTPResponse, globalObject: *JSC.JSGlobalObject, cal const arguments = callframe.argumentsUndef(3).slice(); if (this.isDone()) { - return globalObject.ERR_STREAM_ALREADY_FINISHED("Stream is already ended", .{}).throw(); + return globalObject.ERR(.STREAM_ALREADY_FINISHED, "Stream is already ended", .{}).throw(); } const state = this.raw_response.state(); @@ -463,7 +463,7 @@ pub fn writeHead(this: *NodeHTTPResponse, globalObject: *JSC.JSGlobalObject, cal } if (state.isHttpStatusCalled()) { - return globalObject.ERR_HTTP_HEADERS_SENT("Stream already started", .{}).throw(); + return globalObject.ERR(.HTTP_HEADERS_SENT, "Stream already started", .{}).throw(); } do_it: { @@ -789,12 +789,12 @@ fn writeOrEnd( comptime is_end: bool, ) bun.JSError!JSC.JSValue { if (this.isDone()) { - return globalObject.ERR_STREAM_WRITE_AFTER_END("Stream already ended", .{}).throw(); + return globalObject.ERR(.STREAM_WRITE_AFTER_END, "Stream already ended", .{}).throw(); } const state = this.raw_response.state(); if (!state.isResponsePending()) { - return globalObject.ERR_STREAM_WRITE_AFTER_END("Stream already ended", .{}).throw(); + return globalObject.ERR(.STREAM_WRITE_AFTER_END, "Stream already ended", .{}).throw(); } const input_value = if (arguments.len > 0) arguments[0] else .undefined; @@ -1047,7 +1047,7 @@ pub fn cork(this: *NodeHTTPResponse, globalObject: *JSC.JSGlobalObject, callfram } if (this.flags.request_has_completed or this.flags.socket_closed) { - return globalObject.ERR_STREAM_ALREADY_FINISHED("Stream is already ended", .{}).throw(); + return globalObject.ERR(.STREAM_ALREADY_FINISHED, "Stream is already ended", .{}).throw(); } var result: JSC.JSValue = .zero; diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig index 0ba3eef83f..6b64d19f0f 100644 --- a/src/bun.js/base.zig +++ b/src/bun.js/base.zig @@ -215,7 +215,7 @@ pub fn toInvalidArguments( ctx: *JSC.JSGlobalObject, ) JSC.JSValue { @branchHint(.cold); - return JSC.Error.ERR_INVALID_ARG_TYPE.fmt(ctx, fmt, args); + return JSC.Error.INVALID_ARG_TYPE.fmt(ctx, fmt, args); } pub fn getAllocator(_: *JSC.JSGlobalObject) std.mem.Allocator { diff --git a/src/bun.js/bindings/JSGlobalObject.zig b/src/bun.js/bindings/JSGlobalObject.zig index 4fef77dfce..e293eee25b 100644 --- a/src/bun.js/bindings/JSGlobalObject.zig +++ b/src/bun.js/bindings/JSGlobalObject.zig @@ -47,9 +47,9 @@ pub const JSGlobalObject = opaque { pub inline fn throwMissingArgumentsValue(this: *JSGlobalObject, comptime arg_names: []const []const u8) bun.JSError { return switch (arg_names.len) { 0 => @compileError("requires at least one argument"), - 1 => this.ERR_MISSING_ARGS("The \"{s}\" argument must be specified", .{arg_names[0]}).throw(), - 2 => this.ERR_MISSING_ARGS("The \"{s}\" and \"{s}\" arguments must be specified", .{ arg_names[0], arg_names[1] }).throw(), - 3 => this.ERR_MISSING_ARGS("The \"{s}\", \"{s}\", and \"{s}\" arguments must be specified", .{ arg_names[0], arg_names[1], arg_names[2] }).throw(), + 1 => this.ERR(.MISSING_ARGS, "The \"{s}\" argument must be specified", .{arg_names[0]}).throw(), + 2 => this.ERR(.MISSING_ARGS, "The \"{s}\" and \"{s}\" arguments must be specified", .{ arg_names[0], arg_names[1] }).throw(), + 3 => this.ERR(.MISSING_ARGS, "The \"{s}\", \"{s}\", and \"{s}\" arguments must be specified", .{ arg_names[0], arg_names[1], arg_names[2] }).throw(), else => @compileError("implement this message"), }; } @@ -61,7 +61,7 @@ pub const JSGlobalObject = opaque { comptime field: []const u8, comptime typename: []const u8, ) JSC.JSValue { - return this.ERR_INVALID_ARG_TYPE(comptime std.fmt.comptimePrint("Expected {s} to be a {s} for '{s}'.", .{ field, typename, name_ }), .{}).toJS(); + return this.ERR(.INVALID_ARG_TYPE, comptime std.fmt.comptimePrint("Expected {s} to be a {s} for '{s}'.", .{ field, typename, name_ }), .{}).toJS(); } pub fn toJS(this: *JSC.JSGlobalObject, value: anytype, comptime lifetime: JSC.Lifetime) JSC.JSValue { @@ -86,7 +86,7 @@ pub const JSGlobalObject = opaque { ) bun.JSError { const actual_string_value = try determineSpecificType(this, value); defer actual_string_value.deref(); - return this.ERR_INVALID_ARG_VALUE("The \"{s}\" argument is invalid. Received {}", .{ argname, actual_string_value }).throw(); + return this.ERR(.INVALID_ARG_VALUE, "The \"{s}\" argument is invalid. Received {}", .{ argname, actual_string_value }).throw(); } /// Throw an `ERR_INVALID_ARG_VALUE` when the invalid value is a property of an object. @@ -102,9 +102,9 @@ pub const JSGlobalObject = opaque { const actual_string_value = try determineSpecificType(this, value); defer actual_string_value.deref(); if (comptime expected) |_expected| { - return this.ERR_INVALID_ARG_VALUE("The property \"{s}\" is invalid. Expected {s}, received {}", .{ argname, _expected, actual_string_value }).throw(); + return this.ERR(.INVALID_ARG_VALUE, "The property \"{s}\" is invalid. Expected {s}, received {}", .{ argname, _expected, actual_string_value }).throw(); } else { - return this.ERR_INVALID_ARG_VALUE("The property \"{s}\" is invalid. Received {}", .{ argname, actual_string_value }).throw(); + return this.ERR(.INVALID_ARG_VALUE, "The property \"{s}\" is invalid. Received {}", .{ argname, actual_string_value }).throw(); } } @@ -124,7 +124,7 @@ pub const JSGlobalObject = opaque { opt1: []const u8, opt2: []const u8, ) JSError { - return this.ERR_INCOMPATIBLE_OPTION_PAIR("Option \"{s}\" cannot be used in combination with option \"{s}\"", .{ opt1, opt2 }).throw(); + return this.ERR(.INCOMPATIBLE_OPTION_PAIR, "Option \"{s}\" cannot be used in combination with option \"{s}\"", .{ opt1, opt2 }).throw(); } pub fn throwInvalidScryptParams( @@ -134,10 +134,10 @@ pub const JSGlobalObject = opaque { if (err != 0) { var buf: [256]u8 = undefined; const msg = bun.BoringSSL.c.ERR_error_string_n(err, &buf, buf.len); - return this.ERR_CRYPTO_INVALID_SCRYPT_PARAMS("Invalid scrypt params: {s}", .{msg}).throw(); + return this.ERR(.CRYPTO_INVALID_SCRYPT_PARAMS, "Invalid scrypt params: {s}", .{msg}).throw(); } - return this.ERR_CRYPTO_INVALID_SCRYPT_PARAMS("Invalid scrypt params", .{}).throw(); + return this.ERR(.CRYPTO_INVALID_SCRYPT_PARAMS, "Invalid scrypt params", .{}).throw(); } /// "The {argname} argument must be of type {typename}. Received {value}" @@ -149,7 +149,7 @@ pub const JSGlobalObject = opaque { ) bun.JSError { const actual_string_value = try determineSpecificType(this, value); defer actual_string_value.deref(); - return this.ERR_INVALID_ARG_TYPE("The \"{s}\" argument must be of type {s}. Received {}", .{ argname, typename, actual_string_value }).throw(); + return this.ERR(.INVALID_ARG_TYPE, "The \"{s}\" argument must be of type {s}. Received {}", .{ argname, typename, actual_string_value }).throw(); } pub fn throwInvalidArgumentTypeValue2( @@ -160,7 +160,7 @@ pub const JSGlobalObject = opaque { ) JSError { const actual_string_value = try determineSpecificType(this, value); defer actual_string_value.deref(); - return this.ERR_INVALID_ARG_TYPE("The \"{s}\" argument must be {s}. Received {}", .{ argname, typename, actual_string_value }).throw(); + return this.ERR(.INVALID_ARG_TYPE, "The \"{s}\" argument must be {s}. Received {}", .{ argname, typename, actual_string_value }).throw(); } /// "The argument must be one of type . Received " @@ -172,7 +172,7 @@ pub const JSGlobalObject = opaque { ) bun.JSError { const actual_string_value = try determineSpecificType(this, value); defer actual_string_value.deref(); - return this.ERR_INVALID_ARG_TYPE("The \"{s}\" argument must be one of type {s}. Received {}", .{ argname, typename, actual_string_value }).throw(); + return this.ERR(.INVALID_ARG_TYPE, "The \"{s}\" argument must be one of type {s}. Received {}", .{ argname, typename, actual_string_value }).throw(); } pub fn throwInvalidArgumentRangeValue( @@ -181,7 +181,7 @@ pub const JSGlobalObject = opaque { typename: []const u8, value: i64, ) bun.JSError { - return this.ERR_OUT_OF_RANGE("The \"{s}\" is out of range. {s}. Received {}", .{ argname, typename, value }).throw(); + return this.ERR(.OUT_OF_RANGE, "The \"{s}\" is out of range. {s}. Received {}", .{ argname, typename, value }).throw(); } pub fn throwInvalidPropertyTypeValue( @@ -192,7 +192,7 @@ pub const JSGlobalObject = opaque { ) bun.JSError { const ty_str = value.jsTypeString(this).toSlice(this, bun.default_allocator); defer ty_str.deinit(); - return this.ERR_INVALID_ARG_TYPE("The \"{s}\" property must be of type {s}. Received {s}", .{ field, typename, ty_str.slice() }).throw(); + return this.ERR(.INVALID_ARG_TYPE, "The \"{s}\" property must be of type {s}. Received {s}", .{ field, typename, ty_str.slice() }).throw(); } pub fn createNotEnoughArguments( @@ -201,7 +201,7 @@ pub const JSGlobalObject = opaque { comptime expected: usize, got: usize, ) JSC.JSValue { - return JSC.toTypeError(.ERR_MISSING_ARGS, "Not enough arguments to '" ++ name_ ++ "'. Expected {d}, got {d}.", .{ expected, got }, this); + return JSC.toTypeError(.MISSING_ARGS, "Not enough arguments to '" ++ name_ ++ "'. Expected {d}, got {d}.", .{ expected, got }, this); } /// Not enough arguments passed to function named `name_` @@ -323,7 +323,7 @@ pub const JSGlobalObject = opaque { } pub fn createInvalidArgs(this: *JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) JSValue { - return JSC.Error.ERR_INVALID_ARG_TYPE.fmt(this, fmt, args); + return JSC.Error.INVALID_ARG_TYPE.fmt(this, fmt, args); } pub const SysErrOptions = struct { @@ -634,10 +634,7 @@ pub const JSGlobalObject = opaque { } pub fn throwRangeError(this: *JSGlobalObject, value: anytype, options: bun.fmt.OutOfRangeOptions) bun.JSError { - // TODO: - // This works around a Zig compiler bug - // when using this.ERR_OUT_OF_RANGE. - return JSC.Error.ERR_OUT_OF_RANGE.throw(this, "{}", .{bun.fmt.outOfRange(value, options)}); + return this.ERR(.OUT_OF_RANGE, "{}", .{bun.fmt.outOfRange(value, options)}).throw(); } pub const IntegerRange = struct { @@ -730,8 +727,6 @@ pub const JSGlobalObject = opaque { return .{ .globalObject = this }; } - pub usingnamespace @import("ErrorCode").JSGlobalObjectExtensions; - pub fn ERR(global: *JSGlobalObject, comptime code: JSC.Error, comptime fmt: [:0]const u8, args: anytype) @import("ErrorCode").ErrorBuilder(code, fmt, @TypeOf(args)) { return .{ .global = global, .args = args }; } diff --git a/src/bun.js/bindings/JSValue.zig b/src/bun.js/bindings/JSValue.zig index c362367983..89aaed4ad3 100644 --- a/src/bun.js/bindings/JSValue.zig +++ b/src/bun.js/bindings/JSValue.zig @@ -583,18 +583,18 @@ pub const JSValue = enum(i64) { // const double = try this.toNumber(global); const double = this.coerceToDouble(global); if (std.math.isNan(double)) { - return JSC.Error.ERR_SOCKET_BAD_PORT.throw(global, "Invalid port number", .{}); + return JSC.Error.SOCKET_BAD_PORT.throw(global, "Invalid port number", .{}); } const port = this.to(i64); if (0 <= port and port <= 65535) { return @as(u16, @truncate(@max(0, port))); } else { - return JSC.Error.ERR_SOCKET_BAD_PORT.throw(global, "Port number out of range: {d}", .{port}); + return JSC.Error.SOCKET_BAD_PORT.throw(global, "Port number out of range: {d}", .{port}); } } - return JSC.Error.ERR_SOCKET_BAD_PORT.throw(global, "Invalid port number", .{}); + return JSC.Error.SOCKET_BAD_PORT.throw(global, "Invalid port number", .{}); } extern fn JSC__JSValue__isInstanceOf(this: JSValue, global: *JSGlobalObject, constructor: JSValue) bool; diff --git a/src/bun.js/bindings/ZigString.zig b/src/bun.js/bindings/ZigString.zig index 7cdc6ea9ea..de26ea933a 100644 --- a/src/bun.js/bindings/ZigString.zig +++ b/src/bun.js/bindings/ZigString.zig @@ -603,7 +603,7 @@ pub const ZigString = extern struct { pub fn toExternalU16(ptr: [*]const u16, len: usize, global: *JSGlobalObject) JSValue { if (len > String.max_length()) { bun.default_allocator.free(ptr[0..len]); - global.ERR_STRING_TOO_LONG("Cannot create a string longer than 2^32-1 characters", .{}).throw() catch {}; // TODO: propagate? + global.ERR(.STRING_TOO_LONG, "Cannot create a string longer than 2^32-1 characters", .{}).throw() catch {}; // TODO: propagate? return .zero; } return ZigString__toExternalU16(ptr, len, global); @@ -790,7 +790,7 @@ pub const ZigString = extern struct { this.assertGlobal(); if (this.len > String.max_length()) { bun.default_allocator.free(@constCast(this.byteSlice())); - global.ERR_STRING_TOO_LONG("Cannot create a string longer than 2^32-1 characters", .{}).throw() catch {}; // TODO: propagate? + global.ERR(.STRING_TOO_LONG, "Cannot create a string longer than 2^32-1 characters", .{}).throw() catch {}; // TODO: propagate? return .zero; } return ZigString__toExternalValue(this, global); @@ -823,7 +823,7 @@ pub const ZigString = extern struct { ) JSValue { if (this.len > String.max_length()) { callback(ctx, @constCast(@ptrCast(this.byteSlice().ptr)), this.len); - global.ERR_STRING_TOO_LONG("Cannot create a string longer than 2^32-1 characters", .{}).throw() catch {}; // TODO: propagate? + global.ERR(.STRING_TOO_LONG, "Cannot create a string longer than 2^32-1 characters", .{}).throw() catch {}; // TODO: propagate? return .zero; } diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 2c46997e73..78e01f03d9 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -313,8 +313,6 @@ pub fn untrackFunction( return private.Bun__untrackFFIFunction(globalObject, value); } -pub usingnamespace @import("./JSPropertyIterator.zig"); - // DOMCall Fields const Bun = JSC.API.Bun; pub const __DOMCall_ptr = Bun.FFIObject.dom_call; @@ -373,7 +371,7 @@ pub fn onJSCInvalidEnvVar(name: [*]const u8, len: usize) callconv(.C) void { /// broke when I just used it. Not sure. ... but this works! fn @"windows process.dlopen"(str: *bun.String) callconv(.C) ?*anyopaque { if (comptime !bun.Environment.isWindows) { - unreachable; + @compileError(unreachable); } var buf: bun.WPathBuffer = undefined; @@ -390,7 +388,7 @@ fn @"windows process.dlopen"(str: *bun.String) callconv(.C) ?*anyopaque { }; buf[data.len] = 0; const LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008; - return bun.windows.LoadLibraryExW(buf[0..data.len :0].ptr, null, LOAD_WITH_ALTERED_SEARCH_PATH); + return bun.windows.kernel32.LoadLibraryExW(buf[0..data.len :0].ptr, null, LOAD_WITH_ALTERED_SEARCH_PATH); } comptime { diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index 204c9a652b..ad202f6e2e 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -447,7 +447,7 @@ const ShellIOReaderAsyncDeinit = bun.shell.Interpreter.AsyncDeinitReader; const ShellIOWriterAsyncDeinit = bun.shell.Interpreter.AsyncDeinitWriter; const TimeoutObject = JSC.BunTimer.TimeoutObject; const ImmediateObject = JSC.BunTimer.ImmediateObject; -const ProcessWaiterThreadTask = if (Environment.isPosix) bun.spawn.WaiterThread.ProcessQueue.ResultTask else opaque {}; +const ProcessWaiterThreadTask = if (Environment.isPosix) bun.spawn.process.WaiterThread.ProcessQueue.ResultTask else opaque {}; const ProcessMiniEventLoopWaiterThreadTask = if (Environment.isPosix) bun.spawn.WaiterThread.ProcessMiniEventLoopQueue.ResultTask else opaque {}; const ShellAsyncSubprocessDone = bun.shell.Interpreter.Cmd.ShellAsyncSubprocessDone; const RuntimeTranspilerStore = JSC.RuntimeTranspilerStore; diff --git a/src/bun.js/ipc.zig b/src/bun.js/ipc.zig index 4e941ab733..f6cf1c2632 100644 --- a/src/bun.js/ipc.zig +++ b/src/bun.js/ipc.zig @@ -452,7 +452,12 @@ const NamedPipeIPCData = struct { mode: Mode, // we will use writer pipe as Duplex - writer: bun.io.StreamingWriter(NamedPipeIPCData, onWrite, onError, null, onPipeClose) = .{}, + writer: bun.io.StreamingWriter(@This(), .{ + .onWrite = onWrite, + .onError = onError, + .onWritable = null, + .onClose = onPipeClose, + }) = .{}, incoming: bun.ByteList = .{}, // Maybe we should use IPCBuffer here as well disconnected: bool = false, diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index d75af7ccba..b4908c2cfa 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -450,7 +450,7 @@ pub fn Bun__Process__send_(globalObject: *JSGlobalObject, callFrame: *JSC.CallFr const vm = globalObject.bunVM(); const ipc_instance = vm.getIPCInstance() orelse { - const ex = globalObject.ERR_IPC_CHANNEL_CLOSED("Channel closed.", .{}).toJS(); + const ex = globalObject.ERR(.IPC_CHANNEL_CLOSED, "Channel closed.", .{}).toJS(); if (callback.isFunction()) { Bun__Process__queueNextTick1(globalObject, callback, ex); } else { @@ -1205,7 +1205,7 @@ pub const VirtualMachine = struct { // lookups on start for obscure flags which we do not want others to // depend on. if (map.get("BUN_FEATURE_FLAG_FORCE_WAITER_THREAD") != null) { - bun.spawn.WaiterThread.setShouldUseWaiterThread(); + bun.spawn.process.WaiterThread.setShouldUseWaiterThread(); } // Only allowed for testing diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index ed7952b02c..de45ad525b 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -2268,7 +2268,7 @@ pub const ModuleLoader = struct { var virtual_source_to_use: ?logger.Source = null; var blob_to_deinit: ?JSC.WebCore.Blob = null; var lr = options.getLoaderAndVirtualSource(_specifier.slice(), jsc_vm, &virtual_source_to_use, &blob_to_deinit, type_attribute_str) catch { - ret.* = JSC.ErrorableResolvedSource.err(error.JSErrorObject, globalObject.MODULE_NOT_FOUND("Blob not found", .{}).toJS().asVoid()); + ret.* = JSC.ErrorableResolvedSource.err(error.JSErrorObject, globalObject.ERR(.MODULE_NOT_FOUND, "Blob not found", .{}).toJS().asVoid()); return null; }; defer if (blob_to_deinit) |*blob| blob.deinit(); diff --git a/src/bun.js/node/node_crypto_binding.zig b/src/bun.js/node/node_crypto_binding.zig index f95b46c364..c8dff5011f 100644 --- a/src/bun.js/node/node_crypto_binding.zig +++ b/src/bun.js/node/node_crypto_binding.zig @@ -239,7 +239,7 @@ const random = struct { const max: i64 = @intFromFloat(@trunc(max_value.asNumber())); if (max <= min) { - return global.ERR_OUT_OF_RANGE("The value of \"max\" is out of range. It must be greater than the value of \"min\" ({d}). Received {d}", .{ + return global.ERR(.OUT_OF_RANGE, "The value of \"max\" is out of range. It must be greater than the value of \"min\" ({d}). Received {d}", .{ min, max, }).throw(); @@ -247,9 +247,9 @@ const random = struct { if (max - min > max_range) { if (min_specified) { - return global.ERR_OUT_OF_RANGE("The value of \"max - min\" is out of range. It must be <= {d}. Received {d}", .{ max_range, max - min }).throw(); + return global.ERR(.OUT_OF_RANGE, "The value of \"max - min\" is out of range. It must be <= {d}. Received {d}", .{ max_range, max - min }).throw(); } - return global.ERR_OUT_OF_RANGE("The value of \"max\" is out of range. It must be <= {d}. Received {d}", .{ max_range, max - min }).throw(); + return global.ERR(.OUT_OF_RANGE, "The value of \"max\" is out of range. It must be <= {d}. Received {d}", .{ max_range, max - min }).throw(); } const res = std.crypto.random.intRangeLessThan(i64, min, max); @@ -453,17 +453,17 @@ pub fn timingSafeEqual(global: *JSGlobalObject, callFrame: *JSC.CallFrame) JSErr const l_value, const r_value = callFrame.argumentsAsArray(2); const l_buf = l_value.asArrayBuffer(global) orelse { - return global.ERR_INVALID_ARG_TYPE("The \"buf1\" argument must be an instance of ArrayBuffer, Buffer, TypedArray, or DataView.", .{}).throw(); + return global.ERR(.INVALID_ARG_TYPE, "The \"buf1\" argument must be an instance of ArrayBuffer, Buffer, TypedArray, or DataView.", .{}).throw(); }; const l = l_buf.byteSlice(); const r_buf = r_value.asArrayBuffer(global) orelse { - return global.ERR_INVALID_ARG_TYPE("The \"buf2\" argument must be an instance of ArrayBuffer, Buffer, TypedArray, or DataView.", .{}).throw(); + return global.ERR(.INVALID_ARG_TYPE, "The \"buf2\" argument must be an instance of ArrayBuffer, Buffer, TypedArray, or DataView.", .{}).throw(); }; const r = r_buf.byteSlice(); if (l.len != r.len) { - return global.ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH("Input buffers must have the same byte length", .{}).throw(); + return global.ERR(.CRYPTO_TIMING_SAFE_EQUAL_LENGTH, "Input buffers must have the same byte length", .{}).throw(); } return JSC.jsBoolean(BoringSSL.CRYPTO_memcmp(l.ptr, r.ptr, l.len) == 0); @@ -482,7 +482,7 @@ pub fn setFips(_: *JSGlobalObject, _: *JSC.CallFrame) JSError!JSValue { } pub fn setEngine(global: *JSGlobalObject, _: *JSC.CallFrame) JSError!JSValue { - return global.ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED("Custom engines not supported by BoringSSL", .{}).throw(); + return global.ERR(.CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED, "Custom engines not supported by BoringSSL", .{}).throw(); } fn forEachHash(_: *const BoringSSL.EVP_MD, maybe_from: ?[*:0]const u8, _: ?[*:0]const u8, ctx: *anyopaque) callconv(.c) void { @@ -706,12 +706,12 @@ const Scrypt = struct { if (err != 0) { var buf: [256]u8 = undefined; const msg = BoringSSL.ERR_error_string_n(err, &buf, buf.len); - const exception = global.ERR_CRYPTO_OPERATION_FAILED("Scrypt failed: {s}", .{msg}).toJS(); + const exception = global.ERR(.CRYPTO_OPERATION_FAILED, "Scrypt failed: {s}", .{msg}).toJS(); vm.eventLoop().runCallback(callback, global, .undefined, &.{exception}); return; } - const exception = global.ERR_CRYPTO_OPERATION_FAILED("Scrypt failed", .{}).toJS(); + const exception = global.ERR(.CRYPTO_OPERATION_FAILED, "Scrypt failed", .{}).toJS(); vm.eventLoop().runCallback(callback, global, .undefined, &.{exception}); return; } diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index 7aa10b2b2b..59968e8052 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -5,6 +5,7 @@ const std = @import("std"); const bun = @import("bun"); const strings = bun.strings; const windows = bun.windows; +const c = bun.c; const string = bun.string; const JSC = bun.JSC; const PathString = JSC.PathString; @@ -761,8 +762,8 @@ pub fn NewAsyncCpTask(comptime is_shell: bool) type { const dest = args.dest.osPath(&dest_buf); if (Environment.isWindows) { - const attributes = windows.GetFileAttributesW(src); - if (attributes == windows.INVALID_FILE_ATTRIBUTES) { + const attributes = c.GetFileAttributesW(src); + if (attributes == c.INVALID_FILE_ATTRIBUTES) { this.finishConcurrently(.{ .err = .{ .errno = @intFromEnum(C.SystemErrno.ENOENT), .syscall = .copyfile, @@ -770,7 +771,7 @@ pub fn NewAsyncCpTask(comptime is_shell: bool) type { } }); return; } - const file_or_symlink = (attributes & windows.FILE_ATTRIBUTE_DIRECTORY) == 0 or (attributes & windows.FILE_ATTRIBUTE_REPARSE_POINT) != 0; + const file_or_symlink = (attributes & c.FILE_ATTRIBUTE_DIRECTORY) == 0 or (attributes & c.FILE_ATTRIBUTE_REPARSE_POINT) != 0; if (file_or_symlink) { const r = nodefs._copySingleFileSync( src, @@ -1920,10 +1921,10 @@ pub const Arguments = struct { if (str.eqlComptime("dir")) break :link_type .dir; if (str.eqlComptime("file")) break :link_type .file; if (str.eqlComptime("junction")) break :link_type .junction; - return ctx.ERR_INVALID_ARG_VALUE("Symlink type must be one of \"dir\", \"file\", or \"junction\". Received \"{}\"", .{str}).throw(); + return ctx.ERR(.INVALID_ARG_VALUE, "Symlink type must be one of \"dir\", \"file\", or \"junction\". Received \"{}\"", .{str}).throw(); } // not a string. fallthrough to auto detect. - return ctx.ERR_INVALID_ARG_VALUE("Symlink type must be one of \"dir\", \"file\", or \"junction\".", .{}).throw(); + return ctx.ERR(.INVALID_ARG_VALUE, "Symlink type must be one of \"dir\", \"file\", or \"junction\".", .{}).throw(); } break :link_type .unspecified; }; @@ -2625,7 +2626,7 @@ pub const Arguments = struct { const buf_len = buffer.slice().len; if (buf_len == 0) { - return ctx.ERR_INVALID_ARG_VALUE("The argument 'buffer' is empty and cannot be written.", .{}).throw(); + return ctx.ERR(.INVALID_ARG_VALUE, "The argument 'buffer' is empty and cannot be written.", .{}).throw(); } // validateOffsetLengthRead(offset, length, buffer.byteLength); if (@mod(length, 1) != 0) { @@ -2877,7 +2878,7 @@ pub const Arguments = struct { // https://github.com/nodejs/node/blob/6f946c95b9da75c70e868637de8161bc8d048379/lib/internal/fs/utils.js#L916 const allow_string_object = false; const data = try StringOrBuffer.fromJSWithEncodingMaybeAsync(ctx, bun.default_allocator, data_value, encoding, arguments.will_be_async, allow_string_object) orelse { - return ctx.ERR_INVALID_ARG_TYPE("The \"data\" argument must be of type string or an instance of Buffer, TypedArray, or DataView", .{}).throw(); + return ctx.ERR(.INVALID_ARG_TYPE, "The \"data\" argument must be of type string or an instance of Buffer, TypedArray, or DataView", .{}).throw(); }; return .{ @@ -3990,15 +3991,6 @@ pub const NodeFS = struct { mode: Mode, comptime return_path: bool, ) Maybe(Return.Mkdir) { - const callbacks = struct { - pub fn onCreateDir(c: Ctx, dirpath: bun.OSPathSliceZ) void { - if (Ctx != void) { - c.onCreateDir(dirpath); - } - return; - } - }; - const Char = bun.OSPathChar; const len: u16 = @truncate(path.len); @@ -4042,7 +4034,7 @@ pub const NodeFS = struct { } }, .result => { - callbacks.onCreateDir(ctx, path); + if (Ctx != void) ctx.onCreateDir(path); if (!return_path) { return .{ .result = .{ .none = {} } }; } @@ -4084,7 +4076,7 @@ pub const NodeFS = struct { } }, .result => { - callbacks.onCreateDir(ctx, parent); + if (Ctx != void) ctx.onCreateDir(parent); // We found a parent that worked working_mem[i] = std.fs.path.sep; break; @@ -4115,7 +4107,7 @@ pub const NodeFS = struct { }, .result => { - callbacks.onCreateDir(ctx, parent); + if (Ctx != void) ctx.onCreateDir(parent); working_mem[i] = std.fs.path.sep; }, } @@ -4141,7 +4133,7 @@ pub const NodeFS = struct { .result => {}, } - callbacks.onCreateDir(ctx, working_mem[0..len :0]); + if (Ctx != void) ctx.onCreateDir(working_mem[0..len :0]); if (!return_path) { return .{ .result = .{ .none = {} } }; } @@ -6048,8 +6040,8 @@ pub const NodeFS = struct { const dest = dest_buf[0..dest_dir_len :0]; if (Environment.isWindows) { - const attributes = windows.GetFileAttributesW(src); - if (attributes == windows.INVALID_FILE_ATTRIBUTES) { + const attributes = bun.c.GetFileAttributesW(src); + if (attributes == bun.c.INVALID_FILE_ATTRIBUTES) { return .{ .err = .{ .errno = @intFromEnum(C.SystemErrno.ENOENT), .syscall = .copyfile, @@ -6057,7 +6049,7 @@ pub const NodeFS = struct { } }; } - if ((attributes & windows.FILE_ATTRIBUTE_DIRECTORY) == 0) { + if ((attributes & bun.c.FILE_ATTRIBUTE_DIRECTORY) == 0) { const r = this._copySingleFileSync( src, dest, @@ -6509,12 +6501,12 @@ pub const NodeFS = struct { if (Environment.isWindows) { const src_enoent_maybe = ret.initErrWithP(.ENOENT, .copyfile, this.osPathIntoSyncErrorBuf(src)); const dst_enoent_maybe = ret.initErrWithP(.ENOENT, .copyfile, this.osPathIntoSyncErrorBuf(dest)); - const stat_ = reuse_stat orelse switch (windows.GetFileAttributesW(src)) { - windows.INVALID_FILE_ATTRIBUTES => return ret.errnoSysP(0, .copyfile, this.osPathIntoSyncErrorBuf(src)).?, + const stat_ = reuse_stat orelse switch (bun.c.GetFileAttributesW(src)) { + bun.c.INVALID_FILE_ATTRIBUTES => return ret.errnoSysP(0, .copyfile, this.osPathIntoSyncErrorBuf(src)).?, else => |result| result, }; - if (stat_ & windows.FILE_ATTRIBUTE_REPARSE_POINT == 0) { - if (windows.CopyFileW(src, dest, @intFromBool(mode.shouldntOverwrite())) == 0) { + if (stat_ & bun.c.FILE_ATTRIBUTE_REPARSE_POINT == 0) { + if (bun.c.CopyFileW(src, dest, @intFromBool(mode.shouldntOverwrite())) == 0) { var err = windows.GetLastError(); var errpath: bun.OSPathSliceZ = undefined; switch (err) { @@ -6580,7 +6572,7 @@ pub const NodeFS = struct { fn throwInvalidFdError(global: *JSC.JSGlobalObject, value: JSC.JSValue) bun.JSError { if (value.isNumber()) { - return global.ERR_OUT_OF_RANGE("The value of \"fd\" is out of range. It must be an integer. Received {d}", .{bun.fmt.double(value.asNumber())}).throw(); + return global.ERR(.OUT_OF_RANGE, "The value of \"fd\" is out of range. It must be an integer. Received {d}", .{bun.fmt.double(value.asNumber())}).throw(); } return global.throwInvalidArgumentTypeValue("fd", "number", value); } diff --git a/src/bun.js/node/node_zlib_binding.zig b/src/bun.js/node/node_zlib_binding.zig index 6fe612d7d8..1b2fdeb155 100644 --- a/src/bun.js/node/node_zlib_binding.zig +++ b/src/bun.js/node/node_zlib_binding.zig @@ -23,7 +23,7 @@ pub fn crc32(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE const buffer: JSC.Buffer = JSC.Buffer.fromJS(globalThis, data) orelse { const ty_str = data.jsTypeString(globalThis).toSlice(globalThis, bun.default_allocator); defer ty_str.deinit(); - return globalThis.ERR_INVALID_ARG_TYPE("The \"data\" property must be an instance of Buffer, TypedArray, DataView, or ArrayBuffer. Received {s}", .{ty_str.slice()}).throw(); + return globalThis.ERR(.INVALID_ARG_TYPE, "The \"data\" property must be an instance of Buffer, TypedArray, DataView, or ArrayBuffer. Received {s}", .{ty_str.slice()}).throw(); }; break :blk ZigString.Slice.fromUTF8NeverFree(buffer.slice()); }; @@ -42,10 +42,10 @@ pub fn crc32(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE const max = std.math.maxInt(u32); if (@floor(valuef) != valuef) { - return globalThis.ERR_OUT_OF_RANGE("The value of \"{s}\" is out of range. It must be an integer. Received {}", .{ "value", valuef }).throw(); + return globalThis.ERR(.OUT_OF_RANGE, "The value of \"{s}\" is out of range. It must be an integer. Received {}", .{ "value", valuef }).throw(); } if (valuef < min or valuef > max) { - return globalThis.ERR_OUT_OF_RANGE("The value of \"{s}\" is out of range. It must be >= {d} and <= {d}. Received {d}", .{ "value", min, max, valuef }).throw(); + return globalThis.ERR(.OUT_OF_RANGE, "The value of \"{s}\" is out of range. It must be >= {d} and <= {d}. Received {d}", .{ "value", min, max, valuef }).throw(); } break :blk @intFromFloat(valuef); }; @@ -61,7 +61,7 @@ pub fn CompressionStream(comptime T: type) type { const arguments = callframe.argumentsUndef(7).slice(); if (arguments.len != 7) { - return globalThis.ERR_MISSING_ARGS("write(flush, in, in_off, in_len, out, out_off, out_len)", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "write(flush, in, in_off, in_len, out, out_off, out_len)", .{}).throw(); } var in_off: u32 = 0; @@ -149,7 +149,7 @@ pub fn CompressionStream(comptime T: type) type { this_value.ensureStillAlive(); - if (!(this.checkError(global, this_value) catch return global.reportActiveExceptionAsUnhandled(error.JSError))) { + if (!(checkError(this, global, this_value) catch return global.reportActiveExceptionAsUnhandled(error.JSError))) { return; } @@ -160,14 +160,14 @@ pub fn CompressionStream(comptime T: type) type { vm.eventLoop().runCallback(write_callback, global, this_value, &.{}); - if (this.pending_close) _ = this._close(); + if (this.pending_close) _ = closeInternal(this); } pub fn writeSync(this: *T, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const arguments = callframe.argumentsUndef(7).slice(); if (arguments.len != 7) { - return globalThis.ERR_MISSING_ARGS("writeSync(flush, in, in_off, in_len, out, out_off, out_len)", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "writeSync(flush, in, in_off, in_len, out, out_off, out_len)", .{}).throw(); } var in_off: u32 = 0; @@ -211,7 +211,7 @@ pub fn CompressionStream(comptime T: type) type { const this_value = callframe.this(); this.stream.doWork(); - if (try this.checkError(globalThis, this_value)) { + if (try checkError(this, globalThis, this_value)) { this.stream.updateWriteResult(&this.write_result.?[1], &this.write_result.?[0]); this.write_in_progress = false; } @@ -223,7 +223,7 @@ pub fn CompressionStream(comptime T: type) type { pub fn reset(this: *T, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const err = this.stream.reset(); if (err.isError()) { - try this.emitError(globalThis, callframe.this(), err); + try emitError(this, globalThis, callframe.this(), err); } return .undefined; } @@ -231,11 +231,11 @@ pub fn CompressionStream(comptime T: type) type { pub fn close(this: *T, globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { _ = globalThis; _ = callframe; - this._close(); + closeInternal(this); return .undefined; } - fn _close(this: *T) void { + fn closeInternal(this: *T) void { if (this.write_in_progress) { this.pending_close = true; return; @@ -261,7 +261,7 @@ pub fn CompressionStream(comptime T: type) type { fn checkError(this: *T, globalThis: *JSC.JSGlobalObject, this_value: JSC.JSValue) !bool { const err = this.stream.getErrorInfo(); if (!err.isError()) return true; - try this.emitError(globalThis, this_value, err); + try emitError(this, globalThis, this_value, err); return false; } @@ -277,7 +277,7 @@ pub fn CompressionStream(comptime T: type) type { _ = try callback.call(globalThis, this_value, &.{ msg_value, err_value, code_value }); this.write_in_progress = false; - if (this.pending_close) _ = this._close(); + if (this.pending_close) _ = closeInternal(this); } pub fn finalize(this: *T) void { @@ -321,7 +321,15 @@ pub const SNativeZlib = struct { pub const fromJS = js.fromJS; pub const fromJSDirect = js.fromJSDirect; - pub usingnamespace CompressionStream(@This()); + const impl = CompressionStream(@This()); + pub const write = impl.write; + pub const runFromJSThread = impl.runFromJSThread; + pub const writeSync = impl.writeSync; + pub const reset = impl.reset; + pub const close = impl.close; + pub const setOnError = impl.setOnError; + pub const getOnError = impl.getOnError; + pub const finalize = impl.finalize; ref_count: RefCount, mode: bun.zlib.NodeMode, @@ -371,7 +379,7 @@ pub const SNativeZlib = struct { const this_value = callframe.this(); if (arguments.len != 7) { - return globalThis.ERR_MISSING_ARGS("init(windowBits, level, memLevel, strategy, writeResult, writeCallback, dictionary)", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "init(windowBits, level, memLevel, strategy, writeResult, writeCallback, dictionary)", .{}).throw(); } const windowBits = try validators.validateInt32(globalThis, arguments[0], "windowBits", .{}, null, null); @@ -400,7 +408,7 @@ pub const SNativeZlib = struct { const arguments = callframe.argumentsUndef(2).slice(); if (arguments.len != 2) { - return globalThis.ERR_MISSING_ARGS("params(level, strategy)", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "params(level, strategy)", .{}).throw(); } const level = try validators.validateInt32(globalThis, arguments[0], "level", .{}, null, null); @@ -408,7 +416,7 @@ pub const SNativeZlib = struct { const err = this.stream.setParams(level, strategy); if (err.isError()) { - try this.emitError(globalThis, callframe.this(), err); + try impl.emitError(this, globalThis, callframe.this(), err); } return .undefined; } @@ -695,7 +703,15 @@ pub const SNativeBrotli = struct { pub const fromJS = js.fromJS; pub const fromJSDirect = js.fromJSDirect; - pub usingnamespace CompressionStream(@This()); + const impl = CompressionStream(@This()); + pub const write = impl.write; + pub const runFromJSThread = impl.runFromJSThread; + pub const writeSync = impl.writeSync; + pub const reset = impl.reset; + pub const close = impl.close; + pub const setOnError = impl.setOnError; + pub const getOnError = impl.getOnError; + pub const finalize = impl.finalize; ref_count: RefCount, mode: bun.zlib.NodeMode, @@ -751,7 +767,7 @@ pub const SNativeBrotli = struct { const arguments = callframe.argumentsUndef(3).slice(); const this_value = callframe.this(); if (arguments.len != 3) { - return globalThis.ERR_MISSING_ARGS("init(params, writeResult, writeCallback)", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "init(params, writeResult, writeCallback)", .{}).throw(); } // this does not get gc'd because it is stored in the JS object's `this._writeState`. and the JS object is tied to the native handle as `_handle[owner_symbol]`. @@ -764,7 +780,7 @@ pub const SNativeBrotli = struct { var err = this.stream.init(); if (err.isError()) { - try this.emitError(globalThis, this_value, err); + try impl.emitError(this, globalThis, this_value, err); return JSC.jsBoolean(false); } @@ -777,7 +793,7 @@ pub const SNativeBrotli = struct { } err = this.stream.setParams(@intCast(i), d); if (err.isError()) { - // try this.emitError(globalThis, err); //XXX: onerror isn't set yet + // try impl.emitError(this, globalThis, this_value, err); //XXX: onerror isn't set yet return JSC.jsBoolean(false); } } diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 84ab5b8743..0b650760d1 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -726,7 +726,7 @@ pub const Encoding = enum(u8) { } pub fn throwEncodingError(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) bun.JSError { - return globalObject.ERR_INVALID_ARG_VALUE("encoding '{}' is an invalid encoding", .{value.fmtString(globalObject)}).throw(); + return globalObject.ERR(.INVALID_ARG_VALUE, "encoding '{}' is an invalid encoding", .{value.fmtString(globalObject)}).throw(); } pub fn encodeWithSize(encoding: Encoding, globalObject: *JSC.JSGlobalObject, comptime size: usize, input: *const [size]u8) JSC.JSValue { @@ -1004,18 +1004,18 @@ pub const PathLike = union(enum) { if (arg.as(JSC.DOMURL)) |domurl| { var str: bun.String = domurl.fileSystemPath() catch |err| switch (err) { error.NotFileUrl => { - return ctx.ERR_INVALID_URL_SCHEME("URL must be a non-empty \"file:\" path", .{}).throw(); + return ctx.ERR(.INVALID_URL_SCHEME, "URL must be a non-empty \"file:\" path", .{}).throw(); }, error.InvalidPath => { - return ctx.ERR_INVALID_FILE_URL_PATH("URL must be a non-empty \"file:\" path", .{}).throw(); + return ctx.ERR(.INVALID_FILE_URL_PATH, "URL must be a non-empty \"file:\" path", .{}).throw(); }, error.InvalidHost => { - return ctx.ERR_INVALID_FILE_URL_HOST("URL must be a non-empty \"file:\" path", .{}).throw(); + return ctx.ERR(.INVALID_FILE_URL_HOST, "URL must be a non-empty \"file:\" path", .{}).throw(); }, }; defer str.deref(); if (str.isEmpty()) { - return ctx.ERR_INVALID_ARG_VALUE("URL must be a non-empty \"file:\" path", .{}).throw(); + return ctx.ERR(.INVALID_ARG_VALUE, "URL must be a non-empty \"file:\" path", .{}).throw(); } arguments.eat(); @@ -1109,7 +1109,7 @@ pub const Valid = struct { pub fn pathNullBytes(slice: []const u8, global: *JSC.JSGlobalObject) bun.JSError!void { if (bun.strings.indexOfChar(slice, 0) != null) { - return global.ERR_INVALID_ARG_VALUE("The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received {}", .{bun.fmt.quote(slice)}).throw(); + return global.ERR(.INVALID_ARG_VALUE, "The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received {}", .{bun.fmt.quote(slice)}).throw(); } } }; @@ -1359,7 +1359,7 @@ pub fn modeFromJS(ctx: *JSC.JSGlobalObject, value: JSC.JSValue) bun.JSError!?Mod break :brk std.fmt.parseInt(Mode, slice, 8) catch { var formatter = bun.JSC.ConsoleObject.Formatter{ .globalThis = ctx }; defer formatter.deinit(); - return ctx.throwValue(ctx.ERR_INVALID_ARG_VALUE("The argument 'mode' must be a 32-bit unsigned integer or an octal string. Received {}", .{value.toFmt(&formatter)}).toJS()); + return ctx.throwValue(ctx.ERR(.INVALID_ARG_VALUE, "The argument 'mode' must be a 32-bit unsigned integer or an octal string. Received {}", .{value.toFmt(&formatter)}).toJS()); }; }; @@ -1525,7 +1525,7 @@ pub const FileSystemFlags = enum(c_int) { pub fn fromJS(ctx: *JSC.JSGlobalObject, val: JSC.JSValue) bun.JSError!?FileSystemFlags { if (val.isNumber()) { if (!val.isInt32()) { - return ctx.throwValue(ctx.ERR_OUT_OF_RANGE("The value of \"flags\" is out of range. It must be an integer. Received {d}", .{val.asNumber()}).toJS()); + return ctx.throwValue(ctx.ERR(.OUT_OF_RANGE, "The value of \"flags\" is out of range. It must be an integer. Received {d}", .{val.asNumber()}).toJS()); } const number = val.coerce(i32, ctx); return @as(FileSystemFlags, @enumFromInt(@max(number, 0))); @@ -1582,19 +1582,19 @@ pub const FileSystemFlags = enum(c_int) { .copy_file => 0, // constexpr int kDefaultCopyMode = 0; }); } - return global.ERR_INVALID_ARG_TYPE("mode must be int32 or null/undefined", .{}).throw(); + return global.ERR(.INVALID_ARG_TYPE, "mode must be int32 or null/undefined", .{}).throw(); } const min, const max = .{ 0, 7 }; if (value.isInt32()) { const int: i32 = value.asInt32(); if (int < min or int > max) { - return global.ERR_OUT_OF_RANGE(comptime std.fmt.comptimePrint("mode is out of range: >= {d} and <= {d}", .{ min, max }), .{}).throw(); + return global.ERR(.OUT_OF_RANGE, comptime std.fmt.comptimePrint("mode is out of range: >= {d} and <= {d}", .{ min, max }), .{}).throw(); } return @enumFromInt(int); } else { const float = value.asNumber(); if (std.math.isNan(float) or std.math.isInf(float) or float < min or float > max) { - return global.ERR_OUT_OF_RANGE(comptime std.fmt.comptimePrint("mode is out of range: >= {d} and <= {d}", .{ min, max }), .{}).throw(); + return global.ERR(.OUT_OF_RANGE, comptime std.fmt.comptimePrint("mode is out of range: >= {d} and <= {d}", .{ min, max }), .{}).throw(); } return @enumFromInt(@as(i32, @intFromFloat(float))); } @@ -1928,7 +1928,7 @@ pub const Process = struct { buf2[len2] = 0; break :str buf2[0..len2 :0].ptr; } else null; - _ = bun.windows.SetEnvironmentVariableW(buf1[0..len1 :0].ptr, str2); + _ = bun.c.SetEnvironmentVariableW(buf1[0..len1 :0].ptr, str2); } comptime { diff --git a/src/bun.js/node/util/parse_args.zig b/src/bun.js/node/util/parse_args.zig index 722a4baf6b..816ad73ad2 100644 --- a/src/bun.js/node/util/parse_args.zig +++ b/src/bun.js/node/util/parse_args.zig @@ -184,7 +184,7 @@ fn checkOptionLikeValue(globalThis: *JSGlobalObject, token: OptionToken) bun.JSE var err: JSValue = undefined; if (token.raw.asBunString(globalThis).hasPrefixComptime("--")) { err = JSC.toTypeError( - .ERR_PARSE_ARGS_INVALID_OPTION_VALUE, + .PARSE_ARGS_INVALID_OPTION_VALUE, "Option '{}' argument is ambiguous.\nDid you forget to specify the option argument for '{}'?\nTo specify an option argument starting with a dash use '{}=-XYZ'.", .{ raw_name, raw_name, raw_name }, globalThis, @@ -192,7 +192,7 @@ fn checkOptionLikeValue(globalThis: *JSGlobalObject, token: OptionToken) bun.JSE } else { const token_name = token.name.asBunString(globalThis); err = JSC.toTypeError( - .ERR_PARSE_ARGS_INVALID_OPTION_VALUE, + .PARSE_ARGS_INVALID_OPTION_VALUE, "Option '{}' argument is ambiguous.\nDid you forget to specify the option argument for '{}'?\nTo specify an option argument starting with a dash use '--{}=-XYZ' or '{}-XYZ'.", .{ raw_name, raw_name, token_name, raw_name }, globalThis, @@ -209,7 +209,7 @@ fn checkOptionUsage(globalThis: *JSGlobalObject, options: []const OptionDefiniti switch (option.type) { .string => if (token.value == .jsvalue and !token.value.jsvalue.isString()) { const err = JSC.toTypeError( - .ERR_PARSE_ARGS_INVALID_OPTION_VALUE, + .PARSE_ARGS_INVALID_OPTION_VALUE, "Option '{s}{s}{s}--{s} ' argument missing", .{ if (!option.short_name.isEmpty()) "-" else "", @@ -223,7 +223,7 @@ fn checkOptionUsage(globalThis: *JSGlobalObject, options: []const OptionDefiniti }, .boolean => if (token.value != .jsvalue or !token.value.jsvalue.isUndefined()) { const err = JSC.toTypeError( - .ERR_PARSE_ARGS_INVALID_OPTION_VALUE, + .PARSE_ARGS_INVALID_OPTION_VALUE, "Option '{s}{s}{s}--{s}' does not take an argument", .{ if (!option.short_name.isEmpty()) "-" else "", @@ -240,12 +240,12 @@ fn checkOptionUsage(globalThis: *JSGlobalObject, options: []const OptionDefiniti const raw_name = OptionToken.RawNameFormatter{ .token = token, .globalThis = globalThis }; const err = if (allow_positionals) (JSC.toTypeError( - .ERR_PARSE_ARGS_UNKNOWN_OPTION, + .PARSE_ARGS_UNKNOWN_OPTION, "Unknown option '{}'. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- \"{}\"", .{ raw_name, raw_name }, globalThis, )) else (JSC.toTypeError( - .ERR_PARSE_ARGS_UNKNOWN_OPTION, + .PARSE_ARGS_UNKNOWN_OPTION, "Unknown option '{}'", .{raw_name}, globalThis, @@ -316,7 +316,7 @@ fn parseOptionDefinitions(globalThis: *JSGlobalObject, options_obj: JSValue, opt try validators.validateString(globalThis, short_option, "options.{s}.short", .{option.long_name}); var short_option_str = try short_option.toBunString(globalThis); if (short_option_str.length() != 1) { - const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, "options.{s}.short must be a single character", .{option.long_name}, globalThis); + const err = JSC.toTypeError(.INVALID_ARG_VALUE, "options.{s}.short must be a single character", .{option.long_name}, globalThis); return globalThis.throwValue(err); } option.short_name = short_option_str; @@ -579,7 +579,7 @@ const ParseArgsState = struct { .positional => |token| { if (!this.allow_positionals) { const err = JSC.toTypeError( - .ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL, + .PARSE_ARGS_UNEXPECTED_POSITIONAL, "Unexpected argument '{s}'. This command does not take positional arguments", .{token.value.asBunString(globalThis)}, globalThis, diff --git a/src/bun.js/node/util/validators.zig b/src/bun.js/node/util/validators.zig index 4da3a76b76..4b06201246 100644 --- a/src/bun.js/node/util/validators.zig +++ b/src/bun.js/node/util/validators.zig @@ -21,7 +21,7 @@ pub fn throwErrInvalidArgValue( args: anytype, ) bun.JSError { @branchHint(.cold); - return globalThis.ERR_INVALID_ARG_VALUE(fmt, args).throw(); + return globalThis.ERR(.INVALID_ARG_VALUE, fmt, args).throw(); } pub fn throwErrInvalidArgTypeWithMessage( @@ -30,7 +30,7 @@ pub fn throwErrInvalidArgTypeWithMessage( args: anytype, ) bun.JSError { @branchHint(.cold); - return globalThis.ERR_INVALID_ARG_TYPE(fmt, args).throw(); + return globalThis.ERR(.INVALID_ARG_TYPE, fmt, args).throw(); } pub fn throwErrInvalidArgType( @@ -51,7 +51,7 @@ pub fn throwRangeError( args: anytype, ) bun.JSError { @branchHint(.cold); - return globalThis.ERR_OUT_OF_RANGE(fmt, args).throw(); + return globalThis.ERR(.OUT_OF_RANGE, fmt, args).throw(); } pub fn validateInteger(globalThis: *JSGlobalObject, value: JSValue, comptime name: string, min_value: ?i64, max_value: ?i64) bun.JSError!i64 { diff --git a/src/bun.js/webcore.zig b/src/bun.js/webcore.zig index e0e921749c..cee06364c7 100644 --- a/src/bun.js/webcore.zig +++ b/src/bun.js/webcore.zig @@ -2,8 +2,8 @@ pub usingnamespace @import("./webcore/response.zig"); pub usingnamespace @import("./webcore/encoding.zig"); pub usingnamespace @import("./webcore/streams.zig"); pub usingnamespace @import("./webcore/blob.zig"); -pub usingnamespace @import("./webcore/S3Stat.zig"); -pub usingnamespace @import("./webcore/S3Client.zig"); +pub const S3Stat = @import("./webcore/S3Stat.zig").S3Stat; +pub const S3Client = @import("./webcore/S3Client.zig").S3Client; pub usingnamespace @import("./webcore/request.zig"); pub usingnamespace @import("./webcore/body.zig"); pub const CookieMap = @import("./webcore/CookieMap.zig").CookieMap; @@ -16,6 +16,7 @@ pub const AbortSignal = @import("./bindings/bindings.zig").AbortSignal; pub const JSValue = @import("./bindings/bindings.zig").JSValue; const Environment = bun.Environment; const UUID7 = @import("./uuid.zig").UUID7; +const c = bun.c; pub const Lifetime = enum { clone, @@ -268,11 +269,11 @@ pub const Prompt = struct { // unset `ENABLE_VIRTUAL_TERMINAL_INPUT` on windows. This prevents backspace from // deleting the entire line const original_mode: if (Environment.isWindows) ?bun.windows.DWORD else void = if (comptime Environment.isWindows) - bun.win32.updateStdioModeFlags(.std_in, .{ .unset = bun.windows.ENABLE_VIRTUAL_TERMINAL_INPUT }) catch null; + bun.windows.updateStdioModeFlags(.std_in, .{ .unset = c.ENABLE_VIRTUAL_TERMINAL_INPUT }) catch null; defer if (comptime Environment.isWindows) { if (original_mode) |mode| { - _ = bun.windows.SetConsoleMode(bun.FD.stdin().native(), mode); + _ = bun.c.SetConsoleMode(bun.FD.stdin().native(), mode); } }; @@ -371,13 +372,13 @@ pub const Crypto = struct { const BoringSSL = bun.BoringSSL.c; fn throwInvalidParameter(globalThis: *JSC.JSGlobalObject) bun.JSError { - return globalThis.ERR_CRYPTO_SCRYPT_INVALID_PARAMETER("Invalid scrypt parameters", .{}).throw(); + return globalThis.ERR(.CRYPTO_SCRYPT_INVALID_PARAMETER, "Invalid scrypt parameters", .{}).throw(); } fn throwInvalidParams(globalThis: *JSC.JSGlobalObject, comptime error_type: @Type(.enum_literal), comptime message: [:0]const u8, fmt: anytype) bun.JSError { if (error_type != .RangeError) @compileError("Error type not added!"); BoringSSL.ERR_clear_error(); - return globalThis.ERR_CRYPTO_INVALID_SCRYPT_PARAMS(message, fmt).throw(); + return globalThis.ERR(.CRYPTO_INVALID_SCRYPT_PARAMS, message, fmt).throw(); } pub fn timingSafeEqual(_: *@This(), global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { @@ -395,7 +396,7 @@ pub const Crypto = struct { const len = a.len; if (b.len != len) { - return globalThis.ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH("Input buffers must have the same byte length", .{}).throw(); + return globalThis.ERR(.CRYPTO_TIMING_SAFE_EQUAL_LENGTH, "Input buffers must have the same byte length", .{}).throw(); } return JSC.jsBoolean(bun.BoringSSL.c.CRYPTO_memcmp(a.ptr, b.ptr, len) == 0); @@ -478,7 +479,7 @@ pub const Crypto = struct { if (arguments[0].isString()) { encoding_value = arguments[0]; break :brk try JSC.Node.Encoding.fromJS(encoding_value, globalThis) orelse { - return globalThis.ERR_UNKNOWN_ENCODING("Encoding must be one of base64, base64url, hex, or buffer", .{}).throw(); + return globalThis.ERR(.UNKNOWN_ENCODING, "Encoding must be one of base64, base64url, hex, or buffer", .{}).throw(); }; } } @@ -535,7 +536,7 @@ pub const Crypto = struct { } pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*Crypto { - return JSC.Error.ERR_ILLEGAL_CONSTRUCTOR.throw(globalThis, "Crypto is not constructable", .{}); + return JSC.Error.ILLEGAL_CONSTRUCTOR.throw(globalThis, "Crypto is not constructable", .{}); } pub export fn CryptoObject__create(globalThis: *JSC.JSGlobalObject) JSC.JSValue { diff --git a/src/bun.js/webcore/S3Client.zig b/src/bun.js/webcore/S3Client.zig index a5f1eee166..6b9935ca9b 100644 --- a/src/bun.js/webcore/S3Client.zig +++ b/src/bun.js/webcore/S3Client.zig @@ -139,7 +139,7 @@ pub const S3Client = struct { defer args.deinit(); const path: JSC.Node.PathLike = try JSC.Node.PathLike.fromJS(globalThis, &args) orelse { if (args.len() == 0) { - return globalThis.ERR_MISSING_ARGS("Expected a path ", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a path ", .{}).throw(); } return globalThis.throwInvalidArguments("Expected a path", .{}); }; @@ -156,7 +156,7 @@ pub const S3Client = struct { defer args.deinit(); const path: JSC.Node.PathLike = try JSC.Node.PathLike.fromJS(globalThis, &args) orelse { if (args.len() == 0) { - return globalThis.ERR_MISSING_ARGS("Expected a path to presign", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a path to presign", .{}).throw(); } return globalThis.throwInvalidArguments("Expected a path to presign", .{}); }; @@ -174,7 +174,7 @@ pub const S3Client = struct { defer args.deinit(); const path: JSC.Node.PathLike = try JSC.Node.PathLike.fromJS(globalThis, &args) orelse { if (args.len() == 0) { - return globalThis.ERR_MISSING_ARGS("Expected a path to check if it exists", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a path to check if it exists", .{}).throw(); } return globalThis.throwInvalidArguments("Expected a path to check if it exists", .{}); }; @@ -191,7 +191,7 @@ pub const S3Client = struct { defer args.deinit(); const path: JSC.Node.PathLike = try JSC.Node.PathLike.fromJS(globalThis, &args) orelse { if (args.len() == 0) { - return globalThis.ERR_MISSING_ARGS("Expected a path to check the size of", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a path to check the size of", .{}).throw(); } return globalThis.throwInvalidArguments("Expected a path to check the size of", .{}); }; @@ -208,7 +208,7 @@ pub const S3Client = struct { defer args.deinit(); const path: JSC.Node.PathLike = try JSC.Node.PathLike.fromJS(globalThis, &args) orelse { if (args.len() == 0) { - return globalThis.ERR_MISSING_ARGS("Expected a path to check the stat of", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a path to check the stat of", .{}).throw(); } return globalThis.throwInvalidArguments("Expected a path to check the stat of", .{}); }; @@ -224,11 +224,11 @@ pub const S3Client = struct { var args = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments); defer args.deinit(); const path: JSC.Node.PathLike = try JSC.Node.PathLike.fromJS(globalThis, &args) orelse { - return globalThis.ERR_MISSING_ARGS("Expected a path to write to", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a path to write to", .{}).throw(); }; errdefer path.deinit(); const data = args.nextEat() orelse { - return globalThis.ERR_MISSING_ARGS("Expected a Blob-y thing to write", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a Blob-y thing to write", .{}).throw(); }; const options = args.nextEat(); @@ -258,7 +258,7 @@ pub const S3Client = struct { var args = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments); defer args.deinit(); const path: JSC.Node.PathLike = try JSC.Node.PathLike.fromJS(globalThis, &args) orelse { - return globalThis.ERR_MISSING_ARGS("Expected a path to unlink", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a path to unlink", .{}).throw(); }; errdefer path.deinit(); const options = args.nextEat(); diff --git a/src/bun.js/webcore/S3File.zig b/src/bun.js/webcore/S3File.zig index 6a880eed7a..99ac3145f7 100644 --- a/src/bun.js/webcore/S3File.zig +++ b/src/bun.js/webcore/S3File.zig @@ -154,7 +154,7 @@ pub fn write(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE } const data = args.nextEat() orelse { - return globalThis.ERR_MISSING_ARGS("Expected a Blob-y thing to upload", .{}).throw(); + return globalThis.ERR(.MISSING_ARGS, "Expected a Blob-y thing to upload", .{}).throw(); }; switch (path_or_blob) { @@ -475,7 +475,7 @@ pub const S3BlobStatTask = struct { pub fn getPresignUrlFrom(this: *Blob, globalThis: *JSC.JSGlobalObject, extra_options: ?JSValue) bun.JSError!JSValue { if (!this.isS3()) { - return globalThis.ERR_INVALID_THIS("presign is only possible for s3:// files", .{}).throw(); + return globalThis.ERR(.INVALID_THIS, "presign is only possible for s3:// files", .{}).throw(); } var method: bun.http.Method = .GET; diff --git a/src/bun.js/webcore/TextDecoder.zig b/src/bun.js/webcore/TextDecoder.zig index abb5d627b8..2d95f009f5 100644 --- a/src/bun.js/webcore/TextDecoder.zig +++ b/src/bun.js/webcore/TextDecoder.zig @@ -231,7 +231,7 @@ fn decodeSlice(this: *TextDecoder, globalThis: *JSC.JSGlobalObject, buffer_slice if (deinit) bun.default_allocator.free(input); if (comptime fail_if_invalid) { if (err == error.InvalidByteSequence) { - return globalThis.ERR_ENCODING_INVALID_ENCODED_DATA("Invalid byte sequence", .{}).throw(); + return globalThis.ERR(.ENCODING_INVALID_ENCODED_DATA, "Invalid byte sequence", .{}).throw(); } } @@ -270,7 +270,7 @@ fn decodeSlice(this: *TextDecoder, globalThis: *JSC.JSGlobalObject, buffer_slice if (saw_error and this.fatal) { decoded.deinit(bun.default_allocator); - return globalThis.ERR_ENCODING_INVALID_ENCODED_DATA("The encoded data was not valid {s} data", .{@tagName(utf16_encoding)}).throw(); + return globalThis.ERR(.ENCODING_INVALID_ENCODED_DATA, "The encoded data was not valid {s} data", .{@tagName(utf16_encoding)}).throw(); } var output = bun.String.fromUTF16(decoded.items); diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index dac86c7c90..f2f06b6db2 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -2251,7 +2251,7 @@ pub const Blob = struct { return try Blob.Store.init(list.items, allocator); } - pub fn FileOpenerMixin(comptime This: type) type { + pub fn FileOpener(comptime This: type) type { return struct { context: *This, @@ -2264,7 +2264,7 @@ pub const Blob = struct { else bun.O.RDONLY | __opener_flags; - pub inline fn getFdByOpening(this: *This, comptime Callback: OpenCallback) void { + fn getFdByOpening(this: *This, comptime Callback: OpenCallback) void { var buf: bun.PathBuffer = undefined; var path_string = if (@hasField(This, "file_store")) this.file_store.pathlike.path @@ -2344,7 +2344,7 @@ pub const Blob = struct { Callback(this, this.opened_fd); } - pub const OpenCallback = *const fn (*This, bun.FileDescriptor) void; + const OpenCallback = *const fn (*This, bun.FileDescriptor) void; pub fn getFd(this: *This, comptime Callback: OpenCallback) void { if (this.opened_fd != invalid_fd) { @@ -2368,15 +2368,13 @@ pub const Blob = struct { } } - this.getFdByOpening(Callback); + getFdByOpening(this, Callback); } }; } - pub fn FileCloserMixin(comptime This: type) type { + pub fn FileCloser(comptime This: type) type { return struct { - const Closer = @This(); - fn scheduleClose(request: *io.Request) io.Action { var this: *This = @alignCast(@fieldParentPtr("io_request", request)); return io.Action{ diff --git a/src/bun.js/webcore/blob/ReadFile.zig b/src/bun.js/webcore/blob/ReadFile.zig index 5eb0c0efab..ef8699b0c3 100644 --- a/src/bun.js/webcore/blob/ReadFile.zig +++ b/src/bun.js/webcore/blob/ReadFile.zig @@ -7,8 +7,8 @@ const invalid_fd = bun.invalid_fd; const SystemError = JSC.SystemError; const SizeType = Blob.SizeType; const io = bun.io; -const FileOpenerMixin = Store.FileOpenerMixin; -const FileCloserMixin = Store.FileCloserMixin; +const FileOpener = Store.FileOpener; +const FileCloser = Store.FileCloser; const Environment = bun.Environment; const bloblog = bun.Output.scoped(.WriteFile, true); const JSPromise = JSC.JSPromise; @@ -85,8 +85,8 @@ pub const ReadFile = struct { close_after_io: bool = false, state: std.atomic.Value(ClosingState) = std.atomic.Value(ClosingState).init(.running), - pub usingnamespace FileOpenerMixin(ReadFile); - pub usingnamespace FileCloserMixin(ReadFile); + pub const getFd = FileOpener(@This()).getFd; + pub const doClose = FileCloser(@This()).doClose; pub fn update(this: *ReadFile) void { if (Environment.isWindows) return; //why @@ -541,8 +541,8 @@ pub const ReadFile = struct { }; pub const ReadFileUV = struct { - pub usingnamespace FileOpenerMixin(ReadFileUV); - pub usingnamespace FileCloserMixin(ReadFileUV); + pub const getFd = FileOpener(@This()).getFd; + pub const doClose = FileCloser(@This()).doClose; loop: *libuv.Loop, file_store: FileStore, diff --git a/src/bun.js/webcore/blob/WriteFile.zig b/src/bun.js/webcore/blob/WriteFile.zig index 9bdbc8ebb8..ea6667245e 100644 --- a/src/bun.js/webcore/blob/WriteFile.zig +++ b/src/bun.js/webcore/blob/WriteFile.zig @@ -7,8 +7,8 @@ const invalid_fd = bun.invalid_fd; const SystemError = JSC.SystemError; const SizeType = Blob.SizeType; const io = bun.io; -const FileOpenerMixin = Blob.Store.FileOpenerMixin; -const FileCloserMixin = Blob.Store.FileCloserMixin; +const FileOpener = Blob.Store.FileOpener; +const FileCloser = Blob.Store.FileCloser; const Environment = bun.Environment; const bloblog = bun.Output.scoped(.WriteFile, true); const JSPromise = JSC.JSPromise; @@ -44,8 +44,8 @@ pub const WriteFile = struct { pub const io_tag = io.Poll.Tag.WriteFile; - pub usingnamespace FileOpenerMixin(WriteFile); - pub usingnamespace FileCloserMixin(WriteFile); + pub const getFd = FileOpener(@This()).getFd; + pub const doClose = FileCloser(WriteFile).doClose; pub const open_flags = bun.O.WRONLY | bun.O.CREAT | bun.O.TRUNC | bun.O.NONBLOCK; diff --git a/src/bun.js/webcore/body.zig b/src/bun.js/webcore/body.zig index a3a63a0889..cb09d8c641 100644 --- a/src/bun.js/webcore/body.zig +++ b/src/bun.js/webcore/body.zig @@ -1226,7 +1226,7 @@ pub fn BodyMixin(comptime Type: type) type { } fn handleBodyAlreadyUsed(globalObject: *JSC.JSGlobalObject) JSValue { - return globalObject.ERR_BODY_ALREADY_USED("Body already used", .{}).reject(); + return globalObject.ERR(.BODY_ALREADY_USED, "Body already used", .{}).reject(); } pub fn getArrayBuffer( @@ -1303,7 +1303,7 @@ pub fn BodyMixin(comptime Type: type) type { var encoder = this.getFormDataEncoding() orelse { // TODO: catch specific errors from getFormDataEncoding - return globalObject.ERR_FORMDATA_PARSE_ERROR("Can't decode form data from body because of incorrect MIME type/boundary", .{}).reject(); + return globalObject.ERR(.FORMDATA_PARSE_ERROR, "Can't decode form data from body because of incorrect MIME type/boundary", .{}).reject(); }; if (value.* == .Locked) { @@ -1319,7 +1319,8 @@ pub fn BodyMixin(comptime Type: type) type { blob.slice(), encoder.encoding, ) catch |err| { - return globalObject.ERR_FORMDATA_PARSE_ERROR( + return globalObject.ERR( + .FORMDATA_PARSE_ERROR, "FormData parse error {s}", .{ @errorName(err), diff --git a/src/bun.js/webcore/fetch.zig b/src/bun.js/webcore/fetch.zig index cc2a2d598f..c0143dd700 100644 --- a/src/bun.js/webcore/fetch.zig +++ b/src/bun.js/webcore/fetch.zig @@ -188,7 +188,7 @@ pub const FetchTasklet = struct { pub fn fromJS(globalThis: *JSGlobalObject, value: JSValue) bun.JSError!HTTPRequestBody { var body_value = try Body.Value.fromJS(globalThis, value); if (body_value == .Used or (body_value == .Locked and (body_value.Locked.action != .none or body_value.Locked.isDisturbed2(globalThis)))) { - return globalThis.ERR_BODY_ALREADY_USED("body already used", .{}).throw(); + return globalThis.ERR(.BODY_ALREADY_USED, "body already used", .{}).throw(); } if (body_value == .Locked) { if (body_value.Locked.readable.has()) { @@ -1478,11 +1478,11 @@ pub fn Bun__fetchPreconnect_( } if (url_str.tag == .Dead) { - return globalObject.ERR_INVALID_ARG_TYPE("Invalid URL", .{}).throw(); + return globalObject.ERR(.INVALID_ARG_TYPE, "Invalid URL", .{}).throw(); } if (url_str.isEmpty()) { - return globalObject.ERR_INVALID_ARG_TYPE(fetch_error_blank_url, .{}).throw(); + return globalObject.ERR(.INVALID_ARG_TYPE, fetch_error_blank_url, .{}).throw(); } const url = ZigURL.parse(url_str.toOwnedSlice(bun.default_allocator) catch bun.outOfMemory()); @@ -1493,7 +1493,7 @@ pub fn Bun__fetchPreconnect_( if (url.hostname.len == 0) { bun.default_allocator.free(url.href); - return globalObject.ERR_INVALID_ARG_TYPE(fetch_error_blank_url, .{}).throw(); + return globalObject.ERR(.INVALID_ARG_TYPE, fetch_error_blank_url, .{}).throw(); } if (!url.hasValidPort()) { @@ -1545,7 +1545,7 @@ pub fn Bun__fetch_( } if (arguments.len == 0) { - const err = JSC.toTypeError(.ERR_MISSING_ARGS, fetch_error_no_args, .{}, ctx); + const err = JSC.toTypeError(.MISSING_ARGS, fetch_error_no_args, .{}, ctx); return JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err); } @@ -1689,7 +1689,7 @@ pub fn Bun__fetch_( if (url_str.isEmpty()) { is_error = true; - const err = JSC.toTypeError(.ERR_INVALID_URL, fetch_error_blank_url, .{}, ctx); + const err = JSC.toTypeError(.INVALID_URL, fetch_error_blank_url, .{}, ctx); return JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err); } @@ -1708,7 +1708,7 @@ pub fn Bun__fetch_( } url = ZigURL.fromString(allocator, url_str) catch { - const err = JSC.toTypeError(.ERR_INVALID_URL, "fetch() URL is invalid", .{}, ctx); + const err = JSC.toTypeError(.INVALID_URL, "fetch() URL is invalid", .{}, ctx); is_error = true; return JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM( globalThis, @@ -2007,7 +2007,7 @@ pub fn Bun__fetch_( if (proxy_arg.isString() and proxy_arg.getLength(ctx) > 0) { var href = try JSC.URL.hrefFromJS(proxy_arg, globalThis); if (href.tag == .Dead) { - const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, "fetch() proxy URL is invalid", .{}, ctx); + const err = JSC.toTypeError(.INVALID_ARG_VALUE, "fetch() proxy URL is invalid", .{}, ctx); is_error = true; return JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err); } @@ -2106,7 +2106,7 @@ pub fn Bun__fetch_( if (request) |req| { if (req.body.value == .Used or (req.body.value == .Locked and (req.body.value.Locked.action != .none or req.body.value.Locked.isDisturbed(Request, globalThis, first_arg)))) { - return globalThis.ERR_BODY_ALREADY_USED("Request body already used", .{}).throw(); + return globalThis.ERR(.BODY_ALREADY_USED, "Request body already used", .{}).throw(); } if (req.body.value == .Locked) { @@ -2247,7 +2247,7 @@ pub fn Bun__fetch_( if (proxy != null and unix_socket_path.length() > 0) { is_error = true; - const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, fetch_error_proxy_unix, .{}, ctx); + const err = JSC.toTypeError(.INVALID_ARG_VALUE, fetch_error_proxy_unix, .{}, ctx); return JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err); } @@ -2288,7 +2288,7 @@ pub fn Bun__fetch_( break :blob blob; } else { // Consistent with what Node.js does - it rejects, not a 404. - const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, "Failed to resolve blob:{s}", .{ + const err = JSC.toTypeError(.INVALID_ARG_VALUE, "Failed to resolve blob:{s}", .{ url_path_decoded, }, ctx); is_error = true; @@ -2363,14 +2363,14 @@ pub fn Bun__fetch_( if (url.protocol.len > 0) { if (!(url.isHTTP() or url.isHTTPS() or url.isS3())) { - const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, "protocol must be http:, https: or s3:", .{}, ctx); + const err = JSC.toTypeError(.INVALID_ARG_VALUE, "protocol must be http:, https: or s3:", .{}, ctx); is_error = true; return JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err); } } if (!method.hasRequestBody() and body.hasBody()) { - const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, fetch_error_unexpected_body, .{}, ctx); + const err = JSC.toTypeError(.INVALID_ARG_VALUE, fetch_error_unexpected_body, .{}, ctx); is_error = true; return JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err); } diff --git a/src/bun.js/webcore/request.zig b/src/bun.js/webcore/request.zig index 1b7af9818f..a609761f4d 100644 --- a/src/bun.js/webcore/request.zig +++ b/src/bun.js/webcore/request.zig @@ -767,7 +767,7 @@ pub const Request = struct { if (!globalThis.hasException()) { // globalThis.throw can cause GC, which could cause the above string to be freed. // so we must increment the reference count before calling it. - return globalThis.ERR_INVALID_URL("Failed to construct 'Request': Invalid URL \"{}\"", .{req.url}).throw(); + return globalThis.ERR(.INVALID_URL, "Failed to construct 'Request': Invalid URL \"{}\"", .{req.url}).throw(); } return error.JSError; } diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 30a4806173..c762ec0378 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -1739,7 +1739,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime abi_name: []const u8) type { fn getThis(global: *JSGlobalObject, callframe: *const JSC.CallFrame) bun.JSError!*ThisSink { return switch (fromJSExtern(callframe.this())) { .detached => global.throw("This " ++ abi_name ++ " has already been closed. A \"direct\" ReadableStream terminates its underlying socket once `async pull()` returns.", .{}), - .cast_failed => global.ERR_INVALID_THIS("Expected " ++ abi_name, .{}).throw(), + .cast_failed => global.ERR(.INVALID_THIS, "Expected " ++ abi_name, .{}).throw(), else => |ptr| @ptrFromInt(@intFromEnum(ptr)), }; } @@ -1762,7 +1762,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime abi_name: []const u8) type { const args = args_list.ptr[0..args_list.len]; if (args.len == 0) { - return globalThis.throwValue(JSC.toTypeError(.ERR_MISSING_ARGS, "write() expects a string, ArrayBufferView, or ArrayBuffer", .{}, globalThis)); + return globalThis.throwValue(JSC.toTypeError(.MISSING_ARGS, "write() expects a string, ArrayBufferView, or ArrayBuffer", .{}, globalThis)); } const arg = args[0]; @@ -1770,7 +1770,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime abi_name: []const u8) type { defer arg.ensureStillAlive(); if (arg.isEmptyOrUndefinedOrNull()) { - return globalThis.throwValue(JSC.toTypeError(.ERR_STREAM_NULL_VALUES, "write() expects a string, ArrayBufferView, or ArrayBuffer", .{}, globalThis)); + return globalThis.throwValue(JSC.toTypeError(.STREAM_NULL_VALUES, "write() expects a string, ArrayBufferView, or ArrayBuffer", .{}, globalThis)); } if (arg.asArrayBuffer(globalThis)) |buffer| { @@ -1783,7 +1783,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime abi_name: []const u8) type { } if (!arg.isString()) { - return globalThis.throwValue(JSC.toTypeError(.ERR_INVALID_ARG_TYPE, "write() expects a string, ArrayBufferView, or ArrayBuffer", .{}, globalThis)); + return globalThis.throwValue(JSC.toTypeError(.INVALID_ARG_TYPE, "write() expects a string, ArrayBufferView, or ArrayBuffer", .{}, globalThis)); } const str = arg.toString(globalThis); @@ -1820,7 +1820,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime abi_name: []const u8) type { const args = args_list.ptr[0..args_list.len]; if (args.len == 0 or !args[0].isString()) { const err = JSC.toTypeError( - if (args.len == 0) .ERR_MISSING_ARGS else .ERR_INVALID_ARG_TYPE, + if (args.len == 0) .MISSING_ARGS else .INVALID_ARG_TYPE, "writeUTF8() expects a string", .{}, globalThis, @@ -2002,7 +2002,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime abi_name: []const u8) type { // JSC.markBinding(@src()); // var this = @ptrCast(*ThisSocket, @alignCast( fromJS(globalThis, callframe.this()) orelse { -// const err = JSC.toTypeError(.ERR_INVALID_THIS, "Expected Socket", .{}, globalThis); +// const err = JSC.toTypeError(.INVALID_THIS, "Expected Socket", .{}, globalThis); // globalThis.throwValue( err); // return .zero; // })); @@ -3141,7 +3141,11 @@ pub fn ReadableStreamSource( const supports_ref = setRefUnrefFn != null; - pub usingnamespace @field(JSC.Codegen, "JS" ++ name_ ++ "InternalReadableStreamSource"); + pub const js = @field(JSC.Codegen, "JS" ++ name_ ++ "InternalReadableStreamSource"); + pub const toJS = js.toJS; + pub const fromJS = js.fromJS; + pub const fromJSDirect = js.fromJSDirect; + pub const drainFromJS = JSReadableStreamSource.drain; pub const startFromJS = JSReadableStreamSource.start; pub const pullFromJS = JSReadableStreamSource.pull; @@ -3220,7 +3224,7 @@ pub fn ReadableStreamSource( }, .pending => { const out = result.toJS(globalThis); - ReadableStreamSourceType.pendingPromiseSetCached(this_jsvalue, globalThis, out); + js.pendingPromiseSetCached(this_jsvalue, globalThis, out); return out; }, .temporary_and_done, .owned_and_done, .into_array_and_done => { @@ -3263,7 +3267,7 @@ pub fn ReadableStreamSource( this.globalThis = globalObject; if (value.isUndefined()) { - ReadableStreamSourceType.onDrainCallbackSetCached(this.this_jsvalue, globalObject, .undefined); + js.onDrainCallbackSetCached(this.this_jsvalue, globalObject, .undefined); return true; } @@ -3272,7 +3276,7 @@ pub fn ReadableStreamSource( return false; } const cb = value.withAsyncContextIfNeeded(globalObject); - ReadableStreamSourceType.onDrainCallbackSetCached(this.this_jsvalue, globalObject, cb); + js.onDrainCallbackSetCached(this.this_jsvalue, globalObject, cb); return true; } @@ -3289,7 +3293,7 @@ pub fn ReadableStreamSource( JSC.markBinding(@src()); - if (ReadableStreamSourceType.onDrainCallbackGetCached(this.this_jsvalue)) |val| { + if (js.onDrainCallbackGetCached(this.this_jsvalue)) |val| { return val; } @@ -3398,10 +3402,10 @@ pub fn ReadableStreamSource( pub const AutoFlusher = @import("./AutoFlusher.zig"); pub const FileSink = struct { + ref_count: RefCount, writer: IOWriter = .{}, event_loop_handle: JSC.EventLoopHandle, written: usize = 0, - ref_count: bun.ptr.RefCount(FileSink, "ref_count", deinit, .{}), pending: StreamResult.Writable.Pending = .{ .result = .{ .done = {} }, }, @@ -3424,16 +3428,16 @@ pub const FileSink = struct { const log = Output.scoped(.FileSink, false); - // TODO: this usingnamespace is load-bearing, likely due to a compiler bug. - pub usingnamespace brk: { - const RefCount = bun.ptr.RefCount(FileSink, "ref_count", deinit, .{}); - break :brk struct { - pub const ref = RefCount.ref; - pub const deref = RefCount.deref; - }; - }; + pub const RefCount = bun.ptr.RefCount(FileSink, "ref_count", deinit, .{}); + pub const ref = RefCount.ref; + pub const deref = RefCount.deref; - pub const IOWriter = bun.io.StreamingWriter(@This(), onWrite, onError, onReady, onClose); + pub const IOWriter = bun.io.StreamingWriter(@This(), opaque { + pub const onClose = FileSink.onClose; + pub const onWritable = FileSink.onReady; + pub const onError = FileSink.onError; + pub const onWrite = FileSink.onWrite; + }); pub const Poll = IOWriter; pub fn memoryCost(this: *const FileSink) usize { @@ -4635,7 +4639,7 @@ pub const FileReader = struct { const this_value = this.parent().this_jsvalue; const globalThis = this.parent().globalThis; if (this_value != .zero) { - if (Source.onDrainCallbackGetCached(this_value)) |cb| { + if (Source.js.onDrainCallbackGetCached(this_value)) |cb| { const buffered = this.buffered; this.buffered = .{}; this.parent().incrementCount(); diff --git a/src/bun.zig b/src/bun.zig index 7afafa9818..49a952a844 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -1545,7 +1545,7 @@ pub fn reloadProcess( if (comptime Environment.isWindows) { // on windows we assume that we have a parent process that is monitoring us and will restart us if we exit with a magic exit code // see becomeWatcherManager - const rc = bun.windows.TerminateProcess(bun.windows.GetCurrentProcess(), win32.watcher_reload_exit); + const rc = c.TerminateProcess(c.GetCurrentProcess(), windows.watcher_reload_exit); if (rc == 0) { const err = bun.windows.GetLastError(); if (may_return) { @@ -1562,7 +1562,6 @@ pub fn reloadProcess( } } - const PosixSpawn = posix.spawn; const dupe_argv = allocator.allocSentinel(?[*:0]const u8, bun.argv.len, null) catch unreachable; for (bun.argv, dupe_argv) |src, *dest| { dest.* = (allocator.dupeZ(u8, src) catch unreachable).ptr; @@ -1589,24 +1588,24 @@ pub fn reloadProcess( // macOS doesn't have CLOEXEC, so we must go through posix_spawn if (comptime Environment.isMac) { - var actions = PosixSpawn.Actions.init() catch unreachable; + var actions = spawn.Actions.init() catch unreachable; actions.inherit(.stdin()) catch unreachable; actions.inherit(.stdout()) catch unreachable; actions.inherit(.stderr()) catch unreachable; - var attrs = PosixSpawn.Attr.init() catch unreachable; + var attrs = spawn.Attr.init() catch unreachable; attrs.resetSignals() catch {}; attrs.set( - C.translated.POSIX_SPAWN_CLOEXEC_DEFAULT | + c.POSIX_SPAWN_CLOEXEC_DEFAULT | // Apple Extension: If this bit is set, rather // than returning to the caller, posix_spawn(2) // and posix_spawnp(2) will behave as a more // featureful execve(2). - C.translated.POSIX_SPAWN_SETEXEC | - C.translated.POSIX_SPAWN_SETSIGDEF | C.translated.POSIX_SPAWN_SETSIGMASK, + c.POSIX_SPAWN_SETEXEC | + c.POSIX_SPAWN_SETSIGDEF | c.POSIX_SPAWN_SETSIGMASK, ) catch unreachable; - switch (PosixSpawn.spawnZ(exec_path, actions, attrs, @as([*:null]?[*:0]const u8, @ptrCast(newargv)), @as([*:null]?[*:0]const u8, @ptrCast(envp)))) { + switch (spawn.spawnZ(exec_path, actions, attrs, @as([*:null]?[*:0]const u8, @ptrCast(newargv)), @as([*:null]?[*:0]const u8, @ptrCast(envp)))) { .err => |err| { if (may_return) { Output.errGeneric("Failed to reload process: {s}", .{@tagName(err.getErrno())}); @@ -1929,8 +1928,8 @@ const WindowsStat = extern struct { pub const Stat = if (Environment.isWindows) windows.libuv.uv_stat_t else std.posix.Stat; pub const StatFS = switch (Environment.os) { - .mac => C.translated.struct_statfs, - .linux => C.translated.struct_statfs, + .mac => bun.c.struct_statfs, + .linux => bun.c.struct_statfs, else => windows.libuv.uv_statfs_t, }; @@ -1997,201 +1996,7 @@ pub fn initArgv(allocator: std.mem.Allocator) !void { } } -pub const posix = struct { - pub const spawn = @import("./bun.js/api/bun/spawn.zig").PosixSpawn; -}; - -pub const win32 = struct { - const w = std.os.windows; - - /// Returns the original mode, or null on failure - pub fn updateStdioModeFlags(i: bun.FD.Stdio, opts: struct { set: w.DWORD = 0, unset: w.DWORD = 0 }) !w.DWORD { - const fd = i.fd(); - var original_mode: w.DWORD = 0; - if (windows.GetConsoleMode(fd.cast(), &original_mode) != 0) { - if (windows.SetConsoleMode(fd.cast(), (original_mode | opts.set) & ~opts.unset) == 0) { - return windows.getLastError(); - } - } else return windows.getLastError(); - return original_mode; - } - - const watcherChildEnv: [:0]const u16 = strings.toUTF16Literal("_BUN_WATCHER_CHILD"); - // magic exit code to indicate to the watcher manager that the child process should be re-spawned - // this was randomly generated - we need to avoid using a common exit code that might be used by the script itself - const watcher_reload_exit: w.DWORD = 3224497970; - - pub const spawn = @import("./bun.js/api/bun/spawn.zig").PosixSpawn; - - pub fn isWatcherChild() bool { - var buf: [1]u16 = undefined; - return windows.GetEnvironmentVariableW(@constCast(watcherChildEnv.ptr), &buf, 1) > 0; - } - - pub fn becomeWatcherManager(allocator: std.mem.Allocator) noreturn { - // this process will be the parent of the child process that actually runs the script - var procinfo: std.os.windows.PROCESS_INFORMATION = undefined; - C.windows_enable_stdio_inheritance(); - const job = windows.CreateJobObjectA(null, null) orelse Output.panic( - "Could not create watcher Job Object: {s}", - .{@tagName(std.os.windows.kernel32.GetLastError())}, - ); - var jeli = std.mem.zeroes(windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION); - jeli.BasicLimitInformation.LimitFlags = - windows.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | - windows.JOB_OBJECT_LIMIT_BREAKAWAY_OK | - windows.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK | - windows.JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION; - if (windows.SetInformationJobObject( - job, - windows.JobObjectExtendedLimitInformation, - &jeli, - @sizeOf(windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION), - ) == 0) { - Output.panic( - "Could not configure watcher Job Object: {s}", - .{@tagName(std.os.windows.kernel32.GetLastError())}, - ); - } - - while (true) { - spawnWatcherChild(allocator, &procinfo, job) catch |err| { - handleErrorReturnTrace(err, @errorReturnTrace()); - if (err == error.Win32Error) { - Output.panic("Failed to spawn process: {s}\n", .{@tagName(std.os.windows.kernel32.GetLastError())}); - } - Output.panic("Failed to spawn process: {s}\n", .{@errorName(err)}); - }; - w.WaitForSingleObject(procinfo.hProcess, w.INFINITE) catch |err| { - Output.panic("Failed to wait for child process: {s}\n", .{@errorName(err)}); - }; - var exit_code: w.DWORD = 0; - if (w.kernel32.GetExitCodeProcess(procinfo.hProcess, &exit_code) == 0) { - const err = windows.GetLastError(); - _ = std.os.windows.ntdll.NtClose(procinfo.hProcess); - Output.panic("Failed to get exit code of child process: {s}\n", .{@tagName(err)}); - } - _ = std.os.windows.ntdll.NtClose(procinfo.hProcess); - - // magic exit code to indicate that the child process should be re-spawned - if (exit_code == watcher_reload_exit) { - continue; - } else { - Global.exit(exit_code); - } - } - } - - pub fn spawnWatcherChild( - allocator: std.mem.Allocator, - procinfo: *std.os.windows.PROCESS_INFORMATION, - job: w.HANDLE, - ) !void { - // https://devblogs.microsoft.com/oldnewthing/20230209-00/?p=107812 - var attr_size: usize = undefined; - _ = windows.InitializeProcThreadAttributeList(null, 1, 0, &attr_size); - const p = try allocator.alloc(u8, attr_size); - defer allocator.free(p); - if (windows.InitializeProcThreadAttributeList(p.ptr, 1, 0, &attr_size) == 0) { - return error.Win32Error; - } - if (windows.UpdateProcThreadAttribute( - p.ptr, - 0, - windows.PROC_THREAD_ATTRIBUTE_JOB_LIST, - @ptrCast(&job), - @sizeOf(w.HANDLE), - null, - null, - ) == 0) { - return error.Win32Error; - } - - const flags: std.os.windows.DWORD = w.CREATE_UNICODE_ENVIRONMENT | windows.EXTENDED_STARTUPINFO_PRESENT; - - const image_path = windows.exePathW(); - var wbuf: WPathBuffer = undefined; - @memcpy(wbuf[0..image_path.len], image_path); - wbuf[image_path.len] = 0; - - const image_pathZ = wbuf[0..image_path.len :0]; - - const kernelenv = w.kernel32.GetEnvironmentStringsW(); - defer { - if (kernelenv) |envptr| { - _ = w.kernel32.FreeEnvironmentStringsW(envptr); - } - } - - var size: usize = 0; - if (kernelenv) |pointer| { - // check that env is non-empty - if (pointer[0] != 0 or pointer[1] != 0) { - // array is terminated by two nulls - while (pointer[size] != 0 or pointer[size + 1] != 0) size += 1; - size += 1; - } - } - // now pointer[size] is the first null - - const envbuf = try allocator.alloc(u16, size + watcherChildEnv.len + 4); - defer allocator.free(envbuf); - if (kernelenv) |pointer| { - @memcpy(envbuf[0..size], pointer); - } - @memcpy(envbuf[size .. size + watcherChildEnv.len], watcherChildEnv); - envbuf[size + watcherChildEnv.len] = '='; - envbuf[size + watcherChildEnv.len + 1] = '1'; - envbuf[size + watcherChildEnv.len + 2] = 0; - envbuf[size + watcherChildEnv.len + 3] = 0; - - var startupinfo = windows.STARTUPINFOEXW{ - .StartupInfo = .{ - .cb = @sizeOf(windows.STARTUPINFOEXW), - .lpReserved = null, - .lpDesktop = null, - .lpTitle = null, - .dwX = 0, - .dwY = 0, - .dwXSize = 0, - .dwYSize = 0, - .dwXCountChars = 0, - .dwYCountChars = 0, - .dwFillAttribute = 0, - .dwFlags = w.STARTF_USESTDHANDLES, - .wShowWindow = 0, - .cbReserved2 = 0, - .lpReserved2 = null, - .hStdInput = std.io.getStdIn().handle, - .hStdOutput = std.io.getStdOut().handle, - .hStdError = std.io.getStdErr().handle, - }, - .lpAttributeList = p.ptr, - }; - @memset(std.mem.asBytes(procinfo), 0); - const rc = w.kernel32.CreateProcessW( - image_pathZ.ptr, - bun.windows.GetCommandLineW(), - null, - null, - 1, - flags, - envbuf.ptr, - null, - @ptrCast(&startupinfo), - procinfo, - ); - if (rc == 0) { - return error.Win32Error; - } - var is_in_job: w.BOOL = 0; - _ = windows.IsProcessInJob(procinfo.hProcess, job, &is_in_job); - assert(is_in_job != 0); - _ = std.os.windows.ntdll.NtClose(procinfo.hThread); - } -}; - -pub usingnamespace if (@import("builtin").target.os.tag != .windows) posix else win32; +pub const spawn = @import("./bun.js/api/bun/spawn.zig").PosixSpawn; pub fn isRegularFile(mode: anytype) bool { return S.ISREG(@intCast(mode)); @@ -3186,7 +2991,7 @@ pub fn getRoughTickCount() timespec { pub var clock_id: std.os.linux.CLOCK = .REALTIME; pub fn get() void { var res = timespec{}; - _ = std.os.linux.clock_getres(.MONOTONIC_COARSE, @ptrCast(&res)); + std.posix.clock_getres(.MONOTONIC_COARSE, @ptrCast(&res)) catch {}; if (res.ms() <= 1) { clock_id = .MONOTONIC_COARSE; } else { @@ -3774,7 +3579,7 @@ pub const WPathBufferPool = if (Environment.isWindows) PathBufferPoolT(bun.WPath pub const OSPathBufferPool = if (Environment.isWindows) WPathBufferPool else PathBufferPool; pub const S3 = @import("./s3/client.zig"); -pub const ptr = @import("./ptr.zig"); +pub const ptr = @import("ptr.zig"); const Allocator = std.mem.Allocator; diff --git a/src/c-headers-for-zig.h b/src/c-headers-for-zig.h index 512812aeff..6e791455d6 100644 --- a/src/c-headers-for-zig.h +++ b/src/c-headers-for-zig.h @@ -42,3 +42,8 @@ #include #include #endif + +#if WINDOWS +#include +#include +#endif diff --git a/src/c.zig b/src/c.zig index 1c1c93e0d3..ca9bba572d 100644 --- a/src/c.zig +++ b/src/c.zig @@ -12,7 +12,7 @@ const std = @import("std"); const bun = @import("bun"); const Environment = @import("./env.zig"); -pub const translated = @import("translated-c-headers"); +const translated = @import("translated-c-headers"); const PlatformSpecific = switch (Environment.os) { .mac => @import("darwin_c.zig"), diff --git a/src/cli.zig b/src/cli.zig index 200f1312e2..97f1a74935 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -1626,9 +1626,9 @@ pub const Command = struct { if (comptime Environment.isWindows) { if (global_cli_ctx.debug.hot_reload == .watch) { - if (!bun.isWatcherChild()) { + if (!bun.windows.isWatcherChild()) { // this is noreturn - bun.becomeWatcherManager(allocator); + bun.windows.becomeWatcherManager(allocator); } else { bun.auto_reload_on_crash = true; } diff --git a/src/cli/bunx_command.zig b/src/cli/bunx_command.zig index 626dd1eed9..ae1314495c 100644 --- a/src/cli/bunx_command.zig +++ b/src/cli/bunx_command.zig @@ -543,7 +543,7 @@ pub const BunxCommand = struct { if (bun.strings.hasPrefix(out, bunx_cache_dir)) { const is_stale = is_stale: { if (Environment.isWindows) { - const fd = bun.sys.openat(bun.invalid_fd, destination, bun.O.RDONLY, 0).unwrap() catch { + const fd = bun.sys.openat(.cwd(), destination, bun.O.RDONLY, 0).unwrap() catch { // if we cant open this, we probably will just fail when we run it // and that error message is likely going to be better than the one from `bun add` break :is_stale false; diff --git a/src/cli/filter_run.zig b/src/cli/filter_run.zig index 3b2c0e597c..8bd6ca0176 100644 --- a/src/cli/filter_run.zig +++ b/src/cli/filter_run.zig @@ -67,7 +67,7 @@ pub const ProcessHandle = struct { var argv = [_:null]?[*:0]const u8{ this.state.shell_bin, if (Environment.isPosix) "-c" else "exec", this.config.combined, null }; this.start_time = std.time.Instant.now() catch null; - var spawned: bun.spawn.SpawnProcessResult = brk: { + var spawned: bun.spawn.process.SpawnProcessResult = brk: { // Get the envp with the PATH configured // There's probably a more optimal way to do this where you have a std.ArrayList shared @@ -411,7 +411,7 @@ const AbortHandler = struct { }; std.posix.sigaction(std.posix.SIG.INT, &action, null); } else { - const res = bun.windows.SetConsoleCtrlHandler(windowsCtrlHandler, std.os.windows.TRUE); + const res = bun.c.SetConsoleCtrlHandler(windowsCtrlHandler, std.os.windows.TRUE); if (res == 0) { if (Environment.isDebug) { Output.warn("Failed to set abort handler\n", .{}); @@ -424,7 +424,7 @@ const AbortHandler = struct { // only necessary on Windows, as on posix we pass the SA_RESETHAND flag if (Environment.isWindows) { // restores default Ctrl+C behavior - _ = bun.windows.SetConsoleCtrlHandler(null, std.os.windows.FALSE); + _ = bun.c.SetConsoleCtrlHandler(null, std.os.windows.FALSE); } } }; diff --git a/src/cli/init_command.zig b/src/cli/init_command.zig index 3a7979afe3..1b4e8cd285 100644 --- a/src/cli/init_command.zig +++ b/src/cli/init_command.zig @@ -41,11 +41,11 @@ pub const InitCommand = struct { // unset `ENABLE_VIRTUAL_TERMINAL_INPUT` on windows. This prevents backspace from // deleting the entire line const original_mode: if (Environment.isWindows) ?bun.windows.DWORD else void = if (comptime Environment.isWindows) - bun.win32.updateStdioModeFlags(.std_in, .{ .unset = bun.windows.ENABLE_VIRTUAL_TERMINAL_INPUT }) catch null; + bun.windows.updateStdioModeFlags(.std_in, .{ .unset = bun.windows.ENABLE_VIRTUAL_TERMINAL_INPUT }) catch null; defer if (comptime Environment.isWindows) { if (original_mode) |mode| { - _ = bun.windows.SetConsoleMode(bun.FD.stdin().native(), mode); + _ = bun.c.SetConsoleMode(bun.FD.stdin().native(), mode); } }; @@ -206,7 +206,7 @@ pub const InitCommand = struct { // Set raw mode to read single characters without echo const original_mode: if (Environment.isWindows) ?bun.windows.DWORD else void = if (comptime Environment.isWindows) - bun.win32.updateStdioModeFlags(.std_in, .{ + bun.windows.updateStdioModeFlags(.std_in, .{ // virtual terminal input enables arrow keys, processed input lets ctrl+c kill the program .set = bun.windows.ENABLE_VIRTUAL_TERMINAL_INPUT | bun.windows.ENABLE_PROCESSED_INPUT, // disabling line input sends keys immediately, disabling echo input makes sure it doesn't print to the terminal @@ -219,7 +219,7 @@ pub const InitCommand = struct { defer { if (comptime Environment.isWindows) { if (original_mode) |mode| { - _ = bun.windows.SetConsoleMode( + _ = bun.c.SetConsoleMode( bun.FD.stdin().native(), mode, ); diff --git a/src/cli/publish_command.zig b/src/cli/publish_command.zig index ae79a19294..3213435f75 100644 --- a/src/cli/publish_command.zig +++ b/src/cli/publish_command.zig @@ -680,11 +680,11 @@ pub const PublishCommand = struct { // unset `ENABLE_VIRTUAL_TERMINAL_INPUT` on windows. This prevents backspace from // deleting the entire line const original_mode: if (Environment.isWindows) ?bun.windows.DWORD else void = if (comptime Environment.isWindows) - bun.win32.updateStdioModeFlags(.std_in, .{ .unset = bun.windows.ENABLE_VIRTUAL_TERMINAL_INPUT }) catch null; + bun.windows.updateStdioModeFlags(.std_in, .{ .unset = bun.windows.ENABLE_VIRTUAL_TERMINAL_INPUT }) catch null; defer if (comptime Environment.isWindows) { if (original_mode) |mode| { - _ = bun.windows.SetConsoleMode(bun.FD.stdin().native(), mode); + _ = bun.c.SetConsoleMode(bun.FD.stdin().native(), mode); } }; diff --git a/src/codegen/generate-node-errors.ts b/src/codegen/generate-node-errors.ts index 2227f6c2ae..0d402d535f 100644 --- a/src/codegen/generate-node-errors.ts +++ b/src/codegen/generate-node-errors.ts @@ -58,25 +58,25 @@ const JSC = bun.JSC; pub fn ErrorBuilder(comptime code: Error, comptime fmt: [:0]const u8, Args: type) type { return struct { - globalThis: *JSC.JSGlobalObject, + global: *JSC.JSGlobalObject, args: Args, // Throw this error as a JS exception pub inline fn throw(this: @This()) bun.JSError { - return code.throw(this.globalThis, fmt, this.args); + return code.throw(this.global, fmt, this.args); } /// Turn this into a JSValue pub inline fn toJS(this: @This()) JSC.JSValue { - return code.fmt(this.globalThis, fmt, this.args); + return code.fmt(this.global, fmt, this.args); } /// Turn this into a JSPromise that is already rejected. pub inline fn reject(this: @This()) JSC.JSValue { if (comptime bun.FeatureFlags.breaking_changes_1_3) { - return JSC.JSPromise.rejectedPromise(this.globalThis, code.fmt(this.globalThis, fmt, this.args)).toJS(); + return JSC.JSPromise.rejectedPromise(this.globalThis, code.fmt(this.global, fmt, this.args)).toJS(); } else { - return JSC.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(this.globalThis, code.fmt(this.globalThis, fmt, this.args)); + return JSC.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(this.global, code.fmt(this.global, fmt, this.args)); } } }; @@ -87,17 +87,16 @@ pub const Error = enum(u8) { `; let i = 0; -let listForUsingNamespace = ""; for (let [code, constructor, name, ...other_constructors] of NodeErrors) { if (name == null) name = constructor.name; + + // it's useful to avoid the prefix, but module not found has a prefixed and unprefixed version + const codeWithoutPrefix = code === 'ERR_MODULE_NOT_FOUND' ? code : code.replace(/^ERR_/, ''); + enumHeader += ` ${code} = ${i},\n`; listHeader += ` { JSC::ErrorType::${constructor.name}, "${name}"_s, "${code}"_s },\n`; zig += ` /// ${name}: ${code} (instanceof ${constructor.name})\n`; - zig += ` ${code} = ${i},\n`; - listForUsingNamespace += ` /// ${name}: ${code} (instanceof ${constructor.name})\n`; - listForUsingNamespace += ` pub inline fn ${code}(globalThis: *JSC.JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) ErrorBuilder(Error.${code}, fmt, @TypeOf(args)) {\n`; - listForUsingNamespace += ` return .{ .globalThis = globalThis, .args = args };\n`; - listForUsingNamespace += ` }\n`; + zig += ` ${codeWithoutPrefix} = ${i},\n`; i++; for (const con of other_constructors) { @@ -106,11 +105,7 @@ for (let [code, constructor, name, ...other_constructors] of NodeErrors) { enumHeader += ` ${code}_${con.name} = ${i},\n`; listHeader += ` { JSC::ErrorType::${con.name}, "${con.name}"_s, "${code}"_s },\n`; zig += ` /// ${name}: ${code} (instanceof ${con.name})\n`; - zig += ` ${code}_${con.name} = ${i},\n`; - listForUsingNamespace += ` /// ${name}: ${code} (instanceof ${con.name})\n`; - listForUsingNamespace += ` pub inline fn ${code}_${con.name}(globalThis: *JSC.JSGlobalObject, comptime fmt: [:0]const u8, args: anytype) ErrorBuilder(Error.${code}_${con.name}, fmt, @TypeOf(args)) {\n`; - listForUsingNamespace += ` return .{ .globalThis = globalThis, .args = args };\n`; - listForUsingNamespace += ` }\n`; + zig += ` ${codeWithoutPrefix}_${con.name} = ${i},\n`; i++; } } @@ -151,10 +146,6 @@ zig += ` } }; - -pub const JSGlobalObjectExtensions = struct { -${listForUsingNamespace} -}; `; await Bun.write(path.join(outputDir, "ErrorCode+List.h"), enumHeader); diff --git a/src/codegen/process_windows_translate_c.zig b/src/codegen/process_windows_translate_c.zig new file mode 100644 index 0000000000..8bbfd5cf57 --- /dev/null +++ b/src/codegen/process_windows_translate_c.zig @@ -0,0 +1,72 @@ +// translate-c is unable to translate the unsuffixed windows functions +// like `SetCurrentDirectory` since they are defined with an odd macro +// that translate-c doesn't handle. +// +// #define SetCurrentDirectory __MINGW_NAME_AW(SetCurrentDirectory) +// +// In these cases, it's better to just reference the underlying function +// directly: SetCurrentDirectoryW. To make the error better, a post +// processing step is applied to the translate-c file. +const std = @import("std"); +const mem = std.mem; + +const symbol_replacements = std.StaticStringMap([]const u8).initComptime(&.{ + &.{ "NTSTATUS", "@import(\"std\").os.windows.NTSTATUS" }, + &.{ "HANDLE", "@import(\"std\").os.windows.HANDLE" }, + &.{ "PHANDLE", "*HANDLE" }, +}); + +pub fn main() !void { + const gpa = std.heap.smp_allocator; + var args = try std.process.argsWithAllocator(gpa); + errdefer args.deinit(); + assert(args.skip()); + + const in = brk: { + const in_path = args.next() orelse @panic("missing argument"); + const in = try std.fs.openFileAbsolute(in_path, .{}); + defer in.close(); + break :brk try in.readToEndAllocOptions(gpa, std.math.maxInt(u32), null, 1, 0); + }; + defer gpa.free(in); + + var out = try std.ArrayList(u8).initCapacity(gpa, in.len); + defer out.deinit(); + const w = out.writer(); + + var i: usize = 0; + while (mem.indexOfPos(u8, in, i, "pub const ")) |pub_i| { + var tokenizer = std.zig.Tokenizer.init(in); + tokenizer.index = pub_i + "pub const ".len; + const symbol_name_token = tokenizer.next(); + assert(symbol_name_token.tag == .identifier); + const symbol_name = in[symbol_name_token.loc.start..symbol_name_token.loc.end]; + try w.writeAll(in[i..symbol_name_token.loc.end]); + i = symbol_name_token.loc.end; + var end_of_line = mem.indexOfScalarPos(u8, in, symbol_name_token.loc.end, '\n') orelse in.len; + if (in[end_of_line - 1] != ';') { + // skip multiline decl + try w.writeAll(in[i..end_of_line]); + i = end_of_line; + continue; + } + end_of_line += 1; // include the \n + if (symbol_replacements.get(symbol_name)) |replace| { + try w.print(" = {s};\n", .{replace}); + } else if (mem.startsWith(u8, in[i..], " = __MINGW_NAME_AW(")) { + try w.print(" = @compileError(\"Use '{s}W' instead.\");\n", .{symbol_name}); + } else { + try w.writeAll(in[i..end_of_line]); + } + i = end_of_line; + } + try w.writeAll(in[i..]); + try std.fs.cwd().writeFile(.{ + .sub_path = args.next() orelse @panic("missing argument"), + .data = out.items, + }); +} + +fn assert(cond: bool) void { + if (!cond) @panic("unhandled"); +} diff --git a/src/crash_handler.zig b/src/crash_handler.zig index b3c6034834..e2c1bcabea 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -294,7 +294,7 @@ pub fn crashHandler( if (std.os.windows.HRESULT_CODE(result) == .SUCCESS and name[0] != 0) { writer.print("({})", .{bun.fmt.utf16(bun.span(name))}) catch std.posix.abort(); } else { - writer.print("(thread {d})", .{bun.windows.GetCurrentThreadId()}) catch std.posix.abort(); + writer.print("(thread {d})", .{bun.c.GetCurrentThreadId()}) catch std.posix.abort(); } }, .mac, .linux => {}, diff --git a/src/deps/brotli_decoder.zig b/src/deps/brotli_c.zig similarity index 61% rename from src/deps/brotli_decoder.zig rename to src/deps/brotli_c.zig index c205836cd6..a490b8af87 100644 --- a/src/deps/brotli_decoder.zig +++ b/src/deps/brotli_c.zig @@ -1,4 +1,5 @@ -const bun = @import("bun"); +// TODO: prefer generating this file via translate_c +const bun = @import("root").bun; const std = @import("std"); pub const brotli_alloc_func = ?*const fn (?*anyopaque, usize) callconv(.C) ?*anyopaque; @@ -195,9 +196,138 @@ pub const BrotliDecoderParameter = enum(c_uint) { pub const BROTLI_UINT32_MAX = ~@import("std").zig.c_translation.cast(u32, @as(c_int, 0)); pub const BROTLI_SIZE_MAX = ~@import("std").zig.c_translation.cast(usize, @as(c_int, 0)); -pub const SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH = @as(c_int, 4); -pub const SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH = @as(c_int, 31); -pub const SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS = @as(c_int, 64); -pub const SHARED_BROTLI_MAX_COMPOUND_DICTS = @as(c_int, 15); pub const BROTLI_LAST_ERROR_CODE = BROTLI_DECODER_ERROR_UNREACHABLE; pub const BrotliSharedDictionaryStruct = struct_BrotliSharedDictionaryStruct; + +pub const struct_BrotliEncoderPreparedDictionaryStruct = opaque {}; +pub const BrotliEncoderPreparedDictionary = struct_BrotliEncoderPreparedDictionaryStruct; +extern fn BrotliSharedDictionaryCreateInstance(alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) ?*BrotliSharedDictionary; +extern fn BrotliSharedDictionaryDestroyInstance(dict: ?*BrotliSharedDictionary) void; +extern fn BrotliSharedDictionaryAttach(dict: ?*BrotliSharedDictionary, @"type": BrotliSharedDictionaryType, data_size: usize, data: [*c]const u8) c_int; +pub const BROTLI_MODE_GENERIC: c_int = 0; +pub const BROTLI_MODE_TEXT: c_int = 1; +pub const BROTLI_MODE_FONT: c_int = 2; +pub const BrotliEncoderMode = enum(c_uint) { + generic = 0, + text = 1, + font = 2, +}; +pub const BROTLI_OPERATION_PROCESS: c_int = 0; +pub const BROTLI_OPERATION_FLUSH: c_int = 1; +pub const BROTLI_OPERATION_FINISH: c_int = 2; +pub const BROTLI_OPERATION_EMIT_METADATA: c_int = 3; + +pub const BROTLI_PARAM_MODE: c_int = 0; +pub const BROTLI_PARAM_QUALITY: c_int = 1; +pub const BROTLI_PARAM_LGWIN: c_int = 2; +pub const BROTLI_PARAM_LGBLOCK: c_int = 3; +pub const BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: c_int = 4; +pub const BROTLI_PARAM_SIZE_HINT: c_int = 5; +pub const BROTLI_PARAM_LARGE_WINDOW: c_int = 6; +pub const BROTLI_PARAM_NPOSTFIX: c_int = 7; +pub const BROTLI_PARAM_NDIRECT: c_int = 8; +pub const BROTLI_PARAM_STREAM_OFFSET: c_int = 9; +pub const BrotliEncoderParameter = enum(c_uint) { + mode = 0, + quality = 1, + lgwin = 2, + lgblock = 3, + disable_literal_context_modeling = 4, + size_hint = 5, + large_window = 6, + npostfix = 7, + ndirect = 8, + stream_offset = 9, + // update kMaxBrotliParam in src/js/node/zlib.ts if this list changes +}; + +pub extern fn BrotliEncoderSetParameter(state: *BrotliEncoder, param: c_uint, value: u32) c_int; +pub extern fn BrotliEncoderCreateInstance(alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) ?*BrotliEncoder; +pub extern fn BrotliEncoderDestroyInstance(state: *BrotliEncoder) void; +pub extern fn BrotliEncoderPrepareDictionary(@"type": BrotliSharedDictionaryType, data_size: usize, data: [*c]const u8, quality: c_int, alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) *BrotliEncoderPreparedDictionary; +pub extern fn BrotliEncoderDestroyPreparedDictionary(dictionary: *BrotliEncoderPreparedDictionary) void; +pub extern fn BrotliEncoderAttachPreparedDictionary(state: *BrotliEncoder, dictionary: ?*const BrotliEncoderPreparedDictionary) c_int; +pub extern fn BrotliEncoderMaxCompressedSize(input_size: usize) usize; +pub extern fn BrotliEncoderCompress(quality: c_int, lgwin: c_int, mode: BrotliEncoderMode, input_size: usize, input_buffer: [*]const u8, encoded_size: *usize, encoded_buffer: [*]u8) c_int; +pub extern fn BrotliEncoderCompressStream(state: *BrotliEncoder, op: BrotliEncoder.Operation, available_in: *usize, next_in: *?[*]const u8, available_out: *usize, next_in: ?*?[*]u8, total_out: ?*usize) c_int; +pub extern fn BrotliEncoderIsFinished(state: *BrotliEncoder) c_int; +pub extern fn BrotliEncoderHasMoreOutput(state: *BrotliEncoder) c_int; +pub extern fn BrotliEncoderTakeOutput(state: *BrotliEncoder, size: *usize) ?[*]const u8; +pub extern fn BrotliEncoderEstimatePeakMemoryUsage(quality: c_int, lgwin: c_int, input_size: usize) usize; +pub extern fn BrotliEncoderGetPreparedDictionarySize(dictionary: ?*const BrotliEncoderPreparedDictionary) usize; +pub extern fn BrotliEncoderVersion() u32; + +pub const BrotliEncoder = opaque { + pub const Operation = enum(c_uint) { + process = 0, + flush = 1, + finish = 2, + emit_metadata = 3, + }; + + pub fn createInstance(alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) callconv(.C) ?*BrotliEncoder { + return BrotliEncoderCreateInstance(alloc_func, free_func, @"opaque"); + } + + pub fn destroyInstance(state: *BrotliEncoder) callconv(.C) void { + return BrotliEncoderDestroyInstance(state); + } + + pub fn hasMoreOutput(state: *BrotliEncoder) callconv(.C) bool { + return BrotliEncoderHasMoreOutput(state) > 0; + } + + pub fn takeOutput(state: *BrotliEncoder) []const u8 { + var size: usize = 0; + if (BrotliEncoderTakeOutput(state, &size)) |ptr| { + return ptr[0..size]; + } + + return ""; + } + + pub const CompressionResult = struct { + success: bool = false, + has_more: bool = false, + output: []const u8 = "", + }; + + // https://github.com/google/brotli/blob/2ad58d8603294f5ee33d23bb725e0e6a17c1de50/go/cbrotli/writer.go#L23-L40 + pub fn compressStream(state: *BrotliEncoder, op: Operation, data: []const u8) CompressionResult { + var available_in = data.len; + var next_in: ?[*]const u8 = data.ptr; + + var available_out: usize = 0; + + var result = CompressionResult{}; + + result.success = BrotliEncoderCompressStream(state, op, &available_in, &next_in, &available_out, null, null) > 0; + + if (result.success) { + result.output = takeOutput(state); + } + + result.has_more = BrotliEncoderHasMoreOutput(state) > 0; + + return result; + } + + pub fn setParameter(state: *BrotliEncoder, param: BrotliEncoderParameter, value: u32) bool { + return BrotliEncoderSetParameter(state, @intFromEnum(param), value) > 0; + } +}; + +pub const SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH = 4; +pub const SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH = 31; +pub const SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS = 64; +pub const SHARED_BROTLI_MAX_COMPOUND_DICTS = 15; +pub const BROTLI_MIN_WINDOW_BITS = 10; +pub const BROTLI_MAX_WINDOW_BITS = 24; +pub const BROTLI_LARGE_MAX_WINDOW_BITS = 30; +pub const BROTLI_MIN_INPUT_BLOCK_BITS = 16; +pub const BROTLI_MAX_INPUT_BLOCK_BITS = 24; +pub const BROTLI_MIN_QUALITY = 0; +pub const BROTLI_MAX_QUALITY = 11; +pub const BROTLI_DEFAULT_QUALITY = 11; +pub const BROTLI_DEFAULT_WINDOW = 22; +pub const BROTLI_DEFAULT_MODE = BROTLI_MODE_GENERIC; diff --git a/src/deps/brotli_encoder.zig b/src/deps/brotli_encoder.zig deleted file mode 100644 index 6e557f2ae4..0000000000 --- a/src/deps/brotli_encoder.zig +++ /dev/null @@ -1,143 +0,0 @@ -const bun = @import("bun"); -const std = @import("std"); - -pub const brotli_alloc_func = ?*const fn (?*anyopaque, usize) callconv(.C) ?*anyopaque; -pub const brotli_free_func = ?*const fn (?*anyopaque, ?*anyopaque) callconv(.C) void; -pub const struct_BrotliSharedDictionaryStruct = opaque {}; -pub const BrotliSharedDictionary = struct_BrotliSharedDictionaryStruct; -pub const BROTLI_SHARED_DICTIONARY_RAW: c_int = 0; -pub const BROTLI_SHARED_DICTIONARY_SERIALIZED: c_int = 1; -pub const enum_BrotliSharedDictionaryType = c_uint; -pub const BrotliSharedDictionaryType = enum_BrotliSharedDictionaryType; -pub const struct_BrotliEncoderPreparedDictionaryStruct = opaque {}; -pub const BrotliEncoderPreparedDictionary = struct_BrotliEncoderPreparedDictionaryStruct; -extern fn BrotliSharedDictionaryCreateInstance(alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) ?*BrotliSharedDictionary; -extern fn BrotliSharedDictionaryDestroyInstance(dict: ?*BrotliSharedDictionary) void; -extern fn BrotliSharedDictionaryAttach(dict: ?*BrotliSharedDictionary, @"type": BrotliSharedDictionaryType, data_size: usize, data: [*c]const u8) c_int; -pub const BROTLI_MODE_GENERIC: c_int = 0; -pub const BROTLI_MODE_TEXT: c_int = 1; -pub const BROTLI_MODE_FONT: c_int = 2; -pub const BrotliEncoderMode = enum(c_uint) { - generic = 0, - text = 1, - font = 2, -}; -pub const BROTLI_OPERATION_PROCESS: c_int = 0; -pub const BROTLI_OPERATION_FLUSH: c_int = 1; -pub const BROTLI_OPERATION_FINISH: c_int = 2; -pub const BROTLI_OPERATION_EMIT_METADATA: c_int = 3; - -pub const BROTLI_PARAM_MODE: c_int = 0; -pub const BROTLI_PARAM_QUALITY: c_int = 1; -pub const BROTLI_PARAM_LGWIN: c_int = 2; -pub const BROTLI_PARAM_LGBLOCK: c_int = 3; -pub const BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: c_int = 4; -pub const BROTLI_PARAM_SIZE_HINT: c_int = 5; -pub const BROTLI_PARAM_LARGE_WINDOW: c_int = 6; -pub const BROTLI_PARAM_NPOSTFIX: c_int = 7; -pub const BROTLI_PARAM_NDIRECT: c_int = 8; -pub const BROTLI_PARAM_STREAM_OFFSET: c_int = 9; -pub const BrotliEncoderParameter = enum(c_uint) { - mode = 0, - quality = 1, - lgwin = 2, - lgblock = 3, - disable_literal_context_modeling = 4, - size_hint = 5, - large_window = 6, - npostfix = 7, - ndirect = 8, - stream_offset = 9, - // update kMaxBrotliParam in src/js/node/zlib.ts if this list changes -}; - -pub extern fn BrotliEncoderSetParameter(state: *BrotliEncoder, param: c_uint, value: u32) c_int; -pub extern fn BrotliEncoderCreateInstance(alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) ?*BrotliEncoder; -pub extern fn BrotliEncoderDestroyInstance(state: *BrotliEncoder) void; -pub extern fn BrotliEncoderPrepareDictionary(@"type": BrotliSharedDictionaryType, data_size: usize, data: [*c]const u8, quality: c_int, alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) *BrotliEncoderPreparedDictionary; -pub extern fn BrotliEncoderDestroyPreparedDictionary(dictionary: *BrotliEncoderPreparedDictionary) void; -pub extern fn BrotliEncoderAttachPreparedDictionary(state: *BrotliEncoder, dictionary: ?*const BrotliEncoderPreparedDictionary) c_int; -pub extern fn BrotliEncoderMaxCompressedSize(input_size: usize) usize; -pub extern fn BrotliEncoderCompress(quality: c_int, lgwin: c_int, mode: BrotliEncoderMode, input_size: usize, input_buffer: [*]const u8, encoded_size: *usize, encoded_buffer: [*]u8) c_int; -pub extern fn BrotliEncoderCompressStream(state: *BrotliEncoder, op: BrotliEncoder.Operation, available_in: *usize, next_in: *?[*]const u8, available_out: *usize, next_in: ?*?[*]u8, total_out: ?*usize) c_int; -pub extern fn BrotliEncoderIsFinished(state: *BrotliEncoder) c_int; -pub extern fn BrotliEncoderHasMoreOutput(state: *BrotliEncoder) c_int; -pub extern fn BrotliEncoderTakeOutput(state: *BrotliEncoder, size: *usize) ?[*]const u8; -pub extern fn BrotliEncoderEstimatePeakMemoryUsage(quality: c_int, lgwin: c_int, input_size: usize) usize; -pub extern fn BrotliEncoderGetPreparedDictionarySize(dictionary: ?*const BrotliEncoderPreparedDictionary) usize; -pub extern fn BrotliEncoderVersion() u32; - -pub const BrotliEncoder = opaque { - pub const Operation = enum(c_uint) { - process = 0, - flush = 1, - finish = 2, - emit_metadata = 3, - }; - - pub fn createInstance(alloc_func: brotli_alloc_func, free_func: brotli_free_func, @"opaque": ?*anyopaque) callconv(.C) ?*BrotliEncoder { - return BrotliEncoderCreateInstance(alloc_func, free_func, @"opaque"); - } - - pub fn destroyInstance(state: *BrotliEncoder) callconv(.C) void { - return BrotliEncoderDestroyInstance(state); - } - - pub fn hasMoreOutput(state: *BrotliEncoder) callconv(.C) bool { - return BrotliEncoderHasMoreOutput(state) > 0; - } - - pub fn takeOutput(state: *BrotliEncoder) []const u8 { - var size: usize = 0; - if (BrotliEncoderTakeOutput(state, &size)) |ptr| { - return ptr[0..size]; - } - - return ""; - } - - pub const CompressionResult = struct { - success: bool = false, - has_more: bool = false, - output: []const u8 = "", - }; - - // https://github.com/google/brotli/blob/2ad58d8603294f5ee33d23bb725e0e6a17c1de50/go/cbrotli/writer.go#L23-L40 - pub fn compressStream(state: *BrotliEncoder, op: Operation, data: []const u8) CompressionResult { - var available_in = data.len; - var next_in: ?[*]const u8 = data.ptr; - - var available_out: usize = 0; - - var result = CompressionResult{}; - - result.success = BrotliEncoderCompressStream(state, op, &available_in, &next_in, &available_out, null, null) > 0; - - if (result.success) { - result.output = takeOutput(state); - } - - result.has_more = BrotliEncoderHasMoreOutput(state) > 0; - - return result; - } - - pub fn setParameter(state: *BrotliEncoder, param: BrotliEncoderParameter, value: u32) bool { - return BrotliEncoderSetParameter(state, @intFromEnum(param), value) > 0; - } -}; - -pub const SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH = 4; -pub const SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH = 31; -pub const SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS = 64; -pub const SHARED_BROTLI_MAX_COMPOUND_DICTS = 15; -pub const BROTLI_MIN_WINDOW_BITS = 10; -pub const BROTLI_MAX_WINDOW_BITS = 24; -pub const BROTLI_LARGE_MAX_WINDOW_BITS = 30; -pub const BROTLI_MIN_INPUT_BLOCK_BITS = 16; -pub const BROTLI_MAX_INPUT_BLOCK_BITS = 24; -pub const BROTLI_MIN_QUALITY = 0; -pub const BROTLI_MAX_QUALITY = 11; -pub const BROTLI_DEFAULT_QUALITY = 11; -pub const BROTLI_DEFAULT_WINDOW = 22; -pub const BROTLI_DEFAULT_MODE = BROTLI_MODE_GENERIC; diff --git a/src/deps/libuv.zig b/src/deps/libuv.zig index 3149b3d45b..3906c6e536 100644 --- a/src/deps/libuv.zig +++ b/src/deps/libuv.zig @@ -384,7 +384,18 @@ pub const Handle = extern struct { endgame_next: ?*uv_handle_t = null, flags: c_uint, - pub usingnamespace HandleMixin(Handle); + const handle_impl = HandleMixin(@This()); + pub const getData = handle_impl.getData; + pub const getLoop = handle_impl.getLoop; + pub const setData = handle_impl.setData; + pub const close = handle_impl.close; + pub const hasRef = handle_impl.hasRef; + pub const ref = handle_impl.ref; + pub const unref = handle_impl.unref; + pub const isClosing = handle_impl.isClosing; + pub const isClosed = handle_impl.isClosed; + pub const isActive = handle_impl.isActive; + pub const fd = handle_impl.fd; pub const Type = enum(c_uint) { unknown = 0, @@ -574,7 +585,18 @@ pub const struct_uv_async_s = extern struct { async_cb: uv_async_cb, async_sent: u8, - pub usingnamespace HandleMixin(@This()); + const handle_impl = HandleMixin(@This()); + pub const getData = handle_impl.getData; + pub const getLoop = handle_impl.getLoop; + pub const setData = handle_impl.setData; + pub const close = handle_impl.close; + pub const hasRef = handle_impl.hasRef; + pub const ref = handle_impl.ref; + pub const unref = handle_impl.unref; + pub const isClosing = handle_impl.isClosing; + pub const isClosed = handle_impl.isClosed; + pub const isActive = handle_impl.isActive; + pub const fd = handle_impl.fd; pub fn init(this: *@This(), loop: *Loop, callback: uv_async_cb) void { @memset(std.mem.asBytes(this), 0); @@ -1019,7 +1041,29 @@ pub const struct_uv_stream_s = extern struct { read_req: uv_read_t, stream: union_unnamed_384, - pub usingnamespace StreamMixin(@This()); + const handle_impl = HandleMixin(@This()); + pub const getData = handle_impl.getData; + pub const getLoop = handle_impl.getLoop; + pub const setData = handle_impl.setData; + pub const close = handle_impl.close; + pub const hasRef = handle_impl.hasRef; + pub const ref = handle_impl.ref; + pub const unref = handle_impl.unref; + pub const isClosing = handle_impl.isClosing; + pub const isClosed = handle_impl.isClosed; + pub const isActive = handle_impl.isActive; + pub const fd = handle_impl.fd; + const stream_impl = StreamMixin(@This()); + pub const getWriteQueueSize = stream_impl.getWriteQueueSize; + pub const listen = stream_impl.listen; + pub const accept = stream_impl.accept; + pub const readStart = stream_impl.readStart; + pub const readStop = stream_impl.readStop; + pub const write = stream_impl.write; + pub const tryWrite = stream_impl.tryWrite; + pub const tryWrite2 = stream_impl.tryWrite2; + pub const isReadable = stream_impl.isReadable; + pub const isWritable = stream_impl.isWritable; }; const union_unnamed_390 = extern union { fd: c_int, @@ -1315,7 +1359,29 @@ pub const Pipe = extern struct { name: [*]WCHAR, pipe: union_unnamed_405, - pub usingnamespace StreamMixin(@This()); + const handle_impl = HandleMixin(@This()); + pub const getData = handle_impl.getData; + pub const getLoop = handle_impl.getLoop; + pub const setData = handle_impl.setData; + pub const close = handle_impl.close; + pub const hasRef = handle_impl.hasRef; + pub const ref = handle_impl.ref; + pub const unref = handle_impl.unref; + pub const isClosing = handle_impl.isClosing; + pub const isClosed = handle_impl.isClosed; + pub const isActive = handle_impl.isActive; + pub const fd = handle_impl.fd; + const stream_impl = StreamMixin(@This()); + pub const getWriteQueueSize = stream_impl.getWriteQueueSize; + pub const listen = stream_impl.listen; + pub const accept = stream_impl.accept; + pub const readStart = stream_impl.readStart; + pub const readStop = stream_impl.readStop; + pub const write = stream_impl.write; + pub const tryWrite = stream_impl.tryWrite; + pub const tryWrite2 = stream_impl.tryWrite2; + pub const isReadable = stream_impl.isReadable; + pub const isWritable = stream_impl.isWritable; pub fn init(this: *Pipe, loop: *Loop, ipc: bool) Maybe(void) { if (uv_pipe_init(loop, this, if (ipc) 1 else 0).toError(.pipe)) |err| return .{ .err = err }; @@ -1419,9 +1485,9 @@ pub const struct_uv_tty_s = extern struct { handle: HANDLE, tty: union_unnamed_420, - pub fn init(this: *uv_tty_t, loop: *uv_loop_t, fd: uv_file) Maybe(void) { + pub fn init(this: *uv_tty_t, loop: *uv_loop_t, file: uv_file) Maybe(void) { // last param is ignored - return if (uv_tty_init(loop, this, fd, 0).toError(.open)) |err| + return if (uv_tty_init(loop, this, file, 0).toError(.open)) |err| .{ .err = err } else .{ .result = {} }; @@ -1437,7 +1503,29 @@ pub const struct_uv_tty_s = extern struct { return uv_tty_set_mode(this, @intFromEnum(mode)); } - pub usingnamespace StreamMixin(@This()); + const handle_impl = HandleMixin(@This()); + pub const getData = handle_impl.getData; + pub const getLoop = handle_impl.getLoop; + pub const setData = handle_impl.setData; + pub const close = handle_impl.close; + pub const hasRef = handle_impl.hasRef; + pub const ref = handle_impl.ref; + pub const unref = handle_impl.unref; + pub const isClosing = handle_impl.isClosing; + pub const isClosed = handle_impl.isClosed; + pub const isActive = handle_impl.isActive; + pub const fd = handle_impl.fd; + const stream_impl = StreamMixin(@This()); + pub const getWriteQueueSize = stream_impl.getWriteQueueSize; + pub const listen = stream_impl.listen; + pub const accept = stream_impl.accept; + pub const readStart = stream_impl.readStart; + pub const readStop = stream_impl.readStop; + pub const write = stream_impl.write; + pub const tryWrite = stream_impl.tryWrite; + pub const tryWrite2 = stream_impl.tryWrite2; + pub const isReadable = stream_impl.isReadable; + pub const isWritable = stream_impl.isWritable; }; pub const uv_tty_t = struct_uv_tty_s; const union_unnamed_423 = extern union { @@ -1468,7 +1556,18 @@ pub const struct_uv_poll_s = extern struct { mask_events_2: u8, events: u8, - pub usingnamespace HandleMixin(@This()); + const handle_impl = HandleMixin(@This()); + pub const getData = handle_impl.getData; + pub const getLoop = handle_impl.getLoop; + pub const setData = handle_impl.setData; + pub const close = handle_impl.close; + pub const hasRef = handle_impl.hasRef; + pub const ref = handle_impl.ref; + pub const unref = handle_impl.unref; + pub const isClosing = handle_impl.isClosing; + pub const isClosed = handle_impl.isClosed; + pub const isActive = handle_impl.isActive; + pub const fd = handle_impl.fd; }; pub const Poll = struct_uv_poll_s; const union_unnamed_424 = extern union { @@ -1520,7 +1619,18 @@ pub const Process = extern struct { return uv_spawn(loop, handle, options); } - pub usingnamespace HandleMixin(@This()); + const handle_impl = HandleMixin(@This()); + pub const getData = handle_impl.getData; + pub const getLoop = handle_impl.getLoop; + pub const setData = handle_impl.setData; + pub const close = handle_impl.close; + pub const hasRef = handle_impl.hasRef; + pub const ref = handle_impl.ref; + pub const unref = handle_impl.unref; + pub const isClosing = handle_impl.isClosing; + pub const isClosed = handle_impl.isClosed; + pub const isActive = handle_impl.isActive; + pub const fd = handle_impl.fd; pub fn kill(this: *@This(), signum: c_int) ReturnCode { return uv_process_kill(@alignCast(@ptrCast(this)), signum); @@ -1805,7 +1915,13 @@ pub const fs_t = extern struct { sys_errno_: DWORD, file: union_unnamed_450, fs: union_unnamed_451, - pub usingnamespace ReqMixin(@This()); + + const req_impl = ReqMixin(@This()); + pub const setData = req_impl.setData; + pub const getLoop = req_impl.loop; + pub const getData = req_impl.getData; + pub const cancel = req_impl.cancel; + const UV_FS_CLEANEDUP = 0x0010; pub inline fn deinit(this: *fs_t) void { @@ -1881,7 +1997,11 @@ pub const struct_uv_work_s = extern struct { after_work_cb: uv_after_work_cb, work_req: struct_uv__work, - pub usingnamespace ReqMixin(@This()); + const req_impl = ReqMixin(@This()); + pub const setData = req_impl.setData; + pub const getLoop = req_impl.loop; + pub const getData = req_impl.getData; + pub const cancel = req_impl.cancel; }; const struct_unnamed_458 = extern struct { overlapped: OVERLAPPED, @@ -1912,7 +2032,11 @@ pub const struct_uv_random_s = extern struct { cb: uv_random_cb, work_req: struct_uv__work, - pub usingnamespace ReqMixin(@This()); + const req_impl = ReqMixin(@This()); + pub const setData = req_impl.setData; + pub const getLoop = req_impl.loop; + pub const getData = req_impl.getData; + pub const cancel = req_impl.cancel; }; pub const struct_uv_env_item_s = extern struct { name: [*]u8, @@ -2841,8 +2965,6 @@ pub const addrinfo = std.os.windows.ws2_32.addrinfo; // https://docs.libuv.org/en/v1.x/stream.html fn StreamMixin(comptime Type: type) type { return struct { - pub usingnamespace HandleMixin(Type); - pub fn getWriteQueueSize(this: *Type) usize { return uv_stream_get_write_queue_size(@ptrCast(this)); } diff --git a/src/deps/picohttp.zig b/src/deps/picohttp.zig index dc0b6ce904..f9d5b2761d 100644 --- a/src/deps/picohttp.zig +++ b/src/deps/picohttp.zig @@ -370,4 +370,12 @@ pub const Headers = struct { } }; -pub usingnamespace c; +pub const phr_header = c.phr_header; +pub const phr_chunked_decoder = c.phr_chunked_decoder; +pub const struct_phr_header = c.struct_phr_header; +pub const struct_phr_chunked_decoder = c.struct_phr_chunked_decoder; +pub const phr_parse_request = c.phr_parse_request; +pub const phr_parse_response = c.phr_parse_response; +pub const phr_parse_headers = c.phr_parse_headers; +pub const phr_decode_chunked = c.phr_decode_chunked; +pub const phr_decode_chunked_is_in_data = c.phr_decode_chunked_is_in_data; diff --git a/src/deps/picohttpparser.zig b/src/deps/picohttpparser.zig index 185ed822e5..db7aefd9b3 100644 --- a/src/deps/picohttpparser.zig +++ b/src/deps/picohttpparser.zig @@ -1,5 +1,4 @@ -pub usingnamespace @import("std").zig.c_builtins; - +// TODO: use translate-c for this pub const struct_phr_header = extern struct { name: [*c]const u8, name_len: usize, diff --git a/src/deps/uws.zig b/src/deps/uws.zig index 63c2a9ac7e..a8a2d0f2f7 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -231,7 +231,7 @@ pub const UpgradedDuplex = struct { this.onInternalReceiveData(payload); } else { // node.js errors in this case with the same error, lets keep it consistent - const error_value = globalObject.ERR_STREAM_WRAP("Stream has StringDecoder set or is in objectMode", .{}).toJS(); + const error_value = globalObject.ERR(.STREAM_WRAP, "Stream has StringDecoder set or is in objectMode", .{}).toJS(); error_value.ensureStillAlive(); this.handlers.onError(this.handlers.ctx, error_value); } @@ -558,7 +558,12 @@ pub const WindowsNamedPipe = if (Environment.isWindows) struct { pipe: if (Environment.isWindows) ?*uv.Pipe else void, // any duplex vm: *bun.JSC.VirtualMachine, //TODO: create a timeout version that dont need the JSC VM - writer: bun.io.StreamingWriter(WindowsNamedPipe, onWrite, onError, onWritable, onPipeClose) = .{}, + writer: bun.io.StreamingWriter(@This(), .{ + .onClose = onClose, + .onWritable = onWritable, + .onError = onError, + .onWrite = onWrite, + }) = .{}, incoming: bun.ByteList = .{}, // Maybe we should use IPCBuffer here as well ssl_error: CertError = .{}, @@ -2523,9 +2528,9 @@ pub const create_bun_socket_error_t = enum(c_int) { bun.debugAssert(false); break :brk .null; }, - .load_ca_file => globalObject.ERR_BORINGSSL("Failed to load CA file", .{}).toJS(), - .invalid_ca_file => globalObject.ERR_BORINGSSL("Invalid CA file", .{}).toJS(), - .invalid_ca => globalObject.ERR_BORINGSSL("Invalid CA", .{}).toJS(), + .load_ca_file => globalObject.ERR(.BORINGSSL, "Failed to load CA file", .{}).toJS(), + .invalid_ca_file => globalObject.ERR(.BORINGSSL, "Invalid CA file", .{}).toJS(), + .invalid_ca => globalObject.ERR(.BORINGSSL, "Invalid CA", .{}).toJS(), }; } }; diff --git a/src/env.zig b/src/env.zig index f6fa1d55c1..6387a76ec1 100644 --- a/src/env.zig +++ b/src/env.zig @@ -34,9 +34,13 @@ pub const export_cpp_apis = @import("builtin").output_mode == .Obj or isTest; pub const build_options = @import("build_options"); +/// Set if compiling with `-Dno_llvm` +/// All places this is used is working around a Zig bug. +pub const zig_self_hosted_backend = build_options.zig_self_hosted_backend; + pub const reported_nodejs_version = build_options.reported_nodejs_version; pub const baseline = build_options.baseline; -pub const enableSIMD: bool = !baseline; +pub const enableSIMD: bool = !baseline and !zig_self_hosted_backend; pub const git_sha = build_options.sha; pub const git_sha_short = if (build_options.sha.len > 0) build_options.sha[0..9] else ""; pub const git_sha_shorter = if (build_options.sha.len > 0) build_options.sha[0..6] else ""; diff --git a/src/fd.zig b/src/fd.zig index cf40557487..c0b1be3f5e 100644 --- a/src/fd.zig +++ b/src/fd.zig @@ -1,4 +1,8 @@ -const backing_int = if (is_posix) c_int else u64; +/// Remove once https://github.com/ziglang/zig/pull/23341/files merges +/// This does not affect Bun's CI which runs release builds only (and uses Arm macs which do not crash) +const workaround_linux = is_posix and @import("builtin").mode == .Debug and !@import("builtin").cpu.arch.isAARCH64(); + +const backing_int = if (is_posix and !workaround_linux) c_int else u64; const WindowsHandleNumber = u63; const HandleNumber = if (is_posix) c_int else WindowsHandleNumber; /// Abstraction over file descriptors. On POSIX, fd is a wrapper around a "fd_t", @@ -21,7 +25,7 @@ pub const FD = packed struct(backing_int) { value: Value, kind: Kind, pub const Kind = if (is_posix) - enum(u0) { system } + enum(if (workaround_linux) u32 else u0) { system } else enum(u1) { system = 0, uv = 1 }; pub const Value = if (is_posix) @@ -266,7 +270,7 @@ pub const FD = packed struct(backing_int) { null; }, .windows => |handle| result: { - break :result switch (bun.windows.NtClose(handle)) { + break :result switch (bun.c.NtClose(handle)) { .SUCCESS => null, else => |rc| bun.sys.Error{ .errno = if (bun.windows.Win32Error.fromNTStatus(rc).toSystemErrno()) |errno| @intFromEnum(errno) else 1, @@ -395,7 +399,7 @@ pub const FD = packed struct(backing_int) { pub fn hash(_: @This(), fd: FD) u64 { // a file descriptor is i32 on linux, u64 on windows // the goal here is to do zero work and widen the 32 bit type to 64 - return @as(if (os == .windows) u64 else u32, @bitCast(fd)); + return @as(if (backing_int == u64) u64 else u32, @bitCast(fd)); } pub fn eql(_: @This(), a: FD, b: FD) bool { diff --git a/src/install/bin.zig b/src/install/bin.zig index 97a5315379..27fa700999 100644 --- a/src/install/bin.zig +++ b/src/install/bin.zig @@ -640,7 +640,7 @@ pub const Bin = extern struct { if (comptime !Environment.isWindows) this.createSymlink(abs_target, abs_dest, global) else { - const target = bun.sys.openat(bun.invalid_fd, abs_target, bun.O.RDONLY, 0).unwrap() catch |err| { + const target = bun.sys.openat(.cwd(), abs_target, bun.O.RDONLY, 0).unwrap() catch |err| { if (err != error.EISDIR) { // ignore directories, creating a shim for one won't do anything this.err = err; @@ -659,7 +659,7 @@ pub const Bin = extern struct { if (comptime !Environment.isWindows) { // any error here is ignored - const bin = bun.sys.File.openat(bun.invalid_fd, abs_target, bun.O.RDWR, 0o664).unwrap() catch return; + const bin = bun.sys.File.openat(.cwd(), abs_target, bun.O.RDWR, 0o664).unwrap() catch return; defer bin.close(); var shebang_buf: [1024]u8 = undefined; diff --git a/src/install/install.zig b/src/install/install.zig index d410ca96ff..8b0e7940d6 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -8962,7 +8962,7 @@ pub const PackageManager = struct { } if (env.get("BUN_FEATURE_FLAG_FORCE_WAITER_THREAD") != null) { - bun.spawn.WaiterThread.setShouldUseWaiterThread(); + bun.spawn.process.WaiterThread.setShouldUseWaiterThread(); } if (PackageManager.verbose_install) { @@ -11189,7 +11189,7 @@ pub const PackageManager = struct { // Now that we've run the install step // We can save our in-memory package.json to disk const workspace_package_json_file = (try bun.sys.File.openat( - bun.invalid_fd, + .cwd(), path, bun.O.RDWR, 0, diff --git a/src/io/PipeWriter.zig b/src/io/PipeWriter.zig index 57f6555963..e3ac5ec5ca 100644 --- a/src/io/PipeWriter.zig +++ b/src/io/PipeWriter.zig @@ -31,18 +31,17 @@ pub fn PosixPipeWriter( comptime onWrite: fn (*This, written: usize, status: WriteStatus) void, comptime registerPoll: ?fn (*This) void, comptime onError: fn (*This, bun.sys.Error) void, - comptime onWritable: fn (*This) void, + comptime _: fn (*This) void, comptime getFileType: *const fn (*This) FileType, ) type { - _ = onWritable; // autofix return struct { - pub fn _tryWrite(this: *This, force_sync: bool, buf_: []const u8) WriteResult { + fn tryWrite(this: *This, force_sync: bool, buf_: []const u8) WriteResult { return switch (if (!force_sync) getFileType(this) else .file) { - inline else => |ft| return _tryWriteWithWriteFn(this, buf_, comptime writeToFileType(ft)), + inline else => |ft| return tryWriteWithWriteFn(this, buf_, comptime writeToFileType(ft)), }; } - fn _tryWriteWithWriteFn(this: *This, buf: []const u8, comptime write_fn: *const fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) WriteResult { + fn tryWriteWithWriteFn(this: *This, buf: []const u8, comptime write_fn: *const fn (bun.FileDescriptor, []const u8) JSC.Maybe(usize)) WriteResult { const fd = getFd(this); var offset: usize = 0; @@ -147,7 +146,7 @@ pub fn PosixPipeWriter( var drained: usize = 0; while (drained < trimmed.len) { - const attempt = _tryWrite(parent, parent.getForceSync(), trimmed[drained..]); + const attempt = tryWrite(parent, parent.getForceSync(), trimmed[drained..]); switch (attempt) { .pending => |pending| { drained += pending; @@ -178,15 +177,18 @@ pub fn PosixPipeWriter( const PollOrFd = @import("./pipes.zig").PollOrFd; -pub fn PosixBufferedWriter( - comptime Parent: type, - comptime onWrite: *const fn (*Parent, amount: usize, status: WriteStatus) void, - comptime onError: *const fn (*Parent, bun.sys.Error) void, - comptime onClose: ?*const fn (*Parent) void, - comptime getBuffer: *const fn (*Parent) []const u8, - comptime onWritable: ?*const fn (*Parent) void, -) type { +/// See below for the expected signature of `function_table`. In many cases, the +/// function table can be the same as `Parent`. `anytype` is used because of a +/// dependency loop in Zig. +pub fn PosixBufferedWriter(Parent: type, function_table: anytype) type { return struct { + const PosixWriter = @This(); + const onWrite: *const fn (*Parent, amount: usize, status: WriteStatus) void = function_table.onWrite; + const onError: *const fn (*Parent, bun.sys.Error) void = function_table.onError; + const onClose: ?*const fn (*Parent) void = function_table.onClose; + const getBuffer: *const fn (*Parent) []const u8 = function_table.getBuffer; + const onWritable: ?*const fn (*Parent) void = function_table.onWritable; + handle: PollOrFd = .{ .closed = {} }, parent: *Parent = undefined, is_done: bool = false, @@ -194,12 +196,14 @@ pub fn PosixBufferedWriter( closed_without_reporting: bool = false, close_fd: bool = true, + const internals = PosixPipeWriter(@This(), getFd, getBufferInternal, _onWrite, registerPoll, _onError, _onWritable, getFileType); + pub const onPoll = internals.onPoll; + pub const drainBufferedData = internals.drainBufferedData; + pub fn memoryCost(_: *const @This()) usize { return @sizeOf(@This()); } - const PosixWriter = @This(); - pub const auto_poll = if (@hasDecl(Parent, "auto_poll")) Parent.auto_poll else true; pub fn createPoll(this: *@This(), fd: bun.FileDescriptor) *Async.FilePoll { @@ -294,8 +298,6 @@ pub fn PosixBufferedWriter( return getBuffer(this.parent); } - pub usingnamespace PosixPipeWriter(@This(), getFd, getBufferInternal, _onWrite, registerPoll, _onError, _onWritable, getFileType); - pub fn end(this: *PosixWriter) void { if (this.is_done) { return; @@ -375,22 +377,27 @@ pub fn PosixBufferedWriter( }; } -pub fn PosixStreamingWriter( - comptime Parent: type, - comptime onWrite: fn (*Parent, amount: usize, status: WriteStatus) void, - comptime onError: fn (*Parent, bun.sys.Error) void, - comptime onReady: ?fn (*Parent) void, - comptime onClose: fn (*Parent) void, -) type { +/// See below for the expected signature of `function_table`. In many cases, the +/// function table can be the same as `Parent`. `anytype` is used because of a +/// dependency loop in Zig. +pub fn PosixStreamingWriter(comptime Parent: type, comptime function_table: anytype) type { return struct { + const onWrite: fn (*Parent, amount: usize, status: WriteStatus) void = function_table.onWrite; + const onError: fn (*Parent, bun.sys.Error) void = function_table.onError; + const onReady: ?fn (*Parent) void = function_table.onReady; + const onClose: fn (*Parent) void = function_table.onClose; + outgoing: StreamBuffer = .{}, handle: PollOrFd = .{ .closed = {} }, parent: *Parent = undefined, is_done: bool = false, closed_without_reporting: bool = false, - force_sync: bool = false, + const internals = PosixPipeWriter(@This(), getFd, getBuffer, _onWrite, registerPoll, _onError, _onWritable, getFileType); + pub const onPoll = internals.onPoll; + pub const drainBufferedData = internals.drainBufferedData; + pub fn getForceSync(this: *const @This()) bool { return this.force_sync; } @@ -463,7 +470,7 @@ pub fn PosixStreamingWriter( this.outgoing.list.clearRetainingCapacity(); } - onWrite(@ptrCast(this.parent), written, status); + onWrite(this.parent, written, status); } pub fn setParent(this: *PosixWriter, parent: *Parent) void { @@ -493,7 +500,7 @@ pub fn PosixStreamingWriter( fn registerPoll(this: *PosixWriter) void { const poll = this.getPoll() orelse return; - switch (poll.registerWithFd(@as(*Parent, @ptrCast(this.parent)).loop(), .writable, .dispatch, poll.fd)) { + switch (poll.registerWithFd(this.parent.loop(), .writable, .dispatch, poll.fd)) { .err => |err| { onError(this.parent, err); this.close(); @@ -515,7 +522,7 @@ pub fn PosixStreamingWriter( const buf_len = this.outgoing.size() - before_len; - return this._maybeWriteNewlyBufferedData(buf_len); + return this.maybeWriteNewlyBufferedData(buf_len); } pub fn writeLatin1(this: *PosixWriter, buf: []const u8) WriteResult { @@ -536,10 +543,10 @@ pub fn PosixStreamingWriter( const buf_len = this.outgoing.size() - before_len; - return this._maybeWriteNewlyBufferedData(buf_len); + return this.maybeWriteNewlyBufferedData(buf_len); } - fn _maybeWriteNewlyBufferedData(this: *PosixWriter, buf_len: usize) WriteResult { + fn maybeWriteNewlyBufferedData(this: *PosixWriter, buf_len: usize) WriteResult { bun.assert(!this.is_done); if (this.shouldBuffer(0)) { @@ -549,13 +556,13 @@ pub fn PosixStreamingWriter( return .{ .wrote = buf_len }; } - return @This()._tryWriteNewlyBufferedData(this, this.outgoing.slice()); + return this.tryWriteNewlyBufferedData(this.outgoing.slice()); } - fn _tryWriteNewlyBufferedData(this: *PosixWriter, buf: []const u8) WriteResult { + fn tryWriteNewlyBufferedData(this: *PosixWriter, buf: []const u8) WriteResult { bun.assert(!this.is_done); - const rc = @This()._tryWrite(this, this.force_sync, buf); + const rc = internals.tryWrite(this, this.force_sync, buf); switch (rc) { .wrote => |amt| { @@ -614,10 +621,10 @@ pub fn PosixStreamingWriter( return .{ .err = bun.sys.Error.oom }; }; - return this._tryWriteNewlyBufferedData(this.outgoing.slice()); + return this.tryWriteNewlyBufferedData(this.outgoing.slice()); } - const rc = @This()._tryWrite(this, this.force_sync, buf); + const rc = internals.tryWrite(this, this.force_sync, buf); switch (rc) { .pending => |amt| { @@ -650,8 +657,6 @@ pub fn PosixStreamingWriter( return rc; } - pub usingnamespace PosixPipeWriter(@This(), getFd, getBuffer, _onWrite, registerPoll, _onError, _onWritable, getFileType); - pub fn flush(this: *PosixWriter) WriteResult { if (this.closed_without_reporting or this.is_done) { return .{ .done = 0 }; @@ -734,11 +739,11 @@ pub fn PosixStreamingWriter( if (this.closed_without_reporting) { this.closed_without_reporting = false; bun.assert(this.getFd() == bun.invalid_fd); - onClose(@ptrCast(this.parent)); + onClose(this.parent); return; } - this.handle.close(@ptrCast(this.parent), onClose); + this.handle.close(this.parent, onClose); } pub fn start(this: *PosixWriter, fd: bun.FileDescriptor, is_pollable: bool) JSC.Maybe(void) { @@ -748,7 +753,7 @@ pub fn PosixStreamingWriter( return JSC.Maybe(void){ .result = {} }; } - const loop = @as(*Parent, @ptrCast(this.parent)).eventLoop(); + const loop = this.parent.eventLoop(); var poll = this.getPoll() orelse brk: { this.handle = .{ .poll = Async.FilePoll.init(loop, fd, .{}, PosixWriter, this) }; break :brk this.handle.poll; @@ -919,14 +924,10 @@ fn BaseWindowsPipeWriter( }; } -pub fn WindowsBufferedWriter( - comptime Parent: type, - comptime onWrite: *const fn (*Parent, amount: usize, status: WriteStatus) void, - comptime onError: *const fn (*Parent, bun.sys.Error) void, - comptime onClose: ?*const fn (*Parent) void, - comptime getBuffer: *const fn (*Parent) []const u8, - comptime onWritable: ?*const fn (*Parent) void, -) type { +/// See below for the expected signature of `function_table`. In many cases, the +/// function table can be the same as `Parent`. `anytype` is used because of a +/// dependency loop in Zig. +pub fn WindowsBufferedWriter(Parent: type, function_table: anytype) type { return struct { source: ?Source = null, owns_fd: bool = true, @@ -937,9 +938,29 @@ pub fn WindowsBufferedWriter( write_buffer: uv.uv_buf_t = uv.uv_buf_t.init(""), pending_payload_size: usize = 0, + const onWrite: *const fn (*Parent, amount: usize, status: WriteStatus) void = function_table.onWrite; + const onError: *const fn (*Parent, bun.sys.Error) void = function_table.onError; + const onClose: ?*const fn (*Parent) void = function_table.onClose; + const getBuffer: *const fn (*Parent) []const u8 = function_table.getBuffer; + const onWritable: ?*const fn (*Parent) void = function_table.onWritable; + const WindowsWriter = @This(); - pub usingnamespace BaseWindowsPipeWriter(WindowsWriter, Parent); + const internals = BaseWindowsPipeWriter(WindowsWriter, Parent); + pub const getFd = internals.getFd; + pub const hasRef = internals.hasRef; + pub const enableKeepingProcessAlive = internals.enableKeepingProcessAlive; + pub const disableKeepingProcessAlive = internals.disableKeepingProcessAlive; + pub const close = internals.close; + pub const updateRef = internals.updateRef; + pub const setParent = internals.setParent; + pub const watch = internals.watch; + pub const startWithPipe = internals.startWithPipe; + pub const startSync = internals.startSync; + pub const startWithFile = internals.startWithFile; + pub const start = internals.start; + pub const setPipe = internals.setPipe; + pub const getStream = internals.getStream; fn onCloseSource(this: *WindowsWriter) void { if (onClose) |onCloseFn| { @@ -1179,15 +1200,18 @@ pub const StreamBuffer = struct { } }; -pub fn WindowsStreamingWriter( - comptime Parent: type, - /// reports the amount written and done means that we dont have any other pending data to send (but we may send more data) - comptime onWrite: fn (*Parent, amount: usize, status: WriteStatus) void, - comptime onError: fn (*Parent, bun.sys.Error) void, - comptime onWritable: ?fn (*Parent) void, - comptime onClose: fn (*Parent) void, -) type { +/// See below for the expected signature of `function_table`. In many cases, the +/// function table can be the same as `Parent`. `anytype` is used because of a +/// dependency loop in Zig. +pub fn WindowsStreamingWriter(comptime Parent: type, function_table: anytype) type { return struct { + /// reports the amount written and done means that we dont have any + /// other pending data to send (but we may send more data) + const onWrite: fn (*Parent, amount: usize, status: WriteStatus) void = function_table.onWrite; + const onError: fn (*Parent, bun.sys.Error) void = function_table.onError; + const onWritable: ?fn (*Parent) void = function_table.onWritable; + const onClose: fn (*Parent) void = function_table.onClose; + source: ?Source = null, /// if the source of this writer is a file descriptor, calling end() will not close it. /// if it is a path, then we claim ownership and the backing fd will be closed by end(). @@ -1207,7 +1231,21 @@ pub fn WindowsStreamingWriter( // some error happed? we will not report onClose only onError closed_without_reporting: bool = false, - pub usingnamespace BaseWindowsPipeWriter(WindowsWriter, Parent); + const internals = BaseWindowsPipeWriter(WindowsWriter, Parent); + pub const getFd = internals.getFd; + pub const hasRef = internals.hasRef; + pub const enableKeepingProcessAlive = internals.enableKeepingProcessAlive; + pub const disableKeepingProcessAlive = internals.disableKeepingProcessAlive; + pub const close = internals.close; + pub const updateRef = internals.updateRef; + pub const setParent = internals.setParent; + pub const watch = internals.watch; + pub const startWithPipe = internals.startWithPipe; + pub const startSync = internals.startSync; + pub const startWithFile = internals.startWithFile; + pub const start = internals.start; + pub const setPipe = internals.setPipe; + pub const getStream = internals.getStream; pub fn memoryCost(this: *const WindowsWriter) usize { return @sizeOf(@This()) + this.current_payload.memoryCost() + this.outgoing.memoryCost(); diff --git a/src/jsc.zig b/src/jsc.zig index 59477eaafd..0ce27f5860 100644 --- a/src/jsc.zig +++ b/src/jsc.zig @@ -1,4 +1,8 @@ -// Top-level so it can access all files +//! The `bun.JSC` namespace contains +//! 1. bindings for JavaScriptCore APIs (bun.JSC.*) +//! 2. zig components for Bun APIs (in bun.JSC.API or bun.JSC.*) +//! 3. zig components for Node APIs (in bun.JSC.Node) +//! 4. zig components for Web APIs (in bun.JSC.WebCore) pub usingnamespace @import("./bun.js/base.zig"); pub usingnamespace @import("./bun.js/bindings/bindings.zig"); pub usingnamespace @import("./bun.js/bindings/exports.zig"); @@ -73,6 +77,10 @@ pub const Node = struct { pub const Crypto = @import("./bun.js/node/node_crypto_binding.zig"); }; +pub const js_property_iterator = @import("bun.js/bindings/JSPropertyIterator.zig"); +pub const JSPropertyIterator = js_property_iterator.JSPropertyIterator; +pub const JSPropertyIteratorOptions = js_property_iterator.JSPropertyIteratorOptions; + const std = @import("std"); const Syscall = @import("./sys.zig"); const Output = @import("./output.zig"); diff --git a/src/main.zig b/src/main.zig index 93d75179f3..74813f5533 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -pub const bun = @import("bun"); +const bun = @import("bun"); const Output = bun.Output; const Environment = bun.Environment; diff --git a/src/output.zig b/src/output.zig index 9a4d4acba3..40151ee6be 100644 --- a/src/output.zig +++ b/src/output.zig @@ -10,6 +10,7 @@ const ComptimeStringMap = bun.ComptimeStringMap; const use_mimalloc = bun.use_mimalloc; const writeStream = std.json.writeStream; const WriteStream = std.json.WriteStream; +const c = bun.c; const SystemTimer = @import("./system_timer.zig").Timer; @@ -170,15 +171,15 @@ pub const Source = struct { const handles = &.{ &stdin, &stdout, &stderr }; inline for (console_mode, handles) |mode, handle| { if (mode) |m| { - _ = w.SetConsoleMode(handle.*, m); + _ = c.SetConsoleMode(handle.*, m); } } if (console_output_codepage != 0) - _ = w.kernel32.SetConsoleOutputCP(console_output_codepage); + _ = c.SetConsoleOutputCP(console_output_codepage); if (console_codepage != 0) - _ = w.SetConsoleCP(console_codepage); + _ = c.SetConsoleCP(console_codepage); } pub fn init() void { @@ -199,14 +200,14 @@ pub const Source = struct { // https://learn.microsoft.com/en-us/windows/console/setconsoleoutputcp const CP_UTF8 = 65001; - console_output_codepage = w.kernel32.GetConsoleOutputCP(); - _ = w.kernel32.SetConsoleOutputCP(CP_UTF8); + console_output_codepage = c.GetConsoleOutputCP(); + _ = c.SetConsoleOutputCP(CP_UTF8); - console_codepage = w.kernel32.GetConsoleOutputCP(); - _ = w.SetConsoleCP(CP_UTF8); + console_codepage = c.GetConsoleOutputCP(); + _ = c.SetConsoleCP(CP_UTF8); var mode: w.DWORD = undefined; - if (w.kernel32.GetConsoleMode(stdin, &mode) != 0) { + if (c.GetConsoleMode(stdin, &mode) != 0) { console_mode[0] = mode; bun_stdio_tty[0] = 1; // There are no flags to set on standard in, but just in case something @@ -216,16 +217,16 @@ pub const Source = struct { // intentionally set for any purpose, and instead only caused problems. } - if (w.kernel32.GetConsoleMode(stdout, &mode) != 0) { + if (c.GetConsoleMode(stdout, &mode) != 0) { console_mode[1] = mode; bun_stdio_tty[1] = 1; - _ = w.SetConsoleMode(stdout, w.ENABLE_PROCESSED_OUTPUT | std.os.windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | w.ENABLE_WRAP_AT_EOL_OUTPUT | mode); + _ = c.SetConsoleMode(stdout, w.ENABLE_PROCESSED_OUTPUT | std.os.windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | w.ENABLE_WRAP_AT_EOL_OUTPUT | mode); } - if (w.kernel32.GetConsoleMode(stderr, &mode) != 0) { + if (c.GetConsoleMode(stderr, &mode) != 0) { console_mode[2] = mode; bun_stdio_tty[2] = 1; - _ = w.SetConsoleMode(stderr, w.ENABLE_PROCESSED_OUTPUT | std.os.windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | w.ENABLE_WRAP_AT_EOL_OUTPUT | mode); + _ = c.SetConsoleMode(stderr, w.ENABLE_PROCESSED_OUTPUT | std.os.windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | w.ENABLE_WRAP_AT_EOL_OUTPUT | mode); } } }; @@ -881,8 +882,7 @@ pub fn prettyFmt(comptime fmt: string, comptime is_enabled: bool) [:0]const u8 { @setEvalBranchQuota(9999); comptime var i: usize = 0; comptime while (i < fmt.len) { - const c = fmt[i]; - switch (c) { + switch (fmt[i]) { '\\' => { i += 1; if (i < fmt.len) { diff --git a/src/ptr/ref_count.zig b/src/ptr/ref_count.zig index a1bc5d96a5..81672bb78f 100644 --- a/src/ptr/ref_count.zig +++ b/src/ptr/ref_count.zig @@ -63,8 +63,9 @@ pub const RefCountOptions = struct { /// /// const ref_ptr = RefPtr(T).initRef(existing_raw_pointer); /// -pub fn RefCount(T: type, field_name: []const u8, destructor: fn (*T) void, options: RefCountOptions) type { +pub fn RefCount(T: type, field_name: []const u8, destructor_untyped: anytype, options: RefCountOptions) type { return struct { + const destructor: fn (*T) void = destructor_untyped; active_counts: u32, thread: if (enable_single_threaded_checks) ?bun.DebugThreadLock else void, debug: if (enable_debug) DebugData(false) else void, diff --git a/src/s3/error.zig b/src/s3/error.zig index a9d9c4c6aa..519e19ccd3 100644 --- a/src/s3/error.zig +++ b/src/s3/error.zig @@ -16,22 +16,22 @@ pub fn getSignErrorMessage(comptime err: anyerror) [:0]const u8 { } pub fn getJSSignError(err: anyerror, globalThis: *JSC.JSGlobalObject) JSC.JSValue { return switch (err) { - error.MissingCredentials => return globalThis.ERR_S3_MISSING_CREDENTIALS(getSignErrorMessage(error.MissingCredentials), .{}).toJS(), - error.InvalidMethod => return globalThis.ERR_S3_INVALID_METHOD(getSignErrorMessage(error.InvalidMethod), .{}).toJS(), - error.InvalidPath => return globalThis.ERR_S3_INVALID_PATH(getSignErrorMessage(error.InvalidPath), .{}).toJS(), - error.InvalidEndpoint => return globalThis.ERR_S3_INVALID_ENDPOINT(getSignErrorMessage(error.InvalidEndpoint), .{}).toJS(), - error.InvalidSessionToken => return globalThis.ERR_S3_INVALID_SESSION_TOKEN(getSignErrorMessage(error.InvalidSessionToken), .{}).toJS(), - else => return globalThis.ERR_S3_INVALID_SIGNATURE(getSignErrorMessage(error.SignError), .{}).toJS(), + error.MissingCredentials => return globalThis.ERR(.S3_MISSING_CREDENTIALS, getSignErrorMessage(error.MissingCredentials), .{}).toJS(), + error.InvalidMethod => return globalThis.ERR(.S3_INVALID_METHOD, getSignErrorMessage(error.InvalidMethod), .{}).toJS(), + error.InvalidPath => return globalThis.ERR(.S3_INVALID_PATH, getSignErrorMessage(error.InvalidPath), .{}).toJS(), + error.InvalidEndpoint => return globalThis.ERR(.S3_INVALID_ENDPOINT, getSignErrorMessage(error.InvalidEndpoint), .{}).toJS(), + error.InvalidSessionToken => return globalThis.ERR(.S3_INVALID_SESSION_TOKEN, getSignErrorMessage(error.InvalidSessionToken), .{}).toJS(), + else => return globalThis.ERR(.S3_INVALID_SIGNATURE, getSignErrorMessage(error.SignError), .{}).toJS(), }; } pub fn throwSignError(err: anyerror, globalThis: *JSC.JSGlobalObject) bun.JSError { return switch (err) { - error.MissingCredentials => globalThis.ERR_S3_MISSING_CREDENTIALS(getSignErrorMessage(error.MissingCredentials), .{}).throw(), - error.InvalidMethod => globalThis.ERR_S3_INVALID_METHOD(getSignErrorMessage(error.InvalidMethod), .{}).throw(), - error.InvalidPath => globalThis.ERR_S3_INVALID_PATH(getSignErrorMessage(error.InvalidPath), .{}).throw(), - error.InvalidEndpoint => globalThis.ERR_S3_INVALID_ENDPOINT(getSignErrorMessage(error.InvalidEndpoint), .{}).throw(), - error.InvalidSessionToken => globalThis.ERR_S3_INVALID_SESSION_TOKEN(getSignErrorMessage(error.InvalidSessionToken), .{}).throw(), - else => globalThis.ERR_S3_INVALID_SIGNATURE(getSignErrorMessage(error.SignError), .{}).throw(), + error.MissingCredentials => globalThis.ERR(.S3_MISSING_CREDENTIALS, getSignErrorMessage(error.MissingCredentials), .{}).throw(), + error.InvalidMethod => globalThis.ERR(.S3_INVALID_METHOD, getSignErrorMessage(error.InvalidMethod), .{}).throw(), + error.InvalidPath => globalThis.ERR(.S3_INVALID_PATH, getSignErrorMessage(error.InvalidPath), .{}).throw(), + error.InvalidEndpoint => globalThis.ERR(.S3_INVALID_ENDPOINT, getSignErrorMessage(error.InvalidEndpoint), .{}).throw(), + error.InvalidSessionToken => globalThis.ERR(.S3_INVALID_SESSION_TOKEN, getSignErrorMessage(error.InvalidSessionToken), .{}).throw(), + else => globalThis.ERR(.S3_INVALID_SIGNATURE, getSignErrorMessage(error.SignError), .{}).throw(), }; } pub fn getSignErrorCodeAndMessage(err: anyerror) ErrorCodeAndMessage { diff --git a/src/shell/IOWriter.zig b/src/shell/IOWriter.zig index 873fc19f85..e4a09658c4 100644 --- a/src/shell/IOWriter.zig +++ b/src/shell/IOWriter.zig @@ -33,14 +33,13 @@ const SHRINK_THRESHOLD = 1024 * 128; pub const auto_poll = false; -pub const WriterImpl = bun.io.BufferedWriter( - IOWriter, - onWrite, - onError, - onClose, - getBuffer, - null, -); +pub const WriterImpl = bun.io.BufferedWriter(IOWriter, struct { + pub const onWrite = IOWriter.onWrite; + pub const onError = IOWriter.onError; + pub const onClose = IOWriter.onClose; + pub const getBuffer = IOWriter.getBuffer; + pub const onWritable = null; +}); pub const Poll = WriterImpl; // pub fn __onClose(_: *IOWriter) void {} diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index fc2a9d63c2..9b5c76309c 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -50,35 +50,35 @@ pub const AnyPostgresError = error{ pub fn postgresErrorToJS(globalObject: *JSC.JSGlobalObject, message: ?[]const u8, err: AnyPostgresError) JSValue { const error_code: JSC.Error = switch (err) { - error.ConnectionClosed => JSC.Error.ERR_POSTGRES_CONNECTION_CLOSED, - error.ExpectedRequest => JSC.Error.ERR_POSTGRES_EXPECTED_REQUEST, - error.ExpectedStatement => JSC.Error.ERR_POSTGRES_EXPECTED_STATEMENT, - error.InvalidBackendKeyData => JSC.Error.ERR_POSTGRES_INVALID_BACKEND_KEY_DATA, - error.InvalidBinaryData => JSC.Error.ERR_POSTGRES_INVALID_BINARY_DATA, - error.InvalidByteSequence => JSC.Error.ERR_POSTGRES_INVALID_BYTE_SEQUENCE, - error.InvalidByteSequenceForEncoding => JSC.Error.ERR_POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING, - error.InvalidCharacter => JSC.Error.ERR_POSTGRES_INVALID_CHARACTER, - error.InvalidMessage => JSC.Error.ERR_POSTGRES_INVALID_MESSAGE, - error.InvalidMessageLength => JSC.Error.ERR_POSTGRES_INVALID_MESSAGE_LENGTH, - error.InvalidQueryBinding => JSC.Error.ERR_POSTGRES_INVALID_QUERY_BINDING, - error.InvalidServerKey => JSC.Error.ERR_POSTGRES_INVALID_SERVER_KEY, - error.InvalidServerSignature => JSC.Error.ERR_POSTGRES_INVALID_SERVER_SIGNATURE, - error.MultidimensionalArrayNotSupportedYet => JSC.Error.ERR_POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET, - error.NullsInArrayNotSupportedYet => JSC.Error.ERR_POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET, - error.Overflow => JSC.Error.ERR_POSTGRES_OVERFLOW, - error.PBKDFD2 => JSC.Error.ERR_POSTGRES_AUTHENTICATION_FAILED_PBKDF2, - error.SASL_SIGNATURE_MISMATCH => JSC.Error.ERR_POSTGRES_SASL_SIGNATURE_MISMATCH, - error.SASL_SIGNATURE_INVALID_BASE64 => JSC.Error.ERR_POSTGRES_SASL_SIGNATURE_INVALID_BASE64, - error.TLSNotAvailable => JSC.Error.ERR_POSTGRES_TLS_NOT_AVAILABLE, - error.TLSUpgradeFailed => JSC.Error.ERR_POSTGRES_TLS_UPGRADE_FAILED, - error.UnexpectedMessage => JSC.Error.ERR_POSTGRES_UNEXPECTED_MESSAGE, - error.UNKNOWN_AUTHENTICATION_METHOD => JSC.Error.ERR_POSTGRES_UNKNOWN_AUTHENTICATION_METHOD, - error.UNSUPPORTED_AUTHENTICATION_METHOD => JSC.Error.ERR_POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD, - error.UnsupportedByteaFormat => JSC.Error.ERR_POSTGRES_UNSUPPORTED_BYTEA_FORMAT, - error.UnsupportedArrayFormat => JSC.Error.ERR_POSTGRES_UNSUPPORTED_ARRAY_FORMAT, - error.UnsupportedIntegerSize => JSC.Error.ERR_POSTGRES_UNSUPPORTED_INTEGER_SIZE, - error.UnsupportedNumericFormat => JSC.Error.ERR_POSTGRES_UNSUPPORTED_NUMERIC_FORMAT, - error.UnknownFormatCode => JSC.Error.ERR_POSTGRES_UNKNOWN_FORMAT_CODE, + error.ConnectionClosed => .POSTGRES_CONNECTION_CLOSED, + error.ExpectedRequest => .POSTGRES_EXPECTED_REQUEST, + error.ExpectedStatement => .POSTGRES_EXPECTED_STATEMENT, + error.InvalidBackendKeyData => .POSTGRES_INVALID_BACKEND_KEY_DATA, + error.InvalidBinaryData => .POSTGRES_INVALID_BINARY_DATA, + error.InvalidByteSequence => .POSTGRES_INVALID_BYTE_SEQUENCE, + error.InvalidByteSequenceForEncoding => .POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING, + error.InvalidCharacter => .POSTGRES_INVALID_CHARACTER, + error.InvalidMessage => .POSTGRES_INVALID_MESSAGE, + error.InvalidMessageLength => .POSTGRES_INVALID_MESSAGE_LENGTH, + error.InvalidQueryBinding => .POSTGRES_INVALID_QUERY_BINDING, + error.InvalidServerKey => .POSTGRES_INVALID_SERVER_KEY, + error.InvalidServerSignature => .POSTGRES_INVALID_SERVER_SIGNATURE, + error.MultidimensionalArrayNotSupportedYet => .POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET, + error.NullsInArrayNotSupportedYet => .POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET, + error.Overflow => .POSTGRES_OVERFLOW, + error.PBKDFD2 => .POSTGRES_AUTHENTICATION_FAILED_PBKDF2, + error.SASL_SIGNATURE_MISMATCH => .POSTGRES_SASL_SIGNATURE_MISMATCH, + error.SASL_SIGNATURE_INVALID_BASE64 => .POSTGRES_SASL_SIGNATURE_INVALID_BASE64, + error.TLSNotAvailable => .POSTGRES_TLS_NOT_AVAILABLE, + error.TLSUpgradeFailed => .POSTGRES_TLS_UPGRADE_FAILED, + error.UnexpectedMessage => .POSTGRES_UNEXPECTED_MESSAGE, + error.UNKNOWN_AUTHENTICATION_METHOD => .POSTGRES_UNKNOWN_AUTHENTICATION_METHOD, + error.UNSUPPORTED_AUTHENTICATION_METHOD => .POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD, + error.UnsupportedByteaFormat => .POSTGRES_UNSUPPORTED_BYTEA_FORMAT, + error.UnsupportedArrayFormat => .POSTGRES_UNSUPPORTED_ARRAY_FORMAT, + error.UnsupportedIntegerSize => .POSTGRES_UNSUPPORTED_INTEGER_SIZE, + error.UnsupportedNumericFormat => .POSTGRES_UNSUPPORTED_NUMERIC_FORMAT, + error.UnknownFormatCode => .POSTGRES_UNKNOWN_FORMAT_CODE, error.JSError => { return globalObject.takeException(error.JSError); }, @@ -1470,13 +1470,13 @@ pub const PostgresSQLConnection = struct { switch (this.status) { .connected => { - this.failFmt(.ERR_POSTGRES_IDLE_TIMEOUT, "Idle timeout reached after {}", .{bun.fmt.fmtDurationOneDecimal(@as(u64, this.idle_timeout_interval_ms) *| std.time.ns_per_ms)}); + this.failFmt(.POSTGRES_IDLE_TIMEOUT, "Idle timeout reached after {}", .{bun.fmt.fmtDurationOneDecimal(@as(u64, this.idle_timeout_interval_ms) *| std.time.ns_per_ms)}); }, else => { - this.failFmt(.ERR_POSTGRES_CONNECTION_TIMEOUT, "Connection timeout after {}", .{bun.fmt.fmtDurationOneDecimal(@as(u64, this.connection_timeout_ms) *| std.time.ns_per_ms)}); + this.failFmt(.POSTGRES_CONNECTION_TIMEOUT, "Connection timeout after {}", .{bun.fmt.fmtDurationOneDecimal(@as(u64, this.connection_timeout_ms) *| std.time.ns_per_ms)}); }, .sent_startup_message => { - this.failFmt(.ERR_POSTGRES_CONNECTION_TIMEOUT, "Connection timed out after {} (sent startup message, but never received response)", .{bun.fmt.fmtDurationOneDecimal(@as(u64, this.connection_timeout_ms) *| std.time.ns_per_ms)}); + this.failFmt(.POSTGRES_CONNECTION_TIMEOUT, "Connection timed out after {} (sent startup message, but never received response)", .{bun.fmt.fmtDurationOneDecimal(@as(u64, this.connection_timeout_ms) *| std.time.ns_per_ms)}); }, } return .disarm; @@ -1486,7 +1486,7 @@ pub const PostgresSQLConnection = struct { debug("onMaxLifetimeTimeout", .{}); this.max_lifetime_timer.state = .FIRED; if (this.status == .failed) return .disarm; - this.failFmt(.ERR_POSTGRES_LIFETIME_TIMEOUT, "Max lifetime timeout reached after {}", .{bun.fmt.fmtDurationOneDecimal(@as(u64, this.max_lifetime_interval_ms) *| std.time.ns_per_ms)}); + this.failFmt(.POSTGRES_LIFETIME_TIMEOUT, "Max lifetime timeout reached after {}", .{bun.fmt.fmtDurationOneDecimal(@as(u64, this.max_lifetime_interval_ms) *| std.time.ns_per_ms)}); return .disarm; } diff --git a/src/sql/postgres/postgres_protocol.zig b/src/sql/postgres/postgres_protocol.zig index 57fdd8b311..dc9c713750 100644 --- a/src/sql/postgres/postgres_protocol.zig +++ b/src/sql/postgres/postgres_protocol.zig @@ -809,9 +809,9 @@ pub const ErrorResponse = struct { const error_code: JSC.Error = // https://www.postgresql.org/docs/8.1/errcodes-appendix.html if (code.eqlComptime("42601")) - JSC.Error.ERR_POSTGRES_SYNTAX_ERROR + .POSTGRES_SYNTAX_ERROR else - JSC.Error.ERR_POSTGRES_SERVER_ERROR; + .POSTGRES_SERVER_ERROR; const err = error_code.fmt(globalObject, "{s}", .{b.allocatedSlice()[0..b.len]}); inline for (possible_fields) |field| { diff --git a/src/sql/postgres/postgres_types.zig b/src/sql/postgres/postgres_types.zig index e9f34cf0d2..15258b8412 100644 --- a/src/sql/postgres/postgres_types.zig +++ b/src/sql/postgres/postgres_types.zig @@ -365,16 +365,16 @@ pub const Tag = enum(short) { // Ban these types: if (tag == .NumberObject) { - return globalObject.ERR_INVALID_ARG_TYPE("Number object is ambiguous and cannot be used as a PostgreSQL type", .{}).throw(); + return globalObject.ERR(.INVALID_ARG_TYPE, "Number object is ambiguous and cannot be used as a PostgreSQL type", .{}).throw(); } if (tag == .BooleanObject) { - return globalObject.ERR_INVALID_ARG_TYPE("Boolean object is ambiguous and cannot be used as a PostgreSQL type", .{}).throw(); + return globalObject.ERR(.INVALID_ARG_TYPE, "Boolean object is ambiguous and cannot be used as a PostgreSQL type", .{}).throw(); } // It's something internal if (!tag.isIndexable()) { - return globalObject.ERR_INVALID_ARG_TYPE("Unknown object is not a valid PostgreSQL type", .{}).throw(); + return globalObject.ERR(.INVALID_ARG_TYPE, "Unknown object is not a valid PostgreSQL type", .{}).throw(); } // We will JSON.stringify anything else. diff --git a/src/sys.zig b/src/sys.zig index d8dc518347..93ae508530 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -8,7 +8,8 @@ const posix = std.posix; const assertIsValidWindowsPath = bun.strings.assertIsValidWindowsPath; const default_allocator = bun.default_allocator; -const kernel32 = bun.windows; +const kernel32 = bun.windows.kernel32; +const ntdll = bun.windows.ntdll; const mem = std.mem; const page_size_min = std.heap.page_size_min; const mode_t = posix.mode_t; @@ -43,7 +44,7 @@ pub const syscall = switch (Environment.os) { else => @compileError("not implemented"), }; -/// Non-cancellable verisons of various libc functions are undocumented +/// Non-cancellable versions of various libc functions are undocumented const darwin_nocancel = struct { const c = std.c; pub extern "c" fn @"recvfrom$NOCANCEL"(sockfd: c.fd_t, noalias buf: *anyopaque, len: usize, flags: u32, noalias src_addr: ?*c.sockaddr, noalias addrlen: ?*c.socklen_t) isize; @@ -723,7 +724,7 @@ pub fn chdirOSPath(path: bun.stringZ, destination: if (Environment.isPosix) bun. if (comptime Environment.isWindows) { const wbuf = bun.WPathBufferPool.get(); defer bun.WPathBufferPool.put(wbuf); - if (kernel32.SetCurrentDirectory(bun.strings.toWDirPath(wbuf, destination)) == windows.FALSE) { + if (bun.c.SetCurrentDirectoryW(bun.strings.toWDirPath(wbuf, destination)) == windows.FALSE) { log("SetCurrentDirectory({s}) = {d}", .{ destination, kernel32.GetLastError() }); return Maybe(void).errnoSysPD(0, .chdir, path, destination) orelse Maybe(void).success; } @@ -818,9 +819,9 @@ pub fn statfs(path: [:0]const u8) Maybe(bun.StatFS) { } else { var statfs_ = mem.zeroes(bun.StatFS); const rc = if (Environment.isLinux) - C.translated.statfs(path, &statfs_) + bun.c.statfs(path, &statfs_) else if (Environment.isMac) - C.translated.statfs(path, &statfs_) + bun.c.statfs(path, &statfs_) else @compileError("Unsupported platform"); @@ -980,8 +981,7 @@ pub fn mkdirOSPath(file_path: bun.OSPathSliceZ, flags: mode_t) Maybe(void) { return switch (Environment.os) { else => mkdir(file_path, flags), .windows => { - const rc = kernel32.CreateDirectoryW(file_path, null); - + const rc = bun.c.CreateDirectoryW(file_path, null); if (Maybe(void).errnoSys( rc, .mkdir, @@ -1766,7 +1766,8 @@ pub fn access(path: bun.OSPathSliceZ, mode: i32) Maybe(void) { } }; } } - return Maybe(void).errnoSysP(syscall.access(path, mode), .access, path) orelse .{ .result = {} }; + // TODO: fix that bun's std library fork has a different parameter type. + return Maybe(void).errnoSysP(syscall.access(path, @bitCast(mode)), .access, path) orelse .{ .result = {} }; } pub fn openat(dirfd: bun.FileDescriptor, file_path: [:0]const u8, flags: i32, perm: bun.Mode) Maybe(bun.FileDescriptor) { @@ -3341,21 +3342,21 @@ pub fn existsAtType(fd: bun.FileDescriptor, subpath: anytype) Maybe(ExistsAtType .SecurityQualityOfService = null, }; var basic_info: w.FILE_BASIC_INFORMATION = undefined; - const rc = kernel32.NtQueryAttributesFile(&attr, &basic_info); + const rc = ntdll.NtQueryAttributesFile(&attr, &basic_info); if (JSC.Maybe(bool).errnoSys(rc, .access)) |err| { syslog("NtQueryAttributesFile({}, O_RDONLY, 0) = {}", .{ bun.fmt.fmtOSPath(path, .{}), err }); return .{ .err = err.err }; } - const is_regular_file = basic_info.FileAttributes != kernel32.INVALID_FILE_ATTRIBUTES and + const is_regular_file = basic_info.FileAttributes != bun.c.INVALID_FILE_ATTRIBUTES and // from libuv: directories cannot be read-only // https://github.com/libuv/libuv/blob/eb5af8e3c0ea19a6b0196d5db3212dae1785739b/src/win/fs.c#L2144-L2146 - (basic_info.FileAttributes & kernel32.FILE_ATTRIBUTE_DIRECTORY == 0 or - basic_info.FileAttributes & kernel32.FILE_ATTRIBUTE_READONLY == 0); + (basic_info.FileAttributes & bun.c.FILE_ATTRIBUTE_DIRECTORY == 0 or + basic_info.FileAttributes & bun.c.FILE_ATTRIBUTE_READONLY == 0); - const is_dir = basic_info.FileAttributes != kernel32.INVALID_FILE_ATTRIBUTES and - basic_info.FileAttributes & kernel32.FILE_ATTRIBUTE_DIRECTORY != 0 and - basic_info.FileAttributes & kernel32.FILE_ATTRIBUTE_READONLY == 0; + const is_dir = basic_info.FileAttributes != bun.c.INVALID_FILE_ATTRIBUTES and + basic_info.FileAttributes & bun.c.FILE_ATTRIBUTE_DIRECTORY != 0 and + basic_info.FileAttributes & bun.c.FILE_ATTRIBUTE_READONLY == 0; return if (is_dir) { syslog("NtQueryAttributesFile({}, O_RDONLY, 0) = directory", .{bun.fmt.fmtOSPath(path, .{})}); @@ -3746,7 +3747,7 @@ pub fn writeNonblocking(fd: bun.FileDescriptor, buf: []const u8) Maybe(usize) { pub fn getFileSize(fd: bun.FileDescriptor) Maybe(usize) { if (Environment.isWindows) { var size: windows.LARGE_INTEGER = undefined; - if (windows.GetFileSizeEx(fd.cast(), &size) == windows.FALSE) { + if (windows.kernel32.GetFileSizeEx(fd.cast(), &size) == windows.FALSE) { const err = Error.fromCode(windows.getLastErrno(), .fstat); log("GetFileSizeEx({}) = {s}", .{ fd, err.name() }); return .{ .err = err }; @@ -3967,7 +3968,7 @@ pub const File = struct { if (Environment.isWindows) { const rt = windows.GetFileType(self.handle.cast()); if (rt == windows.FILE_TYPE_UNKNOWN) { - switch (bun.windows.GetLastError()) { + switch (windows.GetLastError()) { .SUCCESS => {}, else => |err| { return .{ .err = Error.fromCode((bun.C.SystemErrno.init(err) orelse bun.C.SystemErrno.EUNKNOWN).toE(), .fstat) }; diff --git a/src/valkey/js_valkey.zig b/src/valkey/js_valkey.zig index 84d7da2d96..8938a24125 100644 --- a/src/valkey/js_valkey.zig +++ b/src/valkey/js_valkey.zig @@ -186,7 +186,7 @@ pub const JSValkeyClient = struct { this.connect() catch |err| { this.poll_ref.unref(this.client.vm); this.client.flags.needs_to_open_socket = true; - const err_value = globalObject.ERR_SOCKET_CLOSED_BEFORE_CONNECTION(" {s} connecting to Valkey", .{@errorName(err)}).toJS(); + const err_value = globalObject.ERR(.SOCKET_CLOSED_BEFORE_CONNECTION, " {s} connecting to Valkey", .{@errorName(err)}).toJS(); promise_ptr.reject(globalObject, err_value); return promise; }; @@ -385,7 +385,7 @@ pub const JSValkeyClient = struct { this.poll_ref.ref(vm); this.connect() catch |err| { - this.failWithJSValue(this.globalObject.ERR_SOCKET_CLOSED_BEFORE_CONNECTION("{s} reconnecting", .{@errorName(err)}).toJS()); + this.failWithJSValue(this.globalObject.ERR(.SOCKET_CLOSED_BEFORE_CONNECTION, "{s} reconnecting", .{@errorName(err)}).toJS()); this.poll_ref.disable(); return; }; @@ -582,7 +582,7 @@ pub const JSValkeyClient = struct { this.connect() catch |err| { this.client.flags.needs_to_open_socket = true; - const err_value = globalThis.ERR_SOCKET_CLOSED_BEFORE_CONNECTION(" {s} connecting to Valkey", .{@errorName(err)}).toJS(); + const err_value = globalThis.ERR(.SOCKET_CLOSED_BEFORE_CONNECTION, " {s} connecting to Valkey", .{@errorName(err)}).toJS(); const promise = JSC.JSPromise.create(globalThis); promise.reject(globalThis, err_value); return promise; diff --git a/src/valkey/valkey.zig b/src/valkey/valkey.zig index 8b9be91a6e..c161449118 100644 --- a/src/valkey/valkey.zig +++ b/src/valkey/valkey.zig @@ -892,11 +892,11 @@ pub const ValkeyClient = struct { if (this.flags.enable_offline_queue) { try this.enqueue(command, &promise); } else { - promise.reject(globalThis, globalThis.ERR_REDIS_CONNECTION_CLOSED("Connection is closed and offline queue is disabled", .{}).toJS()); + promise.reject(globalThis, globalThis.ERR(.REDIS_CONNECTION_CLOSED, "Connection is closed and offline queue is disabled", .{}).toJS()); } }, .failed => { - promise.reject(globalThis, globalThis.ERR_REDIS_CONNECTION_CLOSED("Connection has failed", .{}).toJS()); + promise.reject(globalThis, globalThis.ERR(.REDIS_CONNECTION_CLOSED, "Connection has failed", .{}).toJS()); }, } diff --git a/src/valkey/valkey_protocol.zig b/src/valkey/valkey_protocol.zig index b2c1e4a706..e9b67e8120 100644 --- a/src/valkey/valkey_protocol.zig +++ b/src/valkey/valkey_protocol.zig @@ -35,28 +35,34 @@ pub const RedisError = error{ pub fn valkeyErrorToJS(globalObject: *JSC.JSGlobalObject, message: ?[]const u8, err: RedisError) JSC.JSValue { const error_code: JSC.Error = switch (err) { - error.ConnectionClosed => JSC.Error.ERR_REDIS_CONNECTION_CLOSED, - error.InvalidResponse => JSC.Error.ERR_REDIS_INVALID_RESPONSE, - error.InvalidBulkString => JSC.Error.ERR_REDIS_INVALID_BULK_STRING, - error.InvalidArray => JSC.Error.ERR_REDIS_INVALID_ARRAY, - error.InvalidInteger => JSC.Error.ERR_REDIS_INVALID_INTEGER, - error.InvalidSimpleString => JSC.Error.ERR_REDIS_INVALID_SIMPLE_STRING, - error.InvalidErrorString => JSC.Error.ERR_REDIS_INVALID_ERROR_STRING, - error.InvalidDouble, error.InvalidBoolean, error.InvalidNull, error.InvalidMap, error.InvalidSet, error.InvalidBigNumber, error.InvalidVerbatimString, error.InvalidBlobError, error.InvalidAttribute, error.InvalidPush => JSC.Error.ERR_REDIS_INVALID_RESPONSE, - error.AuthenticationFailed => JSC.Error.ERR_REDIS_AUTHENTICATION_FAILED, - error.InvalidCommand => JSC.Error.ERR_REDIS_INVALID_COMMAND, - error.InvalidArgument => JSC.Error.ERR_REDIS_INVALID_ARGUMENT, - error.UnsupportedProtocol => JSC.Error.ERR_REDIS_INVALID_RESPONSE, - error.InvalidResponseType => JSC.Error.ERR_REDIS_INVALID_RESPONSE_TYPE, - error.ConnectionTimeout => JSC.Error.ERR_REDIS_CONNECTION_TIMEOUT, - error.IdleTimeout => JSC.Error.ERR_REDIS_IDLE_TIMEOUT, - error.JSError => { - return globalObject.takeException(error.JSError); - }, - error.OutOfMemory => { - globalObject.throwOutOfMemory() catch {}; - return globalObject.takeException(error.JSError); - }, + error.ConnectionClosed => .REDIS_CONNECTION_CLOSED, + error.InvalidResponse => .REDIS_INVALID_RESPONSE, + error.InvalidBulkString => .REDIS_INVALID_BULK_STRING, + error.InvalidArray => .REDIS_INVALID_ARRAY, + error.InvalidInteger => .REDIS_INVALID_INTEGER, + error.InvalidSimpleString => .REDIS_INVALID_SIMPLE_STRING, + error.InvalidErrorString => .REDIS_INVALID_ERROR_STRING, + error.InvalidDouble, + error.InvalidBoolean, + error.InvalidNull, + error.InvalidMap, + error.InvalidSet, + error.InvalidBigNumber, + error.InvalidVerbatimString, + error.InvalidBlobError, + error.InvalidAttribute, + error.InvalidPush, + => .REDIS_INVALID_RESPONSE, + error.AuthenticationFailed => .REDIS_AUTHENTICATION_FAILED, + error.InvalidCommand => .REDIS_INVALID_COMMAND, + error.InvalidArgument => .REDIS_INVALID_ARGUMENT, + error.UnsupportedProtocol => .REDIS_INVALID_RESPONSE, + error.InvalidResponseType => .REDIS_INVALID_RESPONSE_TYPE, + error.ConnectionTimeout => .REDIS_CONNECTION_TIMEOUT, + error.IdleTimeout => .REDIS_IDLE_TIMEOUT, + error.JSError => return globalObject.takeException(error.JSError), + error.OutOfMemory => globalObject.throwOutOfMemory() catch + return globalObject.takeException(error.JSError), }; if (message) |msg| { diff --git a/src/windows.zig b/src/windows.zig index 498927506b..e0767bad35 100644 --- a/src/windows.zig +++ b/src/windows.zig @@ -1,6 +1,13 @@ const bun = @import("bun"); +const Output = bun.Output; const windows = std.os.windows; const win32 = windows; + +const c = bun.c; +pub const ntdll = windows.ntdll; +pub const kernel32 = windows.kernel32; +pub const GetLastError = kernel32.GetLastError; + pub const PATH_MAX_WIDE = windows.PATH_MAX_WIDE; pub const MAX_PATH = windows.MAX_PATH; pub const WORD = windows.WORD; @@ -38,7 +45,6 @@ pub const FILETIME = windows.FILETIME; pub const DUPLICATE_SAME_ACCESS = windows.DUPLICATE_SAME_ACCESS; pub const OBJECT_ATTRIBUTES = windows.OBJECT_ATTRIBUTES; -pub const kernel32 = windows.kernel32; pub const IO_STATUS_BLOCK = windows.IO_STATUS_BLOCK; pub const FILE_INFO_BY_HANDLE_CLASS = windows.FILE_INFO_BY_HANDLE_CLASS; pub const FILE_SHARE_READ = windows.FILE_SHARE_READ; @@ -62,9 +68,6 @@ pub const FILE_WRITE_THROUGH = windows.FILE_WRITE_THROUGH; pub const FILE_SEQUENTIAL_ONLY = windows.FILE_SEQUENTIAL_ONLY; pub const FILE_SYNCHRONOUS_IO_NONALERT = windows.FILE_SYNCHRONOUS_IO_NONALERT; pub const FILE_OPEN_REPARSE_POINT = windows.FILE_OPEN_REPARSE_POINT; -pub usingnamespace kernel32; -pub const ntdll = windows.ntdll; -pub usingnamespace ntdll; pub const user32 = windows.user32; pub const advapi32 = windows.advapi32; @@ -3414,7 +3417,7 @@ pub fn GetFinalPathNameByHandle( }); if (return_length == 0) { - bun.sys.syslog("GetFinalPathNameByHandleW({*p}) = {}", .{ hFile, bun.windows.GetLastError() }); + bun.sys.syslog("GetFinalPathNameByHandleW({*p}) = {}", .{ hFile, GetLastError() }); return error.FileNotFound; } @@ -3478,7 +3481,6 @@ pub const ENABLE_VIRTUAL_TERMINAL_INPUT = 0x200; pub const ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002; pub const ENABLE_PROCESSED_OUTPUT = 0x0001; -const SetConsoleMode = kernel32.SetConsoleMode; pub extern fn SetStdHandle(nStdHandle: u32, hHandle: *anyopaque) u32; pub extern fn GetConsoleOutputCP() u32; pub extern "kernel32" fn SetConsoleCP(wCodePageID: std.os.windows.UINT) callconv(std.os.windows.WINAPI) std.os.windows.BOOL; @@ -3667,3 +3669,188 @@ pub extern "kernel32" fn GetCommandLineW() callconv(.winapi) LPWSTR; pub extern "kernel32" fn CreateDirectoryW(lpPathName: [*:0]const u16, lpSecurityAttributes: ?*windows.SECURITY_ATTRIBUTES) callconv(.winapi) BOOL; pub extern "kernel32" fn SetEndOfFile(hFile: HANDLE) callconv(.winapi) BOOL; pub extern "kernel32" fn GetProcessTimes(in_hProcess: HANDLE, out_lpCreationTime: *FILETIME, out_lpExitTime: *FILETIME, out_lpKernelTime: *FILETIME, out_lpUserTime: *FILETIME) callconv(.winapi) BOOL; + +/// Returns the original mode, or null on failure +pub fn updateStdioModeFlags(i: bun.FD.Stdio, opts: struct { set: DWORD = 0, unset: DWORD = 0 }) !DWORD { + const fd = i.fd(); + var original_mode: DWORD = 0; + if (c.GetConsoleMode(fd.cast(), &original_mode) != 0) { + if (c.SetConsoleMode(fd.cast(), (original_mode | opts.set) & ~opts.unset) == 0) { + return getLastError(); + } + } else return getLastError(); + return original_mode; +} + +const watcherChildEnv: [:0]const u16 = bun.strings.toUTF16Literal("_BUN_WATCHER_CHILD"); + +// magic exit code to indicate to the watcher manager that the child process should be re-spawned +// this was randomly generated - we need to avoid using a common exit code that might be used by the script itself +pub const watcher_reload_exit: DWORD = 3224497970; + +pub const spawn = @import("./bun.js/api/bun/spawn.zig").PosixSpawn; + +pub fn isWatcherChild() bool { + var buf: [1]u16 = undefined; + return c.GetEnvironmentVariableW(@constCast(watcherChildEnv.ptr), &buf, 1) > 0; +} + +pub fn becomeWatcherManager(allocator: std.mem.Allocator) noreturn { + // this process will be the parent of the child process that actually runs the script + var procinfo: std.os.windows.PROCESS_INFORMATION = undefined; + bun.C.windows_enable_stdio_inheritance(); + const job = CreateJobObjectA(null, null) orelse Output.panic( + "Could not create watcher Job Object: {s}", + .{@tagName(std.os.windows.kernel32.GetLastError())}, + ); + var jeli = std.mem.zeroes(c.JOBOBJECT_EXTENDED_LIMIT_INFORMATION); + jeli.BasicLimitInformation.LimitFlags = + c.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | + c.JOB_OBJECT_LIMIT_BREAKAWAY_OK | + c.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK | + c.JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION; + if (c.SetInformationJobObject( + job, + c.JobObjectExtendedLimitInformation, + &jeli, + @sizeOf(c.JOBOBJECT_EXTENDED_LIMIT_INFORMATION), + ) == 0) { + Output.panic( + "Could not configure watcher Job Object: {s}", + .{@tagName(std.os.windows.kernel32.GetLastError())}, + ); + } + + while (true) { + spawnWatcherChild(allocator, &procinfo, job) catch |err| { + bun.handleErrorReturnTrace(err, @errorReturnTrace()); + if (err == error.Win32Error) { + Output.panic("Failed to spawn process: {s}\n", .{@tagName(GetLastError())}); + } + Output.panic("Failed to spawn process: {s}\n", .{@errorName(err)}); + }; + windows.WaitForSingleObject(procinfo.hProcess, c.INFINITE) catch |err| { + Output.panic("Failed to wait for child process: {s}\n", .{@errorName(err)}); + }; + var exit_code: DWORD = 0; + if (c.GetExitCodeProcess(procinfo.hProcess, &exit_code) == 0) { + const err = windows.GetLastError(); + _ = c.NtClose(procinfo.hProcess); + Output.panic("Failed to get exit code of child process: {s}\n", .{@tagName(err)}); + } + _ = c.NtClose(procinfo.hProcess); + + // magic exit code to indicate that the child process should be re-spawned + if (exit_code == watcher_reload_exit) { + continue; + } else { + bun.Global.exit(exit_code); + } + } +} + +pub fn spawnWatcherChild( + allocator: std.mem.Allocator, + procinfo: *std.os.windows.PROCESS_INFORMATION, + job: HANDLE, +) !void { + // https://devblogs.microsoft.com/oldnewthing/20230209-00/?p=107812 + var attr_size: usize = undefined; + _ = InitializeProcThreadAttributeList(null, 1, 0, &attr_size); + const p = try allocator.alloc(u8, attr_size); + defer allocator.free(p); + if (InitializeProcThreadAttributeList(p.ptr, 1, 0, &attr_size) == 0) { + return error.Win32Error; + } + if (UpdateProcThreadAttribute( + p.ptr, + 0, + c.PROC_THREAD_ATTRIBUTE_JOB_LIST, + @ptrCast(&job), + @sizeOf(HANDLE), + null, + null, + ) == 0) { + return error.Win32Error; + } + + const flags: DWORD = c.CREATE_UNICODE_ENVIRONMENT | c.EXTENDED_STARTUPINFO_PRESENT; + + const image_path = exePathW(); + var wbuf: WPathBuffer = undefined; + @memcpy(wbuf[0..image_path.len], image_path); + wbuf[image_path.len] = 0; + + const image_pathZ = wbuf[0..image_path.len :0]; + + const kernelenv = kernel32.GetEnvironmentStringsW(); + defer if (kernelenv) |envptr| { + _ = kernel32.FreeEnvironmentStringsW(envptr); + }; + + var size: usize = 0; + if (kernelenv) |pointer| { + // check that env is non-empty + if (pointer[0] != 0 or pointer[1] != 0) { + // array is terminated by two nulls + while (pointer[size] != 0 or pointer[size + 1] != 0) size += 1; + size += 1; + } + } + // now pointer[size] is the first null + + const envbuf = try allocator.alloc(u16, size + watcherChildEnv.len + 4); + defer allocator.free(envbuf); + if (kernelenv) |pointer| { + @memcpy(envbuf[0..size], pointer); + } + @memcpy(envbuf[size .. size + watcherChildEnv.len], watcherChildEnv); + envbuf[size + watcherChildEnv.len] = '='; + envbuf[size + watcherChildEnv.len + 1] = '1'; + envbuf[size + watcherChildEnv.len + 2] = 0; + envbuf[size + watcherChildEnv.len + 3] = 0; + + var startupinfo = STARTUPINFOEXW{ + .StartupInfo = .{ + .cb = @sizeOf(STARTUPINFOEXW), + .lpReserved = null, + .lpDesktop = null, + .lpTitle = null, + .dwX = 0, + .dwY = 0, + .dwXSize = 0, + .dwYSize = 0, + .dwXCountChars = 0, + .dwYCountChars = 0, + .dwFillAttribute = 0, + .dwFlags = c.STARTF_USESTDHANDLES, + .wShowWindow = 0, + .cbReserved2 = 0, + .lpReserved2 = null, + .hStdInput = std.io.getStdIn().handle, + .hStdOutput = std.io.getStdOut().handle, + .hStdError = std.io.getStdErr().handle, + }, + .lpAttributeList = p.ptr, + }; + @memset(std.mem.asBytes(procinfo), 0); + const rc = kernel32.CreateProcessW( + image_pathZ.ptr, + c.GetCommandLineW(), + null, + null, + 1, + flags, + envbuf.ptr, + null, + @ptrCast(&startupinfo), + procinfo, + ); + if (rc == 0) { + return error.Win32Error; + } + var is_in_job: c.BOOL = 0; + _ = c.IsProcessInJob(procinfo.hProcess, job, &is_in_job); + bun.debugAssert(is_in_job != 0); + _ = c.NtClose(procinfo.hThread); +} diff --git a/test/internal/ban-words.test.ts b/test/internal/ban-words.test.ts index 54a547843a..2830120141 100644 --- a/test/internal/ban-words.test.ts +++ b/test/internal/ban-words.test.ts @@ -30,7 +30,7 @@ const words: Record "!= alloc.ptr": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" }, [String.raw`: [a-zA-Z0-9_\.\*\?\[\]\(\)]+ = undefined,`]: { reason: "Do not default a struct field to undefined", limit: 242, regex: true }, - "usingnamespace": { reason: "Zig deprecates this, and will not support it in incremental compilation.", limit: 50 }, + "usingnamespace": { reason: "Zig deprecates this, and will not support it in incremental compilation.", limit: 19 }, "std.fs.Dir": { reason: "Prefer bun.sys + bun.FD instead of std.fs", limit: 180 }, "std.fs.cwd": { reason: "Prefer bun.FD.cwd()", limit: 103 }, @@ -46,6 +46,7 @@ for (const file of files) { if (file.isDirectory()) continue; if (!file.name.endsWith(".zig")) continue; if (file.parentPath.startsWith("src" + path.sep + "deps")) continue; + if (file.parentPath.startsWith("src" + path.sep + "codegen")) continue; const content = await Bun.file(file.parentPath + path.sep + file.name).text(); for (const word of words_keys) { let regex = words[word].regex ? new RegExp(word, "g") : undefined; diff --git a/test/js/node/util/util.test.js b/test/js/node/util/util.test.js index bfdd784c3a..523b7ebf44 100644 --- a/test/js/node/util/util.test.js +++ b/test/js/node/util/util.test.js @@ -303,7 +303,7 @@ describe("util", () => { false, ); // strictEqual( // FIXME: failing test - // util.types.isNativeError(new errors.codes.ERR_IPC_CHANNEL_CLOSED()), + // util.types.isNativeError(new errors.codes.ERR(.IPC_CHANNEL_CLOSED, )), // true // ); });