diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index a0ca01482c0edd..c141af7d8c1c79 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -2995,116 +2995,6 @@ pub const JSGlobalObject = opaque { return .zero; } - /// Pass a JSOrMemoryError!JSValue and variants through the C ABI boundary - /// - /// In C++, WebKit represents a thrown JavaScript expression as - /// JSValue.zero/nullptr, and stores the actual exception on the global. In - /// Zig, we represent this zero as a distinct Zig error type - /// 'error.JSError'. Instead of using JSValue.zero directly, we pass the - /// Zig error to this function as "proof" there is an error. In debug, this - /// will also assert that an error is actually present. - /// - /// If .zero is exposed to JS, it will be considered a JSCell but with a - /// null pointer and will segfault via null-pointer dereference. - /// - /// Ideally, we can use this function as little as possible, and instead - /// have auto-generated wrappers that do this conversion. It is ugly to use - /// on purpose. - pub inline fn errorUnionToCPP(global: *JSGlobalObject, result: anytype) RemoveError(@TypeOf(result)) { - const T = @TypeOf(result); - - const unwrapped = switch (@typeInfo(T)) { - .ErrorUnion => result catch |err| { - bun.handleErrorReturnTrace(err, @errorReturnTrace()); - return global.errorSetToCPP(err, T); - }, - .ErrorSet => return global.errorSetToCPP(result, T), - else => result, - }; - - // Validate exception state aligns with return value. - // Currently only enabled for JSValue. - const Return = RemoveError(T); - if (bun.Environment.isDebug and Return == JSValue) { - const null_value: Return = comptime if (Return == JSC.JSValue) - .zero - else - null; - - if (unwrapped == null_value) { - std.debug.assert(global.hasException()); // Exception was cleared, yet returned. - } else if (Return == JSC.JSValue and unwrapped == .undefined) { - // TODO: a lot of our code returns undefined when it throws an error. - } else { - if (global.tryTakeException()) |exception| { - bun.Output.err("assertion failure", "Pending exception while returning non-empty JSValue", .{}); - bun.Output.printErrorln("Exception thrown:", .{}); - bun.Output.flush(); - global.bunVM().printErrorLikeObjectToConsole(exception); - bun.Output.printErrorln("Value returned:", .{}); - bun.Output.flush(); - if (Return == JSValue) { - unwrapped.print(global, .Log, .Error); - } else { - bun.Output.printErrorln(" {any}", .{unwrapped}); - } - bun.Output.flush(); - @panic("Pending exception while returning non-empty JSValue"); - } - } - } - - return unwrapped; - } - - pub fn RemoveError(T: type) type { - return switch (@typeInfo(T)) { - .ErrorSet => bun.JSC.JSValue, - .ErrorUnion => |eu| if (@typeInfo(eu.payload) == .Pointer) - ?eu.payload - else - eu.payload, - else => T, - }; - } - - inline fn errorSetToCPP(global: *JSGlobalObject, err: anytype, T: type) RemoveError(T) { - const info = @typeInfo(@TypeOf(err)); - comptime bun.assert(info == .ErrorSet); - const Return = RemoveError(T); - const null_value: Return = comptime if (Return == JSC.JSValue) - .zero - else - null; - - const possible_errors = comptime parseErrorSet( - T, - info.ErrorSet orelse - @compileError("host function cannot return 'anyerror!JSValue'"), - ); - - if (possible_errors.OutOfMemory and err == error.OutOfMemory) { - if (global.hasException()) { - if (comptime bun.Environment.isDebug) bun.Output.panic("attempted to throw OutOfMemory without an exception", .{}); - } else { - global.throwOutOfMemory(); - } - return null_value; - } - - if (possible_errors.JSError and err == error.JSError) { - if (!global.hasException()) { - if (comptime bun.Environment.isDebug) bun.Output.panic("attempted to throw JSError without an exception", .{}); - global.throwOutOfMemory(); - } - return null_value; - } - - // all errors have now been handled. parseErrorSet will report - // a compile error if there is another possible error - unreachable; - } - pub fn createInvalidArgumentType( this: *JSGlobalObject, comptime name_: []const u8, diff --git a/src/bun.zig b/src/bun.zig index 6bc162224221ca..352c6c9148562c 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -4118,6 +4118,3 @@ pub inline fn isComptimeKnown(x: anytype) bool { pub inline fn itemOrNull(comptime T: type, slice: []const T, index: usize) ?T { return if (index < slice.len) slice[index] else null; } - -/// Code used by the classes generator -pub const gen_classes_lib = @import("gen_classes_lib.zig"); diff --git a/src/codegen/generate-js2native.ts b/src/codegen/generate-js2native.ts index f1443a2df4d4b1..eb98745618cd13 100644 --- a/src/codegen/generate-js2native.ts +++ b/src/codegen/generate-js2native.ts @@ -201,9 +201,7 @@ export function getJS2NativeZig(gs2NativeZigPath: string) { .filter(x => x.type === "zig") .flatMap(call => [ `export fn ${symbol(call)}_workaround(global: *JSC.JSGlobalObject) callconv(JSC.conv) JSC.JSValue {`, - ` return global.errorUnionToCPP(@import(${JSON.stringify(path.relative(path.dirname(gs2NativeZigPath), call.filename))}).${ - call.symbol - }(global));`, + ` return JSC.toJSHostValue(global, @import(${JSON.stringify(path.relative(path.dirname(gs2NativeZigPath), call.filename))}).${call.symbol}(global));`, "}", ]), ...wrapperCalls diff --git a/src/gen_classes_lib.zig b/src/gen_classes_lib.zig deleted file mode 100644 index 7533184fd5663b..00000000000000 --- a/src/gen_classes_lib.zig +++ /dev/null @@ -1,52 +0,0 @@ -/// Handwritten utility functions for ZigGeneratedClasses.zig -const bun = @import("root").bun; -const JSC = bun.JSC; -const JSValue = JSC.JSValue; -const JSGlobalObject = JSC.JSGlobalObject; - -pub const WrappedMethod = fn (*anyopaque, *JSGlobalObject, *JSC.CallFrame) callconv(JSC.conv) JSValue; -pub const WrappedMethodWithThis = fn (*anyopaque, *JSGlobalObject, *JSC.CallFrame, JSValue) callconv(JSC.conv) JSValue; -pub const WrappedConstructor = fn (*JSGlobalObject, *JSC.CallFrame) callconv(JSC.conv) ?*anyopaque; -pub const WrappedClassGetterCallback = fn (*anyopaque, *JSGlobalObject) callconv(JSC.conv) JSValue; - -pub const wrapHostFunction = JSC.toJSHostFunction; - -pub fn wrapMethod(comptime T: type, comptime func: anytype) WrappedMethod { - return struct { - pub fn call(ptr: *anyopaque, global: *JSGlobalObject, call_frame: *JSC.CallFrame) callconv(JSC.conv) JSValue { - return global.errorUnionToCPP(func(@as(*T, @alignCast(@ptrCast(ptr))), global, call_frame)); - } - }.call; -} - -pub fn wrapMethodWithThis(comptime T: type, comptime func: anytype) WrappedMethodWithThis { - return struct { - pub fn call(ptr: *anyopaque, global: *JSGlobalObject, call_frame: *JSC.CallFrame, this_value: JSValue) callconv(JSC.conv) JSValue { - return global.errorUnionToCPP(func(@as(*T, @alignCast(@ptrCast(ptr))), global, call_frame, this_value)); - } - }.call; -} - -pub fn wrapConstructor(comptime T: type, comptime func: anytype) WrappedConstructor { - return struct { - pub fn call(global: *JSGlobalObject, call_frame: *JSC.CallFrame) callconv(JSC.conv) ?*anyopaque { - return @as(?*T, global.errorUnionToCPP(func(global, call_frame))); - } - }.call; -} - -pub fn wrapGetterCallback(comptime T: type, comptime func: anytype) WrappedClassGetterCallback { - return struct { - pub fn call(ptr: *anyopaque, global: *JSGlobalObject) callconv(JSC.conv) JSValue { - return func(@as(*T, @alignCast(@ptrCast(ptr))), global); - } - }.call; -} - -pub fn wrapGetterWithValueCallback(comptime T: type, comptime func: anytype) WrappedClassGetterCallback { - return struct { - pub fn call(ptr: *anyopaque, global: *JSGlobalObject) callconv(JSC.conv) JSValue { - return func(@as(*T, @alignCast(@ptrCast(ptr))), global); - } - }.call; -}