From b6b3626c1452f57f341698c78e48fcd10dbff71a Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Wed, 21 Jan 2026 13:01:25 -0800 Subject: [PATCH] fix(bindings): handle errors from String.toJS() for oversized strings (#26213) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - When a string exceeds `WTF::String::MaxLength` (~4GB), `bun.String.createUninitialized()` returns a `.Dead` tag - The C++ layer now properly throws `ERR_STRING_TOO_LONG` when this happens - Updated `String.toJS()` in Zig to return `bun.JSError!jsc.JSValue` instead of just `jsc.JSValue` - Updated ~40 Zig caller files to handle the error with `try` - C++ callers updated with `RETURN_IF_EXCEPTION` checks ## Test plan - [x] `bun bd test test/js/node/buffer.test.js` - 449 tests pass - [x] `bun bd test/js/node/test/parallel/test-buffer-tostring-rangeerror.js` - passes 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Claude Bot --- src/bake/DevServer.zig | 10 +- src/bake/FrameworkRouter.zig | 22 ++-- src/bake/production.zig | 14 +- src/bun.js/BuildMessage.zig | 2 +- src/bun.js/ResolveMessage.zig | 4 +- src/bun.js/api/Archive.zig | 4 +- src/bun.js/api/BunObject.zig | 8 +- src/bun.js/api/JSTranspiler.zig | 5 +- src/bun.js/api/Timer.zig | 10 +- src/bun.js/api/bun/Terminal.zig | 2 +- src/bun.js/api/bun/dns.zig | 4 +- src/bun.js/api/bun/js_bun_spawn_bindings.zig | 10 +- src/bun.js/api/bun/socket.zig | 62 ++++----- src/bun.js/api/bun/socket/Listener.zig | 6 +- src/bun.js/api/bun/socket/SocketAddress.zig | 12 +- .../bun/socket/WindowsNamedPipeContext.zig | 24 ++-- .../api/bun/socket/tls_socket_functions.zig | 4 +- src/bun.js/api/bun/subprocess.zig | 11 +- src/bun.js/api/bun/udp_socket.zig | 16 +-- src/bun.js/api/filesystem_router.zig | 2 +- src/bun.js/api/glob.zig | 12 +- src/bun.js/api/html_rewriter.zig | 20 +-- src/bun.js/api/server.zig | 6 +- src/bun.js/api/server/RequestContext.zig | 27 ++-- src/bun.js/api/server/SSLConfig.zig | 2 +- src/bun.js/api/server/ServerWebSocket.zig | 2 +- src/bun.js/bindings/BunDebugger.cpp | 6 +- src/bun.js/bindings/BunPlugin.cpp | 8 +- src/bun.js/bindings/BunString.cpp | 34 ++++- src/bun.js/bindings/JSGlobalObject.zig | 2 +- src/bun.js/bindings/ModuleLoader.cpp | 3 +- src/bun.js/bindings/S3Error.cpp | 18 ++- src/bun.js/bindings/bindings.cpp | 35 +++-- src/bun.js/event_loop/ManagedTask.zig | 6 +- src/bun.js/ipc.zig | 17 +-- src/bun.js/jsc/array_buffer.zig | 6 +- src/bun.js/node/net/BlockList.zig | 8 +- src/bun.js/node/node_cluster_binding.zig | 2 +- src/bun.js/node/node_fs.zig | 20 +-- src/bun.js/node/node_fs_binding.zig | 4 +- src/bun.js/node/node_fs_watcher.zig | 6 +- src/bun.js/node/node_os.zig | 8 +- src/bun.js/node/node_process.zig | 10 +- src/bun.js/node/node_zlib_binding.zig | 4 +- src/bun.js/node/types.zig | 15 +-- src/bun.js/node/util/parse_args.zig | 20 +-- src/bun.js/test/expect.zig | 12 +- src/bun.js/test/jest.zig | 2 +- src/bun.js/webcore/Blob.zig | 39 +++--- src/bun.js/webcore/Body.zig | 28 ++-- src/bun.js/webcore/ReadableStream.zig | 4 +- src/bun.js/webcore/Response.zig | 6 +- src/bun.js/webcore/S3Stat.zig | 4 +- src/bun.js/webcore/Sink.zig | 2 +- src/bun.js/webcore/encoding.zig | 14 +- src/bun.js/webcore/fetch.zig | 4 +- src/bun.js/webcore/fetch/FetchTasklet.zig | 16 ++- src/bun.js/webcore/streams.zig | 6 +- src/cli/pack_command.zig | 8 +- src/crash_handler.zig | 6 +- src/deps/c_ares.zig | 16 +-- src/deps/lol-html.zig | 4 +- src/deps/uws.zig | 2 +- src/deps/uws/socket.zig | 120 +++++------------- src/fd.zig | 5 +- src/install/PackageManager/UpdateRequest.zig | 2 +- src/install/dependency.zig | 4 +- src/install/hosted_git_info.zig | 14 +- src/napi/napi.zig | 8 +- src/patch.zig | 4 +- src/sql/mysql/js/JSMySQLConnection.zig | 2 +- src/sql/postgres/PostgresSQLConnection.zig | 6 +- src/string.zig | 8 +- src/sys/Error.zig | 2 +- src/transpiler.zig | 11 +- src/valkey/js_valkey.zig | 10 +- test/internal/ban-limits.json | 2 +- test/js/bun/s3/s3.test.ts | 3 +- 78 files changed, 471 insertions(+), 436 deletions(-) diff --git a/src/bake/DevServer.zig b/src/bake/DevServer.zig index 86f0bdb196..895a6e90b5 100644 --- a/src/bake/DevServer.zig +++ b/src/bake/DevServer.zig @@ -1355,7 +1355,7 @@ fn computeArgumentsForFrameworkRequest( const relative_path_buf = bun.path_buffer_pool.get(); defer bun.path_buffer_pool.put(relative_path_buf); var route_name = bun.String.cloneUTF8(dev.relativePath(relative_path_buf, keys[fromOpaqueFileId(.server, route.file_page.unwrap().?).get()])); - try arr.putIndex(global, 0, route_name.transferToJS(global)); + try arr.putIndex(global, 0, try route_name.transferToJS(global)); } n = 1; while (true) { @@ -1366,7 +1366,7 @@ fn computeArgumentsForFrameworkRequest( relative_path_buf, keys[fromOpaqueFileId(.server, layout).get()], )); - try arr.putIndex(global, @intCast(n), layout_name.transferToJS(global)); + try arr.putIndex(global, @intCast(n), try layout_name.transferToJS(global)); n += 1; } route = dev.router.routePtr(route.parent.unwrap() orelse break); @@ -1383,7 +1383,7 @@ fn computeArgumentsForFrameworkRequest( std.mem.asBytes(&generation), }) catch |err| bun.handleOom(err); defer str.deref(); - const js = str.toJS(dev.vm.global); + const js = try str.toJS(dev.vm.global); framework_bundle.cached_client_bundle_url = .create(js, dev.vm.global); break :str js; }, @@ -2091,7 +2091,7 @@ fn generateCssJSArray(dev: *DevServer, route_bundle: *RouteBundle) bun.JSError!j }) catch unreachable; const str = bun.String.cloneUTF8(path); defer str.deref(); - try arr.putIndex(dev.vm.global, @intCast(i), str.toJS(dev.vm.global)); + try arr.putIndex(dev.vm.global, @intCast(i), try str.toJS(dev.vm.global)); } return arr; } @@ -2136,7 +2136,7 @@ fn makeArrayForServerComponentsPatch(dev: *DevServer, global: *jsc.JSGlobalObjec defer bun.path_buffer_pool.put(relative_path_buf); const str = bun.String.cloneUTF8(dev.relativePath(relative_path_buf, names[item.get()])); defer str.deref(); - try arr.putIndex(global, @intCast(i), str.toJS(global)); + try arr.putIndex(global, @intCast(i), try str.toJS(global)); } return arr; } diff --git a/src/bake/FrameworkRouter.zig b/src/bake/FrameworkRouter.zig index 010c60b202..103e04623c 100644 --- a/src/bake/FrameworkRouter.zig +++ b/src/bake/FrameworkRouter.zig @@ -839,7 +839,7 @@ pub const MatchedParams = struct { const value_str = bun.String.cloneUTF8(param.value); defer value_str.deref(); - _ = obj.putBunStringOneOrArray(global, &key_str, value_str.toJS(global)) catch unreachable; + _ = obj.putBunStringOneOrArray(global, &key_str, value_str.toJS(global) catch unreachable) catch unreachable; } return obj; } @@ -1247,7 +1247,7 @@ pub const JSFrameworkRouter = struct { for (params_out.params.slice()) |param| { const value = bun.String.cloneUTF8(param.value); defer value.deref(); - obj.put(global, param.key, value.toJS(global)); + obj.put(global, param.key, try value.toJS(global)); } break :params obj; } else .null, @@ -1271,8 +1271,8 @@ pub const JSFrameworkRouter = struct { const route = jsfr.router.routePtr(route_index); return (try jsc.JSObject.create(.{ .part = try partToJS(global, route.part, allocator), - .page = jsfr.fileIdToJS(global, route.file_page), - .layout = jsfr.fileIdToJS(global, route.file_layout), + .page = try jsfr.fileIdToJS(global, route.file_page), + .layout = try jsfr.fileIdToJS(global, route.file_layout), // .notFound = jsfr.fileIdToJS(global, route.file_not_found), .children = brk: { var len: usize = 0; @@ -1295,8 +1295,8 @@ pub const JSFrameworkRouter = struct { const route = jsfr.router.routePtr(route_index); return (try jsc.JSObject.create(.{ .part = try partToJS(global, route.part, allocator), - .page = jsfr.fileIdToJS(global, route.file_page), - .layout = jsfr.fileIdToJS(global, route.file_layout), + .page = try jsfr.fileIdToJS(global, route.file_page), + .layout = try jsfr.fileIdToJS(global, route.file_layout), // .notFound = jsfr.fileIdToJS(global, route.file_not_found), .parent = if (route.parent.unwrap()) |parent| try routeToJsonInverse(jsfr, global, parent, allocator) @@ -1341,8 +1341,8 @@ pub const JSFrameworkRouter = struct { var out = bun.String.init(rendered.items); const obj = JSValue.createEmptyObject(global, 2); - obj.put(global, "kind", bun.String.static(@tagName(parsed.kind)).toJS(global)); - obj.put(global, "pattern", out.transferToJS(global)); + obj.put(global, "kind", try bun.String.static(@tagName(parsed.kind)).toJS(global)); + obj.put(global, "pattern", try out.transferToJS(global)); return obj; } @@ -1352,7 +1352,7 @@ pub const JSFrameworkRouter = struct { var it = pattern.iterate(); while (it.next()) |part| try part.toStringForInternalUse(rendered.writer()); var str = bun.String.cloneUTF8(rendered.items); - return str.transferToJS(global); + return try str.transferToJS(global); } fn partToJS(global: *JSGlobalObject, part: Part, temp_allocator: Allocator) !JSValue { @@ -1360,7 +1360,7 @@ pub const JSFrameworkRouter = struct { defer rendered.deinit(); try part.toStringForInternalUse(rendered.writer()); var str = bun.String.cloneUTF8(rendered.items); - return str.transferToJS(global); + return try str.transferToJS(global); } pub fn getFileIdForRouter(jsfr: *JSFrameworkRouter, abs_path: []const u8, _: Route.Index, _: Route.FileKind) !OpaqueFileId { @@ -1377,7 +1377,7 @@ pub const JSFrameworkRouter = struct { }); } - pub fn fileIdToJS(jsfr: *JSFrameworkRouter, global: *JSGlobalObject, id: OpaqueFileId.Optional) JSValue { + pub fn fileIdToJS(jsfr: *JSFrameworkRouter, global: *JSGlobalObject, id: OpaqueFileId.Optional) bun.JSError!JSValue { return jsfr.files.items[(id.unwrap() orelse return .null).get()].toJS(global); } }; diff --git a/src/bake/production.zig b/src/bake/production.zig index ffed2b5127..3c18ac7d95 100644 --- a/src/bake/production.zig +++ b/src/bake/production.zig @@ -182,7 +182,7 @@ pub fn buildWithVm(ctx: bun.cli.Command.Context, cwd: []const u8, vm: *VirtualMa .pending => unreachable, .fulfilled => |resolved| config: { bun.assert(resolved.isUndefined()); - const default = BakeGetDefaultExportFromModule(vm.global, config_entry_point_string.toJS(vm.global)); + const default = BakeGetDefaultExportFromModule(vm.global, try config_entry_point_string.toJS(vm.global)); if (!default.isObject()) { return global.throwInvalidArguments( @@ -485,7 +485,7 @@ pub fn buildWithVm(ctx: bun.cli.Command.Context, cwd: []const u8, vm: *VirtualMa for (router.types, 0..) |router_type, i| { if (router_type.client_file.unwrap()) |client_file| { - const str = (try bun.String.createFormat("{s}{s}", .{ + const str = try (try bun.String.createFormat("{s}{s}", .{ public_path, pt.outputFile(client_file).dest_path, })).toJS(global); @@ -542,7 +542,7 @@ pub fn buildWithVm(ctx: bun.cli.Command.Context, cwd: []const u8, vm: *VirtualMa bun.assert(output_file.dest_path[0] != '.'); // CSS chunks must be in contiguous order!! bun.assert(output_file.loader.isCSS()); - str.* = (try bun.String.createFormat("{s}{s}", .{ public_path, output_file.dest_path })).toJS(global); + str.* = try (try bun.String.createFormat("{s}{s}", .{ public_path, output_file.dest_path })).toJS(global); } // Route URL patterns with parameter placeholders. @@ -659,10 +659,10 @@ pub fn buildWithVm(ctx: bun.cli.Command.Context, cwd: []const u8, vm: *VirtualMa // Init the items var pattern_string = bun.String.cloneUTF8(pattern.slice()); defer pattern_string.deref(); - try route_patterns.putIndex(global, @intCast(nav_index), pattern_string.toJS(global)); + try route_patterns.putIndex(global, @intCast(nav_index), try pattern_string.toJS(global)); var src_path = bun.String.cloneUTF8(bun.path.relative(cwd, pt.inputFile(main_file_route_index).absPath())); - try route_source_files.putIndex(global, @intCast(nav_index), src_path.transferToJS(global)); + try route_source_files.putIndex(global, @intCast(nav_index), try src_path.transferToJS(global)); try route_nested_files.putIndex(global, @intCast(nav_index), file_list); try route_type_and_flags.putIndex(global, @intCast(nav_index), JSValue.jsNumberFromInt32(@bitCast(TypeAndFlags{ @@ -993,7 +993,7 @@ pub const PerThread = struct { return try loadModule( pt.vm, pt.vm.global, - pt.module_keys[id.get()].toJS(pt.vm.global), + try pt.module_keys[id.get()].toJS(pt.vm.global), ); } @@ -1010,7 +1010,7 @@ pub const PerThread = struct { try pt.all_server_files.putIndex( pt.vm.global, @intCast(id.get()), - pt.module_keys[id.get()].toJS(pt.vm.global), + try pt.module_keys[id.get()].toJS(pt.vm.global), ); } diff --git a/src/bun.js/BuildMessage.zig b/src/bun.js/BuildMessage.zig index 8855b9ef38..ced3a1df92 100644 --- a/src/bun.js/BuildMessage.zig +++ b/src/bun.js/BuildMessage.zig @@ -94,7 +94,7 @@ pub const BuildMessage = struct { _: *jsc.CallFrame, ) bun.JSError!jsc.JSValue { var object = jsc.JSValue.createEmptyObject(globalThis, 4); - object.put(globalThis, ZigString.static("name"), bun.String.static("BuildMessage").toJS(globalThis)); + object.put(globalThis, ZigString.static("name"), try bun.String.static("BuildMessage").toJS(globalThis)); object.put(globalThis, ZigString.static("position"), this.getPosition(globalThis)); object.put(globalThis, ZigString.static("message"), this.getMessage(globalThis)); object.put(globalThis, ZigString.static("level"), this.getLevel(globalThis)); diff --git a/src/bun.js/ResolveMessage.zig b/src/bun.js/ResolveMessage.zig index c7707cb693..817cd6a628 100644 --- a/src/bun.js/ResolveMessage.zig +++ b/src/bun.js/ResolveMessage.zig @@ -13,7 +13,7 @@ pub const ResolveMessage = struct { return globalThis.throw("ResolveMessage is not constructable", .{}); } - pub fn getCode(this: *ResolveMessage, globalObject: *jsc.JSGlobalObject) jsc.JSValue { + pub fn getCode(this: *ResolveMessage, globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { switch (this.msg.metadata) { .resolve => |resolve| { const code: []const u8 = brk: { @@ -153,7 +153,7 @@ pub const ResolveMessage = struct { _: *jsc.CallFrame, ) bun.JSError!jsc.JSValue { var object = jsc.JSValue.createEmptyObject(globalThis, 7); - object.put(globalThis, ZigString.static("name"), bun.String.static("ResolveMessage").toJS(globalThis)); + object.put(globalThis, ZigString.static("name"), try bun.String.static("ResolveMessage").toJS(globalThis)); object.put(globalThis, ZigString.static("position"), this.getPosition(globalThis)); object.put(globalThis, ZigString.static("message"), this.getMessage(globalThis)); object.put(globalThis, ZigString.static("level"), this.getLevel(globalThis)); diff --git a/src/bun.js/api/Archive.zig b/src/bun.js/api/Archive.zig index bd1c65d6f9..f34a806580 100644 --- a/src/bun.js/api/Archive.zig +++ b/src/bun.js/api/Archive.zig @@ -712,7 +712,7 @@ const WriteContext = struct { return switch (this.result) { .success => .{ .resolve = .js_undefined }, .err => |e| .{ .reject = globalThis.createErrorInstance("{s}", .{@errorName(e)}) }, - .sys_err => |sys_err| .{ .reject = sys_err.toJS(globalThis) }, + .sys_err => |sys_err| .{ .reject = try sys_err.toJS(globalThis) }, }; } @@ -866,7 +866,7 @@ const FilesContext = struct { blob_ptr.name = bun.String.cloneUTF8(entry.path); blob_ptr.last_modified = @floatFromInt(entry.mtime * 1000); - try map_ptr.set(globalThis, blob_ptr.name.toJS(globalThis), blob_ptr.toJS(globalThis)); + try map_ptr.set(globalThis, try blob_ptr.name.toJS(globalThis), blob_ptr.toJS(globalThis)); } return .{ .resolve = map }; diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 46d3421428..be6a22d4dd 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -606,7 +606,7 @@ fn getMain(globalThis: *jsc.JSGlobalObject) callconv(jsc.conv) jsc.JSValue { } } - return vm.main_resolved_path.toJS(globalThis); + return vm.main_resolved_path.toJS(globalThis) catch .zero; } return ZigString.init(vm.main).toJS(globalThis); @@ -1103,7 +1103,7 @@ pub export fn Bun__escapeHTML16(globalObject: *jsc.JSGlobalObject, input_value: assert(len > 0); const input_slice = ptr[0..len]; const escaped = strings.escapeHTMLForUTF16Input(globalObject.bunVM().allocator, input_slice) catch { - return globalObject.throwValue(bun.String.static("Out of memory").toJS(globalObject)) catch .zero; + return globalObject.throwValue(ZigString.init("Out of memory").toErrorInstance(globalObject)) catch return .zero; }; return switch (escaped) { @@ -1121,7 +1121,7 @@ pub export fn Bun__escapeHTML8(globalObject: *jsc.JSGlobalObject, input_value: J const allocator = if (input_slice.len <= 32) stack_allocator.get() else stack_allocator.fallback_allocator; const escaped = strings.escapeHTMLForLatin1Input(allocator, input_slice) catch { - return globalObject.throwValue(bun.String.static("Out of memory").toJS(globalObject)) catch .zero; + return globalObject.throwValue(ZigString.init("Out of memory").toErrorInstance(globalObject)) catch return .zero; }; switch (escaped) { @@ -1238,7 +1238,7 @@ pub fn mmapFile(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun. .result => |map| map, .err => |err| { - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, }; diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 2524468d1a..059c92297d 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -569,7 +569,10 @@ pub const TransformTask = struct { } fn finish(this: *TransformTask, promise: *jsc.JSPromise) bun.JSTerminated!void { - return promise.resolve(this.global, this.output_code.transferToJS(this.global)); + const value = this.output_code.transferToJS(this.global) catch |e| { + return promise.reject(this.global, this.global.takeException(e)); + }; + return promise.resolve(this.global, value); } pub fn deinit(this: *TransformTask) void { diff --git a/src/bun.js/api/Timer.zig b/src/bun.js/api/Timer.zig index 1daaaeae89..b6f0474711 100644 --- a/src/bun.js/api/Timer.zig +++ b/src/bun.js/api/Timer.zig @@ -351,13 +351,15 @@ pub const All = struct { }, }; var warning_type_string = bun.String.createAtomIfPossible(@tagName(warning_type)); - // these arguments are valid so emitWarning won't throw + // Ignore errors from transferToJS since this is just a warning and shouldn't interrupt execution + const warning_js = warning_string.transferToJS(globalThis) catch return; + const warning_type_js = warning_type_string.transferToJS(globalThis) catch return; globalThis.emitWarning( - warning_string.transferToJS(globalThis), - warning_type_string.transferToJS(globalThis), + warning_js, + warning_type_js, .js_undefined, .js_undefined, - ) catch unreachable; + ) catch {}; } const CountdownOverflowBehavior = enum(u8) { diff --git a/src/bun.js/api/bun/Terminal.zig b/src/bun.js/api/bun/Terminal.zig index d6a660f1c4..0eabeb96f6 100644 --- a/src/bun.js/api/bun/Terminal.zig +++ b/src/bun.js/api/bun/Terminal.zig @@ -618,7 +618,7 @@ pub fn write( .done => |amt| JSValue.jsNumber(@as(i32, @intCast(amt))), .wrote => |amt| JSValue.jsNumber(@as(i32, @intCast(amt))), .pending => |amt| JSValue.jsNumber(@as(i32, @intCast(amt))), - .err => |err| globalObject.throwValue(err.toJS(globalObject)), + .err => |err| globalObject.throwValue(try err.toJS(globalObject)), }; } diff --git a/src/bun.js/api/bun/dns.zig b/src/bun.js/api/bun/dns.zig index a2907374c1..6c8ee6c99c 100644 --- a/src/bun.js/api/bun/dns.zig +++ b/src/bun.js/api/bun/dns.zig @@ -2659,7 +2659,7 @@ pub const Resolver = struct { const channel: *c_ares.Channel = switch (this.getChannel()) { .result => |res| res, .err => |err| { - return globalThis.throwValue(err.toJSWithSyscallAndHostname(globalThis, "getHostByAddr", ip)); + return globalThis.throwValue(try err.toJSWithSyscallAndHostname(globalThis, "getHostByAddr", ip)); }, }; @@ -3038,7 +3038,7 @@ pub const Resolver = struct { var channel: *c_ares.Channel = switch (this.getChannel()) { .result => |res| res, .err => |err| { - return globalThis.throwValue(err.toJSWithSyscall(globalThis, "query" ++ &[_]u8{std.ascii.toUpper(type_name[0])} ++ type_name[1..])); + return globalThis.throwValue(try err.toJSWithSyscall(globalThis, "query" ++ &[_]u8{std.ascii.toUpper(type_name[0])} ++ type_name[1..])); }, }; diff --git a/src/bun.js/api/bun/js_bun_spawn_bindings.zig b/src/bun.js/api/bun/js_bun_spawn_bindings.zig index 45c33a5a19..a711c7aa88 100644 --- a/src/bun.js/api/bun/js_bun_spawn_bindings.zig +++ b/src/bun.js/api/bun/js_bun_spawn_bindings.zig @@ -622,7 +622,7 @@ pub fn spawnMaybeSync( else => {}, } - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, .result => |result| result, }; @@ -767,7 +767,7 @@ pub fn spawnMaybeSync( subprocess.stdio_pipes.items[@intCast(ipc_channel)].buffer, ).asErr()) |err| { subprocess.deref(); - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); } subprocess.stdio_pipes.items[@intCast(ipc_channel)] = .unavailable; } @@ -845,7 +845,7 @@ pub fn spawnMaybeSync( if (subprocess.stdin == .buffer) { if (subprocess.stdin.buffer.start().asErr()) |err| { _ = subprocess.tryKill(subprocess.killSignal); - _ = globalThis.throwValue(err.toJS(globalThis)) catch {}; + _ = globalThis.throwValue(err.toJS(globalThis) catch return error.JSError) catch {}; return error.JSError; } } @@ -853,7 +853,7 @@ pub fn spawnMaybeSync( if (subprocess.stdout == .pipe) { if (subprocess.stdout.pipe.start(subprocess, event_loop).asErr()) |err| { _ = subprocess.tryKill(subprocess.killSignal); - _ = globalThis.throwValue(err.toJS(globalThis)) catch {}; + _ = globalThis.throwValue(err.toJS(globalThis) catch return error.JSError) catch {}; return error.JSError; } if ((is_sync or !lazy) and subprocess.stdout == .pipe) { @@ -864,7 +864,7 @@ pub fn spawnMaybeSync( if (subprocess.stderr == .pipe) { if (subprocess.stderr.pipe.start(subprocess, event_loop).asErr()) |err| { _ = subprocess.tryKill(subprocess.killSignal); - _ = globalThis.throwValue(err.toJS(globalThis)) catch {}; + _ = globalThis.throwValue(err.toJS(globalThis) catch return error.JSError) catch {}; return error.JSError; } diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index b26f9fbc6f..ecbc3e9d7f 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -279,7 +279,7 @@ pub fn NewSocket(comptime ssl: bool) type { return this.handlers orelse @panic("No handlers set on Socket"); } - pub fn handleConnectError(this: *This, errno: c_int) void { + pub fn handleConnectError(this: *This, errno: c_int) bun.JSError!void { const handlers = this.getHandlers(); log("onConnectError {s} ({d}, {d})", .{ if (handlers.is_server) "S" else "C", errno, this.ref_count.get() }); // Ensure the socket is still alive for any defer's we have @@ -328,7 +328,7 @@ pub fn NewSocket(comptime ssl: bool) type { // reject the promise on connect() error const err_value = err.toErrorInstance(globalObject); - promise.asPromise().?.reject(globalObject, err_value) catch {}; // TODO: properly propagate exception upwards + try promise.asPromise().?.reject(globalObject, err_value); } return; @@ -349,13 +349,13 @@ pub fn NewSocket(comptime ssl: bool) type { // The error is effectively handled, but we should still reject the promise. var promise = val.asPromise().?; const err_ = err.toErrorInstance(globalObject); - promise.rejectAsHandled(globalObject, err_) catch {}; // TODO: properly propagate exception upwards + try promise.rejectAsHandled(globalObject, err_); } } - pub fn onConnectError(this: *This, _: Socket, errno: c_int) void { + pub fn onConnectError(this: *This, _: Socket, errno: c_int) bun.JSError!void { jsc.markBinding(@src()); - this.handleConnectError(errno); + try this.handleConnectError(errno); } pub fn markActive(this: *This) void { @@ -528,7 +528,7 @@ pub fn NewSocket(comptime ssl: bool) type { }; } - pub fn onHandshake(this: *This, s: Socket, success: i32, ssl_error: uws.us_bun_verify_error_t) void { + pub fn onHandshake(this: *This, s: Socket, success: i32, ssl_error: uws.us_bun_verify_error_t) bun.JSError!void { jsc.markBinding(@src()); this.flags.handshake_complete = true; this.socket = s; @@ -583,7 +583,7 @@ pub fn NewSocket(comptime ssl: bool) type { const authorization_error: JSValue = if (ssl_error.error_no == 0) JSValue.jsNull() else - ssl_error.toJS(globalObject); + try ssl_error.toJS(globalObject); result = callback.call(globalObject, this_value, &[_]JSValue{ this_value, @@ -597,7 +597,7 @@ pub fn NewSocket(comptime ssl: bool) type { } } - pub fn onClose(this: *This, _: Socket, err: c_int, _: ?*anyopaque) void { + pub fn onClose(this: *This, _: Socket, err: c_int, _: ?*anyopaque) bun.JSError!void { jsc.markBinding(@src()); const handlers = this.getHandlers(); log("onClose {s}", .{if (handlers.is_server) "S" else "C"}); @@ -632,7 +632,7 @@ pub fn NewSocket(comptime ssl: bool) type { var js_error: JSValue = .js_undefined; if (err != 0) { // errors here are always a read error - js_error = bun.sys.Error.fromCodeInt(err, .read).toJS(globalObject); + js_error = try bun.sys.Error.fromCodeInt(err, .read).toJS(globalObject); } _ = callback.call(globalObject, this_value, &[_]JSValue{ @@ -777,7 +777,7 @@ pub fn NewSocket(comptime ssl: bool) type { }; } - pub fn getLocalFamily(this: *This, globalThis: *jsc.JSGlobalObject) JSValue { + pub fn getLocalFamily(this: *This, globalThis: *jsc.JSGlobalObject) bun.JSError!JSValue { if (this.socket.isDetached()) { return .js_undefined; } @@ -785,8 +785,8 @@ pub fn NewSocket(comptime ssl: bool) type { var buf: [64]u8 = [_]u8{0} ** 64; const address_bytes: []const u8 = this.socket.localAddress(&buf) orelse return .js_undefined; return switch (address_bytes.len) { - 4 => bun.String.static("IPv4").toJS(globalThis), - 16 => bun.String.static("IPv6").toJS(globalThis), + 4 => try bun.String.static("IPv4").toJS(globalThis), + 16 => try bun.String.static("IPv6").toJS(globalThis), else => return .js_undefined, }; } @@ -818,7 +818,7 @@ pub fn NewSocket(comptime ssl: bool) type { return JSValue.jsNumber(this.socket.localPort()); } - pub fn getRemoteFamily(this: *This, globalThis: *jsc.JSGlobalObject) JSValue { + pub fn getRemoteFamily(this: *This, globalThis: *jsc.JSGlobalObject) bun.JSError!JSValue { if (this.socket.isDetached()) { return .js_undefined; } @@ -826,8 +826,8 @@ pub fn NewSocket(comptime ssl: bool) type { var buf: [64]u8 = [_]u8{0} ** 64; const address_bytes: []const u8 = this.socket.remoteAddress(&buf) orelse return .js_undefined; return switch (address_bytes.len) { - 4 => bun.String.static("IPv4").toJS(globalThis), - 16 => bun.String.static("IPv6").toJS(globalThis), + 4 => try bun.String.static("IPv4").toJS(globalThis), + 16 => try bun.String.static("IPv6").toJS(globalThis), else => return .js_undefined, }; } @@ -1694,18 +1694,18 @@ pub fn NewWrappedHandler(comptime tls: bool) type { } } - pub fn onHandshake(this: WrappedSocket, socket: Socket, success: i32, ssl_error: uws.us_bun_verify_error_t) void { + pub fn onHandshake(this: WrappedSocket, socket: Socket, success: i32, ssl_error: uws.us_bun_verify_error_t) bun.JSError!void { // only TLS will call onHandshake if (comptime tls) { - TLSSocket.onHandshake(this.tls, socket, success, ssl_error); + try TLSSocket.onHandshake(this.tls, socket, success, ssl_error); } } - pub fn onClose(this: WrappedSocket, socket: Socket, err: c_int, data: ?*anyopaque) void { + pub fn onClose(this: WrappedSocket, socket: Socket, err: c_int, data: ?*anyopaque) bun.JSError!void { if (comptime tls) { - TLSSocket.onClose(this.tls, socket, err, data); + try TLSSocket.onClose(this.tls, socket, err, data); } else { - TLSSocket.onClose(this.tcp, socket, err, data); + try TLSSocket.onClose(this.tcp, socket, err, data); } } @@ -1744,11 +1744,11 @@ pub fn NewWrappedHandler(comptime tls: bool) type { } } - pub fn onConnectError(this: WrappedSocket, socket: Socket, errno: c_int) void { + pub fn onConnectError(this: WrappedSocket, socket: Socket, errno: c_int) bun.JSError!void { if (comptime tls) { - TLSSocket.onConnectError(this.tls, socket, errno); + try TLSSocket.onConnectError(this.tls, socket, errno); } else { - TLSSocket.onConnectError(this.tcp, socket, errno); + try TLSSocket.onConnectError(this.tcp, socket, errno); } } }; @@ -1793,7 +1793,7 @@ pub const DuplexUpgradeContext = struct { const socket = TLSSocket.Socket.fromDuplex(&this.upgrade); if (this.tls) |tls| { - tls.onHandshake(socket, @intFromBool(success), ssl_error); + tls.onHandshake(socket, @intFromBool(success), ssl_error) catch {}; } } @@ -1819,7 +1819,7 @@ pub const DuplexUpgradeContext = struct { } } else { if (this.tls) |tls| { - tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ECONNREFUSED)); + tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ECONNREFUSED)) catch {}; } } } @@ -1836,7 +1836,7 @@ pub const DuplexUpgradeContext = struct { const socket = TLSSocket.Socket.fromDuplex(&this.upgrade); if (this.tls) |tls| { - tls.onClose(socket, 0, null); + tls.onClose(socket, 0, null) catch {}; } this.deinitInNextTick(); @@ -1856,8 +1856,8 @@ pub const DuplexUpgradeContext = struct { if (this.tls) |tls| { const socket = TLSSocket.Socket.fromDuplex(&this.upgrade); - tls.handleConnectError(errno); - tls.onClose(socket, errno, null); + tls.handleConnectError(errno) catch {}; + tls.onClose(socket, errno, null) catch {}; } }, } @@ -2036,7 +2036,7 @@ pub fn jsCreateSocketPair(global: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JS const rc = std.c.socketpair(std.posix.AF.UNIX, std.posix.SOCK.STREAM, 0, &fds_); if (rc != 0) { const err = bun.sys.Error.fromCode(bun.sys.getErrno(rc), .socketpair); - return global.throwValue(err.toJS(global)); + return global.throwValue(try err.toJS(global)); } _ = bun.FD.fromNative(fds_[0]).updateNonblocking(true); @@ -2068,12 +2068,12 @@ pub fn jsSetSocketOptions(global: *jsc.JSGlobalObject, callframe: *jsc.CallFrame if (is_for_send_buffer) { const result = bun.sys.setsockopt(file_descriptor, std.posix.SOL.SOCKET, std.posix.SO.SNDBUF, buffer_size); if (result.asErr()) |err| { - return global.throwValue(err.toJS(global)); + return global.throwValue(try err.toJS(global)); } } else if (is_for_recv_buffer) { const result = bun.sys.setsockopt(file_descriptor, std.posix.SOL.SOCKET, std.posix.SO.RCVBUF, buffer_size); if (result.asErr()) |err| { - return global.throwValue(err.toJS(global)); + return global.throwValue(try err.toJS(global)); } } } diff --git a/src/bun.js/api/bun/socket/Listener.zig b/src/bun.js/api/bun/socket/Listener.zig index b9661b6615..1e56a58dc2 100644 --- a/src/bun.js/api/bun/socket/Listener.zig +++ b/src/bun.js/api/bun/socket/Listener.zig @@ -830,7 +830,7 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock 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.sys.SystemErrno.ENOENT else bun.sys.SystemErrno.ECONNREFUSED)); + socket.handleConnectError(@intFromEnum(if (port == null) bun.sys.SystemErrno.ENOENT else bun.sys.SystemErrno.ECONNREFUSED)) catch {}; if (maybe_previous == null) socket.deref(); return promise_value; }; @@ -862,8 +862,8 @@ pub fn getsockname(this: *Listener, globalThis: *jsc.JSGlobalObject, callFrame: else => return .js_undefined, }; const family_js = switch (address_bytes.len) { - 4 => bun.String.static("IPv4").toJS(globalThis), - 16 => bun.String.static("IPv6").toJS(globalThis), + 4 => try bun.String.static("IPv4").toJS(globalThis), + 16 => try bun.String.static("IPv6").toJS(globalThis), else => return .js_undefined, }; const address_js = ZigString.init(bun.fmt.formatIp(address_zig, &text_buf) catch unreachable).toJS(globalThis); diff --git a/src/bun.js/api/bun/socket/SocketAddress.zig b/src/bun.js/api/bun/socket/SocketAddress.zig index d3957ca47f..ac3cf0f857 100644 --- a/src/bun.js/api/bun/socket/SocketAddress.zig +++ b/src/bun.js/api/bun/socket/SocketAddress.zig @@ -327,10 +327,10 @@ pub fn finalize(this: *SocketAddress) void { /// This method is slightly faster if you are creating a lot of socket addresses /// that will not be around for very long. `createDTO` is even faster, but /// requires callers to already have a presentation-formatted address. -pub fn intoDTO(this: *SocketAddress, global: *jsc.JSGlobalObject) jsc.JSValue { +pub fn intoDTO(this: *SocketAddress, global: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { var addr_str = this.address(); defer this._presentation = .dead; - return JSSocketAddressDTO__create(global, addr_str.transferToJS(global), this.port(), this.family() == AF.INET6); + return JSSocketAddressDTO__create(global, try addr_str.transferToJS(global), this.port(), this.family() == AF.INET6); } /// Directly create a socket address DTO. This is a POJO with address, port, and family properties. @@ -351,7 +351,7 @@ extern "c" fn JSSocketAddressDTO__create(globalObject: *jsc.JSGlobalObject, addr // ============================================================================= -pub fn getAddress(this: *SocketAddress, global: *jsc.JSGlobalObject) jsc.JSValue { +pub fn getAddress(this: *SocketAddress, global: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { // toJS increments ref count const addr_ = this.address(); return switch (addr_.tag) { @@ -389,7 +389,7 @@ pub fn address(this: *SocketAddress) bun.String { /// /// NOTE: node's `net.SocketAddress` wants `"ipv4"` and `"ipv6"` while Bun's APIs /// use `"IPv4"` and `"IPv6"`. This is annoying. -pub fn getFamily(this: *SocketAddress, global: *jsc.JSGlobalObject) JSValue { +pub fn getFamily(this: *SocketAddress, global: *jsc.JSGlobalObject) bun.JSError!JSValue { // NOTE: cannot use global.commonStrings().IPv[4,6]() b/c this needs to be // lower case. return switch (this.family()) { @@ -452,8 +452,8 @@ pub fn estimatedSize(this: *SocketAddress) usize { pub fn toJSON(this: *SocketAddress, global: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!jsc.JSValue { return (try jsc.JSObject.create(.{ - .address = this.getAddress(global), - .family = this.getFamily(global), + .address = try this.getAddress(global), + .family = try this.getFamily(global), .port = this.port(), .flowlabel = this.flowLabel() orelse 0, }, global)).toJS(); diff --git a/src/bun.js/api/bun/socket/WindowsNamedPipeContext.zig b/src/bun.js/api/bun/socket/WindowsNamedPipeContext.zig index 5969f43dfb..aaeb1abb35 100644 --- a/src/bun.js/api/bun/socket/WindowsNamedPipeContext.zig +++ b/src/bun.js/api/bun/socket/WindowsNamedPipeContext.zig @@ -57,11 +57,11 @@ fn onHandshake(this: *WindowsNamedPipeContext, success: bool, ssl_error: uws.us_ switch (this.socket) { .tls => |tls| { const socket = TLSSocket.Socket.fromNamedPipe(&this.named_pipe); - tls.onHandshake(socket, @intFromBool(success), ssl_error); + tls.onHandshake(socket, @intFromBool(success), ssl_error) catch {}; }, .tcp => |tcp| { const socket = TCPSocket.Socket.fromNamedPipe(&this.named_pipe); - tcp.onHandshake(socket, @intFromBool(success), ssl_error); + tcp.onHandshake(socket, @intFromBool(success), ssl_error) catch {}; }, .none => {}, } @@ -99,20 +99,20 @@ fn onError(this: *WindowsNamedPipeContext, err: bun.sys.Error) void { if (this.is_open) { switch (this.socket) { .tls => |tls| { - tls.handleError(err.toJS(this.globalThis)); + tls.handleError(err.toJS(this.globalThis) catch return); }, .tcp => |tcp| { - tcp.handleError(err.toJS(this.globalThis)); + tcp.handleError(err.toJS(this.globalThis) catch return); }, else => {}, } } else { switch (this.socket) { .tls => |tls| { - tls.handleConnectError(err.errno); + tls.handleConnectError(err.errno) catch {}; }, .tcp => |tcp| { - tcp.handleConnectError(err.errno); + tcp.handleConnectError(err.errno) catch {}; }, else => {}, } @@ -138,11 +138,11 @@ fn onClose(this: *WindowsNamedPipeContext) void { this.socket = .none; switch (socket) { .tls => |tls| { - tls.onClose(TLSSocket.Socket.fromNamedPipe(&this.named_pipe), 0, null); + tls.onClose(TLSSocket.Socket.fromNamedPipe(&this.named_pipe), 0, null) catch {}; tls.deref(); }, .tcp => |tcp| { - tcp.onClose(TCPSocket.Socket.fromNamedPipe(&this.named_pipe), 0, null); + tcp.onClose(TCPSocket.Socket.fromNamedPipe(&this.named_pipe), 0, null) catch {}; tcp.deref(); }, .none => {}, @@ -211,10 +211,10 @@ pub fn open(globalThis: *jsc.JSGlobalObject, fd: bun.FileDescriptor, ssl_config: errdefer { switch (socket) { .tls => |tls| { - tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT)); + tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT)) catch {}; }, .tcp => |tcp| { - tcp.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT)); + tcp.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT)) catch {}; }, .none => {}, } @@ -231,10 +231,10 @@ pub fn connect(globalThis: *jsc.JSGlobalObject, path: []const u8, ssl_config: ?j errdefer { switch (socket) { .tls => |tls| { - tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT)); + tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT)) catch {}; }, .tcp => |tcp| { - tcp.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT)); + tcp.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ENOENT)) catch {}; }, .none => {}, } diff --git a/src/bun.js/api/bun/socket/tls_socket_functions.zig b/src/bun.js/api/bun/socket/tls_socket_functions.zig index 5277aa7798..6f4041cf29 100644 --- a/src/bun.js/api/bun/socket/tls_socket_functions.zig +++ b/src/bun.js/api/bun/socket/tls_socket_functions.zig @@ -404,7 +404,7 @@ pub fn getEphemeralKeyInfo(this: *This, globalObject: *jsc.JSGlobalObject, _: *j switch (kid) { BoringSSL.EVP_PKEY_DH => { - result.put(globalObject, ZigString.static("type"), bun.String.static("DH").toJS(globalObject)); + result.put(globalObject, ZigString.static("type"), try bun.String.static("DH").toJS(globalObject)); result.put(globalObject, ZigString.static("size"), JSValue.jsNumber(bits)); }, @@ -427,7 +427,7 @@ pub fn getEphemeralKeyInfo(this: *This, globalObject: *jsc.JSGlobalObject, _: *j curve_name = ""; } } - result.put(globalObject, ZigString.static("type"), bun.String.static("ECDH").toJS(globalObject)); + result.put(globalObject, ZigString.static("type"), try bun.String.static("ECDH").toJS(globalObject)); result.put(globalObject, ZigString.static("name"), ZigString.fromUTF8(curve_name).toJS(globalObject)); result.put(globalObject, ZigString.static("size"), JSValue.jsNumber(bits)); }, diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index b9b2e03918..7de67a335f 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -328,7 +328,7 @@ pub fn asyncDispose(this: *Subprocess, global: *JSGlobalObject, callframe: *jsc. .result => {}, .err => |err| { // Signal 9 should always be fine, but just in case that somehow fails. - return global.throwValue(err.toJS(global)); + return global.throwValue(try err.toJS(global)); }, } @@ -381,7 +381,7 @@ pub fn kill( .result => {}, .err => |err| { // EINVAL or ENOSYS means the signal is not supported in the current platform (most likely unsupported on windows) - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, } @@ -659,7 +659,7 @@ pub fn onProcessExit(this: *Subprocess, process: *Process, status: bun.spawn.Sta switch (status) { .exited => |exited| promise.asAnyPromise().?.resolve(globalThis, JSValue.jsNumber(exited.code)) catch {}, // TODO: properly propagate exception upwards - .err => |err| promise.asAnyPromise().?.reject(globalThis, err.toJS(globalThis)) catch {}, // TODO: properly propagate exception upwards + .err => |err| promise.asAnyPromise().?.reject(globalThis, err.toJS(globalThis) catch return) catch {}, // TODO: properly propagate exception upwards .signaled => promise.asAnyPromise().?.resolve(globalThis, JSValue.jsNumber(128 +% @intFromEnum(status.signaled))) catch {}, // TODO: properly propagate exception upwards else => { // crash in debug mode @@ -672,7 +672,7 @@ pub fn onProcessExit(this: *Subprocess, process: *Process, status: bun.spawn.Sta if (consumeOnExitCallback(this_jsvalue, globalThis)) |callback| { const waitpid_value: JSValue = if (status == .err) - status.err.toJS(globalThis) + (status.err.toJS(globalThis) catch return) else .js_undefined; @@ -814,7 +814,8 @@ pub fn getExited( return jsc.JSPromise.resolvedPromiseValue(globalThis, JSValue.jsNumber(signal.toExitCode() orelse 254)); }, .err => |err| { - return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis)); + const js_err = err.toJS(globalThis) catch return .zero; + return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, js_err); }, else => { const promise = jsc.JSPromise.create(globalThis).toJS(); diff --git a/src/bun.js/api/bun/udp_socket.zig b/src/bun.js/api/bun/udp_socket.zig index 19c7941164..5f0bc7b247 100644 --- a/src/bun.js/api/bun/udp_socket.zig +++ b/src/bun.js/api/bun/udp_socket.zig @@ -96,9 +96,9 @@ fn onData(socket: *uws.udp.Socket, buf: *uws.udp.PacketBuffer, packets: c_int) c _ = callback.call(globalThis, thisValue, &.{ thisValue, - udpSocket.config.binary_type.toJS(slice, globalThis) catch return, // TODO: properly propagate exception upwards + udpSocket.config.binary_type.toJS(slice, globalThis) catch return, .jsNumber(port), - hostname_string.transferToJS(globalThis), + hostname_string.transferToJS(globalThis) catch return, }) catch |err| { udpSocket.callErrorHandler(.zero, globalThis.takeException(err)); }; @@ -310,7 +310,7 @@ pub const UDPSocket = struct { .message = bun.handleOom(bun.String.createFormat("bind {s} {f}", .{ code, this.config.hostname })), }; const error_value = sys_err.toErrorInstance(globalThis); - error_value.put(globalThis, "address", this.config.hostname.toJS(globalThis)); + error_value.put(globalThis, "address", try this.config.hostname.toJS(globalThis)); return globalThis.throwValue(error_value); } @@ -326,11 +326,11 @@ pub const UDPSocket = struct { const ret = this.socket.?.connect(address_z, connect.port); if (ret != 0) { if (bun.sys.Maybe(void).errnoSys(ret, .connect)) |*sys_err| { - return globalThis.throwValue(sys_err.err.toJS(globalThis)); + return globalThis.throwValue(try sys_err.err.toJS(globalThis)); } if (bun.c_ares.Error.initEAI(ret)) |eai_err| { - return globalThis.throwValue(eai_err.toJSWithSyscallAndHostname(globalThis, "connect", address_slice.slice())); + return globalThis.throwValue(try eai_err.toJSWithSyscallAndHostname(globalThis, "connect", address_slice.slice())); } } this.connect_info = .{ .port = connect.port }; @@ -822,7 +822,7 @@ pub const UDPSocket = struct { return JSValue.jsBoolean(this.closed); } - pub fn getHostname(this: *This, _: *JSGlobalObject) JSValue { + pub fn getHostname(this: *This, _: *JSGlobalObject) bun.JSError!JSValue { return this.config.hostname.toJS(this.globalThis); } @@ -833,7 +833,7 @@ pub const UDPSocket = struct { fn createSockAddr(globalThis: *JSGlobalObject, address_bytes: []const u8, port: u16) JSValue { var sockaddr = SocketAddress.init(address_bytes, port) catch return .js_undefined; - return sockaddr.intoDTO(globalThis); + return sockaddr.intoDTO(globalThis) catch .js_undefined; } pub fn getAddress(this: *This, globalThis: *JSGlobalObject) JSValue { @@ -861,7 +861,7 @@ pub const UDPSocket = struct { pub fn getBinaryType( this: *This, globalThis: *JSGlobalObject, - ) JSValue { + ) bun.JSError!JSValue { return switch (this.config.binary_type) { .Buffer => bun.String.static("buffer").toJS(globalThis), .Uint8Array => bun.String.static("uint8array").toJS(globalThis), diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig index 11a6959265..f89bd91d5c 100644 --- a/src/bun.js/api/filesystem_router.zig +++ b/src/bun.js/api/filesystem_router.zig @@ -361,7 +361,7 @@ pub const FileSystemRouter = struct { ); } - pub fn getStyle(_: *FileSystemRouter, globalThis: *jsc.JSGlobalObject) JSValue { + pub fn getStyle(_: *FileSystemRouter, globalThis: *jsc.JSGlobalObject) bun.JSError!JSValue { return bun.String.static("nextjs").toJS(globalThis); } diff --git a/src/bun.js/api/glob.zig b/src/bun.js/api/glob.zig index 462b4932eb..ab3018d2fc 100644 --- a/src/bun.js/api/glob.zig +++ b/src/bun.js/api/glob.zig @@ -44,7 +44,7 @@ const ScanOpts = struct { const cwd = switch (bun.sys.getcwd((&path_buf))) { .result => |cwd| cwd, .err => |err| { - const errJs = err.toJS(globalThis); + const errJs = try err.toJS(globalThis); return globalThis.throwValue(errJs); }, }; @@ -135,9 +135,9 @@ pub const WalkTask = struct { syscall: Syscall.Error, unknown: anyerror, - pub fn toJS(this: Err, globalThis: *JSGlobalObject) JSValue { + pub fn toJS(this: Err, globalThis: *JSGlobalObject) bun.JSError!JSValue { return switch (this) { - .syscall => |err| err.toJS(globalThis), + .syscall => |err| try err.toJS(globalThis), .unknown => |err| ZigString.fromBytes(@errorName(err)).toJS(globalThis), }; } @@ -237,7 +237,7 @@ fn makeGlobWalker( only_files, )) { .err => |err| { - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, else => {}, } @@ -254,7 +254,7 @@ fn makeGlobWalker( only_files, )) { .err => |err| { - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, else => {}, } @@ -345,7 +345,7 @@ pub fn __scanSync(this: *Glob, globalThis: *JSGlobalObject, callframe: *jsc.Call switch (try globWalker.walk()) { .err => |err| { - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, .result => {}, } diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index 56f534720d..8d168ceb6e 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -1106,8 +1106,8 @@ fn createLOLHTMLStringError() bun.String { return bun.String.cloneUTF8(err.slice()); } -fn htmlStringValue(input: LOLHTML.HTMLString, globalObject: *JSGlobalObject) JSValue { - return input.toJS(globalObject); +fn htmlStringValue(input: LOLHTML.HTMLString, globalObject: *JSGlobalObject) bun.JSError!JSValue { + return try input.toJS(globalObject); } pub const TextChunk = struct { @@ -1446,10 +1446,10 @@ pub const Comment = struct { pub fn getText( this: *Comment, globalObject: *JSGlobalObject, - ) JSValue { + ) bun.JSError!JSValue { if (this.comment == null) return JSValue.jsNull(); - return this.comment.?.getText().toJS(globalObject); + return try this.comment.?.getText().toJS(globalObject); } pub fn setText( @@ -1594,11 +1594,11 @@ pub const EndTag = struct { pub fn getName( this: *EndTag, globalObject: *JSGlobalObject, - ) JSValue { + ) bun.JSError!JSValue { if (this.end_tag == null) return .js_undefined; - return this.end_tag.?.getName().toJS(globalObject); + return try this.end_tag.?.getName().toJS(globalObject); } pub fn setName( @@ -1740,7 +1740,7 @@ pub const Element = struct { // // fn wrap(comptime name: string) /// Returns the value for a given attribute name: ZigString on the element, or null if it is not found. - pub fn getAttribute_(this: *Element, globalObject: *JSGlobalObject, name: ZigString) JSValue { + pub fn getAttribute_(this: *Element, globalObject: *JSGlobalObject, name: ZigString) bun.JSError!JSValue { if (this.element == null) return JSValue.jsNull(); @@ -1751,7 +1751,7 @@ pub const Element = struct { if (attr.len == 0) return JSValue.jsNull(); - return attr.toJS(globalObject); + return try attr.toJS(globalObject); } /// Returns a boolean indicating whether an attribute exists on the element. @@ -1911,11 +1911,11 @@ pub const Element = struct { return callFrame.this(); } - pub fn getTagName(this: *Element, globalObject: *JSGlobalObject) JSValue { + pub fn getTagName(this: *Element, globalObject: *JSGlobalObject) bun.JSError!JSValue { if (this.element == null) return .js_undefined; - return htmlStringValue(this.element.?.tagName(), globalObject); + return try htmlStringValue(this.element.?.tagName(), globalObject); } pub fn setTagName(this: *Element, global: *JSGlobalObject, value: JSValue) JSError!void { diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index b92f61c709..f6860711e5 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -1330,7 +1330,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d return jsc.JSValue.jsNumber(@as(i32, @intCast(@as(u31, @truncate(this.activeSocketsCount()))))); } - pub fn getAddress(this: *ThisServer, globalThis: *JSGlobalObject) jsc.JSValue { + pub fn getAddress(this: *ThisServer, globalThis: *JSGlobalObject) bun.JSError!jsc.JSValue { switch (this.config.address) { .unix => |unix| { var value = bun.String.cloneUTF8(unix); @@ -1429,7 +1429,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d @panic("unreachable"); } - pub fn getProtocol(this: *ThisServer, globalThis: *JSGlobalObject) jsc.JSValue { + pub fn getProtocol(this: *ThisServer, globalThis: *JSGlobalObject) bun.JSError!jsc.JSValue { _ = this; return bun.String.static(if (ssl_enabled) "https" else "http").toJS(globalThis); } @@ -1784,7 +1784,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d else => |e| { var sys_err = bun.sys.Error.fromCode(e, .listen); sys_err.path = unix; - error_instance = sys_err.toJS(globalThis); + error_instance = sys_err.toJS(globalThis) catch return; }, } }, diff --git a/src/bun.js/api/server/RequestContext.zig b/src/bun.js/api/server/RequestContext.zig index 04829d8163..42ed6a3bf6 100644 --- a/src/bun.js/api/server/RequestContext.zig +++ b/src/bun.js/api/server/RequestContext.zig @@ -918,17 +918,26 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, file.pathlike.fd else switch (bun.sys.open(file.pathlike.path.sliceZ(&file_buf), bun.O.RDONLY | bun.O.NONBLOCK | bun.O.CLOEXEC, 0)) { .result => |_fd| _fd, - .err => |err| return this.runErrorHandler(err.withPath(file.pathlike.path.slice()).toJS(globalThis)), + .err => |err| { + const js_err = err.withPath(file.pathlike.path.slice()).toJS(globalThis) catch { + return this.renderProductionError(500); + }; + return this.runErrorHandler(js_err); + }, }; // stat only blocks if the target is a file descriptor const stat: bun.Stat = switch (bun.sys.fstat(fd)) { .result => |result| result, .err => |err| { - this.runErrorHandler(err.withPathLike(file.pathlike).toJS(globalThis)); + // Close fd before toJS call, which might throw if (auto_close) { fd.close(); } + const js_err = err.withPathLike(file.pathlike).toJS(globalThis) catch { + return this.renderProductionError(500); + }; + this.runErrorHandler(js_err); return; }, }; @@ -945,9 +954,8 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, }; var sys = err.withPathLike(file.pathlike).toSystemError(); sys.message = bun.String.static("MacOS does not support sending non-regular files"); - this.runErrorHandler(sys.toErrorInstance( - globalThis, - )); + const js_err = sys.toErrorInstance(globalThis); + this.runErrorHandler(js_err); return; } } @@ -964,7 +972,8 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, }; var sys = err.withPathLike(file.pathlike).toShellSystemError(); sys.message = bun.String.static("File must be regular or FIFO"); - this.runErrorHandler(sys.toErrorInstance(globalThis)); + const js_err = sys.toErrorInstance(globalThis); + this.runErrorHandler(js_err); return; } } @@ -1043,7 +1052,8 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, if (result == .err) { if (this.server) |server| { - this.runErrorHandler(result.err.toErrorInstance(server.globalThis)); + const js_err = result.err.toErrorInstance(server.globalThis); + this.runErrorHandler(js_err); } return; } @@ -1853,7 +1863,8 @@ pub fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, .message = bun.String.static("Stream already used, please create a new one"), }; stream.value.unprotect(); - this.runErrorHandler(err.toErrorInstance(globalThis)); + const js_err = err.toErrorInstance(globalThis); + this.runErrorHandler(js_err); return; } diff --git a/src/bun.js/api/server/SSLConfig.zig b/src/bun.js/api/server/SSLConfig.zig index dbc10d8234..9991ff2c17 100644 --- a/src/bun.js/api/server/SSLConfig.zig +++ b/src/bun.js/api/server/SSLConfig.zig @@ -48,7 +48,7 @@ fn readFromBlob( ); const result = switch (maybe) { .result => |result| result, - .err => |err| return global.throwValue(err.toJS(global)), + .err => |err| return global.throwValue(try err.toJS(global)), }; if (result.null_terminated.len == 0) return error.EmptyFile; return bun.default_allocator.dupeZ(u8, result.null_terminated); diff --git a/src/bun.js/api/server/ServerWebSocket.zig b/src/bun.js/api/server/ServerWebSocket.zig index b885878409..6b3cdfdf6b 100644 --- a/src/bun.js/api/server/ServerWebSocket.zig +++ b/src/bun.js/api/server/ServerWebSocket.zig @@ -1113,7 +1113,7 @@ pub fn terminate( pub fn getBinaryType( this: *ServerWebSocket, globalThis: *jsc.JSGlobalObject, -) JSValue { +) bun.JSError!JSValue { log("getBinaryType()", .{}); return switch (this.#flags.binary_type) { diff --git a/src/bun.js/bindings/BunDebugger.cpp b/src/bun.js/bindings/BunDebugger.cpp index 25573fb197..f3fe73a76b 100644 --- a/src/bun.js/bindings/BunDebugger.cpp +++ b/src/bun.js/bindings/BunDebugger.cpp @@ -586,7 +586,11 @@ extern "C" void Bun__startJSDebuggerThread(Zig::GlobalObject* debuggerGlobalObje MarkedArgumentBuffer arguments; arguments.append(jsNumber(static_cast(scriptId))); - arguments.append(Bun::toJS(debuggerGlobalObject, *portOrPathString)); + auto* portOrPathJS = Bun::toJS(debuggerGlobalObject, *portOrPathString); + if (!portOrPathJS) [[unlikely]] { + return; + } + arguments.append(portOrPathJS); arguments.append(JSFunction::create(vm, debuggerGlobalObject, 3, String(), jsFunctionCreateConnection, ImplementationVisibility::Public)); arguments.append(JSFunction::create(vm, debuggerGlobalObject, 1, String("send"_s), jsFunctionSend, ImplementationVisibility::Public)); arguments.append(JSFunction::create(vm, debuggerGlobalObject, 0, String("disconnect"_s), jsFunctionDisconnect, ImplementationVisibility::Public)); diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index 218b836e0e..1ed7bcb428 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -813,12 +813,16 @@ EncodedJSValue BunPlugin::OnResolve::run(JSC::JSGlobalObject* globalObject, BunS JSC::JSObject* paramsObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 2); const auto& builtinNames = WebCore::builtinNames(vm); + auto* pathJS = Bun::toJS(globalObject, *path); + RETURN_IF_EXCEPTION(scope, {}); paramsObject->putDirect( vm, builtinNames.pathPublicName(), - Bun::toJS(globalObject, *path)); + pathJS); + auto* importerJS = Bun::toJS(globalObject, *importer); + RETURN_IF_EXCEPTION(scope, {}); paramsObject->putDirect( vm, builtinNames.importerPublicName(), - Bun::toJS(globalObject, *importer)); + importerJS); arguments.append(paramsObject); auto result = AsyncContextFrame::call(globalObject, function, JSC::jsUndefined(), arguments); diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index fddb5c8cbe..008485671c 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -40,6 +40,7 @@ #include "wtf/StdLibExtras.h" #include "wtf/text/StringImpl.h" #include "wtf/text/StringToIntegerConversion.h" +#include "ErrorCode.h" using namespace JSC; extern "C" BunString BunString__fromBytes(const char* bytes, size_t length); @@ -105,14 +106,19 @@ extern "C" [[ZIG_EXPORT(zero_is_throw)]] JSC::EncodedJSValue BunString__createUT return JSValue::encode(jsString(vm, WTF::move(str))); } -extern "C" JSC::EncodedJSValue BunString__transferToJS(BunString* bunString, JSC::JSGlobalObject* globalObject) +extern "C" [[ZIG_EXPORT(zero_is_throw)]] JSC::EncodedJSValue BunString__transferToJS(BunString* bunString, JSC::JSGlobalObject* globalObject) { auto& vm = JSC::getVM(globalObject); - if (bunString->tag == BunStringTag::Empty || bunString->tag == BunStringTag::Dead) [[unlikely]] { + if (bunString->tag == BunStringTag::Empty) [[unlikely]] { return JSValue::encode(JSC::jsEmptyString(vm)); } + if (bunString->tag == BunStringTag::Dead) [[unlikely]] { + auto scope = DECLARE_THROW_SCOPE(vm); + return Bun::ERR::STRING_TOO_LONG(scope, globalObject); + } + if (bunString->tag == BunStringTag::WTFStringImpl) [[likely]] { #if ASSERT_ENABLED unsigned refCount = bunString->impl.wtf->refCount(); @@ -153,9 +159,16 @@ namespace Bun { JSC::JSString* toJS(JSC::JSGlobalObject* globalObject, BunString bunString) { - if (bunString.tag == BunStringTag::Empty || bunString.tag == BunStringTag::Dead) { + if (bunString.tag == BunStringTag::Empty) { return JSC::jsEmptyString(globalObject->vm()); } + + if (bunString.tag == BunStringTag::Dead) [[unlikely]] { + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + Bun::ERR::STRING_TOO_LONG(scope, globalObject); + return nullptr; + } + if (bunString.tag == BunStringTag::WTFStringImpl) { #if ASSERT_ENABLED ASSERT(bunString.impl.wtf->hasAtLeastOneRef() && !bunString.impl.wtf->isEmpty()); @@ -350,9 +363,16 @@ WTF::String toCrossThreadShareable(const WTF::String& string) } -extern "C" JSC::EncodedJSValue BunString__toJS(JSC::JSGlobalObject* globalObject, const BunString* bunString) +extern "C" [[ZIG_EXPORT(zero_is_throw)]] JSC::EncodedJSValue BunString__toJS(JSC::JSGlobalObject* globalObject, const BunString* bunString) { - return JSValue::encode(Bun::toJS(globalObject, *bunString)); + auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_THROW_SCOPE(vm); + auto* result = Bun::toJS(globalObject, *bunString); + RETURN_IF_EXCEPTION(scope, {}); + if (!result) [[unlikely]] { + return {}; + } + return JSValue::encode(result); } extern "C" [[ZIG_EXPORT(nothrow)]] BunString BunString__fromUTF16Unitialized(size_t length) @@ -500,7 +520,9 @@ extern "C" JSC::EncodedJSValue BunString__createArray( RETURN_IF_EXCEPTION(throwScope, {}); for (size_t i = 0; i < length; ++i) { - array->putDirectIndex(globalObject, i, Bun::toJS(globalObject, *ptr++)); + auto* str = Bun::toJS(globalObject, *ptr++); + RETURN_IF_EXCEPTION(throwScope, {}); + array->putDirectIndex(globalObject, i, str); RETURN_IF_EXCEPTION(throwScope, {}); } diff --git a/src/bun.js/bindings/JSGlobalObject.zig b/src/bun.js/bindings/JSGlobalObject.zig index fa2a092018..6ce923f88e 100644 --- a/src/bun.js/bindings/JSGlobalObject.zig +++ b/src/bun.js/bindings/JSGlobalObject.zig @@ -29,7 +29,7 @@ pub const JSGlobalObject = opaque { pub fn throwTODO(this: *JSGlobalObject, msg: []const u8) bun.JSError { const err = this.createErrorInstance("{s}", .{msg}); - err.put(this, ZigString.static("name"), bun.String.static("TODOError").toJS(this)); + err.put(this, ZigString.static("name"), (bun.String.static("TODOError").toJS(this)) catch return error.JSError); return this.throwValue(err); } diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index fa63cfebc8..d2b048c538 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -469,7 +469,8 @@ extern "C" void Bun__onFulfillAsyncModule( RELEASE_AND_RETURN(scope, promise->reject(vm, globalObject, JSValue::decode(res->result.err.value))); } - auto specifierValue = Bun::toJS(globalObject, *specifier); + auto* specifierValue = Bun::toJS(globalObject, *specifier); + RETURN_IF_EXCEPTION(scope, ); auto* map = globalObject->esmRegistryMap(); RETURN_IF_EXCEPTION(scope, ); diff --git a/src/bun.js/bindings/S3Error.cpp b/src/bun.js/bindings/S3Error.cpp index 1485b617ae..31ddb1afc7 100644 --- a/src/bun.js/bindings/S3Error.cpp +++ b/src/bun.js/bindings/S3Error.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "ZigGeneratedClasses.h" #include "S3Error.h" @@ -26,6 +27,7 @@ SYSV_ABI JSC::EncodedJSValue S3Error__toErrorInstance(const S3Error* arg0, S3Error err = *arg0; auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_CATCH_SCOPE(vm); WTF::String message; if (err.message.tag != BunStringTag::Empty) { @@ -39,14 +41,22 @@ SYSV_ABI JSC::EncodedJSValue S3Error__toErrorInstance(const S3Error* arg0, result->putDirect(vm, vm.propertyNames->name, defaultGlobalObject(globalObject)->commonStrings().s3ErrorString(globalObject), JSC::PropertyAttribute::DontEnum | 0); if (err.code.tag != BunStringTag::Empty) { JSC::JSValue code = Bun::toJS(globalObject, err.code); - result->putDirect(vm, names.codePublicName(), code, - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum | 0); + if (scope.exception()) { + scope.clearException(); + } else { + result->putDirect(vm, names.codePublicName(), code, + JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum | 0); + } } if (err.path.tag != BunStringTag::Empty) { JSC::JSValue path = Bun::toJS(globalObject, err.path); - result->putDirect(vm, names.pathPublicName(), path, - JSC::PropertyAttribute::DontDelete | 0); + if (scope.exception()) { + scope.clearException(); + } else { + result->putDirect(vm, names.pathPublicName(), path, + JSC::PropertyAttribute::DontDelete | 0); + } } return JSC::JSValue::encode(result); diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 90c73b4fc0..12eb49535a 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -2213,10 +2213,10 @@ JSC::EncodedJSValue JSGlobalObject__createOutOfMemoryError(JSC::JSGlobalObject* JSC::EncodedJSValue SystemError__toErrorInstance(const SystemError* arg0, JSC::JSGlobalObject* globalObject) { - ASSERT_NO_PENDING_EXCEPTION(globalObject); SystemError err = *arg0; auto& vm = JSC::getVM(globalObject); + auto scope = DECLARE_CATCH_SCOPE(vm); WTF::String message = WTF::emptyString(); if (err.message.tag != BunStringTag::Empty) { @@ -2231,17 +2231,29 @@ JSC::EncodedJSValue SystemError__toErrorInstance(const SystemError* arg0, JSC::J if (err.code.tag != BunStringTag::Empty) { JSC::JSValue code = Bun::toJS(globalObject, err.code); - result->putDirect(vm, clientData->builtinNames().codePublicName(), code, JSC::PropertyAttribute::DontDelete | 0); + if (scope.exception()) { + scope.clearException(); + } else { + result->putDirect(vm, clientData->builtinNames().codePublicName(), code, JSC::PropertyAttribute::DontDelete | 0); + } } if (err.path.tag != BunStringTag::Empty) { JSC::JSValue path = Bun::toJS(globalObject, err.path); - result->putDirect(vm, clientData->builtinNames().pathPublicName(), path, JSC::PropertyAttribute::DontDelete | 0); + if (scope.exception()) { + scope.clearException(); + } else { + result->putDirect(vm, clientData->builtinNames().pathPublicName(), path, JSC::PropertyAttribute::DontDelete | 0); + } } if (err.dest.tag != BunStringTag::Empty) { JSC::JSValue dest = Bun::toJS(globalObject, err.dest); - result->putDirect(vm, clientData->builtinNames().destPublicName(), dest, JSC::PropertyAttribute::DontDelete | 0); + if (scope.exception()) { + scope.clearException(); + } else { + result->putDirect(vm, clientData->builtinNames().destPublicName(), dest, JSC::PropertyAttribute::DontDelete | 0); + } } if (err.fd >= 0) { @@ -2251,23 +2263,29 @@ JSC::EncodedJSValue SystemError__toErrorInstance(const SystemError* arg0, JSC::J if (err.syscall.tag != BunStringTag::Empty) { JSC::JSValue syscall = Bun::toJS(globalObject, err.syscall); - result->putDirect(vm, names.syscallPublicName(), syscall, JSC::PropertyAttribute::DontDelete | 0); + if (scope.exception()) { + scope.clearException(); + } else { + result->putDirect(vm, names.syscallPublicName(), syscall, JSC::PropertyAttribute::DontDelete | 0); + } } if (err.hostname.tag != BunStringTag::Empty) { JSC::JSValue hostname = Bun::toJS(globalObject, err.hostname); - result->putDirect(vm, names.hostnamePublicName(), hostname, JSC::PropertyAttribute::DontDelete | 0); + if (scope.exception()) { + scope.clearException(); + } else { + result->putDirect(vm, names.hostnamePublicName(), hostname, JSC::PropertyAttribute::DontDelete | 0); + } } result->putDirect(vm, names.errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0); - ASSERT_NO_PENDING_EXCEPTION(globalObject); return JSC::JSValue::encode(result); } JSC::EncodedJSValue SystemError__toErrorInstanceWithInfoObject(const SystemError* arg0, JSC::JSGlobalObject* globalObject) { - ASSERT_NO_PENDING_EXCEPTION(globalObject); SystemError err = *arg0; auto& vm = JSC::getVM(globalObject); @@ -2300,7 +2318,6 @@ JSC::EncodedJSValue SystemError__toErrorInstanceWithInfoObject(const SystemError info->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0); result->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0); - ASSERT_NO_PENDING_EXCEPTION(globalObject); return JSC::JSValue::encode(result); } diff --git a/src/bun.js/event_loop/ManagedTask.zig b/src/bun.js/event_loop/ManagedTask.zig index f768a5fc69..3d1fa15554 100644 --- a/src/bun.js/event_loop/ManagedTask.zig +++ b/src/bun.js/event_loop/ManagedTask.zig @@ -4,13 +4,13 @@ const ManagedTask = @This(); ctx: ?*anyopaque, -callback: *const (fn (*anyopaque) bun.JSTerminated!void), +callback: *const (fn (*anyopaque) bun.JSError!void), pub fn task(this: *ManagedTask) Task { return Task.init(this); } -pub fn run(this: *ManagedTask) bun.JSTerminated!void { +pub fn run(this: *ManagedTask) bun.JSError!void { @setRuntimeSafety(false); defer bun.default_allocator.destroy(this); const callback = this.callback; @@ -35,7 +35,7 @@ pub fn New(comptime Type: type, comptime Callback: anytype) type { return managed.task(); } - pub fn wrap(this: ?*anyopaque) bun.JSTerminated!void { + pub fn wrap(this: ?*anyopaque) bun.JSError!void { return @call(bun.callmod_inline, Callback, .{@as(*Type, @ptrCast(@alignCast(this.?)))}); } }; diff --git a/src/bun.js/ipc.zig b/src/bun.js/ipc.zig index 2cfe41a4da..3f2fcb8a5c 100644 --- a/src/bun.js/ipc.zig +++ b/src/bun.js/ipc.zig @@ -663,17 +663,14 @@ pub const SendQueue = struct { log("IPC call continueSend() from onAckNack retry", .{}); return this.continueSend(global, .new_message_appended); } - // too many retries; give up + // too many retries; give up - emit warning if possible var warning = bun.String.static("Handle did not reach the receiving process correctly"); var warning_name = bun.String.static("SentHandleNotReceivedWarning"); - global.emitWarning( - warning.transferToJS(global), - warning_name.transferToJS(global), - .js_undefined, - .js_undefined, - ) catch |e| { - _ = global.takeException(e); - }; + if (warning.transferToJS(global)) |warning_js| { + if (warning_name.transferToJS(global)) |warning_name_js| { + global.emitWarning(warning_js, warning_name_js, .js_undefined, .js_undefined) catch {}; + } else |_| {} + } else |_| {} // (fall through to success code in order to consume the message and continue sending) } // consume the message and continue sending @@ -1037,7 +1034,7 @@ pub fn doSend(ipc: ?*SendQueue, globalObject: *jsc.JSGlobalObject, callFrame: *j if (status == .failure) { const ex = globalObject.createTypeErrorInstance("process.send() failed", .{}); - ex.put(globalObject, jsc.ZigString.static("syscall"), bun.String.static("write").toJS(globalObject)); + ex.put(globalObject, jsc.ZigString.static("syscall"), try bun.String.static("write").toJS(globalObject)); return doSendErr(globalObject, callback, ex, from); } diff --git a/src/bun.js/jsc/array_buffer.zig b/src/bun.js/jsc/array_buffer.zig index add592e206..35051393e2 100644 --- a/src/bun.js/jsc/array_buffer.zig +++ b/src/bun.js/jsc/array_buffer.zig @@ -58,7 +58,7 @@ pub const ArrayBuffer = extern struct { } }, .err => |err| { - return globalObject.throwValue(err.toJS(globalObject)) catch .zero; + return globalObject.throwValue(err.toJS(globalObject) catch return .zero) catch .zero; }, } } @@ -75,7 +75,7 @@ pub const ArrayBuffer = extern struct { const stat = switch (bun.sys.fstat(fd)) { .err => |err| { fd.close(); - return globalObject.throwValue(err.toJS(globalObject)); + return globalObject.throwValue(try err.toJS(globalObject)); }, .result => |fstat| fstat, }; @@ -112,7 +112,7 @@ pub const ArrayBuffer = extern struct { return JSBuffer__fromMmap(globalObject, buf.ptr, buf.len); }, .err => |err| { - return globalObject.throwValue(err.toJS(globalObject)); + return globalObject.throwValue(err.toJS(globalObject) catch return .zero) catch return .zero; }, } } diff --git a/src/bun.js/node/net/BlockList.zig b/src/bun.js/node/net/BlockList.zig index b9af1c7d37..dc0ebe2346 100644 --- a/src/bun.js/node/net/BlockList.zig +++ b/src/bun.js/node/net/BlockList.zig @@ -46,7 +46,7 @@ pub fn isBlockList(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) b pub fn addAddress(this: *@This(), globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue { const arguments = callframe.argumentsAsArray(2); const address_js, var family_js = arguments; - if (family_js.isUndefined()) family_js = bun.String.static("ipv4").toJS(globalThis); + if (family_js.isUndefined()) family_js = try bun.String.static("ipv4").toJS(globalThis); const address = if (address_js.as(SocketAddress)) |sa| sa._addr else blk: { try validators.validateString(globalThis, address_js, "address", .{}); try validators.validateString(globalThis, family_js, "family", .{}); @@ -63,7 +63,7 @@ pub fn addAddress(this: *@This(), globalThis: *jsc.JSGlobalObject, callframe: *j pub fn addRange(this: *@This(), globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue { const arguments = callframe.argumentsAsArray(3); const start_js, const end_js, var family_js = arguments; - if (family_js.isUndefined()) family_js = bun.String.static("ipv4").toJS(globalThis); + if (family_js.isUndefined()) family_js = try bun.String.static("ipv4").toJS(globalThis); const start = if (start_js.as(SocketAddress)) |sa| sa._addr else blk: { try validators.validateString(globalThis, start_js, "start", .{}); try validators.validateString(globalThis, family_js, "family", .{}); @@ -89,7 +89,7 @@ pub fn addRange(this: *@This(), globalThis: *jsc.JSGlobalObject, callframe: *jsc pub fn addSubnet(this: *@This(), globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue { const arguments = callframe.argumentsAsArray(3); const network_js, const prefix_js, var family_js = arguments; - if (family_js.isUndefined()) family_js = bun.String.static("ipv4").toJS(globalThis); + if (family_js.isUndefined()) family_js = try bun.String.static("ipv4").toJS(globalThis); const network = if (network_js.as(SocketAddress)) |sa| sa._addr else blk: { try validators.validateString(globalThis, network_js, "network", .{}); try validators.validateString(globalThis, family_js, "family", .{}); @@ -111,7 +111,7 @@ pub fn addSubnet(this: *@This(), globalThis: *jsc.JSGlobalObject, callframe: *js pub fn check(this: *@This(), globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!jsc.JSValue { const arguments = callframe.argumentsAsArray(2); const address_js, var family_js = arguments; - if (family_js.isUndefined()) family_js = bun.String.static("ipv4").toJS(globalThis); + if (family_js.isUndefined()) family_js = try bun.String.static("ipv4").toJS(globalThis); const address = &(if (address_js.as(SocketAddress)) |sa| sa._addr else blk: { try validators.validateString(globalThis, address_js, "address", .{}); try validators.validateString(globalThis, family_js, "family", .{}); diff --git a/src/bun.js/node/node_cluster_binding.zig b/src/bun.js/node/node_cluster_binding.zig index 583f48d9e7..b613aaf435 100644 --- a/src/bun.js/node/node_cluster_binding.zig +++ b/src/bun.js/node/node_cluster_binding.zig @@ -62,7 +62,7 @@ pub fn sendHelperChild(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFram if (good == .failure) { const ex = globalThis.createTypeErrorInstance("sendInternal() failed", .{}); - ex.put(globalThis, ZigString.static("syscall"), bun.String.static("write").toJS(globalThis)); + ex.put(globalThis, ZigString.static("syscall"), try bun.String.static("write").toJS(globalThis)); const fnvalue = jsc.JSFunction.create(globalThis, "", S.impl, 1, .{}); try fnvalue.callNextTick(globalThis, .{ex}); return .false; diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index d8b27f6cf6..62c7f8e876 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -295,9 +295,9 @@ pub const Async = struct { var promise_value = this.promise.value(); var promise = this.promise.get(); const result = switch (this.result) { - .err => |err| err.toJS(globalObject), + .err => |err| err.toJS(globalObject) catch |e| return promise.reject(globalObject, globalObject.takeException(e)), .result => |*res| brk: { - break :brk globalObject.toJS(res) catch return promise.reject(globalObject, error.JSError); + break :brk globalObject.toJS(res) catch |e| return promise.reject(globalObject, globalObject.takeException(e)); }, }; promise_value.ensureStillAlive(); @@ -399,9 +399,9 @@ pub const Async = struct { var promise_value = this.promise.value(); var promise = this.promise.get(); const result = switch (this.result) { - .err => |err| err.toJS(globalObject), + .err => |err| err.toJS(globalObject) catch |e| return promise.reject(globalObject, globalObject.takeException(e)), .result => |*res| brk: { - break :brk globalObject.toJS(res) catch return promise.reject(globalObject, error.JSError); + break :brk globalObject.toJS(res) catch |e| return promise.reject(globalObject, globalObject.takeException(e)); }, }; promise_value.ensureStillAlive(); @@ -667,9 +667,9 @@ pub fn NewAsyncCpTask(comptime is_shell: bool) type { var promise_value = this.promise.value(); var promise = this.promise.get(); const result = switch (this.result) { - .err => |err| err.toJS(globalObject), + .err => |err| err.toJS(globalObject) catch |e| return promise.reject(globalObject, globalObject.takeException(e)), .result => |*res| brk: { - break :brk globalObject.toJS(res) catch return promise.reject(globalObject, error.JSError); + break :brk globalObject.toJS(res) catch |e| return promise.reject(globalObject, globalObject.takeException(e)); }, }; promise_value.ensureStillAlive(); @@ -1217,13 +1217,13 @@ pub const AsyncReaddirRecursiveTask = struct { const success = this.pending_err == null; var promise_value = this.promise.value(); var promise = this.promise.get(); - const result = if (this.pending_err) |*err| err.toJS(globalObject) else brk: { + const result = if (this.pending_err) |*err| (err.toJS(globalObject) catch |e| return promise.reject(globalObject, globalObject.takeException(e))) else brk: { const res = switch (this.result_list) { .with_file_types => |*res| Return.Readdir{ .with_file_types = res.moveToUnmanaged().items }, .buffers => |*res| Return.Readdir{ .buffers = res.moveToUnmanaged().items }, .files => |*res| Return.Readdir{ .files = res.moveToUnmanaged().items }, }; - break :brk res.toJS(globalObject) catch return promise.reject(globalObject, error.JSError); + break :brk res.toJS(globalObject) catch |e| return promise.reject(globalObject, globalObject.takeException(e)); }; promise_value.ensureStillAlive(); @@ -3159,9 +3159,9 @@ pub const StringOrUndefined = union(enum) { string: bun.String, none: void, - pub fn toJS(this: *StringOrUndefined, globalObject: *jsc.JSGlobalObject) jsc.JSValue { + pub fn toJS(this: *StringOrUndefined, globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { return switch (this.*) { - .string => this.string.transferToJS(globalObject), + .string => try this.string.transferToJS(globalObject), .none => .js_undefined, }; } diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index 156605f221..4bb29b8fb4 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -29,7 +29,7 @@ fn Bindings(comptime function_name: NodeFSFunctionEnum) type { var result = function(&this.node_fs, args, .sync); return switch (result) { - .err => |err| globalObject.throwValue(err.toJS(globalObject)), + .err => |err| globalObject.throwValue(try err.toJS(globalObject)), .result => |*res| globalObject.toJS(res), }; } @@ -227,7 +227,7 @@ pub fn createMemfdForTesting(globalObject: *jsc.JSGlobalObject, callFrame: *jsc. return jsc.JSValue.jsNumber(fd.cast()); }, .err => |err| { - return globalObject.throwValue(err.toJS(globalObject)); + return globalObject.throwValue(try err.toJS(globalObject)); }, } } diff --git a/src/bun.js/node/node_fs_watcher.zig b/src/bun.js/node/node_fs_watcher.zig index 0b0e8afc24..980b90c3c9 100644 --- a/src/bun.js/node/node_fs_watcher.zig +++ b/src/bun.js/node/node_fs_watcher.zig @@ -231,7 +231,7 @@ pub const FSWatcher = struct { switch (this.event) { inline .rename, .change => |*path, event_type| { if (ctx.encoding == .utf8) { - ctx.emitWithFilename(path.string.transferToJS(ctx.globalThis), event_type); + ctx.emitWithFilename(path.string.transferToJS(ctx.globalThis) catch return, event_type); } else { const bytes = path.bytes_to_free; path.bytes_to_free = ""; @@ -487,7 +487,7 @@ pub const FSWatcher = struct { const globalObject = this.globalThis; var args = [_]jsc.JSValue{ EventType.@"error".toJS(globalObject), - err.toJS(globalObject), + err.toJS(globalObject) catch return, }; _ = listener.callWithGlobalThis( globalObject, @@ -518,7 +518,7 @@ pub const FSWatcher = struct { filename = jsc.ZigString.fromUTF8(file_name).toJS(globalObject); } else { // convert to desired encoding - filename = Encoder.toString(file_name, globalObject, this.encoding); + filename = Encoder.toString(file_name, globalObject, this.encoding) catch return; } } diff --git a/src/bun.js/node/node_os.zig b/src/bun.js/node/node_os.zig index ecbf372fa6..0378c8639f 100644 --- a/src/bun.js/node/node_os.zig +++ b/src/bun.js/node/node_os.zig @@ -307,7 +307,7 @@ pub fn homedir(global: *jsc.JSGlobalObject) !bun.String { var out: bun.PathBuffer = undefined; var size: usize = out.len; if (libuv.uv_os_homedir(&out, &size).toError(.uv_os_homedir)) |err| { - return global.throwValue(err.toJS(global)); + return global.throwValue(try err.toJS(global)); } return bun.String.cloneUTF8(out[0..size]); } else { @@ -358,7 +358,7 @@ pub fn homedir(global: *jsc.JSGlobalObject) !bun.String { }; if (ret != 0) { - return global.throwValue(bun.sys.Error.fromCode( + return global.throwValue(try bun.sys.Error.fromCode( @enumFromInt(ret), .uv_os_homedir, ).toJS(global)); @@ -366,7 +366,7 @@ pub fn homedir(global: *jsc.JSGlobalObject) !bun.String { if (result == null) { // in uv__getpwuid_r, null result throws UV_ENOENT. - return global.throwValue(bun.sys.Error.fromCode( + return global.throwValue(try bun.sys.Error.fromCode( .NOENT, .uv_os_homedir, ).toJS(global)); @@ -935,7 +935,7 @@ pub fn userInfo(globalThis: *jsc.JSGlobalObject, options: gen.UserInfoOptions) b const home = try homedir(globalThis); defer home.deref(); - result.put(globalThis, jsc.ZigString.static("homedir"), home.toJS(globalThis)); + result.put(globalThis, jsc.ZigString.static("homedir"), try home.toJS(globalThis)); if (comptime Environment.isWindows) { result.put(globalThis, jsc.ZigString.static("username"), jsc.ZigString.init(bun.env_var.USER.get() orelse "unknown").withEncoding().toJS(globalThis)); diff --git a/src/bun.js/node/node_process.zig b/src/bun.js/node/node_process.zig index fbc29403f1..0674c5f901 100644 --- a/src/bun.js/node/node_process.zig +++ b/src/bun.js/node/node_process.zig @@ -59,7 +59,7 @@ fn createExecArgv(globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { if (worker.execArgv) |execArgv| { const array = try jsc.JSValue.createEmptyArray(globalObject, execArgv.len); for (0..execArgv.len) |i| { - try array.putIndex(globalObject, @intCast(i), bun.String.init(execArgv[i]).toJS(globalObject)); + try array.putIndex(globalObject, @intCast(i), try bun.String.init(execArgv[i]).toJS(globalObject)); } return array; } @@ -80,7 +80,7 @@ fn createExecArgv(globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { const array = try jsc.JSValue.createEmptyArray(globalObject, args.items.len); for (0..args.items.len) |idx| { - try array.putIndex(globalObject, @intCast(idx), args.items[idx].toJS(globalObject)); + try array.putIndex(globalObject, @intCast(idx), try args.items[idx].toJS(globalObject)); } return array; } @@ -234,7 +234,7 @@ fn getCwd_(globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { switch (bun.api.node.path.getCwd(&buf)) { .result => |r| return jsc.ZigString.init(r).withEncoding().toJS(globalObject), .err => |e| { - return globalObject.throwValue(e.toJS(globalObject)); + return globalObject.throwValue(try e.toJS(globalObject)); }, } } @@ -259,7 +259,7 @@ fn setCwd_(globalObject: *jsc.JSGlobalObject, to: *jsc.ZigString) bun.JSError!js .result => |r| r, .err => |err| { _ = Syscall.chdir(fs.top_level_dir, fs.top_level_dir); - return globalObject.throwValue(err.toJS(globalObject)); + return globalObject.throwValue(try err.toJS(globalObject)); }, }; @memcpy(fs.top_level_dir_buf[0..into_cwd_buf.len], into_cwd_buf); @@ -278,7 +278,7 @@ fn setCwd_(globalObject: *jsc.JSGlobalObject, to: *jsc.ZigString) bun.JSError!js return str.transferToJS(globalObject); }, .err => |e| { - return globalObject.throwValue(e.toJS(globalObject)); + return globalObject.throwValue(try e.toJS(globalObject)); }, } } diff --git a/src/bun.js/node/node_zlib_binding.zig b/src/bun.js/node/node_zlib_binding.zig index 75f84afbb5..ab33ca0323 100644 --- a/src/bun.js/node/node_zlib_binding.zig +++ b/src/bun.js/node/node_zlib_binding.zig @@ -258,10 +258,10 @@ pub fn CompressionStream(comptime T: type) type { pub fn emitError(this: *T, globalThis: *jsc.JSGlobalObject, this_value: jsc.JSValue, err_: Error) void { var msg_str = bun.handleOom(bun.String.createFormat("{s}", .{std.mem.sliceTo(err_.msg, 0) orelse ""})); - const msg_value = msg_str.transferToJS(globalThis); + const msg_value = msg_str.transferToJS(globalThis) catch return; const err_value: jsc.JSValue = .jsNumber(err_.err); var code_str = bun.handleOom(bun.String.createFormat("{s}", .{std.mem.sliceTo(err_.code, 0) orelse ""})); - const code_value = code_str.transferToJS(globalThis); + const code_value = code_str.transferToJS(globalThis) catch return; const callback: jsc.JSValue = T.js.errorCallbackGetCached(this_value) orelse Output.panic("Assertion failure: cachedErrorCallback is null in node:zlib binding", .{}); diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index fc67cea5cb..4e5fc66cac 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -440,11 +440,7 @@ pub const Encoding = enum(u8) { return jsc.ArrayBuffer.createBuffer(globalObject, input); }, inline else => |enc| { - const res = jsc.WebCore.encoding.toStringComptime(input, globalObject, enc); - if (res.isError()) { - return globalObject.throwValue(res); - } - return res; + return try jsc.WebCore.encoding.toStringComptime(input, globalObject, enc); }, } } @@ -461,7 +457,7 @@ pub const Encoding = enum(u8) { const encoded_len = bun.base64.encode(&base64_buf, input); var encoded, const bytes = bun.String.createUninitialized(.latin1, encoded_len); @memcpy(@constCast(bytes), base64_buf[0..encoded_len]); - return encoded.transferToJS(globalObject); + return try encoded.transferToJS(globalObject); }, .base64url => { var buf: [std.base64.url_safe_no_pad.Encoder.calcSize(max_size * 4)]u8 = undefined; @@ -485,12 +481,7 @@ pub const Encoding = enum(u8) { return jsc.ArrayBuffer.createBuffer(globalObject, input); }, inline else => |enc| { - const res = jsc.WebCore.encoding.toStringComptime(input, globalObject, enc); - if (res.isError()) { - return globalObject.throwValue(res); - } - - return res; + return try jsc.WebCore.encoding.toStringComptime(input, globalObject, enc); }, } } diff --git a/src/bun.js/node/util/parse_args.zig b/src/bun.js/node/util/parse_args.zig index f7df4974e2..7d91ffc790 100644 --- a/src/bun.js/node/util/parse_args.zig +++ b/src/bun.js/node/util/parse_args.zig @@ -26,7 +26,7 @@ const ValueRef = union(Tag) { }; } - pub fn asJSValue(this: ValueRef, globalObject: *JSGlobalObject) JSValue { + pub fn asJSValue(this: ValueRef, globalObject: *JSGlobalObject) bun.JSError!JSValue { return switch (this) { .jsvalue => |str| str, .bunstr => |str| return str.toJS(globalObject), @@ -96,7 +96,7 @@ const OptionToken = struct { }; /// Returns the raw name of the arg (includes any dashes and excludes inline values), as a JSValue - fn makeRawNameJSValue(this: OptionToken, globalThis: *JSGlobalObject) JSValue { + fn makeRawNameJSValue(this: OptionToken, globalThis: *JSGlobalObject) bun.JSError!JSValue { if (this.optgroup_idx) |optgroup_idx| { const raw = this.raw.asBunString(globalThis); var buf: [8]u8 = undefined; @@ -105,7 +105,7 @@ const OptionToken = struct { } else { switch (this.parse_type) { .lone_short_option, .lone_long_option => { - return this.raw.asJSValue(globalThis); + return try this.raw.asJSValue(globalThis); }, .short_option_and_value => { var raw = this.raw.asBunString(globalThis); @@ -255,7 +255,7 @@ fn storeOption(globalThis: *JSGlobalObject, option_name: ValueRef, option_value: return; } - var value = option_value.asJSValue(globalThis); + var value = try option_value.asJSValue(globalThis); // We store based on the option value rather than option type, // preserving the users intent for author to deal with. @@ -583,7 +583,7 @@ const ParseArgsState = struct { ); return globalThis.throwValue(err); } - const value = token.value.asJSValue(globalThis); + const value = try token.value.asJSValue(globalThis); try this.positionals.push(globalThis, value); }, .@"option-terminator" => {}, @@ -601,7 +601,7 @@ const ParseArgsState = struct { // reuse JSValue for the kind names: "positional", "option", "option-terminator" const kind_idx = @intFromEnum(token_generic); const kind_jsvalue = this.kinds_jsvalues[kind_idx] orelse kindval: { - const val = String.static(@tagName(token_generic)).toJS(globalThis); + const val = try String.static(@tagName(token_generic)).toJS(globalThis); this.kinds_jsvalues[kind_idx] = val; break :kindval val; }; @@ -611,17 +611,17 @@ const ParseArgsState = struct { switch (token_generic) { .option => |token| { obj.put(globalThis, ZigString.static("index"), JSValue.jsNumber(token.index)); - obj.put(globalThis, ZigString.static("name"), token.name.asJSValue(globalThis)); - obj.put(globalThis, ZigString.static("rawName"), token.makeRawNameJSValue(globalThis)); + obj.put(globalThis, ZigString.static("name"), try token.name.asJSValue(globalThis)); + obj.put(globalThis, ZigString.static("rawName"), try token.makeRawNameJSValue(globalThis)); // value exists only for string options, otherwise the property exists with "undefined" as value - var value = token.value.asJSValue(globalThis); + var value = try token.value.asJSValue(globalThis); obj.put(globalThis, ZigString.static("value"), value); obj.put(globalThis, ZigString.static("inlineValue"), if (value.isUndefined()) .js_undefined else JSValue.jsBoolean(token.inline_value)); }, .positional => |token| { obj.put(globalThis, ZigString.static("index"), JSValue.jsNumber(token.index)); - obj.put(globalThis, ZigString.static("value"), token.value.asJSValue(globalThis)); + obj.put(globalThis, ZigString.static("value"), try token.value.asJSValue(globalThis)); }, .@"option-terminator" => |token| { obj.put(globalThis, ZigString.static("index"), JSValue.jsNumber(token.index)); diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index 68b7ac78c8..ffa8303115 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -1029,7 +1029,7 @@ pub const Expect = struct { const err = switch (Output.enable_ansi_colors_stderr) { inline else => |colors| globalThis.createErrorInstance(Output.prettyFmt(fmt, colors), .{ matcher_name, result.toFmt(&formatter) }), }; - err.put(globalThis, ZigString.static("name"), bun.String.static("InvalidMatcherError").toJS(globalThis)); + err.put(globalThis, ZigString.static("name"), try bun.String.static("InvalidMatcherError").toJS(globalThis)); return globalThis.throwValue(err); } @@ -1251,13 +1251,13 @@ pub const Expect = struct { if (arg.isEmptyOrUndefinedOrNull()) { const error_value = bun.String.init("reached unreachable code").toErrorInstance(globalThis); - error_value.put(globalThis, ZigString.static("name"), bun.String.init("UnreachableError").toJS(globalThis)); + error_value.put(globalThis, ZigString.static("name"), try bun.String.init("UnreachableError").toJS(globalThis)); return globalThis.throwValue(error_value); } if (arg.isString()) { const error_value = (try arg.toBunString(globalThis)).toErrorInstance(globalThis); - error_value.put(globalThis, ZigString.static("name"), bun.String.init("UnreachableError").toJS(globalThis)); + error_value.put(globalThis, ZigString.static("name"), try bun.String.init("UnreachableError").toJS(globalThis)); return globalThis.throwValue(error_value); } @@ -1802,7 +1802,7 @@ pub const ExpectMatcherContext = struct { return JSValue.jsBoolean(this.flags.not); } - pub fn getPromise(this: *ExpectMatcherContext, globalThis: *JSGlobalObject) JSValue { + pub fn getPromise(this: *ExpectMatcherContext, globalThis: *JSGlobalObject) bun.JSError!JSValue { return switch (this.flags.promise) { .rejects => bun.String.static("rejects").toJS(globalThis), .resolves => bun.String.static("resolves").toJS(globalThis), @@ -1908,8 +1908,8 @@ pub const ExpectMatcherUtils = struct { const matcher_name = try arguments[0].toBunString(globalThis); defer matcher_name.deref(); - const received = if (arguments.len > 1) arguments[1] else bun.String.static("received").toJS(globalThis); - const expected = if (arguments.len > 2) arguments[2] else bun.String.static("expected").toJS(globalThis); + const received = if (arguments.len > 1) arguments[1] else try bun.String.static("received").toJS(globalThis); + const expected = if (arguments.len > 2) arguments[2] else try bun.String.static("expected").toJS(globalThis); const options = if (arguments.len > 3) arguments[3] else .js_undefined; var is_not = false; diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 1acacb9994..59765900b1 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -386,7 +386,7 @@ pub fn formatLabel(globalThis: *JSGlobalObject, label: string, function_args: [] } const var_path = label[var_start..var_end]; - const value = try function_args[0].getIfPropertyExistsFromPath(globalThis, bun.String.init(var_path).toJS(globalThis)); + const value = try function_args[0].getIfPropertyExistsFromPath(globalThis, try bun.String.init(var_path).toJS(globalThis)); if (!value.isEmptyOrUndefinedOrNull()) { // For primitive strings, use toString() to avoid adding quotes // This matches Jest's behavior (https://github.com/jestjs/jest/issues/7689) diff --git a/src/bun.js/webcore/Blob.zig b/src/bun.js/webcore/Blob.zig index e150209e87..72b4060564 100644 --- a/src/bun.js/webcore/Blob.zig +++ b/src/bun.js/webcore/Blob.zig @@ -260,8 +260,9 @@ const FormDataContext = struct { switch (res) { .err => |err| { - globalThis.throwValue(err.toJS(globalThis)) catch {}; this.failed = true; + const js_err = err.toJS(globalThis) catch return; + globalThis.throwValue(js_err) catch {}; }, .result => |result| { joiner.push(result.slice(), result.buffer.allocator); @@ -1612,7 +1613,7 @@ fn writeStringToFileFast( return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM( globalThis, - err.withPath(pathlike.path.slice()).toJS(globalThis), + err.withPath(pathlike.path.slice()).toJS(globalThis) catch return .zero, ); }, } @@ -1653,11 +1654,11 @@ fn writeStringToFileFast( return .zero; } if (comptime !needs_open) { - return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis)); + return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis) catch return .zero); } return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM( globalThis, - err.withPath(pathlike.path.slice()).toJS(globalThis), + err.withPath(pathlike.path.slice()).toJS(globalThis) catch return .zero, ); }, } @@ -1699,7 +1700,7 @@ fn writeBytesToFileFast( return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM( globalThis, - err.withPath(pathlike.path.slice()).toJS(globalThis), + err.withPath(pathlike.path.slice()).toJS(globalThis) catch return .zero, ); }, } @@ -1732,12 +1733,12 @@ fn writeBytesToFileFast( if (comptime !needs_open) { return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM( globalThis, - err.toJS(globalThis), + err.toJS(globalThis) catch return .zero, ); } return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM( globalThis, - err.withPath(pathlike.path.slice()).toJS(globalThis), + err.withPath(pathlike.path.slice()).toJS(globalThis) catch return .zero, ); }, } @@ -2471,7 +2472,7 @@ pub fn pipeReadableStreamToBlob(this: *Blob, globalThis: *jsc.JSGlobalObject, re break :brk result; }, .err => |err| { - return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.withPath(path).toJS(globalThis)); + return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, try err.withPath(path).toJS(globalThis)); }, } unreachable; @@ -2504,7 +2505,7 @@ pub fn pipeReadableStreamToBlob(this: *Blob, globalThis: *jsc.JSGlobalObject, re switch (sink.writer.startSync(fd, false)) { .err => |err| { sink.deref(); - return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis)); + return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, try err.toJS(globalThis)); }, else => {}, } @@ -2512,7 +2513,7 @@ pub fn pipeReadableStreamToBlob(this: *Blob, globalThis: *jsc.JSGlobalObject, re switch (sink.writer.start(fd, true)) { .err => |err| { sink.deref(); - return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis)); + return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, try err.toJS(globalThis)); }, else => {}, } @@ -2546,7 +2547,7 @@ pub fn pipeReadableStreamToBlob(this: *Blob, globalThis: *jsc.JSGlobalObject, re switch (sink.start(stream_start)) { .err => |err| { sink.deref(); - return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis)); + return jsc.JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, try err.toJS(globalThis)); }, else => {}, } @@ -2733,7 +2734,7 @@ pub fn getWriter( break :brk result; }, .err => |err| { - return globalThis.throwValue(err.withPath(pathlike.path.slice()).toJS(globalThis)); + return globalThis.throwValue(try err.withPath(pathlike.path.slice()).toJS(globalThis)); }, } @compileError("unreachable"); @@ -2766,7 +2767,7 @@ pub fn getWriter( switch (sink.writer.startSync(fd, false)) { .err => |err| { sink.deref(); - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, else => {}, } @@ -2774,7 +2775,7 @@ pub fn getWriter( switch (sink.writer.start(fd, true)) { .err => |err| { sink.deref(); - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, else => {}, } @@ -2813,7 +2814,7 @@ pub fn getWriter( switch (sink.start(stream_start)) { .err => |err| { sink.deref(); - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, else => {}, } @@ -2991,7 +2992,7 @@ pub fn getName( this: *Blob, _: jsc.JSValue, globalThis: *jsc.JSGlobalObject, -) JSValue { +) bun.JSError!JSValue { return if (this.getNameString()) |name| name.toJS(globalThis) else .js_undefined; } @@ -4304,7 +4305,7 @@ pub const Any = union(enum) { return ZigString.Empty.toJS(global); } - const owned = this.InternalBlob.toStringOwned(global); + const owned = try this.InternalBlob.toStringOwned(global); this.* = .{ .Blob = .{} }; return owned; }, @@ -4313,7 +4314,7 @@ pub const Any = union(enum) { defer str.deref(); this.* = .{ .Blob = .{} }; - return str.toJS(global); + return try str.toJS(global); }, } } @@ -4460,7 +4461,7 @@ pub const Internal = struct { return this.bytes.capacity; } - pub fn toStringOwned(this: *@This(), globalThis: *jsc.JSGlobalObject) JSValue { + pub fn toStringOwned(this: *@This(), globalThis: *jsc.JSGlobalObject) bun.JSError!JSValue { const bytes_without_bom = strings.withoutUTF8BOM(this.bytes.items); if (strings.toUTF16Alloc(bun.default_allocator, bytes_without_bom, false, false) catch &[_]u16{}) |out| { const return_value = ZigString.toExternalU16(out.ptr, out.len, globalThis); diff --git a/src/bun.js/webcore/Body.zig b/src/bun.js/webcore/Body.zig index 65721788d4..241a26b408 100644 --- a/src/bun.js/webcore/Body.zig +++ b/src/bun.js/webcore/Body.zig @@ -146,7 +146,7 @@ pub const PendingValue = struct { return null; } - pub fn setPromise(value: *PendingValue, globalThis: *jsc.JSGlobalObject, action: Action, owned_readable: ?jsc.WebCore.ReadableStream) JSValue { + pub fn setPromise(value: *PendingValue, globalThis: *jsc.JSGlobalObject, action: Action, owned_readable: ?jsc.WebCore.ReadableStream) bun.JSError!JSValue { value.action = action; if (owned_readable orelse value.readable.get(globalThis)) |readable| { switch (action) { @@ -164,7 +164,7 @@ pub const PendingValue = struct { } break :brk globalThis.readableStreamToFormData(readable.value, switch (form_data.?.encoding) { - .Multipart => |multipart| bun.String.init(multipart).toJS(globalThis), + .Multipart => |multipart| try bun.String.init(multipart).toJS(globalThis), .URLEncoded => .js_undefined, }); }, @@ -1113,7 +1113,7 @@ pub fn Mixin(comptime Type: type) type { if (readable.isDisturbed(globalObject)) { return handleBodyAlreadyUsed(globalObject); } - return value.Locked.setPromise(globalObject, .{ .getText = {} }, readable); + return try value.Locked.setPromise(globalObject, .{ .getText = {} }, readable); } } if (value.* == .Locked) { @@ -1121,7 +1121,7 @@ pub fn Mixin(comptime Type: type) type { return handleBodyAlreadyUsed(globalObject); } - return value.Locked.setPromise(globalObject, .{ .getText = {} }, null); + return try value.Locked.setPromise(globalObject, .{ .getText = {} }, null); } } @@ -1193,7 +1193,7 @@ pub fn Mixin(comptime Type: type) type { value.toBlobIfPossible(); if (value.* == .Locked) { - return value.Locked.setPromise(globalObject, .{ .getJSON = {} }, readable); + return try value.Locked.setPromise(globalObject, .{ .getJSON = {} }, readable); } } } @@ -1204,7 +1204,7 @@ pub fn Mixin(comptime Type: type) type { value.toBlobIfPossible(); if (value.* == .Locked) { - return value.Locked.setPromise(globalObject, .{ .getJSON = {} }, null); + return try value.Locked.setPromise(globalObject, .{ .getJSON = {} }, null); } } } @@ -1234,7 +1234,7 @@ pub fn Mixin(comptime Type: type) type { } value.toBlobIfPossible(); if (value.* == .Locked) { - return value.Locked.setPromise(globalObject, .{ .getArrayBuffer = {} }, readable); + return try value.Locked.setPromise(globalObject, .{ .getArrayBuffer = {} }, readable); } } } @@ -1245,7 +1245,7 @@ pub fn Mixin(comptime Type: type) type { value.toBlobIfPossible(); if (value.* == .Locked) { - return value.Locked.setPromise(globalObject, .{ .getArrayBuffer = {} }, null); + return try value.Locked.setPromise(globalObject, .{ .getArrayBuffer = {} }, null); } } } @@ -1271,7 +1271,7 @@ pub fn Mixin(comptime Type: type) type { } value.toBlobIfPossible(); if (value.* == .Locked) { - return value.Locked.setPromise(globalObject, .{ .getBytes = {} }, readable); + return try value.Locked.setPromise(globalObject, .{ .getBytes = {} }, readable); } } } @@ -1281,7 +1281,7 @@ pub fn Mixin(comptime Type: type) type { } value.toBlobIfPossible(); if (value.* == .Locked) { - return value.Locked.setPromise(globalObject, .{ .getBytes = {} }, null); + return try value.Locked.setPromise(globalObject, .{ .getBytes = {} }, null); } } } @@ -1322,9 +1322,9 @@ pub fn Mixin(comptime Type: type) type { if (value.* == .Locked) { if (@hasDecl(Type, "getBodyReadableStream")) { - return value.Locked.setPromise(globalObject, .{ .getFormData = encoder }, this.getBodyReadableStream(globalObject)); + return try value.Locked.setPromise(globalObject, .{ .getFormData = encoder }, this.getBodyReadableStream(globalObject)); } else { - return value.Locked.setPromise(globalObject, .{ .getFormData = encoder }, null); + return try value.Locked.setPromise(globalObject, .{ .getFormData = encoder }, null); } } @@ -1374,7 +1374,7 @@ pub fn Mixin(comptime Type: type) type { } value.toBlobIfPossible(); if (value.* == .Locked) { - return value.Locked.setPromise(globalObject, .{ .getBlob = {} }, readable); + return try value.Locked.setPromise(globalObject, .{ .getBlob = {} }, readable); } } } @@ -1389,7 +1389,7 @@ pub fn Mixin(comptime Type: type) type { value.toBlobIfPossible(); if (value.* == .Locked) { - return value.Locked.setPromise(globalObject, .{ .getBlob = {} }, null); + return try value.Locked.setPromise(globalObject, .{ .getBlob = {} }, null); } } } diff --git a/src/bun.js/webcore/ReadableStream.zig b/src/bun.js/webcore/ReadableStream.zig index 4d8bfed8da..5bcf0eccb7 100644 --- a/src/bun.js/webcore/ReadableStream.zig +++ b/src/bun.js/webcore/ReadableStream.zig @@ -647,7 +647,7 @@ pub fn NewSource( .ready => return JSValue.jsNumber(16384), .chunk_size => |size| return JSValue.jsNumber(size), .err => |err| { - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, else => |rc| { return rc.toJS(globalThis); @@ -664,7 +664,7 @@ pub fn NewSource( switch (result) { .err => |err| { if (err == .Error) { - return globalThis.throwValue(err.Error.toJS(globalThis)); + return globalThis.throwValue(try err.Error.toJS(globalThis)); } else { const js_err = err.JSValue; js_err.ensureStillAlive(); diff --git a/src/bun.js/webcore/Response.zig b/src/bun.js/webcore/Response.zig index 4c43c933bc..0386abf933 100644 --- a/src/bun.js/webcore/Response.zig +++ b/src/bun.js/webcore/Response.zig @@ -308,7 +308,7 @@ pub fn isOK(this: *const Response) bool { pub fn getURL( this: *Response, globalThis: *jsc.JSGlobalObject, -) jsc.JSValue { +) bun.JSError!jsc.JSValue { // https://developer.mozilla.org/en-US/docs/Web/API/Response/url return this.#url.toJS(globalThis); } @@ -316,7 +316,7 @@ pub fn getURL( pub fn getResponseType( this: *Response, globalThis: *jsc.JSGlobalObject, -) jsc.JSValue { +) bun.JSError!jsc.JSValue { if (this.#init.status_code < 200) { return bun.String.static("error").toJS(globalThis); } @@ -327,7 +327,7 @@ pub fn getResponseType( pub fn getStatusText( this: *Response, globalThis: *jsc.JSGlobalObject, -) jsc.JSValue { +) bun.JSError!jsc.JSValue { // https://developer.mozilla.org/en-US/docs/Web/API/Response/statusText return this.#init.status_text.toJS(globalThis); } diff --git a/src/bun.js/webcore/S3Stat.zig b/src/bun.js/webcore/S3Stat.zig index 4324a91235..d276314bbf 100644 --- a/src/bun.js/webcore/S3Stat.zig +++ b/src/bun.js/webcore/S3Stat.zig @@ -39,11 +39,11 @@ pub const S3Stat = struct { return jsc.JSValue.jsNumber(this.size); } - pub fn getEtag(this: *@This(), globalObject: *jsc.JSGlobalObject) jsc.JSValue { + pub fn getEtag(this: *@This(), globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { return this.etag.toJS(globalObject); } - pub fn getContentType(this: *@This(), globalObject: *jsc.JSGlobalObject) jsc.JSValue { + pub fn getContentType(this: *@This(), globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { return this.contentType.toJS(globalObject); } diff --git a/src/bun.js/webcore/Sink.zig b/src/bun.js/webcore/Sink.zig index 7ad574fbe4..65fa84dbe2 100644 --- a/src/bun.js/webcore/Sink.zig +++ b/src/bun.js/webcore/Sink.zig @@ -500,7 +500,7 @@ pub fn JSSink(comptime SinkType: type, comptime abi_name: []const u8) type { const maybe_value: bun.sys.Maybe(JSValue) = this.sink.flushFromJS(globalThis, wait); return switch (maybe_value) { .result => |value| value, - .err => |err| return globalThis.throwValue(err.toJS(globalThis)), + .err => |err| return globalThis.throwValue(try err.toJS(globalThis)), }; } diff --git a/src/bun.js/webcore/encoding.zig b/src/bun.js/webcore/encoding.zig index f64cf2c5a5..ce6498fe64 100644 --- a/src/bun.js/webcore/encoding.zig +++ b/src/bun.js/webcore/encoding.zig @@ -70,23 +70,23 @@ export fn Bun__encoding__constructFromUTF16(globalObject: *JSGlobalObject, input // for SQL statement export fn Bun__encoding__toStringUTF8(input: [*]const u8, len: usize, globalObject: *jsc.JSGlobalObject) JSValue { - return toStringComptime(input[0..len], globalObject, .utf8); + return toStringComptime(input[0..len], globalObject, .utf8) catch return .zero; } export fn Bun__encoding__toString(input: [*]const u8, len: usize, globalObject: *jsc.JSGlobalObject, encoding: u8) JSValue { - return toString(input[0..len], globalObject, @enumFromInt(encoding)); + return toString(input[0..len], globalObject, @enumFromInt(encoding)) catch return .zero; } // pub fn writeUTF16AsUTF8(utf16: [*]const u16, len: usize, to: [*]u8, to_len: usize) callconv(.c) i32 { // return @intCast(i32, strings.copyUTF16IntoUTF8(to[0..to_len], []const u16, utf16[0..len]).written); // } -pub fn toString(input: []const u8, globalObject: *JSGlobalObject, encoding: Encoding) JSValue { +pub fn toString(input: []const u8, globalObject: *JSGlobalObject, encoding: Encoding) bun.JSError!JSValue { return switch (encoding) { // treat buffer as utf8 // callers are expected to check that before constructing `Buffer` objects - .buffer, .utf8 => toStringComptime(input, globalObject, .utf8), + .buffer, .utf8 => try toStringComptime(input, globalObject, .utf8), - inline else => |enc| toStringComptime(input, globalObject, enc), + inline else => |enc| try toStringComptime(input, globalObject, enc), }; } @@ -179,9 +179,9 @@ pub fn toBunStringFromOwnedSlice(input: []u8, encoding: Encoding) bun.String { } } -pub fn toStringComptime(input: []const u8, global: *JSGlobalObject, comptime encoding: Encoding) JSValue { +pub fn toStringComptime(input: []const u8, global: *JSGlobalObject, comptime encoding: Encoding) bun.JSError!JSValue { var bun_string = toBunStringComptime(input, encoding); - return bun_string.transferToJS(global); + return try bun_string.transferToJS(global); } pub fn toBunString(input: []const u8, encoding: Encoding) bun.String { diff --git a/src/bun.js/webcore/fetch.zig b/src/bun.js/webcore/fetch.zig index d8dde3c1f7..48259f6ad8 100644 --- a/src/bun.js/webcore/fetch.zig +++ b/src/bun.js/webcore/fetch.zig @@ -1117,7 +1117,7 @@ fn fetchImpl( const opened_fd = switch (opened_fd_res) { .err => |err| { - const rejected_value = JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis)); + const rejected_value = JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis) catch return .zero); is_error = true; return rejected_value; }, @@ -1189,7 +1189,7 @@ fn fetchImpl( switch (res) { .err => |err| { is_error = true; - const rejected_value = JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis)); + const rejected_value = JSPromise.dangerouslyCreateRejectedPromiseValueWithoutNotifyingVM(globalThis, err.toJS(globalThis) catch return .zero); body.detach(); return rejected_value; diff --git a/src/bun.js/webcore/fetch/FetchTasklet.zig b/src/bun.js/webcore/fetch/FetchTasklet.zig index f71373cd54..c615b9a2a5 100644 --- a/src/bun.js/webcore/fetch/FetchTasklet.zig +++ b/src/bun.js/webcore/fetch/FetchTasklet.zig @@ -621,7 +621,21 @@ pub const FetchTasklet = struct { }; var hostname: bun.String = bun.String.cloneUTF8(certificate_info.hostname); defer hostname.deref(); - const js_hostname = hostname.toJS(globalObject); + const js_hostname = hostname.toJS(globalObject) catch |err| { + switch (err) { + error.JSError => {}, + error.OutOfMemory => globalObject.throwOutOfMemory() catch {}, + error.JSTerminated => {}, + } + const hostname_err_result = globalObject.tryTakeException().?; + this.is_waiting_abort = this.result.has_more; + this.abort_reason.set(globalObject, hostname_err_result); + this.signal_store.aborted.store(true, .monotonic); + this.tracker.didCancel(this.global_this); + if (this.http) |http_| http.http_thread.scheduleShutdown(http_); + this.result.fail = error.ERR_TLS_CERT_ALTNAME_INVALID; + return false; + }; js_hostname.ensureStillAlive(); js_cert.ensureStillAlive(); const check_result = check_server_identity.call(globalObject, .js_undefined, &.{ js_hostname, js_cert }) catch |err| globalObject.takeException(err); diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index c4f8b78907..da0e56826b 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -38,7 +38,7 @@ pub const Start = union(Tag) { return jsc.JSValue.jsNumber(@as(Blob.SizeType, @intCast(chunk))); }, .err => |err| { - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); }, .owned_and_done => |list| { return jsc.ArrayBuffer.fromBytes(list.slice(), .Uint8Array).toJS(globalThis); @@ -234,7 +234,7 @@ pub const Result = union(Tag) { pub fn toJSWeak(this: *const @This(), globalObject: *jsc.JSGlobalObject) struct { jsc.JSValue, WasStrong } { return switch (this.*) { .Error => |err| { - return .{ err.toJS(globalObject), WasStrong.Weak }; + return .{ err.toJS(globalObject) catch return .{ .zero, WasStrong.Weak }, WasStrong.Weak }; }, .JSValue => .{ this.JSValue, WasStrong.Strong }, .WeakJSValue => .{ this.WeakJSValue, WasStrong.Weak }, @@ -393,7 +393,7 @@ pub const Result = union(Tag) { pub fn toJS(this: Writable, globalThis: *JSGlobalObject) JSValue { return switch (this) { - .err => |err| jsc.JSPromise.rejectedPromise(globalThis, err.toJS(globalThis)).toJS(), + .err => |err| jsc.JSPromise.rejectedPromise(globalThis, err.toJS(globalThis) catch return .zero).toJS(), .owned => |len| jsc.JSValue.jsNumber(len), .owned_and_done => |len| jsc.JSValue.jsNumber(len), diff --git a/src/cli/pack_command.zig b/src/cli/pack_command.zig index f250eb2798..658a047c2d 100644 --- a/src/cli/pack_command.zig +++ b/src/cli/pack_command.zig @@ -2722,11 +2722,11 @@ pub const bindings = struct { for (entries_info.items, 0..) |entry, i| { const obj = JSValue.createEmptyObject(global, 0); - obj.put(global, "pathname", entry.pathname.toJS(global)); - obj.put(global, "kind", entry.kind.toJS(global)); + obj.put(global, "pathname", try entry.pathname.toJS(global)); + obj.put(global, "kind", try entry.kind.toJS(global)); obj.put(global, "perm", JSValue.jsNumber(entry.perm)); if (entry.contents) |contents| { - obj.put(global, "contents", contents.toJS(global)); + obj.put(global, "contents", try contents.toJS(global)); } try entries.putIndex(global, @intCast(i), obj); } @@ -2734,7 +2734,7 @@ pub const bindings = struct { const result = JSValue.createEmptyObject(global, 4); result.put(global, "entries", entries); result.put(global, "size", JSValue.jsNumber(tarball.len)); - result.put(global, "shasum", shasum_str.toJS(global)); + result.put(global, "shasum", try shasum_str.toJS(global)); result.put(global, "integrity", integrity_value); return result; diff --git a/src/crash_handler.zig b/src/crash_handler.zig index d902410444..52033fcf18 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -1917,15 +1917,15 @@ pub const js_bindings = struct { const list = bun.analytics.packed_features_list; const array = try JSValue.createEmptyArray(global, list.len); for (list, 0..) |feature, i| { - try array.putIndex(global, @intCast(i), bun.String.static(feature).toJS(global)); + try array.putIndex(global, @intCast(i), try bun.String.static(feature).toJS(global)); } obj.put(global, jsc.ZigString.static("features"), array); - obj.put(global, jsc.ZigString.static("version"), bun.String.init(Global.package_json_version).toJS(global)); + obj.put(global, jsc.ZigString.static("version"), try bun.String.init(Global.package_json_version).toJS(global)); obj.put(global, jsc.ZigString.static("is_canary"), jsc.JSValue.jsBoolean(bun.Environment.is_canary)); // This is the source of truth for the git sha. // Not the github ref or the git tag. - obj.put(global, jsc.ZigString.static("revision"), bun.String.init(bun.Environment.git_sha).toJS(global)); + obj.put(global, jsc.ZigString.static("revision"), try bun.String.init(bun.Environment.git_sha).toJS(global)); obj.put(global, jsc.ZigString.static("generated_at"), JSValue.jsNumberFromInt64(@max(std.time.milliTimestamp(), 0))); return obj; diff --git a/src/deps/c_ares.zig b/src/deps/c_ares.zig index f9535416a2..41ecbca7ab 100644 --- a/src/deps/c_ares.zig +++ b/src/deps/c_ares.zig @@ -1395,7 +1395,7 @@ pub const struct_any_reply = struct { char.* = std.ascii.toUpper(char.*); } - transformed.put(globalThis, "type", bun.String.ascii(&upper).toJS(globalThis)); + transformed.put(globalThis, "type", try bun.String.ascii(&upper).toJS(globalThis)); try array.putIndex(globalThis, i.*, transformed); i.* += 1; } @@ -1682,7 +1682,7 @@ pub const Error = enum(i32) { }); } - pub fn reject(this: *Deferred, globalThis: *jsc.JSGlobalObject) bun.JSTerminated!void { + pub fn reject(this: *Deferred, globalThis: *jsc.JSGlobalObject) bun.JSError!void { const system_error = jsc.SystemError{ .errno = @intFromEnum(this.errno), .code = bun.String.static(this.errno.code()), @@ -1695,7 +1695,7 @@ pub const Error = enum(i32) { }; const instance = system_error.toErrorInstance(globalThis); - instance.put(globalThis, "name", bun.String.static("DNSException").toJS(globalThis)); + instance.put(globalThis, "name", try bun.String.static("DNSException").toJS(globalThis)); defer this.deinit(); defer this.hostname = null; @@ -1706,7 +1706,7 @@ pub const Error = enum(i32) { const Context = struct { deferred: *Deferred, globalThis: *jsc.JSGlobalObject, - pub fn callback(context: *@This()) bun.JSTerminated!void { + pub fn callback(context: *@This()) bun.JSError!void { defer bun.default_allocator.destroy(context); try context.deferred.reject(context.globalThis); } @@ -1737,18 +1737,18 @@ pub const Error = enum(i32) { return Deferred.init(this, syscall, host_string, promise.*); } - pub fn toJSWithSyscall(this: Error, globalThis: *jsc.JSGlobalObject, comptime syscall: [:0]const u8) jsc.JSValue { + pub fn toJSWithSyscall(this: Error, globalThis: *jsc.JSGlobalObject, comptime syscall: [:0]const u8) bun.JSError!jsc.JSValue { const instance = (jsc.SystemError{ .errno = @intFromEnum(this), .code = bun.String.static(this.code()[4..]), .syscall = bun.String.static(syscall), .message = bun.handleOom(bun.String.createFormat("{s} {s}", .{ syscall, this.code()[4..] })), }).toErrorInstance(globalThis); - instance.put(globalThis, "name", bun.String.static("DNSException").toJS(globalThis)); + instance.put(globalThis, "name", try bun.String.static("DNSException").toJS(globalThis)); return instance; } - pub fn toJSWithSyscallAndHostname(this: Error, globalThis: *jsc.JSGlobalObject, comptime syscall: [:0]const u8, hostname: []const u8) jsc.JSValue { + pub fn toJSWithSyscallAndHostname(this: Error, globalThis: *jsc.JSGlobalObject, comptime syscall: [:0]const u8, hostname: []const u8) bun.JSError!jsc.JSValue { const instance = (jsc.SystemError{ .errno = @intFromEnum(this), .code = bun.String.static(this.code()[4..]), @@ -1756,7 +1756,7 @@ pub const Error = enum(i32) { .syscall = bun.String.static(syscall), .hostname = bun.String.cloneUTF8(hostname), }).toErrorInstance(globalThis); - instance.put(globalThis, "name", bun.String.static("DNSException").toJS(globalThis)); + instance.put(globalThis, "name", try bun.String.static("DNSException").toJS(globalThis)); return instance; } diff --git a/src/deps/lol-html.zig b/src/deps/lol-html.zig index c4c1885b1c..731c80070e 100644 --- a/src/deps/lol-html.zig +++ b/src/deps/lol-html.zig @@ -609,10 +609,10 @@ pub const HTMLString = extern struct { return bun.String.cloneUTF8(bytes); } - pub fn toJS(this: HTMLString, globalThis: *bun.jsc.JSGlobalObject) bun.jsc.JSValue { + pub fn toJS(this: HTMLString, globalThis: *bun.jsc.JSGlobalObject) bun.JSError!bun.jsc.JSValue { var str = this.toString(); defer str.deref(); - return str.toJS(globalThis); + return try str.toJS(globalThis); } }; diff --git a/src/deps/uws.zig b/src/deps/uws.zig index f25f48094e..a5c24ad121 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -100,7 +100,7 @@ pub const us_bun_verify_error_t = extern struct { code: [*c]const u8 = null, reason: [*c]const u8 = null, - pub fn toJS(this: *const us_bun_verify_error_t, globalObject: *jsc.JSGlobalObject) jsc.JSValue { + pub fn toJS(this: *const us_bun_verify_error_t, globalObject: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { const code = if (this.code == null) "" else this.code[0..bun.len(this.code)]; const reason = if (this.reason == null) "" else this.reason[0..bun.len(this.reason)]; diff --git a/src/deps/uws/socket.zig b/src/deps/uws/socket.zig index 2e8720bfec..81620bf440 100644 --- a/src/deps/uws/socket.zig +++ b/src/deps/uws/socket.zig @@ -163,9 +163,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), TLSSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_close(socket: *us_socket_t, code: i32, reason: ?*anyopaque) callconv(.c) ?*us_socket_t { @@ -175,9 +173,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { code, reason, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_data(socket: *us_socket_t, buf: ?[*]u8, len: i32) callconv(.c) ?*us_socket_t { @@ -186,9 +182,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { TLSSocket.from(socket), if (buf) |data_ptr| data_ptr[0..@as(usize, @intCast(len))] else "", ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_writable(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -196,9 +190,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), TLSSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_timeout(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -206,9 +198,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), TLSSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_long_timeout(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -216,9 +206,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), TLSSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_connect_error(socket: *us_socket_t, code: i32) callconv(.c) ?*us_socket_t { @@ -227,9 +215,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { TLSSocket.from(socket), code, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_connect_error_connecting_socket(socket: *ConnectingSocket, code: i32) callconv(.c) ?*ConnectingSocket { @@ -238,9 +224,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { TLSSocket.fromConnecting(socket), code, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_end(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -248,9 +232,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), TLSSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_handshake(socket: *us_socket_t, success: i32, verify_error: us_bun_verify_error_t, _: ?*anyopaque) callconv(.c) void { @@ -260,9 +242,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { success, verify_error, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return, - }; + if (@TypeOf(res) != void) res catch return; // Exception set on global object } }; @@ -724,9 +704,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), SocketHandlerType.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_close(socket: *us_socket_t, code: i32, reason: ?*anyopaque) callconv(.c) ?*us_socket_t { @@ -736,9 +714,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { code, reason, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_data(socket: *us_socket_t, buf: ?[*]u8, len: i32) callconv(.c) ?*us_socket_t { @@ -747,9 +723,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { SocketHandlerType.from(socket), if (buf) |data_ptr| data_ptr[0..@as(usize, @intCast(len))] else "", ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_writable(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -757,9 +731,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), SocketHandlerType.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_timeout(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -767,9 +739,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), SocketHandlerType.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_connect_error_connecting_socket(socket: *ConnectingSocket, code: i32) callconv(.c) ?*ConnectingSocket { @@ -784,9 +754,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { SocketHandlerType.fromConnecting(socket), code, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_connect_error(socket: *us_socket_t, code: i32) callconv(.c) ?*us_socket_t { @@ -801,9 +769,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { SocketHandlerType.from(socket), code, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_end(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -811,9 +777,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), SocketHandlerType.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_handshake(socket: *us_socket_t, success: i32, verify_error: us_bun_verify_error_t, _: ?*anyopaque) callconv(.c) void { @@ -823,9 +787,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { success, verify_error, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return, - }; + if (@TypeOf(res) != void) res catch return; // Exception set on global object } }; @@ -890,9 +852,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), ThisSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_close(socket: *us_socket_t, code: i32, reason: ?*anyopaque) callconv(.c) ?*us_socket_t { @@ -902,9 +862,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { code, reason, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_data(socket: *us_socket_t, buf: ?[*]u8, len: i32) callconv(.c) ?*us_socket_t { @@ -913,9 +871,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { ThisSocket.from(socket), if (buf) |data_ptr| data_ptr[0..@as(usize, @intCast(len))] else "", ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_fd(socket: *us_socket_t, file_descriptor: c_int) callconv(.c) ?*us_socket_t { @@ -924,9 +880,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { ThisSocket.from(socket), file_descriptor, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_writable(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -934,9 +888,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), ThisSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_timeout(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -944,9 +896,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), ThisSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_long_timeout(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -954,9 +904,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), ThisSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_connect_error_connecting_socket(socket: *ConnectingSocket, code: i32) callconv(.c) ?*ConnectingSocket { @@ -971,9 +919,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { ThisSocket.fromConnecting(socket), code, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_connect_error(socket: *us_socket_t, code: i32) callconv(.c) ?*us_socket_t { @@ -994,9 +940,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { ThisSocket.from(socket), code, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_end(socket: *us_socket_t) callconv(.c) ?*us_socket_t { @@ -1004,9 +948,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { getValue(socket), ThisSocket.from(socket), ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return null, // TODO: declare throw scope - }; + if (@TypeOf(res) != void) res catch return null; // Exception set on global object return socket; } pub fn on_handshake(socket: *us_socket_t, success: i32, verify_error: us_bun_verify_error_t, _: ?*anyopaque) callconv(.c) void { @@ -1016,9 +958,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type { success, verify_error, ); - if (@TypeOf(res) != void) res catch |err| switch (err) { - error.JSTerminated => return, - }; + if (@TypeOf(res) != void) res catch return; // Exception set on global object } }; diff --git a/src/fd.zig b/src/fd.zig index 805a737685..6c3ea0e779 100644 --- a/src/fd.zig +++ b/src/fd.zig @@ -351,10 +351,11 @@ pub const FD = packed struct(backing_int) { } const uv_owned_fd = any_fd.makeLibUVOwned() catch { any_fd.close(); - return global.throwValue((jsc.SystemError{ + const err_instance = (jsc.SystemError{ .message = bun.String.static("EMFILE, too many open files"), .code = bun.String.static("EMFILE"), - }).toErrorInstance(global)) catch .zero; + }).toErrorInstance(global); + return global.vm().throwError(global, err_instance) catch .zero; }; return JSValue.jsNumberFromInt32(uv_owned_fd.uv()); } diff --git a/src/install/PackageManager/UpdateRequest.zig b/src/install/PackageManager/UpdateRequest.zig index eb9deb919e..ab843d9540 100644 --- a/src/install/PackageManager/UpdateRequest.zig +++ b/src/install/PackageManager/UpdateRequest.zig @@ -94,7 +94,7 @@ pub fn fromJS(globalThis: *jsc.JSGlobalObject, input: jsc.JSValue) bun.JSError!j var object = jsc.JSValue.createEmptyObject(globalThis, 2); var name_str = bun.String.init(update_requests[0].name); - object.put(globalThis, "name", name_str.transferToJS(globalThis)); + object.put(globalThis, "name", try name_str.transferToJS(globalThis)); object.put(globalThis, "version", try update_requests[0].version.toJS(update_requests[0].version_buf, globalThis)); return object; } diff --git a/src/install/dependency.zig b/src/install/dependency.zig index 8aff88c322..c415dca88d 100644 --- a/src/install/dependency.zig +++ b/src/install/dependency.zig @@ -286,7 +286,7 @@ pub const Version = struct { pub fn toJS(dep: *const Version, buf: []const u8, globalThis: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { const object = jsc.JSValue.createEmptyObject(globalThis, 0); - object.put(globalThis, "type", bun.String.static(@tagName(dep.tag)).toJS(globalThis)); + object.put(globalThis, "type", try bun.String.static(@tagName(dep.tag)).toJS(globalThis)); switch (dep.tag) { .dist_tag => { @@ -309,7 +309,7 @@ pub const Version = struct { .npm => { object.put(globalThis, "name", try dep.value.npm.name.toJS(buf, globalThis)); var version_str = try bun.String.createFormat("{f}", .{dep.value.npm.version.fmt(buf)}); - object.put(globalThis, "version", version_str.transferToJS(globalThis)); + object.put(globalThis, "version", try version_str.transferToJS(globalThis)); object.put(globalThis, "alias", jsc.JSValue.jsBoolean(dep.value.npm.is_alias)); }, .symlink => { diff --git a/src/install/hosted_git_info.zig b/src/install/hosted_git_info.zig index 9ff70822e8..13bb7fedcd 100644 --- a/src/install/hosted_git_info.zig +++ b/src/install/hosted_git_info.zig @@ -168,40 +168,40 @@ pub const HostedGitInfo = struct { } /// Convert this HostedGitInfo to a JavaScript object - pub fn toJS(self: *const Self, go: *jsc.JSGlobalObject) jsc.JSValue { + pub fn toJS(self: *const Self, go: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { const obj = jsc.JSValue.createEmptyObject(go, 6); obj.put( go, jsc.ZigString.static("type"), - bun.String.fromBytes(self.host_provider.typeStr()).toJS(go), + try bun.String.fromBytes(self.host_provider.typeStr()).toJS(go), ); obj.put( go, jsc.ZigString.static("domain"), - bun.String.fromBytes(self.host_provider.domain()).toJS(go), + try bun.String.fromBytes(self.host_provider.domain()).toJS(go), ); obj.put( go, jsc.ZigString.static("project"), - bun.String.fromBytes(self.project).toJS(go), + try bun.String.fromBytes(self.project).toJS(go), ); obj.put( go, jsc.ZigString.static("user"), - if (self.user) |user| bun.String.fromBytes(user).toJS(go) else .null, + if (self.user) |user| try bun.String.fromBytes(user).toJS(go) else .null, ); obj.put( go, jsc.ZigString.static("committish"), if (self.committish) |committish| - bun.String.fromBytes(committish).toJS(go) + try bun.String.fromBytes(committish).toJS(go) else .null, ); obj.put( go, jsc.ZigString.static("default"), - bun.String.fromBytes(@tagName(self.default_representation)).toJS(go), + try bun.String.fromBytes(@tagName(self.default_representation)).toJS(go), ); return obj; diff --git a/src/napi/napi.zig b/src/napi/napi.zig index 3f8447ed3d..5ab0bb54de 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -411,7 +411,7 @@ pub export fn napi_create_string_latin1(env_: napi_env, str: ?[*]const u8, lengt log("napi_create_string_latin1: {s}", .{slice}); if (slice.len == 0) { - result.set(env, bun.String.empty.toJS(env.toJS())); + result.set(env, bun.String.empty.toJS(env.toJS()) catch return env.setLastError(.generic_failure)); return env.ok(); } @@ -420,7 +420,7 @@ pub export fn napi_create_string_latin1(env_: napi_env, str: ?[*]const u8, lengt @memcpy(bytes, slice); - result.set(env, string.toJS(env.toJS())); + result.set(env, string.toJS(env.toJS()) catch return env.setLastError(.generic_failure)); return env.ok(); } pub export fn napi_create_string_utf8(env_: napi_env, str: ?[*]const u8, length: usize, result_: ?*napi_value) napi_status { @@ -486,14 +486,14 @@ pub export fn napi_create_string_utf16(env_: napi_env, str: ?[*]const char16_t, log("napi_create_string_utf16: {d} {f}", .{ slice.len, bun.fmt.FormatUTF16{ .buf = slice[0..@min(slice.len, 512)] } }); if (slice.len == 0) { - result.set(env, bun.String.empty.toJS(env.toJS())); + result.set(env, bun.String.empty.toJS(env.toJS()) catch return env.setLastError(.generic_failure)); return env.ok(); } var string, const chars = bun.String.createUninitialized(.utf16, slice.len); @memcpy(chars, slice); - result.set(env, string.transferToJS(env.toJS())); + result.set(env, string.transferToJS(env.toJS()) catch return env.setLastError(.generic_failure)); return env.ok(); } diff --git a/src/patch.zig b/src/patch.zig index dc024fe35c..213434cff3 100644 --- a/src/patch.zig +++ b/src/patch.zig @@ -1151,7 +1151,7 @@ pub const TestingAPIs = struct { defer args.deinit(); if (args.patchfile.apply(bun.default_allocator, args.dirfd)) |err| { - return globalThis.throwValue(err.toJS(globalThis)); + return globalThis.throwValue(try err.toJS(globalThis)); } return .true; @@ -1198,7 +1198,7 @@ pub const TestingAPIs = struct { break :brk switch (bun.sys.open(path, bun.O.DIRECTORY | bun.O.RDONLY, 0)) { .err => |e| { - globalThis.throwValue(e.withPath(path).toJS(globalThis)) catch {}; + globalThis.throwValue(e.withPath(path).toJS(globalThis) catch return .initErr(.js_undefined)) catch {}; return .initErr(.js_undefined); }, .result => |fd| fd, diff --git a/src/sql/mysql/js/JSMySQLConnection.zig b/src/sql/mysql/js/JSMySQLConnection.zig index e57908e1e2..a85bc7519f 100644 --- a/src/sql/mysql/js/JSMySQLConnection.zig +++ b/src/sql/mysql/js/JSMySQLConnection.zig @@ -241,7 +241,7 @@ fn SocketHandler(comptime ssl: bool) type { ) void { const handshakeWasSuccessful = this.#connection.doHandshake(success, ssl_error) catch |err| return this.failFmt(err, "Failed to send handshake response", .{}); if (!handshakeWasSuccessful) { - this.failWithJSValue(ssl_error.toJS(this.#globalObject)); + this.failWithJSValue(ssl_error.toJS(this.#globalObject) catch return); } } diff --git a/src/sql/postgres/PostgresSQLConnection.zig b/src/sql/postgres/PostgresSQLConnection.zig index 7cbceae629..0cdbf71600 100644 --- a/src/sql/postgres/PostgresSQLConnection.zig +++ b/src/sql/postgres/PostgresSQLConnection.zig @@ -428,7 +428,7 @@ pub fn onHandshake(this: *PostgresSQLConnection, success: i32, ssl_error: uws.us .verify_ca, .verify_full => { if (ssl_error.error_no != 0) { - this.failWithJSValue(ssl_error.toJS(this.globalObject)); + this.failWithJSValue(ssl_error.toJS(this.globalObject) catch return); return; } @@ -436,7 +436,7 @@ pub fn onHandshake(this: *PostgresSQLConnection, success: i32, ssl_error: uws.us if (BoringSSL.c.SSL_get_servername(ssl_ptr, 0)) |servername| { const hostname = servername[0..bun.len(servername)]; if (!BoringSSL.checkServerIdentity(ssl_ptr, hostname)) { - this.failWithJSValue(ssl_error.toJS(this.globalObject)); + this.failWithJSValue(ssl_error.toJS(this.globalObject) catch return); } } }, @@ -447,7 +447,7 @@ pub fn onHandshake(this: *PostgresSQLConnection, success: i32, ssl_error: uws.us } else { // if we are here is because server rejected us, and the error_no is the cause of this // no matter if reject_unauthorized is false because we are disconnected by the server - this.failWithJSValue(ssl_error.toJS(this.globalObject)); + this.failWithJSValue(ssl_error.toJS(this.globalObject) catch return); } } diff --git a/src/string.zig b/src/string.zig index b3afd217bf..372bc06346 100644 --- a/src/string.zig +++ b/src/string.zig @@ -69,9 +69,9 @@ pub const String = extern struct { } extern fn BunString__transferToJS(this: *String, globalThis: *jsc.JSGlobalObject) jsc.JSValue; - pub fn transferToJS(this: *String, globalThis: *jsc.JSGlobalObject) jsc.JSValue { + pub fn transferToJS(this: *String, globalThis: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { jsc.markBinding(@src()); - return BunString__transferToJS(this, globalThis); + return bun.jsc.fromJSHostCall(globalThis, @src(), BunString__transferToJS, .{ this, globalThis }); } pub fn toOwnedSlice(this: String, allocator: std.mem.Allocator) OOM![]u8 { @@ -543,10 +543,10 @@ pub const String = extern struct { return if (ok) out else error.JSError; } - pub fn toJS(this: *const String, globalObject: *bun.jsc.JSGlobalObject) jsc.JSValue { + pub fn toJS(this: *const String, globalObject: *bun.jsc.JSGlobalObject) bun.JSError!jsc.JSValue { jsc.markBinding(@src()); - return BunString__toJS(globalObject, this); + return bun.jsc.fromJSHostCall(globalObject, @src(), BunString__toJS, .{ globalObject, this }); } pub fn toJSDOMURL(this: *String, globalObject: *bun.jsc.JSGlobalObject) jsc.JSValue { diff --git a/src/sys/Error.zig b/src/sys/Error.zig index 6dc5fe6b94..5d8d6e299d 100644 --- a/src/sys/Error.zig +++ b/src/sys/Error.zig @@ -322,7 +322,7 @@ pub inline fn todo() Error { return Error{ .errno = todo_errno, .syscall = .TODO }; } -pub fn toJS(this: Error, ptr: *jsc.JSGlobalObject) jsc.JSValue { +pub fn toJS(this: Error, ptr: *jsc.JSGlobalObject) bun.JSError!jsc.JSValue { return this.toSystemError().toErrorInstance(ptr); } diff --git a/src/transpiler.zig b/src/transpiler.zig index 0c058e0f77..67b8f66842 100644 --- a/src/transpiler.zig +++ b/src/transpiler.zig @@ -266,8 +266,15 @@ pub const PluginRunner = struct { // Our super slow way of cloning the string into memory owned by jsc const combined_string = std.fmt.allocPrint(this.allocator, "{f}:{f}", .{ user_namespace, file_path }) catch unreachable; var out_ = bun.String.init(combined_string); - const jsval = out_.toJS(this.global_object); - const out = jsval.toBunString(this.global_object) catch @panic("unreachable"); + defer out_.deref(); + const jsval = out_.toJS(this.global_object) catch |err| { + this.allocator.free(combined_string); + return jsc.ErrorableString.err(err, this.global_object.tryTakeException() orelse .js_undefined); + }; + const out = jsval.toBunString(this.global_object) catch |err| { + this.allocator.free(combined_string); + return jsc.ErrorableString.err(err, this.global_object.tryTakeException() orelse .js_undefined); + }; this.allocator.free(combined_string); return jsc.ErrorableString.ok(out); } diff --git a/src/valkey/js_valkey.zig b/src/valkey/js_valkey.zig index 01bdd886d0..66c721b2fa 100644 --- a/src/valkey/js_valkey.zig +++ b/src/valkey/js_valkey.zig @@ -1526,7 +1526,15 @@ fn SocketHandler(comptime ssl: bool) type { defer loop.exit(); this.client.flags.is_manually_closed = true; defer this.client.close(); - try this.client.failWithJSValue(this.globalObject, ssl_error.toJS(this.globalObject)); + const ssl_js_value = ssl_error.toJS(this.globalObject) catch |err| switch (err) { + error.JSTerminated => return error.JSTerminated, + else => { + // Clear any pending exception since we can't convert it to JS + this.globalObject.clearException(); + return; + }, + }; + try this.client.failWithJSValue(this.globalObject, ssl_js_value); return; } } diff --git a/test/internal/ban-limits.json b/test/internal/ban-limits.json index d4e1db49a5..4219d0eb41 100644 --- a/test/internal/ban-limits.json +++ b/test/internal/ban-limits.json @@ -17,7 +17,7 @@ "EXCEPTION_ASSERT(!scope.exception())": 0, "JSValue.false": 0, "JSValue.true": 0, - "TODO: properly propagate exception upwards": 117, + "TODO: properly propagate exception upwards": 114, "alloc.ptr !=": 0, "alloc.ptr ==": 0, "allocator.ptr !=": 1, diff --git a/test/js/bun/s3/s3.test.ts b/test/js/bun/s3/s3.test.ts index 53c56a5d0a..c2c16939dd 100644 --- a/test/js/bun/s3/s3.test.ts +++ b/test/js/bun/s3/s3.test.ts @@ -1075,7 +1075,8 @@ for (let credentials of allCredentials) { await s3file.write("Hello Bun!"); expect.unreachable(); } catch (e: any) { - expect(["ENAMETOOLONG", "ERR_S3_INVALID_PATH"]).toContain(e?.code); + // ERR_STRING_TOO_LONG can occur when the path is too long to convert to a JS string + expect(["ENAMETOOLONG", "ERR_S3_INVALID_PATH", "ERR_STRING_TOO_LONG"]).toContain(e?.code); } }), );