diff --git a/src/bun.js/BuildMessage.zig b/src/bun.js/BuildMessage.zig index 32a336a744..f27f98e230 100644 --- a/src/bun.js/BuildMessage.zig +++ b/src/bun.js/BuildMessage.zig @@ -19,12 +19,8 @@ pub const BuildMessage = struct { pub usingnamespace JSC.Codegen.JSBuildMessage; - pub fn constructor( - globalThis: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) ?*BuildMessage { - globalThis.throw("BuildMessage is not constructable", .{}); - return null; + pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*BuildMessage { + return globalThis.throw2("BuildMessage is not constructable", .{}); } pub fn getNotes(this: *BuildMessage, globalThis: *JSC.JSGlobalObject) JSC.JSValue { diff --git a/src/bun.js/ResolveMessage.zig b/src/bun.js/ResolveMessage.zig index 498519ae7f..3a3313f7ec 100644 --- a/src/bun.js/ResolveMessage.zig +++ b/src/bun.js/ResolveMessage.zig @@ -18,12 +18,8 @@ pub const ResolveMessage = struct { pub usingnamespace JSC.Codegen.JSResolveMessage; - pub fn constructor( - globalThis: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) ?*ResolveMessage { - globalThis.throw("ResolveMessage is not constructable", .{}); - return null; + pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*ResolveMessage { + return globalThis.throw2("ResolveMessage is not constructable", .{}); } pub fn getCode(this: *ResolveMessage, globalObject: *JSC.JSGlobalObject) JSC.JSValue { diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 088acff708..ad5d0d18ab 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -2624,24 +2624,21 @@ pub const Crypto = struct { } // Bun.CryptoHasher(algorithm, hmacKey?: string | Buffer) - pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*CryptoHasher { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*CryptoHasher { const arguments = callframe.arguments(2); if (arguments.len == 0) { - globalThis.throwInvalidArguments("Expected an algorithm name as an argument", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected an algorithm name as an argument", .{}); } const algorithm_name = arguments.ptr[0]; if (algorithm_name.isEmptyOrUndefinedOrNull() or !algorithm_name.isString()) { - globalThis.throwInvalidArguments("algorithm must be a string", .{}); - return null; + return globalThis.throwInvalidArguments2("algorithm must be a string", .{}); } const algorithm = algorithm_name.getZigString(globalThis); if (algorithm.len == 0) { - globalThis.throwInvalidArguments("Invalid algorithm name", .{}); - return null; + return globalThis.throwInvalidArguments2("Invalid algorithm name", .{}); } const hmac_value = arguments.ptr[1]; @@ -2654,18 +2651,16 @@ pub const Crypto = struct { if (!hmac_value.isEmptyOrUndefinedOrNull()) { hmac_key = JSC.Node.StringOrBuffer.fromJS(globalThis, bun.default_allocator, hmac_value) orelse { - globalThis.throwInvalidArguments("key must be a string or buffer", .{}); - return null; + return globalThis.throwInvalidArguments2("key must be a string or buffer", .{}); }; } return CryptoHasher.new(brk: { if (hmac_key) |*key| { - const chosen_algorithm = algorithm_name.toEnumFromMap(globalThis, "algorithm", EVP.Algorithm, EVP.Algorithm.map) catch return null; + const chosen_algorithm = try algorithm_name.toEnumFromMap(globalThis, "algorithm", EVP.Algorithm, EVP.Algorithm.map); if (chosen_algorithm == .ripemd160) { // crashes at runtime. - globalThis.throw("ripemd160 is not supported", .{}); - return null; + return globalThis.throw2("ripemd160 is not supported", .{}); } break :brk .{ @@ -2675,20 +2670,20 @@ pub const Crypto = struct { if (err != 0) { const instance = createCryptoError(globalThis, err); BoringSSL.ERR_clear_error(); - globalThis.throwValue(instance); + return globalThis.throwValue2(instance); } else { globalThis.throwTODO("HMAC is not supported for this algorithm yet"); + return error.JSError; } } - return null; + return error.JSError; }, }; } break :brk .{ .evp = EVP.byName(algorithm, globalThis) orelse return CryptoHasherZig.constructor(algorithm) orelse { - globalThis.throwInvalidArguments("Unsupported algorithm {any}", .{algorithm}); - return null; + return globalThis.throwInvalidArguments2("Unsupported algorithm {any}", .{algorithm}); }, }; }); @@ -3159,9 +3154,8 @@ pub const Crypto = struct { } } - pub fn constructor(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*@This() { - const this = bun.default_allocator.create(@This()) catch return null; - + pub fn constructor(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*@This() { + const this = try bun.default_allocator.create(@This()); this.* = .{ .hashing = Hasher.init() }; return this; } diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 305b179a87..05fb260873 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -724,10 +724,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std return transpiler; } -pub fn constructor( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, -) ?*Transpiler { +pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*Transpiler { var temp = bun.ArenaAllocator.init(getAllocator(globalThis)); const arguments = callframe.arguments(3); var args = JSC.Node.ArgumentsSlice.init( @@ -737,31 +734,21 @@ pub fn constructor( defer temp.deinit(); const transpiler_options: TranspilerOptions = if (arguments.len > 0) - transformOptionsFromJSC(globalThis, temp.allocator(), &args) catch |err| switch (err) { - error.JSError => return null, - error.OutOfMemory => { - globalThis.throwOutOfMemory(); - return null; - }, - } + try transformOptionsFromJSC(globalThis, temp.allocator(), &args) else TranspilerOptions{ .log = logger.Log.init(getAllocator(globalThis)) }; if (globalThis.hasException()) { - return null; + return error.JSError; } const allocator = getAllocator(globalThis); if ((transpiler_options.log.warnings + transpiler_options.log.errors) > 0) { - globalThis.throwValue( - transpiler_options.log.toJS(globalThis.ptr(), allocator, "Failed to create transpiler"), - ); - - return null; + return globalThis.throwValue2(transpiler_options.log.toJS(globalThis.ptr(), allocator, "Failed to create transpiler")); } - var log = allocator.create(logger.Log) catch unreachable; + var log = try allocator.create(logger.Log); log.* = transpiler_options.log; var bundler = Bundler.Bundler.init( allocator, @@ -770,30 +757,22 @@ pub fn constructor( JavaScript.VirtualMachine.get().bundler.env, ) catch |err| { if ((log.warnings + log.errors) > 0) { - globalThis.throwValue( - log.toJS(globalThis.ptr(), allocator, "Failed to create transpiler"), - ); - - return null; + return globalThis.throwValue2(log.toJS(globalThis.ptr(), allocator, "Failed to create transpiler")); } globalThis.throwError(err, "Error creating transpiler"); - return null; + return error.JSError; }; bundler.options.no_macros = transpiler_options.no_macros; bundler.configureLinkerWithAutoJSX(false); bundler.options.env.behavior = .disable; bundler.configureDefines() catch |err| { if ((log.warnings + log.errors) > 0) { - globalThis.throwValue( - log.toJS(globalThis.ptr(), allocator, "Failed to load define"), - ); - - return null; + return globalThis.throwValue2(log.toJS(globalThis.ptr(), allocator, "Failed to load define")); } globalThis.throwError(err, "Failed to load define"); - return null; + return error.JSError; }; if (transpiler_options.macro_map.count() > 0) { @@ -820,7 +799,7 @@ pub fn constructor( bundler.options.hot_module_reloading = transpiler_options.runtime.hot_module_reloading; bundler.options.react_fast_refresh = false; - const transpiler = allocator.create(Transpiler) catch unreachable; + const transpiler = try allocator.create(Transpiler); transpiler.* = Transpiler{ .transpiler_options = transpiler_options, .bundler = bundler, diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index 6b7b949440..ba1e13aa0f 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -593,8 +593,7 @@ const Handlers = struct { }; if (opts.isEmptyOrUndefinedOrNull() or opts.isBoolean() or !opts.isObject()) { - globalObject.throwInvalidArguments("Expected \"handlers\" to be an object", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"handlers\" to be an object", .{}); } const pairs = .{ @@ -2354,23 +2353,20 @@ pub const H2FrameParser = struct { return .undefined; } - pub fn loadSettingsFromJSValue(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, options: JSC.JSValue) bool { + pub fn loadSettingsFromJSValue(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, options: JSC.JSValue) bun.JSError!void { if (options.isEmptyOrUndefinedOrNull() or !options.isObject()) { - globalObject.throw("Expected settings to be a object", .{}); - return false; + return globalObject.throw2("Expected settings to be a object", .{}); } if (options.get(globalObject, "headerTableSize")) |headerTableSize| { if (headerTableSize.isNumber()) { const headerTableSizeValue = headerTableSize.toInt32(); if (headerTableSizeValue > MAX_HEADER_TABLE_SIZE or headerTableSizeValue < 0) { - globalObject.throw("Expected headerTableSize to be a number between 0 and 2^32-1", .{}); - return false; + return globalObject.throw2("Expected headerTableSize to be a number between 0 and 2^32-1", .{}); } this.localSettings.headerTableSize = @intCast(headerTableSizeValue); } else if (!headerTableSize.isEmptyOrUndefinedOrNull()) { - globalObject.throw("Expected headerTableSize to be a number", .{}); - return false; + return globalObject.throw2("Expected headerTableSize to be a number", .{}); } } @@ -2378,8 +2374,7 @@ pub const H2FrameParser = struct { if (enablePush.isBoolean()) { this.localSettings.enablePush = if (enablePush.asBoolean()) 1 else 0; } else if (!enablePush.isEmptyOrUndefinedOrNull()) { - globalObject.throw("Expected enablePush to be a boolean", .{}); - return false; + return globalObject.throw2("Expected enablePush to be a boolean", .{}); } } @@ -2387,13 +2382,11 @@ pub const H2FrameParser = struct { if (initialWindowSize.isNumber()) { const initialWindowSizeValue = initialWindowSize.toInt32(); if (initialWindowSizeValue > MAX_HEADER_TABLE_SIZE or initialWindowSizeValue < 0) { - globalObject.throw("Expected initialWindowSize to be a number between 0 and 2^32-1", .{}); - return false; + return globalObject.throw2("Expected initialWindowSize to be a number between 0 and 2^32-1", .{}); } this.localSettings.initialWindowSize = @intCast(initialWindowSizeValue); } else if (!initialWindowSize.isEmptyOrUndefinedOrNull()) { - globalObject.throw("Expected initialWindowSize to be a number", .{}); - return false; + return globalObject.throw2("Expected initialWindowSize to be a number", .{}); } } @@ -2401,13 +2394,11 @@ pub const H2FrameParser = struct { if (maxFrameSize.isNumber()) { const maxFrameSizeValue = maxFrameSize.toInt32(); if (maxFrameSizeValue > MAX_FRAME_SIZE or maxFrameSizeValue < 16384) { - globalObject.throw("Expected maxFrameSize to be a number between 16,384 and 2^24-1", .{}); - return false; + return globalObject.throw2("Expected maxFrameSize to be a number between 16,384 and 2^24-1", .{}); } this.localSettings.maxFrameSize = @intCast(maxFrameSizeValue); } else if (!maxFrameSize.isEmptyOrUndefinedOrNull()) { - globalObject.throw("Expected maxFrameSize to be a number", .{}); - return false; + return globalObject.throw2("Expected maxFrameSize to be a number", .{}); } } @@ -2415,13 +2406,11 @@ pub const H2FrameParser = struct { if (maxConcurrentStreams.isNumber()) { const maxConcurrentStreamsValue = maxConcurrentStreams.toInt32(); if (maxConcurrentStreamsValue > MAX_HEADER_TABLE_SIZE or maxConcurrentStreamsValue < 0) { - globalObject.throw("Expected maxConcurrentStreams to be a number between 0 and 2^32-1", .{}); - return false; + return globalObject.throw2("Expected maxConcurrentStreams to be a number between 0 and 2^32-1", .{}); } this.localSettings.maxConcurrentStreams = @intCast(maxConcurrentStreamsValue); } else if (!maxConcurrentStreams.isEmptyOrUndefinedOrNull()) { - globalObject.throw("Expected maxConcurrentStreams to be a number", .{}); - return false; + return globalObject.throw2("Expected maxConcurrentStreams to be a number", .{}); } } @@ -2429,13 +2418,11 @@ pub const H2FrameParser = struct { if (maxHeaderListSize.isNumber()) { const maxHeaderListSizeValue = maxHeaderListSize.toInt32(); if (maxHeaderListSizeValue > MAX_HEADER_TABLE_SIZE or maxHeaderListSizeValue < 0) { - globalObject.throw("Expected maxHeaderListSize to be a number between 0 and 2^32-1", .{}); - return false; + return globalObject.throw2("Expected maxHeaderListSize to be a number between 0 and 2^32-1", .{}); } this.localSettings.maxHeaderListSize = @intCast(maxHeaderListSizeValue); } else if (!maxHeaderListSize.isEmptyOrUndefinedOrNull()) { - globalObject.throw("Expected maxHeaderListSize to be a number", .{}); - return false; + return globalObject.throw2("Expected maxHeaderListSize to be a number", .{}); } } @@ -2443,16 +2430,14 @@ pub const H2FrameParser = struct { if (maxHeaderSize.isNumber()) { const maxHeaderSizeValue = maxHeaderSize.toInt32(); if (maxHeaderSizeValue > MAX_HEADER_TABLE_SIZE or maxHeaderSizeValue < 0) { - globalObject.throw("Expected maxHeaderSize to be a number between 0 and 2^32-1", .{}); - return false; + return globalObject.throw2("Expected maxHeaderSize to be a number between 0 and 2^32-1", .{}); } this.localSettings.maxHeaderListSize = @intCast(maxHeaderSizeValue); } else if (!maxHeaderSize.isEmptyOrUndefinedOrNull()) { - globalObject.throw("Expected maxHeaderSize to be a number", .{}); - return false; + return globalObject.throw2("Expected maxHeaderSize to be a number", .{}); } } - return true; + return; } pub fn updateSettings(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSValue { @@ -2465,12 +2450,9 @@ pub const H2FrameParser = struct { const options = args_list.ptr[0]; - if (this.loadSettingsFromJSValue(globalObject, options)) { - this.setSettings(this.localSettings); - return .undefined; - } - - return .zero; + try this.loadSettingsFromJSValue(globalObject, options); + this.setSettings(this.localSettings); + return .undefined; } pub fn getCurrentState(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSValue { @@ -3752,28 +3734,26 @@ pub const H2FrameParser = struct { } } - pub fn constructor(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*H2FrameParser { + pub fn constructor(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*H2FrameParser { const args_list = callframe.arguments(1); if (args_list.len < 1) { - globalObject.throw("Expected 1 argument", .{}); - return null; + return globalObject.throw2("Expected 1 argument", .{}); } const options = args_list.ptr[0]; if (options.isEmptyOrUndefinedOrNull() or options.isBoolean() or !options.isObject()) { - globalObject.throwInvalidArguments("expected options as argument", .{}); - return null; + return globalObject.throwInvalidArguments2("expected options as argument", .{}); } const context_obj = options.get(globalObject, "context") orelse { - globalObject.throw("Expected \"context\" option", .{}); - return null; + return globalObject.throw2("Expected \"context\" option", .{}); }; var handler_js = JSC.JSValue.zero; if (options.get(globalObject, "handlers")) |handlers_| { handler_js = handlers_; } - var handlers = Handlers.fromJS(globalObject, handler_js) catch return null; + var handlers = try Handlers.fromJS(globalObject, handler_js); + errdefer handlers.deinit(); var this = brk: { if (ENABLE_ALLOCATOR_POOL) { @@ -3813,6 +3793,8 @@ pub const H2FrameParser = struct { }); } }; + errdefer this.deinit(); + // check if socket is provided, and if it is a valid native socket if (options.get(globalObject, "native")) |socket_js| { if (JSTLSSocket.fromJS(socket_js)) |socket| { @@ -3837,11 +3819,7 @@ pub const H2FrameParser = struct { } if (options.get(globalObject, "settings")) |settings_js| { if (!settings_js.isEmptyOrUndefinedOrNull()) { - if (!this.loadSettingsFromJSValue(globalObject, settings_js)) { - this.deinit(); - handlers.deinit(); - return null; - } + try this.loadSettingsFromJSValue(globalObject, settings_js); if (settings_js.get(globalObject, "maxOutstandingPings")) |max_pings| { if (max_pings.isNumber()) { diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 888cd176b1..3abf05cfb8 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -843,9 +843,8 @@ pub const Listener = struct { onCreate(false, socket); } - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*Listener { - globalObject.throw("Cannot construct Listener", .{}); - return null; + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*Listener { + return globalObject.throw2("Cannot construct Listener", .{}); } pub fn onNamePipeCreated(comptime ssl: bool, listener: *Listener) *NewSocket(ssl) { @@ -1452,10 +1451,10 @@ fn NewSocket(comptime ssl: bool) type { } } - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*This { - globalObject.throw("Cannot construct Socket", .{}); - return null; + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*This { + return globalObject.throw2("Cannot construct Socket", .{}); } + pub fn resumeFromJS(this: *This, _: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSValue { JSC.markBinding(@src()); diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 9cd2fd8e45..5d7b69a989 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -41,13 +41,6 @@ pub const ResourceUsage = struct { pub usingnamespace JSC.Codegen.JSResourceUsage; rusage: Rusage, - pub fn constructor( - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) ?*Subprocess { - return null; - } - pub fn getCPUTime( this: *ResourceUsage, globalObject: *JSGlobalObject, @@ -393,11 +386,8 @@ pub const Subprocess = struct { this.updateHasPendingActivity(); } - pub fn constructor( - _: *JSC.JSGlobalObject, - _: *JSC.CallFrame, - ) ?*Subprocess { - return null; + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*Subprocess { + return globalObject.throw2("Cannot construct Subprocess", .{}); } const Readable = union(enum) { diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig index 994f58482d..3797da4d07 100644 --- a/src/bun.js/api/filesystem_router.zig +++ b/src/bun.js/api/filesystem_router.zig @@ -49,17 +49,15 @@ pub const FileSystemRouter = struct { pub usingnamespace JSC.Codegen.JSFileSystemRouter; - pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*FileSystemRouter { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*FileSystemRouter { const argument_ = callframe.arguments(1); if (argument_.len == 0) { - globalThis.throwInvalidArguments("Expected object", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected object", .{}); } const argument = argument_.ptr[0]; if (argument.isEmptyOrUndefinedOrNull() or !argument.isObject()) { - globalThis.throwInvalidArguments("Expected object", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected object", .{}); } var vm = globalThis.bunVM(); @@ -71,18 +69,15 @@ pub const FileSystemRouter = struct { var out_buf: [bun.MAX_PATH_BYTES * 2]u8 = undefined; if (argument.get(globalThis, "style")) |style_val| { if (!style_val.getZigString(globalThis).eqlComptime("nextjs")) { - globalThis.throwInvalidArguments("Only 'nextjs' style is currently implemented", .{}); - return null; + return globalThis.throwInvalidArguments2("Only 'nextjs' style is currently implemented", .{}); } } else { - globalThis.throwInvalidArguments("Expected 'style' option (ex: \"style\": \"nextjs\")", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected 'style' option (ex: \"style\": \"nextjs\")", .{}); } if (argument.get(globalThis, "dir")) |dir| { if (!dir.isString()) { - globalThis.throwInvalidArguments("Expected dir to be a string", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected dir to be a string", .{}); } const root_dir_path_ = dir.toSlice(globalThis, globalThis.allocator()); if (!(root_dir_path_.len == 0 or strings.eqlComptime(root_dir_path_.slice(), "."))) { @@ -97,8 +92,7 @@ pub const FileSystemRouter = struct { } } else { // dir is not optional - globalThis.throwInvalidArguments("Expected dir to be a string", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected dir to be a string", .{}); } var arena = globalThis.allocator().create(bun.ArenaAllocator) catch unreachable; arena.* = bun.ArenaAllocator.init(globalThis.allocator()); @@ -106,22 +100,20 @@ pub const FileSystemRouter = struct { var extensions = std.ArrayList(string).init(allocator); if (argument.get(globalThis, "fileExtensions")) |file_extensions| { if (!file_extensions.jsType().isArray()) { - globalThis.throwInvalidArguments("Expected fileExtensions to be an Array", .{}); origin_str.deinit(); arena.deinit(); globalThis.allocator().destroy(arena); - return null; + return globalThis.throwInvalidArguments2("Expected fileExtensions to be an Array", .{}); } var iter = file_extensions.arrayIterator(globalThis); extensions.ensureTotalCapacityPrecise(iter.len) catch unreachable; while (iter.next()) |val| { if (!val.isString()) { - globalThis.throwInvalidArguments("Expected fileExtensions to be an Array of strings", .{}); origin_str.deinit(); arena.deinit(); globalThis.allocator().destroy(arena); - return null; + return globalThis.throwInvalidArguments2("Expected fileExtensions to be an Array of strings", .{}); } if (val.getLength(globalThis) == 0) continue; extensions.appendAssumeCapacity((val.toSlice(globalThis, allocator).clone(allocator) catch unreachable).slice()[1..]); @@ -130,11 +122,10 @@ pub const FileSystemRouter = struct { if (argument.getTruthy(globalThis, "assetPrefix")) |asset_prefix| { if (!asset_prefix.isString()) { - globalThis.throwInvalidArguments("Expected assetPrefix to be a string", .{}); origin_str.deinit(); arena.deinit(); globalThis.allocator().destroy(arena); - return null; + return globalThis.throwInvalidArguments2("Expected assetPrefix to be a string", .{}); } asset_prefix_slice = asset_prefix.toSlice(globalThis, allocator).clone(allocator) catch unreachable; @@ -147,17 +138,15 @@ pub const FileSystemRouter = struct { const path_to_use = (root_dir_path.cloneWithTrailingSlash(allocator) catch unreachable).slice(); const root_dir_info = vm.bundler.resolver.readDirInfo(path_to_use) catch { - globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "reading root directory")); origin_str.deinit(); arena.deinit(); globalThis.allocator().destroy(arena); - return null; + return globalThis.throwValue2(log.toJS(globalThis, globalThis.allocator(), "reading root directory")); } orelse { - globalThis.throw("Unable to find directory: {s}", .{root_dir_path.slice()}); origin_str.deinit(); arena.deinit(); globalThis.allocator().destroy(arena); - return null; + return globalThis.throw2("Unable to find directory: {s}", .{root_dir_path.slice()}); }; var router = Router.init(vm.bundler.fs, allocator, .{ @@ -167,29 +156,26 @@ pub const FileSystemRouter = struct { }) catch unreachable; router.loadRoutes(&log, root_dir_info, Resolver, &vm.bundler.resolver, router.config.dir) catch { - globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "loading routes")); origin_str.deinit(); arena.deinit(); globalThis.allocator().destroy(arena); - return null; + return globalThis.throwValue2(log.toJS(globalThis, globalThis.allocator(), "loading routes")); }; if (argument.get(globalThis, "origin")) |origin| { if (!origin.isString()) { - globalThis.throwInvalidArguments("Expected origin to be a string", .{}); arena.deinit(); globalThis.allocator().destroy(arena); - return null; + return globalThis.throwInvalidArguments2("Expected origin to be a string", .{}); } origin_str = origin.toSlice(globalThis, globalThis.allocator()); } if (log.errors + log.warnings > 0) { - globalThis.throwValue(log.toJS(globalThis, globalThis.allocator(), "loading routes")); origin_str.deinit(); arena.deinit(); globalThis.allocator().destroy(arena); - return null; + return globalThis.throwValue2(log.toJS(globalThis, globalThis.allocator(), "loading routes")); } var fs_router = globalThis.allocator().create(FileSystemRouter) catch unreachable; diff --git a/src/bun.js/api/glob.zig b/src/bun.js/api/glob.zig index afe34b22f7..5571c60ddd 100644 --- a/src/bun.js/api/glob.zig +++ b/src/bun.js/api/glob.zig @@ -314,26 +314,21 @@ fn makeGlobWalker( return globWalker; } -pub fn constructor( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, -) ?*Glob { +pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*Glob { const alloc = getAllocator(globalThis); const arguments_ = callframe.arguments(1); var arguments = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments_.slice()); defer arguments.deinit(); - const pat_arg = arguments.nextEat() orelse { - globalThis.throw("Glob.constructor: expected 1 arguments, got 0", .{}); - return null; + const pat_arg: JSValue = arguments.nextEat() orelse { + return globalThis.throw2("Glob.constructor: expected 1 arguments, got 0", .{}); }; if (!pat_arg.isString()) { - globalThis.throw("Glob.constructor: first argument is not a string", .{}); - return null; + return globalThis.throw2("Glob.constructor: first argument is not a string", .{}); } - const pat_str: []u8 = @constCast((pat_arg.toSliceClone(globalThis) orelse return null).slice()); + const pat_str: []u8 = @constCast((pat_arg.toSliceClone(globalThis) orelse return error.JSError).slice()); const all_ascii = isAllAscii(pat_str); @@ -341,16 +336,10 @@ pub fn constructor( glob.* = .{ .pattern = pat_str, .is_ascii = all_ascii }; if (!all_ascii) { - var codepoints = std.ArrayList(u32).initCapacity(alloc, glob.pattern.len * 2) catch { - globalThis.throwOutOfMemory(); - return null; - }; + var codepoints = try std.ArrayList(u32).initCapacity(alloc, glob.pattern.len * 2); errdefer codepoints.deinit(); - convertUtf8(&codepoints, glob.pattern) catch { - globalThis.throwOutOfMemory(); - return null; - }; + try convertUtf8(&codepoints, glob.pattern); glob.pattern_codepoints = codepoints; } diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index de7f11da1a..7b2b4931f8 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -48,7 +48,7 @@ pub const HTMLRewriter = struct { pub usingnamespace JSC.Codegen.JSHTMLRewriter; - pub fn constructor(_: *JSGlobalObject, _: *JSC.CallFrame) callconv(.C) ?*HTMLRewriter { + pub fn constructor(_: *JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*HTMLRewriter { const rewriter = bun.default_allocator.create(HTMLRewriter) catch bun.outOfMemory(); rewriter.* = HTMLRewriter{ .builder = LOLHTML.HTMLRewriter.Builder.init(), @@ -198,7 +198,8 @@ pub const HTMLRewriter = struct { }; if (kind != .other) { - if (JSC.WebCore.Body.extract(global, response_value)) |body_value| { + { + const body_value = JSC.WebCore.Body.extract(global, response_value) catch return .zero; const resp = bun.new(Response, Response{ .init = .{ .status_code = 200, diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 9c483f0445..3824ebec3f 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -94,7 +94,8 @@ const BlobFileContentResult = struct { data: [:0]const u8, fn init(comptime fieldname: []const u8, js_obj: JSC.JSValue, global: *JSC.JSGlobalObject) bun.JSError!?BlobFileContentResult { - if (JSC.WebCore.Body.Value.fromJS(global, js_obj)) |body| { + { + const body = try JSC.WebCore.Body.Value.fromJS(global, js_obj); if (body == .Blob and body.Blob.store != null and body.Blob.store.?.data == .file) { var fs: JSC.Node.NodeFS = .{}; const read = fs.readFileWithOptions(.{ .path = body.Blob.store.?.data.file.pathlike }, .sync, .null_terminated); @@ -4817,9 +4818,8 @@ pub const ServerWebSocket = struct { return uws.WebSocketBehavior.Wrap(ServerType, @This(), ssl).apply(opts); } - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*ServerWebSocket { - globalObject.throw("Cannot construct ServerWebSocket", .{}); - return null; + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*ServerWebSocket { + return globalObject.throw2("Cannot construct ServerWebSocket", .{}); } pub fn finalize(this: *ServerWebSocket) void { @@ -5852,9 +5852,8 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp pub usingnamespace NamespaceType; pub usingnamespace bun.New(@This()); - pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*ThisServer { - globalThis.throw("Server() is not a constructor", .{}); - return null; + pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*ThisServer { + return globalThis.throw("Server() is not a constructor", .{}); } extern fn JSSocketAddress__create(global: *JSC.JSGlobalObject, ip: JSValue, port: i32, is_ipv6: bool) JSValue; diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index e3687ec989..086f73348e 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -3324,6 +3324,16 @@ pub const JSGlobalObject = opaque { this.vm().throwError(this, instance); } + pub fn throw2( + this: *JSGlobalObject, + comptime fmt: [:0]const u8, + args: anytype, + ) JSError { + const instance = this.createErrorInstance(fmt, args); + bun.assert(instance != .zero); + return this.vm().throwError2(this, instance); + } + pub fn throwPretty( this: *JSGlobalObject, comptime fmt: [:0]const u8, diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index 6a35883383..169c356f67 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -120,11 +120,6 @@ pub const NodeJSFS = struct { pub usingnamespace JSC.Codegen.JSNodeJSFS; pub usingnamespace bun.New(@This()); - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*@This() { - globalObject.throw("Not a constructor", .{}); - return null; - } - pub fn finalize(this: *JSC.Node.NodeJSFS) void { if (this.node_fs.vm) |vm| { if (vm.node_fs == &this.node_fs) { diff --git a/src/bun.js/node/node_zlib_binding.zig b/src/bun.js/node/node_zlib_binding.zig index 096c2a50e7..40a0dea83c 100644 --- a/src/bun.js/node/node_zlib_binding.zig +++ b/src/bun.js/node/node_zlib_binding.zig @@ -321,23 +321,23 @@ pub const SNativeZlib = struct { closed: bool = false, task: JSC.WorkPoolTask = .{ .callback = undefined }, - pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*@This() { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*@This() { const arguments = callframe.argumentsUndef(4).ptr; var mode = arguments[0]; if (!mode.isNumber()) { _ = globalThis.throwInvalidArgumentTypeValue("mode", "number", mode); - return null; + return error.JSError; } const mode_double = mode.asNumber(); if (@mod(mode_double, 1.0) != 0.0) { _ = globalThis.throwInvalidArgumentTypeValue("mode", "integer", mode); - return null; + return error.JSError; } const mode_int: i64 = @intFromFloat(mode_double); if (mode_int < 1 or mode_int > 7) { _ = globalThis.throwRangeError(mode_int, .{ .field_name = "mode", .min = 1, .max = 7 }); - return null; + return error.JSError; } const ptr = SNativeZlib.new(.{ @@ -681,23 +681,23 @@ pub const SNativeBrotli = struct { .callback = undefined, }, - pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*@This() { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*@This() { const arguments = callframe.argumentsUndef(1).ptr; var mode = arguments[0]; if (!mode.isNumber()) { _ = globalThis.throwInvalidArgumentTypeValue("mode", "number", mode); - return null; + return error.JSError; } const mode_double = mode.asNumber(); if (@mod(mode_double, 1.0) != 0.0) { _ = globalThis.throwInvalidArgumentTypeValue("mode", "integer", mode); - return null; + return error.JSError; } const mode_int: i64 = @intFromFloat(mode_double); if (mode_int < 8 or mode_int > 9) { _ = globalThis.throwRangeError(mode_int, .{ .field_name = "mode", .min = 8, .max = 9 }); - return null; + return error.JSError; } const ptr = @This().new(.{ diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 4b78d05bce..ec0b6e4b7f 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -1746,10 +1746,9 @@ pub fn StatType(comptime Big: bool) type { }; } - pub fn constructor(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(JSC.conv) ?*This { + pub fn constructor(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) bun.JSError!*This { if (Big) { - globalObject.throwInvalidArguments("BigIntStats is not a constructor", .{}); - return null; + return globalObject.throwInvalidArguments2("BigIntStats is not a constructor", .{}); } // dev, mode, nlink, uid, gid, rdev, blksize, ino, size, blocks, atimeMs, mtimeMs, ctimeMs, birthtimeMs @@ -1852,9 +1851,8 @@ pub const Dirent = struct { pub usingnamespace JSC.Codegen.JSDirent; pub usingnamespace bun.New(@This()); - pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(JSC.conv) ?*Dirent { - globalObject.throw("Dirent is not a constructor", .{}); - return null; + pub fn constructor(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*Dirent { + return globalObject.throw2("Dirent is not a constructor", .{}); } pub fn toJS(this: *Dirent, globalObject: *JSC.JSGlobalObject) JSC.JSValue { diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index b5c13afbb9..89755654d9 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -422,12 +422,8 @@ pub const Expect = struct { } } - pub fn constructor( - globalThis: *JSGlobalObject, - _: *CallFrame, - ) ?*Expect { - globalThis.throw("expect() cannot be called with new", .{}); - return null; + pub fn constructor(globalThis: *JSGlobalObject, _: *CallFrame) bun.JSError!*Expect { + return globalThis.throw2("expect() cannot be called with new", .{}); } // pass here has a leading underscore to avoid name collision with the pass variable in other functions diff --git a/src/bun.js/webcore.zig b/src/bun.js/webcore.zig index cdc099333f..83c1aade32 100644 --- a/src/bun.js/webcore.zig +++ b/src/bun.js/webcore.zig @@ -744,9 +744,8 @@ pub const Crypto = struct { return str.toJS(globalThis); } - pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*Crypto { - globalThis.throw("Crypto is not constructable", .{}); - return null; + pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*Crypto { + return globalThis.throw2("Crypto is not constructable", .{}); } pub export fn CryptoObject__create(globalThis: *JSC.JSGlobalObject) JSC.JSValue { diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index 72cb780498..83dd25b00d 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -3947,10 +3947,7 @@ pub const Blob = struct { } } - pub fn constructor( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) ?*Blob { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*Blob { const allocator = bun.default_allocator; var blob: Blob = undefined; var arguments = callframe.arguments(2); @@ -3964,12 +3961,11 @@ pub const Blob = struct { else => { blob = get(globalThis, args[0], false, true) catch |err| { if (err == error.InvalidArguments) { - globalThis.throwInvalidArguments("new Blob() expects an Array", .{}); - return null; + return globalThis.throwInvalidArguments2("new Blob() expects an Array", .{}); } if (!globalThis.hasException()) globalThis.throwOutOfMemory(); - return null; + return error.JSError; }; if (args.len > 1) { diff --git a/src/bun.js/webcore/body.zig b/src/bun.js/webcore/body.zig index 9ce2b8ac64..a40a03a526 100644 --- a/src/bun.js/webcore/body.zig +++ b/src/bun.js/webcore/body.zig @@ -530,10 +530,7 @@ pub const Body = struct { } } - pub fn fromJS( - globalThis: *JSGlobalObject, - value: JSValue, - ) ?Value { + pub fn fromJS(globalThis: *JSGlobalObject, value: JSValue) bun.JSError!Value { value.ensureStillAlive(); if (value.isEmptyOrUndefinedOrNull()) { @@ -579,8 +576,7 @@ pub const Body = struct { .InternalBlob = .{ .bytes = std.ArrayList(u8){ .items = bun.default_allocator.dupe(u8, bytes) catch { - globalThis.vm().throwError(globalThis, ZigString.static("Failed to clone ArrayBufferView").toErrorInstance(globalThis)); - return null; + return globalThis.vm().throwError2(globalThis, ZigString.static("Failed to clone ArrayBufferView").toErrorInstance(globalThis)); }, .capacity = bytes.len, .allocator = bun.default_allocator, @@ -615,8 +611,7 @@ pub const Body = struct { if (JSC.WebCore.ReadableStream.fromJS(value, globalThis)) |readable| { if (readable.isDisturbed(globalThis)) { - globalThis.throw("ReadableStream has already been used", .{}); - return null; + return globalThis.throw2("ReadableStream has already been used", .{}); } switch (readable.ptr) { @@ -643,14 +638,13 @@ pub const Body = struct { .Blob = Blob.get(globalThis, value, true, false) catch |err| { if (!globalThis.hasException()) { if (err == error.InvalidArguments) { - globalThis.throwInvalidArguments("Expected an Array", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected an Array", .{}); } - globalThis.throwInvalidArguments("Invalid Body object", .{}); + return globalThis.throwInvalidArguments2("Invalid Body object", .{}); } - return null; + return error.JSError; }, }; } @@ -1091,10 +1085,10 @@ pub const Body = struct { pub fn extract( globalThis: *JSGlobalObject, value: JSValue, - ) ?Body { + ) bun.JSError!Body { var body = Body{ .value = Value{ .Null = {} } }; - body.value = Value.fromJS(globalThis, value) orelse return null; + body.value = try Value.fromJS(globalThis, value); if (body.value == .Blob) assert(body.value.Blob.allocator == null); // owned by Body diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig index 161e46275c..f18f329b6d 100644 --- a/src/bun.js/webcore/encoding.zig +++ b/src/bun.js/webcore/encoding.zig @@ -416,7 +416,7 @@ pub const TextEncoderStreamEncoder = struct { this.destroy(); } - pub fn constructor(_: *JSGlobalObject, _: *JSC.CallFrame) ?*TextEncoderStreamEncoder { + pub fn constructor(_: *JSGlobalObject, _: *JSC.CallFrame) bun.JSError!*TextEncoderStreamEncoder { return TextEncoderStreamEncoder.new(.{}); } @@ -903,10 +903,7 @@ pub const TextDecoder = struct { } } - pub fn constructor( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) ?*TextDecoder { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*TextDecoder { var args_ = callframe.arguments(2); var arguments: []const JSC.JSValue = args_.ptr[0..args_.len]; @@ -921,31 +918,27 @@ pub const TextDecoder = struct { if (EncodingLabel.which(str.slice())) |label| { decoder.encoding = label; } else { - globalThis.throwInvalidArguments("Unsupported encoding label \"{s}\"", .{str.slice()}); - return null; + return globalThis.throwInvalidArguments2("Unsupported encoding label \"{s}\"", .{str.slice()}); } } else if (arguments[0].isUndefined()) { // default to utf-8 decoder.encoding = EncodingLabel.@"UTF-8"; } else { - globalThis.throwInvalidArguments("TextDecoder(encoding) label is invalid", .{}); - return null; + return globalThis.throwInvalidArguments2("TextDecoder(encoding) label is invalid", .{}); } if (arguments.len >= 2) { const options = arguments[1]; if (!options.isObject()) { - globalThis.throwInvalidArguments("TextDecoder(options) is invalid", .{}); - return null; + return globalThis.throwInvalidArguments2("TextDecoder(options) is invalid", .{}); } if (options.get(globalThis, "fatal")) |fatal| { if (fatal.isBoolean()) { decoder.fatal = fatal.asBoolean(); } else { - globalThis.throwInvalidArguments("TextDecoder(options) fatal is invalid. Expected boolean value", .{}); - return null; + return globalThis.throwInvalidArguments2("TextDecoder(options) fatal is invalid. Expected boolean value", .{}); } } @@ -953,8 +946,7 @@ pub const TextDecoder = struct { if (ignoreBOM.isBoolean()) { decoder.ignore_bom = ignoreBOM.asBoolean(); } else { - globalThis.throwInvalidArguments("TextDecoder(options) ignoreBOM is invalid. Expected boolean value", .{}); - return null; + return globalThis.throwInvalidArguments2("TextDecoder(options) ignoreBOM is invalid. Expected boolean value", .{}); } } } diff --git a/src/bun.js/webcore/request.zig b/src/bun.js/webcore/request.zig index 1bf5c3c7c2..242d54404f 100644 --- a/src/bun.js/webcore/request.zig +++ b/src/bun.js/webcore/request.zig @@ -524,15 +524,10 @@ pub const Request = struct { url, }; - pub fn constructInto( - globalThis: *JSC.JSGlobalObject, - arguments: []const JSC.JSValue, - ) ?Request { + pub fn constructInto(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSValue) bun.JSError!Request { var success = false; const vm = globalThis.bunVM(); - const body = vm.initRequestBodyValue(.{ .Null = {} }) catch { - return null; - }; + const body = try vm.initRequestBodyValue(.{ .Null = {} }); var req = Request{ .body = body, }; @@ -547,11 +542,9 @@ pub const Request = struct { } if (arguments.len == 0) { - globalThis.throw("Failed to construct 'Request': 1 argument required, but only 0 present.", .{}); - return null; + return globalThis.throw2("Failed to construct 'Request': 1 argument required, but only 0 present.", .{}); } else if (arguments[0].isEmptyOrUndefinedOrNull() or !arguments[0].isCell()) { - globalThis.throw("Failed to construct 'Request': expected non-empty string or object, got undefined", .{}); - return null; + return globalThis.throw2("Failed to construct 'Request': expected non-empty string or object, got undefined", .{}); } const url_or_object = arguments[0]; @@ -565,16 +558,13 @@ pub const Request = struct { url_or_object.as(JSC.DOMURL) != null; if (is_first_argument_a_url) { - const str = bun.String.tryFromJS(arguments[0], globalThis) orelse { - return null; - }; + const str = try bun.String.fromJS2(arguments[0], globalThis); req.url = str; if (!req.url.isEmpty()) fields.insert(.url); } else if (!url_or_object_type.isObject()) { - globalThis.throw("Failed to construct 'Request': expected non-empty string or object", .{}); - return null; + return globalThis.throw2("Failed to construct 'Request': expected non-empty string or object", .{}); } const values_to_try_ = [_]JSValue{ @@ -610,7 +600,7 @@ pub const Request = struct { fields.insert(.headers); } - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; } if (!fields.contains(.body)) { @@ -618,7 +608,7 @@ pub const Request = struct { .Null, .Empty, .Used => {}, else => { req.body.value = request.body.value.clone(globalThis); - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; fields.insert(.body); }, } @@ -655,19 +645,17 @@ pub const Request = struct { } } - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; } } if (!fields.contains(.body)) { if (value.fastGet(globalThis, .body)) |body_| { fields.insert(.body); - req.body.value = Body.Value.fromJS(globalThis, body_) orelse { - return null; - }; + req.body.value = try Body.Value.fromJS(globalThis, body_); } - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; } if (!fields.contains(.url)) { @@ -680,13 +668,13 @@ pub const Request = struct { } else if (@intFromEnum(value) == @intFromEnum(values_to_try[values_to_try.len - 1]) and !is_first_argument_a_url and value.implementsToString(globalThis)) { - const str = bun.String.tryFromJS(value, globalThis) orelse return null; + const str = bun.String.tryFromJS(value, globalThis) orelse return error.JSError; req.url = str; if (!req.url.isEmpty()) fields.insert(.url); } - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; } if (!fields.contains(.signal)) { @@ -700,16 +688,16 @@ pub const Request = struct { if (!globalThis.hasException()) { globalThis.throw("Failed to construct 'Request': signal is not of type AbortSignal.", .{}); } - return null; + return error.JSError; } } - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; } if (!fields.contains(.method) or !fields.contains(.headers)) { - if (globalThis.hasException()) return null; - if (Response.Init.init(globalThis, value) catch null) |response_init| { + if (globalThis.hasException()) return error.JSError; + if (try Response.Init.init(globalThis, value)) |response_init| { if (!explicit_check or (explicit_check and value.fastGet(globalThis, .headers) != null)) { if (response_init.headers) |headers| { if (!fields.contains(.headers)) { @@ -721,7 +709,7 @@ pub const Request = struct { } } - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; if (!explicit_check or (explicit_check and value.fastGet(globalThis, .method) != null)) { if (!fields.contains(.method)) { @@ -729,20 +717,19 @@ pub const Request = struct { fields.insert(.method); } } - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; } - if (globalThis.hasException()) return null; + if (globalThis.hasException()) return error.JSError; } } if (globalThis.hasException()) { - return null; + return error.JSError; } if (req.url.isEmpty()) { - globalThis.throw("Failed to construct 'Request': url is required.", .{}); - return null; + return globalThis.throw2("Failed to construct 'Request': url is required.", .{}); } const href = JSC.URL.hrefFromString(req.url); @@ -754,7 +741,7 @@ pub const Request = struct { req.url, }).throw(); } - return null; + return error.JSError; } // hrefFromString increments the reference count if they end up being @@ -779,16 +766,12 @@ pub const Request = struct { return req; } - pub fn constructor( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) ?*Request { + + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*Request { const arguments_ = callframe.arguments(2); const arguments = arguments_.ptr[0..arguments_.len]; - const request = constructInto(globalThis, arguments) orelse { - return null; - }; + const request = try constructInto(globalThis, arguments); return Request.new(request); } diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig index 0e0f6ddf27..d336886c8d 100644 --- a/src/bun.js/webcore/response.zig +++ b/src/bun.js/webcore/response.zig @@ -509,76 +509,42 @@ pub const Response = struct { return response.toJS(globalThis); } - pub fn constructor( - globalThis: *JSC.JSGlobalObject, - callframe: *JSC.CallFrame, - ) ?*Response { - const args_list = brk: { - var args = callframe.arguments(2); - if (args.len > 1 and args.ptr[1].isEmptyOrUndefinedOrNull()) { - args.len = 1; + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*Response { + const arguments = callframe.argumentsAsArray(2); + + var init: Init = (brk: { + if (arguments[1].isUndefinedOrNull()) { + break :brk Init{ + .status_code = 200, + .headers = null, + }; } - break :brk args; - }; - - const arguments = args_list.ptr[0..args_list.len]; - - var init: Init = @as(?Init, brk: { - switch (arguments.len) { - 0 => { - break :brk Init{ - .status_code = 200, - .headers = null, - }; - }, - 1 => { - break :brk Init{ - .status_code = 200, - .headers = null, - }; - }, - else => { - if (arguments[1].isObject()) { - break :brk Init.init(globalThis, arguments[1]) catch null; - } - - if (!globalThis.hasException()) { - globalThis.throwInvalidArguments("new Response() requires a Response-like object in the 2nd argument", .{}); - } - - break :brk null; - }, + if (arguments[1].isObject()) { + break :brk try Init.init(globalThis, arguments[1]) orelse unreachable; } - unreachable; - }) orelse return null; + if (!globalThis.hasException()) { + return globalThis.throwInvalidArguments2("Failed to construct 'Response': The provided body value is not of type 'ResponseInit'", .{}); + } + return error.JSError; + }); + errdefer init.deinit(bun.default_allocator); if (globalThis.hasException()) { - init.deinit(bun.default_allocator); - return null; + return error.JSError; } var body: Body = brk: { - switch (arguments.len) { - 0 => { - break :brk Body{ - .value = Body.Value{ .Null = {} }, - }; - }, - else => { - break :brk Body.extract(globalThis, arguments[0]); - }, + if (arguments[0].isUndefinedOrNull()) { + break :brk Body{ + .value = Body.Value{ .Null = {} }, + }; } - unreachable; - } orelse { - init.deinit(bun.default_allocator); - - return null; + break :brk try Body.extract(globalThis, arguments[0]); }; + errdefer body.deinit(bun.default_allocator); if (globalThis.hasException()) { - body.deinit(bun.default_allocator); - init.deinit(bun.default_allocator); - return null; + return error.JSError; } var response = bun.new(Response, Response{ @@ -616,7 +582,7 @@ pub const Response = struct { return that; } - pub fn init(globalThis: *JSGlobalObject, response_init: JSC.JSValue) !?Init { + pub fn init(globalThis: *JSGlobalObject, response_init: JSC.JSValue) bun.JSError!?Init { var result = Init{ .status_code = 200 }; errdefer { result.deinit(bun.default_allocator); @@ -2583,10 +2549,8 @@ pub const Fetch = struct { if (options_object) |options| { if (options.fastGet(globalThis, .body)) |body__| { if (!body__.isUndefined()) { - if (Body.Value.fromJS(ctx.ptr(), body__)) |body_const| { - var body_value = body_const; - break :extract_body body_value.useAsAnyBlob(); - } + var body_value = try Body.Value.fromJS(ctx.ptr(), body__); + break :extract_body body_value.useAsAnyBlob(); } } @@ -2609,10 +2573,8 @@ pub const Fetch = struct { if (request_init_object) |req| { if (req.fastGet(globalThis, .body)) |body__| { if (!body__.isUndefined()) { - if (Body.Value.fromJS(ctx.ptr(), body__)) |body_const| { - var body_value = body_const; - break :extract_body body_value.useAsAnyBlob(); - } + var body_value = try Body.Value.fromJS(ctx.ptr(), body__); + break :extract_body body_value.useAsAnyBlob(); } } } diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index 50281b1440..12c78ff158 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -1728,7 +1728,13 @@ const JavaScriptCoreBindings = struct { output += ` pub fn ${classSymbolName(typeName, "construct")}(globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(JSC.conv) ?*anyopaque { if (comptime Environment.enable_logs) zig("new ${typeName}({})", .{callFrame}); - return @call(.always_inline, wrapConstructor(${typeName}, ${typeName}.constructor), .{globalObject, callFrame}); + return @as(*${typeName}, ${typeName}.constructor(globalObject, callFrame) catch |err| switch (err) { + error.JSError => return null, + error.OutOfMemory => { + globalObject.throwOutOfMemory(); + return null; + }, + }); } `; } diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index f79476c3e3..73b7499b08 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -404,10 +404,9 @@ pub const PostgresSQLQuery = struct { }); } - pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*PostgresSQLQuery { + pub fn constructor(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*PostgresSQLQuery { _ = callframe; - globalThis.throw("PostgresSQLQuery cannot be constructed directly", .{}); - return null; + return globalThis.throw2("PostgresSQLQuery cannot be constructed directly", .{}); } pub fn estimatedSize(this: *PostgresSQLQuery) usize { @@ -1213,10 +1212,9 @@ pub const PostgresSQLConnection = struct { } } - pub fn constructor(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) ?*PostgresSQLConnection { + pub fn constructor(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*PostgresSQLConnection { _ = callframe; - globalObject.throw("PostgresSQLConnection cannot be constructed directly", .{}); - return null; + return globalObject.throw2("PostgresSQLConnection cannot be constructed directly", .{}); } comptime {