mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 18:38:55 +00:00
Replace `catch bun.outOfMemory()`, which can accidentally catch non-OOM-related errors, with either `bun.handleOom` or a manual `catch |err| switch (err)`. (For internal tracking: fixes STAB-1070) --------- Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
67 lines
2.4 KiB
Zig
67 lines
2.4 KiB
Zig
fn isOomOnlyError(comptime ErrorUnionOrSet: type) bool {
|
|
@setEvalBranchQuota(10000);
|
|
const ErrorSet = switch (@typeInfo(ErrorUnionOrSet)) {
|
|
.error_union => |union_info| union_info.error_set,
|
|
.error_set => ErrorUnionOrSet,
|
|
else => @compileError("argument must be an error union or error set"),
|
|
};
|
|
for (@typeInfo(ErrorSet).error_set orelse &.{}) |err| {
|
|
if (!std.mem.eql(u8, err.name, "OutOfMemory")) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// If `error_union_or_set` is `error.OutOfMemory`, calls `bun.outOfMemory`. Otherwise:
|
|
///
|
|
/// * If that was the only possible error, returns the non-error payload for error unions, or
|
|
/// `noreturn` for error sets.
|
|
/// * If other errors are possible, returns the same error union or set, but without
|
|
/// `error.OutOfMemory` in the error set.
|
|
///
|
|
/// Prefer this method over `catch bun.outOfMemory()`, since that could mistakenly catch
|
|
/// non-OOM-related errors.
|
|
///
|
|
/// There are two ways to use this function:
|
|
///
|
|
/// ```
|
|
/// // option 1:
|
|
/// const thing = bun.handleOom(allocateThing());
|
|
/// // option 2:
|
|
/// const thing = allocateThing() catch |err| bun.handleOom(err);
|
|
/// ```
|
|
pub fn handleOom(error_union_or_set: anytype) return_type: {
|
|
const ArgType = @TypeOf(error_union_or_set);
|
|
const arg_info = @typeInfo(ArgType);
|
|
break :return_type if (isOomOnlyError(ArgType)) switch (arg_info) {
|
|
.error_union => |union_info| union_info.payload,
|
|
.error_set => noreturn,
|
|
else => unreachable,
|
|
} else @TypeOf(blk: {
|
|
const err = switch (comptime arg_info) {
|
|
.error_union => if (error_union_or_set) |success| break :blk success else |err| err,
|
|
.error_set => error_union_or_set,
|
|
else => unreachable,
|
|
};
|
|
break :blk switch (err) {
|
|
error.OutOfMemory => unreachable,
|
|
else => |other_error| other_error,
|
|
};
|
|
});
|
|
} {
|
|
const ArgType = @TypeOf(error_union_or_set);
|
|
const err = switch (comptime @typeInfo(ArgType)) {
|
|
.error_union => if (error_union_or_set) |success| return success else |err| err,
|
|
.error_set => error_union_or_set,
|
|
else => unreachable,
|
|
};
|
|
return if (comptime isOomOnlyError(ArgType))
|
|
bun.outOfMemory()
|
|
else switch (err) {
|
|
error.OutOfMemory => bun.outOfMemory(),
|
|
else => |other_error| other_error,
|
|
};
|
|
}
|
|
|
|
const bun = @import("bun");
|
|
const std = @import("std");
|