From befb269b2dbd4eb22150ad2a3d79bb74705d1746 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Fri, 15 Nov 2024 22:14:18 -0800 Subject: [PATCH] zig: align fromJS methods to using JSError (#15165) --- src/bun.js/ConsoleObject.zig | 2 +- src/bun.js/api/BunObject.zig | 154 ++++++--------- src/bun.js/api/JSBundler.zig | 65 +++--- src/bun.js/api/JSTranspiler.zig | 8 +- src/bun.js/api/bun/h2_frame_parser.zig | 71 +++---- src/bun.js/api/bun/socket.zig | 52 ++--- src/bun.js/api/bun/udp_socket.zig | 56 ++---- src/bun.js/api/ffi.zig | 54 ++--- src/bun.js/api/glob.zig | 57 +++--- src/bun.js/api/server.zig | 165 +++++----------- src/bun.js/base.zig | 4 +- src/bun.js/bindings/bindings.cpp | 12 +- src/bun.js/bindings/bindings.zig | 17 +- src/bun.js/node/node_crypto_binding.zig | 10 +- src/bun.js/node/node_fs.zig | 242 ++++++++--------------- src/bun.js/node/node_fs_stat_watcher.zig | 9 +- src/bun.js/node/node_fs_watcher.zig | 24 +-- src/bun.js/node/types.zig | 48 ++--- src/bun.js/test/expect.zig | 23 ++- src/bun.js/webcore/blob.zig | 67 +++---- src/bun.js/webcore/response.zig | 25 +-- src/bun.js/webcore/streams.zig | 12 +- src/bun.zig | 1 + src/install/dependency.zig | 23 +-- src/install/install.zig | 13 +- src/logger.zig | 3 +- src/options.zig | 21 +- src/sql/postgres.zig | 20 +- src/sql/postgres/postgres_types.zig | 3 +- src/string.zig | 5 +- 30 files changed, 481 insertions(+), 785 deletions(-) diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index 08cd6a6eb8..9836d42302 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -683,7 +683,7 @@ pub const FormatOptions = struct { single_line: bool = false, default_indent: u16 = 0, - pub fn fromJS(formatOptions: *FormatOptions, globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSValue) !void { + pub fn fromJS(formatOptions: *FormatOptions, globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSValue) bun.JSError!void { const arg1 = arguments[0]; if (arg1.isObject()) { diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index ad5d0d18ab..f593cbd008 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -1489,46 +1489,46 @@ pub const Crypto = struct { this.salt.deinit(); } - pub fn fromJS(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSValue, is_async: bool) ?PBKDF2 { + pub fn fromJS(globalThis: *JSC.JSGlobalObject, arguments: []const JSC.JSValue, is_async: bool) bun.JSError!PBKDF2 { if (arguments.len < 5) { globalThis.throwNotEnoughArguments("pbkdf2", 5, arguments.len); - return null; + return error.JSError; } if (!arguments[3].isAnyInt()) { _ = globalThis.throwInvalidArgumentTypeValue("keylen", "integer", arguments[3]); - return null; + return error.JSError; } const length = arguments[3].coerce(i64, globalThis); if (!globalThis.hasException() and (length < 0 or length > std.math.maxInt(i32))) { - globalThis.throwInvalidArguments("keylen must be > 0 and < {d}", .{std.math.maxInt(i32)}); + return globalThis.throwInvalidArguments2("keylen must be > 0 and < {d}", .{std.math.maxInt(i32)}); } if (globalThis.hasException()) { - return null; + return error.JSError; } if (!arguments[2].isAnyInt()) { _ = globalThis.throwInvalidArgumentTypeValue("iteration count", "integer", arguments[2]); - return null; + return error.JSError; } const iteration_count = arguments[2].coerce(i64, globalThis); if (!globalThis.hasException() and (iteration_count < 1 or iteration_count > std.math.maxInt(u32))) { - globalThis.throwInvalidArguments("iteration count must be >= 1 and <= maxInt", .{}); + return globalThis.throwInvalidArguments2("iteration count must be >= 1 and <= maxInt", .{}); } if (globalThis.hasException()) { - return null; + return error.JSError; } const algorithm = brk: { if (!arguments[4].isString()) { _ = globalThis.throwInvalidArgumentTypeValue("algorithm", "string", arguments[4]); - return null; + return error.JSError; } break :brk EVP.Algorithm.map.fromJSCaseInsensitive(globalThis, arguments[4]) orelse { @@ -1538,7 +1538,7 @@ pub const Crypto = struct { const name = slice.slice(); globalThis.ERR_CRYPTO_INVALID_DIGEST("Unsupported algorithm \"{s}\"", .{name}).throw(); } - return null; + return error.JSError; }; }; @@ -1558,24 +1558,22 @@ pub const Crypto = struct { out.salt = JSC.Node.StringOrBuffer.fromJSMaybeAsync(globalThis, bun.default_allocator, arguments[1], is_async) orelse { _ = globalThis.throwInvalidArgumentTypeValue("salt", "string or buffer", arguments[1]); - return null; + return error.JSError; }; if (out.salt.slice().len > std.math.maxInt(i32)) { - globalThis.throwInvalidArguments("salt is too long", .{}); - return null; + return globalThis.throwInvalidArguments2("salt is too long", .{}); } out.password = JSC.Node.StringOrBuffer.fromJSMaybeAsync(globalThis, bun.default_allocator, arguments[0], is_async) orelse { if (!globalThis.hasException()) { _ = globalThis.throwInvalidArgumentTypeValue("password", "string or buffer", arguments[0]); } - return null; + return error.JSError; }; if (out.password.slice().len > std.math.maxInt(i32)) { - globalThis.throwInvalidArguments("password is too long", .{}); - return null; + return globalThis.throwInvalidArguments2("password is too long", .{}); } return out; @@ -1696,19 +1694,19 @@ pub const Crypto = struct { .argon2id = .{}, }; - pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) ?Value { + pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) bun.JSError!Value { if (value.isObject()) { if (value.getTruthy(globalObject, "algorithm")) |algorithm_value| { if (!algorithm_value.isString()) { globalObject.throwInvalidArgumentType("hash", "algorithm", "string"); - return null; + return error.JSError; } const algorithm_string = algorithm_value.getZigString(globalObject); switch (PasswordObject.Algorithm.label.getWithEql(algorithm_string, JSC.ZigString.eqlComptime) orelse { globalObject.throwInvalidArgumentType("hash", "algorithm", unknown_password_algorithm_message); - return null; + return error.JSError; }) { .bcrypt => { var algorithm = PasswordObject.Algorithm.Value{ @@ -1718,14 +1716,13 @@ pub const Crypto = struct { if (value.getTruthy(globalObject, "cost")) |rounds_value| { if (!rounds_value.isNumber()) { globalObject.throwInvalidArgumentType("hash", "cost", "number"); - return null; + return error.JSError; } const rounds = rounds_value.coerce(i32, globalObject); if (rounds < 4 or rounds > 31) { - globalObject.throwInvalidArguments("Rounds must be between 4 and 31", .{}); - return null; + return globalObject.throwInvalidArguments2("Rounds must be between 4 and 31", .{}); } algorithm.bcrypt = @as(u6, @intCast(rounds)); @@ -1739,14 +1736,13 @@ pub const Crypto = struct { if (value.getTruthy(globalObject, "timeCost")) |time_value| { if (!time_value.isNumber()) { globalObject.throwInvalidArgumentType("hash", "timeCost", "number"); - return null; + return error.JSError; } const time_cost = time_value.coerce(i32, globalObject); if (time_cost < 1) { - globalObject.throwInvalidArguments("Time cost must be greater than 0", .{}); - return null; + return globalObject.throwInvalidArguments2("Time cost must be greater than 0", .{}); } argon.time_cost = @as(u32, @intCast(time_cost)); @@ -1755,14 +1751,13 @@ pub const Crypto = struct { if (value.getTruthy(globalObject, "memoryCost")) |memory_value| { if (!memory_value.isNumber()) { globalObject.throwInvalidArgumentType("hash", "memoryCost", "number"); - return null; + return error.JSError; } const memory_cost = memory_value.coerce(i32, globalObject); if (memory_cost < 1) { - globalObject.throwInvalidArguments("Memory cost must be greater than 0", .{}); - return null; + return globalObject.throwInvalidArguments2("Memory cost must be greater than 0", .{}); } argon.memory_cost = @as(u32, @intCast(memory_cost)); @@ -1775,14 +1770,14 @@ pub const Crypto = struct { unreachable; } else { globalObject.throwInvalidArgumentType("hash", "options.algorithm", "string"); - return null; + return error.JSError; } } else if (value.isString()) { const algorithm_string = value.getZigString(globalObject); switch (PasswordObject.Algorithm.label.getWithEql(algorithm_string, JSC.ZigString.eqlComptime) orelse { globalObject.throwInvalidArgumentType("hash", "algorithm", unknown_password_algorithm_message); - return null; + return error.JSError; }) { .bcrypt => { return PasswordObject.Algorithm.Value{ @@ -1807,7 +1802,7 @@ pub const Crypto = struct { } } else { globalObject.throwInvalidArgumentType("hash", "algorithm", "string"); - return null; + return error.JSError; } unreachable; @@ -2204,27 +2199,26 @@ pub const Crypto = struct { if (arguments.len < 1) { globalObject.throwNotEnoughArguments("hash", 1, 0); - return JSC.JSValue.undefined; + return error.JSError; } var algorithm = PasswordObject.Algorithm.Value.default; if (arguments.len > 1 and !arguments[1].isEmptyOrUndefinedOrNull()) { - algorithm = PasswordObject.Algorithm.Value.fromJS(globalObject, arguments[1]) orelse - return JSC.JSValue.undefined; + algorithm = try PasswordObject.Algorithm.Value.fromJS(globalObject, arguments[1]); } const password_to_hash = JSC.Node.StringOrBuffer.fromJSToOwnedSlice(globalObject, arguments[0], bun.default_allocator) catch { if (!globalObject.hasException()) { globalObject.throwInvalidArgumentType("hash", "password", "string or TypedArray"); } - return JSC.JSValue.undefined; + return error.JSError; }; + errdefer bun.default_allocator.free(password_to_hash); if (password_to_hash.len == 0) { globalObject.throwInvalidArguments("password must not be empty", .{}); - bun.default_allocator.free(password_to_hash); - return JSC.JSValue.undefined; + return error.JSError; } return hash(globalObject, password_to_hash, algorithm, false); @@ -2240,31 +2234,27 @@ pub const Crypto = struct { if (arguments.len < 1) { globalObject.throwNotEnoughArguments("hash", 1, 0); - return JSC.JSValue.undefined; + return error.JSError; } var algorithm = PasswordObject.Algorithm.Value.default; if (arguments.len > 1 and !arguments[1].isEmptyOrUndefinedOrNull()) { - algorithm = PasswordObject.Algorithm.Value.fromJS(globalObject, arguments[1]) orelse - return JSC.JSValue.undefined; + algorithm = try PasswordObject.Algorithm.Value.fromJS(globalObject, arguments[1]); } var string_or_buffer = JSC.Node.StringOrBuffer.fromJS(globalObject, bun.default_allocator, arguments[0]) orelse { if (!globalObject.hasException()) { globalObject.throwInvalidArgumentType("hash", "password", "string or TypedArray"); } - return JSC.JSValue.undefined; + return error.JSError; }; + defer string_or_buffer.deinit(); if (string_or_buffer.slice().len == 0) { - globalObject.throwInvalidArguments("password must not be empty", .{}); - string_or_buffer.deinit(); - return JSC.JSValue.undefined; + return globalObject.throwInvalidArguments2("password must not be empty", .{}); } - defer string_or_buffer.deinit(); - return hash(globalObject, string_or_buffer.slice(), algorithm, true); } @@ -2365,7 +2355,7 @@ pub const Crypto = struct { if (arguments.len < 2) { globalObject.throwNotEnoughArguments("verify", 2, 0); - return JSC.JSValue.undefined; + return error.JSError; } var algorithm: ?PasswordObject.Algorithm = null; @@ -2373,7 +2363,7 @@ pub const Crypto = struct { if (arguments.len > 2 and !arguments[2].isEmptyOrUndefinedOrNull()) { if (!arguments[2].isString()) { globalObject.throwInvalidArgumentType("verify", "algorithm", "string"); - return JSC.JSValue.undefined; + return error.JSError; } const algorithm_string = arguments[2].getZigString(globalObject); @@ -2382,19 +2372,19 @@ pub const Crypto = struct { if (!globalObject.hasException()) { globalObject.throwInvalidArgumentType("verify", "algorithm", unknown_password_algorithm_message); } - return JSC.JSValue.undefined; + return error.JSError; }; } - const owned_password = JSC.Node.StringOrBuffer.fromJSToOwnedSlice(globalObject, arguments[0], bun.default_allocator) catch |err| { - if (err != error.JSError and !globalObject.hasException()) globalObject.throwInvalidArgumentType("verify", "password", "string or TypedArray"); - return JSC.JSValue.undefined; + const owned_password = JSC.Node.StringOrBuffer.fromJSToOwnedSlice(globalObject, arguments[0], bun.default_allocator) catch { + if (!globalObject.hasException()) globalObject.throwInvalidArgumentType("verify", "password", "string or TypedArray"); + return error.JSError; }; - const owned_hash = JSC.Node.StringOrBuffer.fromJSToOwnedSlice(globalObject, arguments[1], bun.default_allocator) catch |err| { + const owned_hash = JSC.Node.StringOrBuffer.fromJSToOwnedSlice(globalObject, arguments[1], bun.default_allocator) catch { bun.default_allocator.free(owned_password); - if (err != error.JSError and !globalObject.hasException()) globalObject.throwInvalidArgumentType("verify", "hash", "string or TypedArray"); - return JSC.JSValue.undefined; + if (!globalObject.hasException()) globalObject.throwInvalidArgumentType("verify", "hash", "string or TypedArray"); + return error.JSError; }; if (owned_hash.len == 0) { @@ -2486,33 +2476,25 @@ pub const Crypto = struct { pub const digest = JSC.wrapInstanceMethod(CryptoHasher, "digest_", false); pub const hash = JSC.wrapStaticMethod(CryptoHasher, "hash_", false); - fn throwHmacConsumed(globalThis: *JSC.JSGlobalObject) void { - globalThis.throw("HMAC has been consumed and is no longer usable", .{}); + fn throwHmacConsumed(globalThis: *JSC.JSGlobalObject) bun.JSError { + return globalThis.throw2("HMAC has been consumed and is no longer usable", .{}); } - pub fn getByteLength( - this: *CryptoHasher, - globalThis: *JSC.JSGlobalObject, - ) JSC.JSValue { + pub fn getByteLength(this: *CryptoHasher, globalThis: *JSC.JSGlobalObject) JSC.JSValue { return JSC.JSValue.jsNumber(switch (this.*) { .evp => |*inner| inner.size(), .hmac => |inner| if (inner) |hmac| hmac.size() else { - throwHmacConsumed(globalThis); - return JSC.JSValue.zero; + throwHmacConsumed(globalThis) catch return .zero; }, .zig => |*inner| inner.digest_length, }); } - pub fn getAlgorithm( - this: *CryptoHasher, - globalObject: *JSC.JSGlobalObject, - ) JSC.JSValue { + pub fn getAlgorithm(this: *CryptoHasher, globalObject: *JSC.JSGlobalObject) JSC.JSValue { return switch (this.*) { inline .evp, .zig => |*inner| ZigString.fromUTF8(bun.asByteSlice(@tagName(inner.algorithm))).toJS(globalObject), .hmac => |inner| if (inner) |hmac| ZigString.fromUTF8(bun.asByteSlice(@tagName(hmac.algorithm))).toJS(globalObject) else { - throwHmacConsumed(globalObject); - return JSC.JSValue.zero; + throwHmacConsumed(globalObject) catch return .zero; }, }; } @@ -2701,18 +2683,16 @@ pub const Crypto = struct { const arguments = callframe.arguments(2); const input = arguments.ptr[0]; if (input.isEmptyOrUndefinedOrNull()) { - globalThis.throwInvalidArguments("expected blob, string or buffer", .{}); - return JSC.JSValue.zero; + return globalThis.throwInvalidArguments2("expected blob, string or buffer", .{}); } const encoding = arguments.ptr[1]; - const buffer = JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValue(globalThis, globalThis.bunVM().allocator, input, encoding) orelse { + const buffer = try JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValue(globalThis, globalThis.bunVM().allocator, input, encoding) orelse { if (!globalThis.hasException()) globalThis.throwInvalidArguments("expected blob, string or buffer", .{}); - return JSC.JSValue.zero; + return error.JSError; }; defer buffer.deinit(); if (buffer == .blob and buffer.blob.isBunFile()) { - globalThis.throw("Bun.file() is not supported here yet (it needs an async version)", .{}); - return .zero; + return globalThis.throw2("Bun.file() is not supported here yet (it needs an async version)", .{}); } switch (this.*) { @@ -2722,14 +2702,12 @@ pub const Crypto = struct { if (err != 0) { const instance = createCryptoError(globalThis, err); BoringSSL.ERR_clear_error(); - globalThis.throwValue(instance); - return .zero; + return globalThis.throwValue2(instance); } }, .hmac => |inner| { const hmac = inner orelse { - throwHmacConsumed(globalThis); - return JSC.JSValue.zero; + return throwHmacConsumed(globalThis); }; hmac.update(buffer.slice()); @@ -2737,8 +2715,7 @@ pub const Crypto = struct { if (err != 0) { const instance = createCryptoError(globalThis, err); BoringSSL.ERR_clear_error(); - globalThis.throwValue(instance); - return .zero; + return globalThis.throwValue2(instance); } }, .zig => |*inner| { @@ -2762,15 +2739,13 @@ pub const Crypto = struct { }, .hmac => |inner| { const hmac = inner orelse { - throwHmacConsumed(globalObject); - return JSC.JSValue.zero; + return throwHmacConsumed(globalObject); }; new = .{ .hmac = hmac.copy() catch { const err = createCryptoError(globalObject, BoringSSL.ERR_get_error()); BoringSSL.ERR_clear_error(); - globalObject.throwValue(err); - return JSC.JSValue.zero; + return globalObject.throwValue2(err); }, }; }, @@ -2823,7 +2798,7 @@ pub const Crypto = struct { output_digest_buf = std.mem.zeroes(EVP.Digest); } - const result = this.final(globalThis, output_digest_slice); + const result = this.final(globalThis, output_digest_slice) catch return .zero; if (globalThis.hasException()) { return JSC.JSValue.zero; } @@ -2839,19 +2814,18 @@ pub const Crypto = struct { fn digestToEncoding(this: *CryptoHasher, globalThis: *JSGlobalObject, encoding: JSC.Node.Encoding) JSC.JSValue { var output_digest_buf: EVP.Digest = std.mem.zeroes(EVP.Digest); const output_digest_slice: []u8 = &output_digest_buf; - const out = this.final(globalThis, output_digest_slice); + const out = this.final(globalThis, output_digest_slice) catch return .zero; if (globalThis.hasException()) { return JSC.JSValue.zero; } return encoding.encodeWithMaxSize(globalThis, BoringSSL.EVP_MAX_MD_SIZE, out); } - fn final(this: *CryptoHasher, globalThis: *JSGlobalObject, output_digest_slice: []u8) []u8 { + fn final(this: *CryptoHasher, globalThis: *JSGlobalObject, output_digest_slice: []u8) bun.JSError![]u8 { return switch (this.*) { .hmac => |inner| brk: { const hmac: *HMAC = inner orelse { - throwHmacConsumed(globalThis); - return &.{}; + return throwHmacConsumed(globalThis); }; this.hmac = null; defer hmac.deinit(); diff --git a/src/bun.js/api/JSBundler.zig b/src/bun.js/api/JSBundler.zig index edd39ed588..67e85e62d8 100644 --- a/src/bun.js/api/JSBundler.zig +++ b/src/bun.js/api/JSBundler.zig @@ -81,9 +81,7 @@ pub const JSBundler = struct { pub const List = bun.StringArrayHashMapUnmanaged(Config); - const FromJSError = OOM || JSError; - - pub fn fromJS(globalThis: *JSC.JSGlobalObject, config: JSC.JSValue, plugins: *?*Plugin, allocator: std.mem.Allocator) FromJSError!Config { + pub fn fromJS(globalThis: *JSC.JSGlobalObject, config: JSC.JSValue, plugins: *?*Plugin, allocator: std.mem.Allocator) JSError!Config { var this = Config{ .entry_points = bun.StringSet.init(allocator), .external = bun.StringSet.init(allocator), @@ -120,24 +118,20 @@ pub const JSBundler = struct { var i: usize = 0; while (iter.next()) |plugin| : (i += 1) { if (!plugin.isObject()) { - globalThis.throwInvalidArguments("Expected plugin to be an object", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected plugin to be an object", .{}); } - if (plugin.getOptional(globalThis, "name", ZigString.Slice) catch null) |slice| { + if (try plugin.getOptional(globalThis, "name", ZigString.Slice)) |slice| { defer slice.deinit(); if (slice.len == 0) { - globalThis.throwInvalidArguments("Expected plugin to have a non-empty name", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected plugin to have a non-empty name", .{}); } } else { - globalThis.throwInvalidArguments("Expected plugin to have a name", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected plugin to have a name", .{}); } - const function = (plugin.getFunction(globalThis, "setup") catch null) orelse { - globalThis.throwInvalidArguments("Expected plugin to have a setup() function", .{}); - return error.JSError; + const function = try plugin.getFunction(globalThis, "setup") orelse { + return globalThis.throwInvalidArguments2("Expected plugin to have a setup() function", .{}); }; var bun_plugins: *Plugin = plugins.* orelse brk: { @@ -165,16 +159,14 @@ pub const JSBundler = struct { plugin_result = val; }, .rejected => |err| { - globalThis.throwValue(err); - return error.JSError; + return globalThis.throwValue2(err); }, } } } if (plugin_result.toError()) |err| { - globalThis.throwValue(err); - return error.JSError; + return globalThis.throwValue2(err); } else if (globalThis.hasException()) { return error.JSError; } @@ -201,8 +193,7 @@ pub const JSBundler = struct { this.target = target; if (target != .bun and this.bytecode) { - globalThis.throwInvalidArguments("target must be 'bun' when bytecode is true", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("target must be 'bun' when bytecode is true", .{}); } } @@ -248,8 +239,7 @@ pub const JSBundler = struct { this.format = format; if (this.bytecode and format != .cjs) { - globalThis.throwInvalidArguments("format must be 'cjs' when bytecode is true. Eventually we'll add esm support as well.", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("format must be 'cjs' when bytecode is true. Eventually we'll add esm support as well.", .{}); } } @@ -274,8 +264,7 @@ pub const JSBundler = struct { this.minify.identifiers = syntax; } } else { - globalThis.throwInvalidArguments("Expected minify to be a boolean or an object", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected minify to be a boolean or an object", .{}); } } @@ -283,15 +272,13 @@ pub const JSBundler = struct { var iter = entry_points.arrayIterator(globalThis); while (iter.next()) |entry_point| { var slice = entry_point.toSliceOrNull(globalThis) orelse { - globalThis.throwInvalidArguments("Expected entrypoints to be an array of strings", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected entrypoints to be an array of strings", .{}); }; defer slice.deinit(); try this.entry_points.insert(slice.slice()); } } else { - globalThis.throwInvalidArguments("Expected entrypoints to be an array of strings", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected entrypoints to be an array of strings", .{}); } if (try config.getBooleanLoose(globalThis, "emitDCEAnnotations")) |flag| { @@ -313,15 +300,13 @@ pub const JSBundler = struct { var iter = conditions_value.arrayIterator(globalThis); while (iter.next()) |entry_point| { var slice = entry_point.toSliceOrNull(globalThis) orelse { - globalThis.throwInvalidArguments("Expected conditions to be an array of strings", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected conditions to be an array of strings", .{}); }; defer slice.deinit(); try this.conditions.insert(slice.slice()); } } else { - globalThis.throwInvalidArguments("Expected conditions to be an array of strings", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected conditions to be an array of strings", .{}); } } @@ -360,8 +345,7 @@ pub const JSBundler = struct { var iter = externals.arrayIterator(globalThis); while (iter.next()) |entry_point| { var slice = entry_point.toSliceOrNull(globalThis) orelse { - globalThis.throwInvalidArguments("Expected external to be an array of strings", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected external to be an array of strings", .{}); }; defer slice.deinit(); try this.external.insert(slice.slice()); @@ -372,8 +356,7 @@ pub const JSBundler = struct { var iter = drops.arrayIterator(globalThis); while (iter.next()) |entry| { var slice = entry.toSliceOrNull(globalThis) orelse { - globalThis.throwInvalidArguments("Expected drop to be an array of strings", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected drop to be an array of strings", .{}); }; defer slice.deinit(); try this.drop.insert(slice.slice()); @@ -430,15 +413,13 @@ pub const JSBundler = struct { this.names.asset.data = this.names.owned_asset.list.items; } } else { - globalThis.throwInvalidArguments("Expected naming to be a string or an object", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected naming to be a string or an object", .{}); } } if (try config.getOwnObject(globalThis, "define")) |define| { if (!define.isObject()) { - globalThis.throwInvalidArguments("define must be an object", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("define must be an object", .{}); } var define_iter = JSC.JSPropertyIterator(.{ @@ -452,8 +433,7 @@ pub const JSBundler = struct { const value_type = property_value.jsType(); if (!value_type.isStringLike()) { - globalThis.throwInvalidArguments("define \"{s}\" must be a JSON string", .{prop}); - return error.JSError; + return globalThis.throwInvalidArguments2("define \"{s}\" must be a JSON string", .{prop}); } var val = JSC.ZigString.init(""); @@ -487,8 +467,7 @@ pub const JSBundler = struct { while (loader_iter.next()) |prop| { if (!prop.hasPrefixComptime(".") or prop.length() < 2) { - globalThis.throwInvalidArguments("loader property names must be file extensions, such as '.txt'", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("loader property names must be file extensions, such as '.txt'", .{}); } loader_values[loader_iter.i] = try loader_iter.value.toEnumFromMap( diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 05fb260873..c7a6a25359 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -945,12 +945,12 @@ pub fn transform( defer args.arena.deinit(); const code_arg = args.next() orelse { globalThis.throwInvalidArgumentType("transform", "code", "string or Uint8Array"); - return .zero; + return error.JSError; }; - var code = JSC.Node.StringOrBuffer.fromJSWithEncodingMaybeAsync(globalThis, bun.default_allocator, code_arg, .utf8, true) orelse { + var code = try JSC.Node.StringOrBuffer.fromJSWithEncodingMaybeAsync(globalThis, bun.default_allocator, code_arg, .utf8, true) orelse { globalThis.throwInvalidArgumentType("transform", "code", "string or Uint8Array"); - return .zero; + return error.JSError; }; errdefer code.deinit(); @@ -977,7 +977,7 @@ pub fn transform( code_arg.unprotect(); } globalThis.throwOutOfMemory(); - return .zero; + return error.JSError; }; task.schedule(); return task.promise.value(); diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index ba1e13aa0f..42f23fff78 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -616,8 +616,7 @@ const Handlers = struct { inline for (pairs) |pair| { if (opts.getTruthy(globalObject, pair.@"1")) |callback_value| { if (!callback_value.isCell() or !callback_value.isCallable(globalObject.vm())) { - globalObject.throwInvalidArguments("Expected \"{s}\" callback to be a function", .{pair[1]}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"{s}\" callback to be a function", .{pair[1]}); } @field(handlers, pair.@"0") = callback_value; @@ -626,8 +625,7 @@ const Handlers = struct { if (opts.fastGet(globalObject, .@"error")) |callback_value| { if (!callback_value.isCell() or !callback_value.isCallable(globalObject.vm())) { - globalObject.throwInvalidArguments("Expected \"error\" callback to be a function", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"error\" callback to be a function", .{}); } handlers.onError = callback_value; @@ -635,19 +633,16 @@ const Handlers = struct { // onWrite is required for duplex support or if more than 1 parser is attached to the same socket (unliked) if (handlers.onWrite == .zero) { - globalObject.throwInvalidArguments("Expected at least \"write\" callback", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected at least \"write\" callback", .{}); } if (opts.getTruthy(globalObject, "binaryType")) |binary_type_value| { if (!binary_type_value.isString()) { - globalObject.throwInvalidArguments("Expected \"binaryType\" to be a string", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"binaryType\" to be a string", .{}); } - handlers.binary_type = BinaryType.fromJSValue(globalObject, binary_type_value) orelse { - globalObject.throwInvalidArguments("Expected 'binaryType' to be 'ArrayBuffer', 'Uint8Array', or 'Buffer'", .{}); - return error.JSError; + handlers.binary_type = try BinaryType.fromJSValue(globalObject, binary_type_value) orelse { + return globalObject.throwInvalidArguments2("Expected 'binaryType' to be 'ArrayBuffer', 'Uint8Array', or 'Buffer'", .{}); }; } @@ -2943,8 +2938,7 @@ pub const H2FrameParser = struct { JSC.markBinding(@src()); const args_list = callframe.arguments(3); if (args_list.len < 3) { - globalObject.throw("Expected stream, headers and sensitiveHeaders arguments", .{}); - return .zero; + return globalObject.throw2("Expected stream, headers and sensitiveHeaders arguments", .{}); } const stream_arg = args_list.ptr[0]; @@ -2952,29 +2946,24 @@ pub const H2FrameParser = struct { const sensitive_arg = args_list.ptr[2]; if (!stream_arg.isNumber()) { - globalObject.throw("Expected stream to be a number", .{}); - return .zero; + return globalObject.throw2("Expected stream to be a number", .{}); } const stream_id = stream_arg.toU32(); if (stream_id == 0 or stream_id > MAX_STREAM_ID) { - globalObject.throw("Invalid stream id", .{}); - return .zero; + return globalObject.throw2("Invalid stream id", .{}); } var stream = this.streams.getPtr(@intCast(stream_id)) orelse { - globalObject.throw("Invalid stream id", .{}); - return .zero; + return globalObject.throw2("Invalid stream id", .{}); }; if (!headers_arg.isObject()) { - globalObject.throw("Expected headers to be an object", .{}); - return .zero; + return globalObject.throw2("Expected headers to be an object", .{}); } if (!sensitive_arg.isObject()) { - globalObject.throw("Expected sensitiveHeaders to be an object", .{}); - return .zero; + return globalObject.throw2("Expected sensitiveHeaders to be an object", .{}); } // max frame size will be always at least 16384 @@ -2997,14 +2986,12 @@ pub const H2FrameParser = struct { if (header_name.charAt(0) == ':') { const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_PSEUDOHEADER, "\"{s}\" is an invalid pseudoheader or is used incorrectly", .{name}, globalObject); - globalObject.throwValue(exception); - return .zero; + return globalObject.throwValue2(exception); } var js_value = headers_arg.getTruthy(globalObject, name) orelse { const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{name}, globalObject); - globalObject.throwValue(exception); - return .zero; + return globalObject.throwValue2(exception); }; if (js_value.jsType().isArray()) { @@ -3013,21 +3000,18 @@ pub const H2FrameParser = struct { if (SingleValueHeaders.has(name) and value_iter.len > 1) { const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_SINGLE_VALUE_HEADER, "Header field \"{s}\" must only have a single value", .{name}, globalObject); - globalObject.throwValue(exception); - return .zero; + return globalObject.throwValue2(exception); } while (value_iter.next()) |item| { if (item.isEmptyOrUndefinedOrNull()) { const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{name}, globalObject); - globalObject.throwValue(exception); - return .zero; + return globalObject.throwValue2(exception); } const value_str = item.toStringOrNull(globalObject) orelse { const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{name}, globalObject); - globalObject.throwValue(exception); - return .zero; + return globalObject.throwValue2(exception); }; const never_index = sensitive_arg.getTruthy(globalObject, "neverIndex") != null; @@ -3049,8 +3033,7 @@ pub const H2FrameParser = struct { } else { const value_str = js_value.toStringOrNull(globalObject) orelse { const exception = JSC.toTypeError(.ERR_HTTP2_INVALID_HEADER_VALUE, "Invalid value for header \"{s}\"", .{name}, globalObject); - globalObject.throwValue(exception); - return .zero; + return globalObject.throwValue2(exception); }; const never_index = sensitive_arg.getTruthy(globalObject, "neverIndex") != null; @@ -3099,20 +3082,17 @@ pub const H2FrameParser = struct { const stream_arg, const data_arg, const encoding_arg, const close_arg, const callback_arg = args.ptr; if (!stream_arg.isNumber()) { - globalObject.throw("Expected stream to be a number", .{}); - return .zero; + return globalObject.throw2("Expected stream to be a number", .{}); } const stream_id = stream_arg.toU32(); if (stream_id == 0 or stream_id > MAX_STREAM_ID) { - globalObject.throw("Invalid stream id", .{}); - return .zero; + return globalObject.throw2("Invalid stream id", .{}); } const close = close_arg.toBoolean(); var stream = this.streams.getPtr(@intCast(stream_id)) orelse { - globalObject.throw("Invalid stream id", .{}); - return .zero; + return globalObject.throw2("Invalid stream id", .{}); }; if (!stream.canSendData()) { this.dispatchWriteCallback(callback_arg); @@ -3125,23 +3105,24 @@ pub const H2FrameParser = struct { } if (!encoding_arg.isString()) { - return globalObject.throwInvalidArgumentTypeValue("write", "encoding", encoding_arg); + _ = globalObject.throwInvalidArgumentTypeValue("write", "encoding", encoding_arg); + return error.JSError; } break :brk JSC.Node.Encoding.fromJS(encoding_arg, globalObject) orelse { if (!globalObject.hasException()) return globalObject.throwInvalidArgumentTypeValue("write", "encoding", encoding_arg); - return .zero; + return error.JSError; }; }; - var buffer: JSC.Node.StringOrBuffer = JSC.Node.StringOrBuffer.fromJSWithEncoding( + var buffer: JSC.Node.StringOrBuffer = try JSC.Node.StringOrBuffer.fromJSWithEncoding( globalObject, bun.default_allocator, data_arg, encoding, ) orelse { if (!globalObject.hasException()) return globalObject.throwInvalidArgumentTypeValue("write", "Buffer or String", data_arg); - return .zero; + return error.JSError; }; defer buffer.deinit(); diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 3abf05cfb8..050b6ded6e 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -225,8 +225,7 @@ const Handlers = struct { }; if (opts.isEmptyOrUndefinedOrNull() or opts.isBoolean() or !opts.isObject()) { - globalObject.throwInvalidArguments("Expected \"socket\" to be an object", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"socket\" to be an object", .{}); } const pairs = .{ @@ -243,8 +242,7 @@ const Handlers = struct { inline for (pairs) |pair| { if (opts.getTruthyComptime(globalObject, pair.@"1")) |callback_value| { if (!callback_value.isCell() or !callback_value.isCallable(globalObject.vm())) { - globalObject.throwInvalidArguments("Expected \"{s}\" callback to be a function", .{pair[1]}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"{s}\" callback to be a function", .{pair[1]}); } @field(handlers, pair.@"0") = callback_value; @@ -252,19 +250,16 @@ const Handlers = struct { } if (handlers.onData == .zero and handlers.onWritable == .zero) { - globalObject.throwInvalidArguments("Expected at least \"data\" or \"drain\" callback", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected at least \"data\" or \"drain\" callback", .{}); } if (opts.getTruthy(globalObject, "binaryType")) |binary_type_value| { if (!binary_type_value.isString()) { - globalObject.throwInvalidArguments("Expected \"binaryType\" to be a string", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"binaryType\" to be a string", .{}); } - handlers.binary_type = BinaryType.fromJSValue(globalObject, binary_type_value) orelse { - globalObject.throwInvalidArguments("Expected 'binaryType' to be 'ArrayBuffer', 'Uint8Array', or 'Buffer'", .{}); - return error.JSError; + handlers.binary_type = try BinaryType.fromJSValue(globalObject, binary_type_value) orelse { + return globalObject.throwInvalidArguments2("Expected 'binaryType' to be 'ArrayBuffer', 'Uint8Array', or 'Buffer'", .{}); }; } @@ -316,11 +311,7 @@ pub const SocketConfig = struct { exclusive: bool = false, allowHalfOpen: bool = false, - pub fn fromJS( - vm: *JSC.VirtualMachine, - opts: JSC.JSValue, - globalObject: *JSC.JSGlobalObject, - ) bun.JSError!SocketConfig { + pub fn fromJS(vm: *JSC.VirtualMachine, opts: JSC.JSValue, globalObject: *JSC.JSGlobalObject) bun.JSError!SocketConfig { var hostname_or_unix: JSC.ZigString.Slice = JSC.ZigString.Slice.empty; var port: ?u16 = null; var exclusive = false; @@ -350,8 +341,7 @@ pub const SocketConfig = struct { if (opts.getTruthy(globalObject, "unix")) |unix_socket| { if (!unix_socket.isString()) { - globalObject.throwInvalidArguments("Expected \"unix\" to be a string", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"unix\" to be a string", .{}); } hostname_or_unix = unix_socket.getZigString(globalObject).toSlice(bun.default_allocator); @@ -375,8 +365,7 @@ pub const SocketConfig = struct { if (opts.getTruthy(globalObject, "hostname") orelse opts.getTruthy(globalObject, "host")) |hostname| { if (!hostname.isString()) { - globalObject.throwInvalidArguments("Expected \"hostname\" to be a string", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"hostname\" to be a string", .{}); } var port_value = opts.get(globalObject, "port") orelse JSValue.zero; @@ -392,8 +381,7 @@ pub const SocketConfig = struct { } if (port_value.isEmptyOrUndefinedOrNull()) { - globalObject.throwInvalidArguments("Expected \"port\" to be a number between 0 and 65535", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"port\" to be a number between 0 and 65535", .{}); } const porti32 = port_value.coerceToInt32(globalObject); @@ -402,15 +390,13 @@ pub const SocketConfig = struct { } if (porti32 < 0 or porti32 > 65535) { - globalObject.throwInvalidArguments("Expected \"port\" to be a number between 0 and 65535", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"port\" to be a number between 0 and 65535", .{}); } port = @intCast(porti32); if (hostname_or_unix.len == 0) { - globalObject.throwInvalidArguments("Expected \"hostname\" to be a non-empty string", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"hostname\" to be a non-empty string", .{}); } if (hostname_or_unix.len > 0) { @@ -419,12 +405,10 @@ pub const SocketConfig = struct { } if (hostname_or_unix.len == 0) { - globalObject.throwInvalidArguments("Expected \"unix\" or \"hostname\" to be a non-empty string", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected \"unix\" or \"hostname\" to be a non-empty string", .{}); } - globalObject.throwInvalidArguments("Expected either \"hostname\" or \"unix\"", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected either \"hostname\" or \"unix\"", .{}); } errdefer hostname_or_unix.deinit(); @@ -2228,7 +2212,9 @@ fn NewSocket(comptime ssl: bool) type { const buffer: JSC.Node.StringOrBuffer = if (data_value.isUndefined()) JSC.Node.StringOrBuffer.empty else - JSC.Node.StringOrBuffer.fromJSWithEncodingValueMaybeAsync(globalObject, stack_fallback.get(), data_value, encoding_value, false) orelse { + JSC.Node.StringOrBuffer.fromJSWithEncodingValueMaybeAsync(globalObject, stack_fallback.get(), data_value, encoding_value, false) catch { + return .fail; + } orelse { if (!globalObject.hasException()) { _ = globalObject.throwInvalidArgumentTypeValue("data", "string, buffer, or blob", data_value); } @@ -2337,7 +2323,9 @@ fn NewSocket(comptime ssl: bool) type { const buffer: JSC.Node.BlobOrStringOrBuffer = if (args[0].isUndefined()) JSC.Node.BlobOrStringOrBuffer{ .string_or_buffer = JSC.Node.StringOrBuffer.empty } else - JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValueMaybeAsyncAllowRequestResponse(globalObject, stack_fallback.get(), args[0], encoding_value, false, true) orelse { + JSC.Node.BlobOrStringOrBuffer.fromJSWithEncodingValueMaybeAsyncAllowRequestResponse(globalObject, stack_fallback.get(), args[0], encoding_value, false, true) catch { + return .fail; + } orelse { if (!globalObject.hasException()) { _ = globalObject.throwInvalidArgumentTypeValue("data", "string, buffer, or blob", args[0]); } diff --git a/src/bun.js/api/bun/udp_socket.zig b/src/bun.js/api/bun/udp_socket.zig index 7ddbfb5f8b..efaf57a302 100644 --- a/src/bun.js/api/bun/udp_socket.zig +++ b/src/bun.js/api/bun/udp_socket.zig @@ -122,17 +122,15 @@ pub const UDPSocketConfig = struct { on_drain: JSValue = .zero, on_error: JSValue = .zero, - pub fn fromJS(globalThis: *JSGlobalObject, options: JSValue) ?This { + pub fn fromJS(globalThis: *JSGlobalObject, options: JSValue) bun.JSError!This { if (options.isEmptyOrUndefinedOrNull() or !options.isObject()) { - globalThis.throwInvalidArguments("Expected an object", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected an object", .{}); } const hostname = brk: { if (options.getTruthy(globalThis, "hostname")) |value| { if (!value.isString()) { - globalThis.throwInvalidArguments("Expected \"hostname\" to be a string", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected \"hostname\" to be a string", .{}); } const str = value.toBunString(globalThis); defer str.deref(); @@ -147,8 +145,7 @@ pub const UDPSocketConfig = struct { if (options.getTruthy(globalThis, "port")) |value| { const number = value.coerceToInt32(globalThis); if (number < 0 or number > 0xffff) { - globalThis.throwInvalidArguments("Expected \"port\" to be an integer between 0 and 65535", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected \"port\" to be an integer between 0 and 65535", .{}); } break :brk @intCast(number); } else { @@ -163,27 +160,23 @@ pub const UDPSocketConfig = struct { if (options.getTruthy(globalThis, "socket")) |socket| { if (!socket.isObject()) { - globalThis.throwInvalidArguments("Expected \"socket\" to be an object", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected \"socket\" to be an object", .{}); } if (options.getTruthy(globalThis, "binaryType")) |value| { if (!value.isString()) { - globalThis.throwInvalidArguments("Expected \"socket.binaryType\" to be a string", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected \"socket.binaryType\" to be a string", .{}); } - config.binary_type = JSC.BinaryType.fromJSValue(globalThis, value) orelse { - globalThis.throwInvalidArguments("Expected \"socket.binaryType\" to be 'arraybuffer', 'uint8array', or 'buffer'", .{}); - return null; + config.binary_type = try JSC.BinaryType.fromJSValue(globalThis, value) orelse { + return globalThis.throwInvalidArguments2("Expected \"socket.binaryType\" to be 'arraybuffer', 'uint8array', or 'buffer'", .{}); }; } inline for (handlers) |handler| { if (socket.getTruthyComptime(globalThis, handler.@"0")) |value| { if (!value.isCell() or !value.isCallable(globalThis.vm())) { - globalThis.throwInvalidArguments("Expected \"socket.{s}\" to be a function", .{handler.@"0"}); - return null; + return globalThis.throwInvalidArguments2("Expected \"socket.{s}\" to be a function", .{handler.@"0"}); } @field(config, handler.@"1") = value; } @@ -200,23 +193,19 @@ pub const UDPSocketConfig = struct { if (options.getTruthy(globalThis, "connect")) |connect| { if (!connect.isObject()) { - globalThis.throwInvalidArguments("Expected \"connect\" to be an object", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected \"connect\" to be an object", .{}); } const connect_host_js = connect.getTruthy(globalThis, "hostname") orelse { - globalThis.throwInvalidArguments("Expected \"connect.hostname\" to be a string", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected \"connect.hostname\" to be a string", .{}); }; if (!connect_host_js.isString()) { - globalThis.throwInvalidArguments("Expected \"connect.hostname\" to be a string", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected \"connect.hostname\" to be a string", .{}); } const connect_port_js = connect.getTruthy(globalThis, "port") orelse { - globalThis.throwInvalidArguments("Expected \"connect.port\" to be an integer", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected \"connect.port\" to be an integer", .{}); }; const connect_port = connect_port_js.coerceToInt32(globalThis); @@ -292,12 +281,10 @@ pub const UDPSocket = struct { pub usingnamespace bun.New(@This()); - pub fn udpSocket(globalThis: *JSGlobalObject, options: JSValue) JSValue { + pub fn udpSocket(globalThis: *JSGlobalObject, options: JSValue) bun.JSError!JSValue { log("udpSocket", .{}); - const config = UDPSocketConfig.fromJS(globalThis, options) orelse { - return .zero; - }; + const config = try UDPSocketConfig.fromJS(globalThis, options); const vm = globalThis.bunVM(); var this = This.new(.{ @@ -327,16 +314,14 @@ pub const UDPSocket = struct { )) |socket| { this.socket = socket; } else { - globalThis.throw("Failed to bind socket", .{}); - return .zero; + return globalThis.throw2("Failed to bind socket", .{}); } if (config.connect) |connect| { const ret = this.socket.connect(connect.address, connect.port); if (ret != 0) { if (JSC.Maybe(void).errnoSys(ret, .connect)) |err| { - globalThis.throwValue(err.toJS(globalThis)); - return .zero; + return globalThis.throwValue2(err.toJS(globalThis)); } } this.connect_info = .{ .port = connect.port }; @@ -591,14 +576,11 @@ pub const UDPSocket = struct { const args = callframe.arguments(1); if (args.len < 1) { - globalThis.throwInvalidArguments("Expected 1 argument", .{}); - return .zero; + return globalThis.throwInvalidArguments2("Expected 1 argument", .{}); } const options = args.ptr[0]; - const config = UDPSocketConfig.fromJS(globalThis, options) orelse { - return .zero; - }; + const config = try UDPSocketConfig.fromJS(globalThis, options); config.protect(); var previous_config = this.config; diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index 9bfb79b61a..8153adee7f 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -568,7 +568,7 @@ pub const FFI = struct { bun.default_allocator.free(this.items); } - pub fn fromJSArray(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue, comptime property: []const u8) StringArray { + pub fn fromJSArray(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue, comptime property: []const u8) bun.JSError!StringArray { var iter = value.arrayIterator(globalThis); var items = std.ArrayList([:0]const u8).init(bun.default_allocator); @@ -579,7 +579,7 @@ pub const FFI = struct { } items.deinit(); _ = globalThis.throwInvalidArgumentTypeValue(property, "array of strings", val); - return .{}; + return error.JSError; } const str = val.getZigString(globalThis); if (str.isEmpty()) continue; @@ -589,11 +589,11 @@ pub const FFI = struct { return .{ .items = items.items }; } - pub fn fromJSString(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue, comptime property: []const u8) StringArray { + pub fn fromJSString(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue, comptime property: []const u8) bun.JSError!StringArray { if (value == .undefined) return .{}; if (!value.isString()) { _ = globalThis.throwInvalidArgumentTypeValue(property, "array of strings", value); - return .{}; + return error.JSError; } const str = value.getZigString(globalThis); if (str.isEmpty()) return .{}; @@ -602,7 +602,7 @@ pub const FFI = struct { return .{ .items = items.items }; } - pub fn fromJS(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue, comptime property: []const u8) StringArray { + pub fn fromJS(globalThis: *JSC.JSGlobalObject, value: JSC.JSValue, comptime property: []const u8) bun.JSError!StringArray { if (value.isArray()) { return fromJSArray(globalThis, value, property); } @@ -613,7 +613,7 @@ pub const FFI = struct { pub fn Bun__FFI__cc(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const arguments = callframe.arguments(1).slice(); if (arguments.len == 0 or !arguments[0].isObject()) { - return JSC.toInvalidArguments("Expected object", .{}, globalThis); + return globalThis.throwInvalidArguments2("Expected object", .{}); } // Step 1. compile the user's code @@ -630,29 +630,30 @@ pub const FFI = struct { const symbols_object = object.getOwn(globalThis, "symbols") orelse .undefined; if (!globalThis.hasException() and (symbols_object == .zero or !symbols_object.isObject())) { _ = globalThis.throwInvalidArgumentTypeValue("symbols", "object", symbols_object); + return error.JSError; } if (globalThis.hasException()) { - return .zero; + return error.JSError; } - if (generateSymbols(globalThis, &compile_c.symbols.map, symbols_object) catch JSC.JSValue.zero) |val| { + if (try generateSymbols(globalThis, &compile_c.symbols.map, symbols_object)) |val| { if (val != .zero and !globalThis.hasException()) globalThis.throwValue(val); - return .zero; + return error.JSError; } if (compile_c.symbols.map.count() == 0) { globalThis.throw("Expected at least one exported symbol", .{}); - return .zero; + return error.JSError; } if (object.getOwn(globalThis, "library")) |library_value| { - compile_c.libraries = StringArray.fromJS(globalThis, library_value, "library"); + compile_c.libraries = try StringArray.fromJS(globalThis, library_value, "library"); } if (globalThis.hasException()) { - return .zero; + return error.JSError; } if (object.getTruthy(globalThis, "flags")) |flags_value| { @@ -689,7 +690,7 @@ pub const FFI = struct { } if (globalThis.hasException()) { - return .zero; + return error.JSError; } if (object.getTruthy(globalThis, "define")) |define_value| { @@ -710,7 +711,7 @@ pub const FFI = struct { } if (globalThis.hasException()) { bun.default_allocator.free(key); - return .zero; + return error.JSError; } compile_c.define.append(bun.default_allocator, .{ key, owned_value }) catch bun.outOfMemory(); @@ -719,15 +720,15 @@ pub const FFI = struct { } if (globalThis.hasException()) { - return .zero; + return error.JSError; } if (object.getTruthy(globalThis, "include")) |include_value| { - compile_c.include_dirs = StringArray.fromJS(globalThis, include_value, "include"); + compile_c.include_dirs = try StringArray.fromJS(globalThis, include_value, "include"); } if (globalThis.hasException()) { - return .zero; + return error.JSError; } if (object.getOwn(globalThis, "source")) |source_value| { @@ -749,7 +750,7 @@ pub const FFI = struct { } if (globalThis.hasException()) { - return .zero; + return error.JSError; } // Now we compile the code with tinycc. @@ -766,14 +767,14 @@ pub const FFI = struct { } globalThis.throw("{s}", .{combined.items}); - return .zero; + return error.JSError; }, error.JSException => { - return .zero; + return error.JSError; }, error.OutOfMemory => { globalThis.throwOutOfMemory(); - return .zero; + return error.JSError; }, } }; @@ -800,17 +801,17 @@ pub const FFI = struct { globalThis.throwValue(ret); } - return .zero; + return error.JSError; }; switch (function.step) { .failed => |err| { const res = ZigString.init(err.msg).toErrorInstance(globalThis); globalThis.throwValue(res); - return .zero; + return error.JSError; }, .pending => { globalThis.throw("Failed to compile (nothing happend!)", .{}); - return .zero; + return error.JSError; }, .compiled => |*compiled| { const str = ZigString.init(bun.asByteSlice(function_name)); @@ -1296,7 +1297,7 @@ pub const FFI = struct { JSC.Codegen.JSFFI.symbolsValueSetCached(js_object, global, obj); return js_object; } - pub fn generateSymbolForFunction(global: *JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, function: *Function) !?JSValue { + pub fn generateSymbolForFunction(global: *JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, function: *Function) bun.JSError!?JSValue { JSC.markBinding(@src()); var abi_types = std.ArrayListUnmanaged(ABIType){}; @@ -1411,7 +1412,8 @@ pub const FFI = struct { return null; } - pub fn generateSymbols(global: *JSGlobalObject, symbols: *bun.StringArrayHashMapUnmanaged(Function), object: JSC.JSValue) !?JSValue { + + pub fn generateSymbols(global: *JSGlobalObject, symbols: *bun.StringArrayHashMapUnmanaged(Function), object: JSC.JSValue) bun.JSError!?JSValue { JSC.markBinding(@src()); const allocator = VirtualMachine.get().allocator; diff --git a/src/bun.js/api/glob.zig b/src/bun.js/api/glob.zig index 5571c60ddd..09d1d6d113 100644 --- a/src/bun.js/api/glob.zig +++ b/src/bun.js/api/glob.zig @@ -39,7 +39,7 @@ const ScanOpts = struct { follow_symlinks: bool, error_on_broken_symlinks: bool, - fn parseCWD(globalThis: *JSGlobalObject, allocator: std.mem.Allocator, cwdVal: JSC.JSValue, absolute: bool, comptime fnName: string) ?[]const u8 { + fn parseCWD(globalThis: *JSGlobalObject, allocator: std.mem.Allocator, cwdVal: JSC.JSValue, absolute: bool, comptime fnName: string) bun.JSError![]const u8 { const cwd_str_raw = cwdVal.toSlice(globalThis, allocator); if (cwd_str_raw.len == 0) return ""; @@ -48,7 +48,7 @@ const ScanOpts = struct { if (ResolvePath.Platform.auto.isAbsolute(cwd_str_raw.slice())) { const cwd_str = cwd_str_raw.clone(allocator) catch { globalThis.throwOutOfMemory(); - return null; + return error.JSError; }; break :cwd_str cwd_str.ptr[0..cwd_str.len]; } @@ -59,7 +59,7 @@ const ScanOpts = struct { const cwd_str = ResolvePath.joinStringBuf(&path_buf2, &[_][]const u8{cwd_str_raw.slice()}, .auto); break :cwd_str allocator.dupe(u8, cwd_str) catch { globalThis.throwOutOfMemory(); - return null; + return error.JSError; }; } @@ -69,8 +69,7 @@ const ScanOpts = struct { .result => |cwd| cwd, .err => |err| { const errJs = err.toJSC(globalThis); - globalThis.throwValue(errJs); - return null; + return globalThis.throwValue2(errJs); }, }; @@ -81,19 +80,18 @@ const ScanOpts = struct { break :cwd_str allocator.dupe(u8, cwd_str) catch { globalThis.throwOutOfMemory(); - return null; + return error.JSError; }; }; if (cwd_str.len > bun.MAX_PATH_BYTES) { - globalThis.throw("{s}: invalid `cwd`, longer than {d} bytes", .{ fnName, bun.MAX_PATH_BYTES }); - return null; + return globalThis.throw2("{s}: invalid `cwd`, longer than {d} bytes", .{ fnName, bun.MAX_PATH_BYTES }); } return cwd_str; } - fn fromJS(globalThis: *JSGlobalObject, arguments: *ArgumentsSlice, comptime fnName: []const u8, arena: *Arena) ?ScanOpts { + fn fromJS(globalThis: *JSGlobalObject, arguments: *ArgumentsSlice, comptime fnName: []const u8, arena: *Arena) bun.JSError!?ScanOpts { const optsObj: JSValue = arguments.nextEat() orelse return null; var out: ScanOpts = .{ .cwd = null, @@ -106,13 +104,11 @@ const ScanOpts = struct { if (optsObj.isUndefinedOrNull()) return out; if (!optsObj.isObject()) { if (optsObj.isString()) { - if (parseCWD(globalThis, arena.allocator(), optsObj, out.absolute, fnName)) |result| { + { + const result = try parseCWD(globalThis, arena.allocator(), optsObj, out.absolute, fnName); if (result.len > 0) { out.cwd = result; } - } else { - // error - return null; } return out; } @@ -142,13 +138,11 @@ const ScanOpts = struct { return null; } - if (parseCWD(globalThis, arena.allocator(), cwdVal, out.absolute, fnName)) |result| { + { + const result = try parseCWD(globalThis, arena.allocator(), cwdVal, out.absolute, fnName); if (result.len > 0) { out.cwd = result; } - } else { - // error - return null; } } @@ -248,8 +242,8 @@ fn makeGlobWalker( comptime fnName: []const u8, alloc: Allocator, arena: *Arena, -) ?*GlobWalker { - const matchOpts = ScanOpts.fromJS(globalThis, arguments, fnName, arena) orelse return null; +) bun.JSError!?*GlobWalker { + const matchOpts = try ScanOpts.fromJS(globalThis, arguments, fnName, arena) orelse return null; const cwd = matchOpts.cwd; const dot = matchOpts.dot; const absolute = matchOpts.absolute; @@ -260,7 +254,7 @@ fn makeGlobWalker( if (cwd != null) { var globWalker = alloc.create(GlobWalker) catch { globalThis.throwOutOfMemory(); - return null; + return error.JSError; }; globWalker.* = .{}; @@ -276,11 +270,10 @@ fn makeGlobWalker( only_files, ) catch { globalThis.throwOutOfMemory(); - return null; + return error.JSError; }) { .err => |err| { - globalThis.throwValue(err.toJSC(globalThis)); - return null; + return globalThis.throwValue2(err.toJSC(globalThis)); }, else => {}, } @@ -288,7 +281,7 @@ fn makeGlobWalker( } var globWalker = alloc.create(GlobWalker) catch { globalThis.throwOutOfMemory(); - return null; + return error.JSError; }; globWalker.* = .{}; @@ -302,11 +295,10 @@ fn makeGlobWalker( only_files, ) catch { globalThis.throwOutOfMemory(); - return null; + return error.JSError; }) { .err => |err| { - globalThis.throwValue(err.toJSC(globalThis)); - return null; + return globalThis.throwValue2(err.toJSC(globalThis)); }, else => {}, } @@ -381,7 +373,7 @@ pub fn __scan(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFram defer arguments.deinit(); var arena = std.heap.ArenaAllocator.init(alloc); - const globWalker = this.makeGlobWalker(globalThis, &arguments, "scan", alloc, &arena) orelse { + const globWalker = try this.makeGlobWalker(globalThis, &arguments, "scan", alloc, &arena) orelse { arena.deinit(); return .undefined; }; @@ -390,7 +382,7 @@ pub fn __scan(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.CallFram var task = WalkTask.create(globalThis, alloc, globWalker, &this.has_pending_activity) catch { decrPendingActivityFlag(&this.has_pending_activity); globalThis.throwOutOfMemory(); - return .undefined; + return error.JSError; }; task.schedule(); @@ -405,7 +397,7 @@ pub fn __scanSync(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.Call defer arguments.deinit(); var arena = std.heap.ArenaAllocator.init(alloc); - var globWalker = this.makeGlobWalker(globalThis, &arguments, "scanSync", alloc, &arena) orelse { + var globWalker = try this.makeGlobWalker(globalThis, &arguments, "scanSync", alloc, &arena) orelse { arena.deinit(); return .undefined; }; @@ -413,11 +405,10 @@ pub fn __scanSync(this: *Glob, globalThis: *JSGlobalObject, callframe: *JSC.Call switch (globWalker.walk() catch { globalThis.throwOutOfMemory(); - return .undefined; + return error.JSError; }) { .err => |err| { - globalThis.throwValue(err.toJSC(globalThis)); - return JSValue.undefined; + return globalThis.throwValue2(err.toJSC(globalThis)); }, .result => {}, } diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 3824ebec3f..883c526bec 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -200,7 +200,7 @@ const StaticRoute = struct { this.destroy(); } - pub fn fromJS(globalThis: *JSC.JSGlobalObject, argument: JSC.JSValue) ?*Route { + pub fn fromJS(globalThis: *JSC.JSGlobalObject, argument: JSC.JSValue) bun.JSError!*Route { if (argument.as(JSC.WebCore.Response)) |response| { // The user may want to pass in the same Response object multiple endpoints @@ -210,13 +210,11 @@ const StaticRoute = struct { var blob: AnyBlob = brk: { switch (response.body.value) { .Used => { - globalThis.throwInvalidArguments("Response body has already been used", .{}); - return null; + return globalThis.throwInvalidArguments2("Response body has already been used", .{}); }, else => { - globalThis.throwInvalidArguments("Body must be fully buffered before it can be used in a static route. Consider calling new Response(await response.blob()) to buffer the body.", .{}); - return null; + return globalThis.throwInvalidArguments2("Body must be fully buffered before it can be used in a static route. Consider calling new Response(await response.blob()) to buffer the body.", .{}); }, .Null, .Empty => { break :brk AnyBlob{ @@ -229,7 +227,7 @@ const StaticRoute = struct { .Blob, .InternalBlob, .WTFStringImpl => { if (response.body.value == .Blob and response.body.value.Blob.needsToReadFile()) { globalThis.throwTODO("TODO: support Bun.file(path) in static routes"); - return null; + return error.JSError; } var blob = response.body.value.use(); blob.globalThis = globalThis; @@ -255,7 +253,7 @@ const StaticRoute = struct { }) catch { blob.detach(); globalThis.throwOutOfMemory(); - return null; + return error.JSError; } else .{ @@ -272,8 +270,7 @@ const StaticRoute = struct { }); } - globalThis.throwInvalidArguments("Expected a Response object", .{}); - return null; + return globalThis.throwInvalidArguments2("Expected a Response object", .{}); } // HEAD requests have no body. @@ -763,8 +760,7 @@ pub const ServerConfig = struct { defer arena.deinit(); if (!obj.isObject()) { - global.throwInvalidArguments("tls option expects an object", .{}); - return error.JSError; + return global.throwInvalidArguments2("tls option expects an object", .{}); } var any = false; @@ -778,8 +774,7 @@ pub const ServerConfig = struct { if (sliced.len > 0) { result.key_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; if (std.posix.system.access(result.key_file_name, std.posix.F_OK) != 0) { - global.throwInvalidArguments("Unable to access keyFile path", .{}); - return error.JSError; + return global.throwInvalidArguments2("Unable to access keyFile path", .{}); } any = true; result.requires_custom_request_ctx = true; @@ -873,8 +868,7 @@ pub const ServerConfig = struct { if (sliced.len > 0) { result.cert_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; if (std.posix.system.access(result.cert_file_name, std.posix.F_OK) != 0) { - global.throwInvalidArguments("Unable to access certFile path", .{}); - return error.JSError; + return global.throwInvalidArguments2("Unable to access certFile path", .{}); } any = true; result.requires_custom_request_ctx = true; @@ -893,8 +887,7 @@ pub const ServerConfig = struct { any = true; result.requires_custom_request_ctx = true; } else { - global.throwInvalidArguments("ALPNProtocols argument must be an string, Buffer or TypedArray", .{}); - return error.JSError; + return global.throwInvalidArguments2("ALPNProtocols argument must be an string, Buffer or TypedArray", .{}); } } @@ -984,8 +977,7 @@ pub const ServerConfig = struct { result.request_cert = if (request_cert.asBoolean()) 1 else 0; any = true; } else { - global.throw("Expected requestCert to be a boolean", .{}); - return error.JSError; + return global.throw2("Expected requestCert to be a boolean", .{}); } } @@ -994,8 +986,7 @@ pub const ServerConfig = struct { result.reject_unauthorized = if (reject_unauthorized.asBoolean()) 1 else 0; any = true; } else { - global.throw("Expected rejectUnauthorized to be a boolean", .{}); - return error.JSError; + return global.throw2("Expected rejectUnauthorized to be a boolean", .{}); } } @@ -1106,8 +1097,7 @@ pub const ServerConfig = struct { if (sliced.len > 0) { result.ca_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; if (std.posix.system.access(result.ca_file_name, std.posix.F_OK) != 0) { - global.throwInvalidArguments("Invalid caFile path", .{}); - return error.JSError; + return global.throwInvalidArguments2("Invalid caFile path", .{}); } } } @@ -1137,8 +1127,7 @@ pub const ServerConfig = struct { if (sliced.len > 0) { result.dh_params_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; if (std.posix.system.access(result.dh_params_file_name, std.posix.F_OK) != 0) { - global.throwInvalidArguments("Invalid dhParamsFile path", .{}); - return error.JSError; + return global.throwInvalidArguments2("Invalid dhParamsFile path", .{}); } } } @@ -1156,8 +1145,7 @@ pub const ServerConfig = struct { result.low_memory_mode = low_memory_mode.toBoolean(); any = true; } else { - global.throw("Expected lowMemoryMode to be a boolean", .{}); - return error.JSError; + return global.throw2("Expected lowMemoryMode to be a boolean", .{}); } } } @@ -1173,7 +1161,7 @@ pub const ServerConfig = struct { args: *ServerConfig, arguments: *JSC.Node.ArgumentsSlice, allow_bake_config: bool, - ) bun.JSOOM!void { + ) bun.JSError!void { const vm = arguments.vm; const env = vm.bundler.env; @@ -1234,14 +1222,12 @@ pub const ServerConfig = struct { if (arguments.next()) |arg| { if (!arg.isObject()) { - global.throwInvalidArguments("Bun.serve expects an object", .{}); - return error.JSError; + return global.throwInvalidArguments2("Bun.serve expects an object", .{}); } if (arg.get(global, "static")) |static| { if (!static.isObject()) { - global.throwInvalidArguments("Bun.serve expects 'static' to be an object shaped like { [pathname: string]: Response }", .{}); - return error.JSError; + return global.throwInvalidArguments2("Bun.serve expects 'static' to be an object shaped like { [pathname: string]: Response }", .{}); } var iter = JSC.JSPropertyIterator(.{ @@ -1257,27 +1243,19 @@ pub const ServerConfig = struct { if (path.len == 0 or path[0] != '/') { bun.default_allocator.free(path); - global.throwInvalidArguments("Invalid static route \"{s}\". path must start with '/'", .{path}); - return error.JSError; + return global.throwInvalidArguments2("Invalid static route \"{s}\". path must start with '/'", .{path}); } if (!is_ascii) { bun.default_allocator.free(path); - global.throwInvalidArguments("Invalid static route \"{s}\". Please encode all non-ASCII characters in the path.", .{path}); - return error.JSError; + return global.throwInvalidArguments2("Invalid static route \"{s}\". Please encode all non-ASCII characters in the path.", .{path}); } - if (StaticRoute.fromJS(global, value)) |route| { - args.static_routes.append(.{ - .path = path, - .route = route, - }) catch bun.outOfMemory(); - } else if (global.hasException()) { - bun.default_allocator.free(path); - return error.JSError; - } else { - Output.panic("Internal error: expected exception or static route", .{}); - } + const route = try StaticRoute.fromJS(global, value); + args.static_routes.append(.{ + .path = path, + .route = route, + }) catch bun.outOfMemory(); } } @@ -1310,14 +1288,8 @@ pub const ServerConfig = struct { return error.JSError; } - if (WebSocketServer.onCreate(global, websocket_object)) |wss| { - args.websocket = wss; - } else { - if (args.ssl_config) |*conf| { - conf.deinit(); - } - return; - } + errdefer if (args.ssl_config) |*conf| conf.deinit(); + args.websocket = try WebSocketServer.onCreate(global, websocket_object); } if (global.hasException()) return error.JSError; @@ -4181,7 +4153,7 @@ pub const WebSocketServer = struct { _ = vm.uncaughtException(globalObject, error_value, false); } - pub fn fromJS(globalObject: *JSC.JSGlobalObject, object: JSC.JSValue) ?Handler { + pub fn fromJS(globalObject: *JSC.JSGlobalObject, object: JSC.JSValue) bun.JSError!Handler { const vm = globalObject.vm(); var handler = Handler{ .globalObject = globalObject, .vm = VirtualMachine.get() }; @@ -4189,8 +4161,7 @@ pub const WebSocketServer = struct { if (object.getTruthyComptime(globalObject, "message")) |message_| { if (!message_.isCallable(vm)) { - globalObject.throwInvalidArguments("websocket expects a function for the message option", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects a function for the message option", .{}); } const message = message_.withAsyncContextIfNeeded(globalObject); handler.onMessage = message; @@ -4200,8 +4171,7 @@ pub const WebSocketServer = struct { if (object.getTruthy(globalObject, "open")) |open_| { if (!open_.isCallable(vm)) { - globalObject.throwInvalidArguments("websocket expects a function for the open option", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects a function for the open option", .{}); } const open = open_.withAsyncContextIfNeeded(globalObject); handler.onOpen = open; @@ -4211,8 +4181,7 @@ pub const WebSocketServer = struct { if (object.getTruthy(globalObject, "close")) |close_| { if (!close_.isCallable(vm)) { - globalObject.throwInvalidArguments("websocket expects a function for the close option", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects a function for the close option", .{}); } const close = close_.withAsyncContextIfNeeded(globalObject); handler.onClose = close; @@ -4222,8 +4191,7 @@ pub const WebSocketServer = struct { if (object.getTruthy(globalObject, "drain")) |drain_| { if (!drain_.isCallable(vm)) { - globalObject.throwInvalidArguments("websocket expects a function for the drain option", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects a function for the drain option", .{}); } const drain = drain_.withAsyncContextIfNeeded(globalObject); handler.onDrain = drain; @@ -4233,8 +4201,7 @@ pub const WebSocketServer = struct { if (object.getTruthy(globalObject, "onError")) |onError_| { if (!onError_.isCallable(vm)) { - globalObject.throwInvalidArguments("websocket expects a function for the onError option", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects a function for the onError option", .{}); } const onError = onError_.withAsyncContextIfNeeded(globalObject); handler.onError = onError; @@ -4243,8 +4210,7 @@ pub const WebSocketServer = struct { if (object.getTruthy(globalObject, "ping")) |cb| { if (!cb.isCallable(vm)) { - globalObject.throwInvalidArguments("websocket expects a function for the ping option", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects a function for the ping option", .{}); } handler.onPing = cb; cb.ensureStillAlive(); @@ -4253,8 +4219,7 @@ pub const WebSocketServer = struct { if (object.getTruthy(globalObject, "pong")) |cb| { if (!cb.isCallable(vm)) { - globalObject.throwInvalidArguments("websocket expects a function for the pong option", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects a function for the pong option", .{}); } handler.onPong = cb; cb.ensureStillAlive(); @@ -4264,7 +4229,7 @@ pub const WebSocketServer = struct { if (valid) return handler; - return null; + return globalObject.throwInvalidArguments2("WebSocketServer expects a message handler", .{}); } pub fn protect(this: Handler) void { @@ -4340,15 +4305,9 @@ pub const WebSocketServer = struct { .{ "256KB", uws.DEDICATED_COMPRESSOR_256KB }, }); - pub fn onCreate(globalObject: *JSC.JSGlobalObject, object: JSValue) ?WebSocketServer { + pub fn onCreate(globalObject: *JSC.JSGlobalObject, object: JSValue) bun.JSError!WebSocketServer { var server = WebSocketServer{}; - - if (Handler.fromJS(globalObject, object)) |handler| { - server.handler = handler; - } else { - globalObject.throwInvalidArguments("WebSocketServer expects a message handler", .{}); - return null; - } + server.handler = try Handler.fromJS(globalObject, object); if (object.get(globalObject, "perMessageDeflate")) |per_message_deflate| { getter: { @@ -4370,18 +4329,10 @@ pub const WebSocketServer = struct { server.compression |= if (compression.toBoolean()) uws.SHARED_COMPRESSOR else 0; } else if (compression.isString()) { server.compression |= CompressTable.getWithEql(compression.getZigString(globalObject), ZigString.eqlComptime) orelse { - globalObject.throwInvalidArguments( - "WebSocketServer expects a valid compress option, either disable \"shared\" \"dedicated\" \"3KB\" \"4KB\" \"8KB\" \"16KB\" \"32KB\" \"64KB\" \"128KB\" or \"256KB\"", - .{}, - ); - return null; + return globalObject.throwInvalidArguments2("WebSocketServer expects a valid compress option, either disable \"shared\" \"dedicated\" \"3KB\" \"4KB\" \"8KB\" \"16KB\" \"32KB\" \"64KB\" \"128KB\" or \"256KB\"", .{}); }; } else { - globalObject.throwInvalidArguments( - "websocket expects a valid compress option, either disable \"shared\" \"dedicated\" \"3KB\" \"4KB\" \"8KB\" \"16KB\" \"32KB\" \"64KB\" \"128KB\" or \"256KB\"", - .{}, - ); - return null; + return globalObject.throwInvalidArguments2("websocket expects a valid compress option, either disable \"shared\" \"dedicated\" \"3KB\" \"4KB\" \"8KB\" \"16KB\" \"32KB\" \"64KB\" \"128KB\" or \"256KB\"", .{}); } } @@ -4390,18 +4341,10 @@ pub const WebSocketServer = struct { server.compression |= if (compression.toBoolean()) uws.SHARED_DECOMPRESSOR else 0; } else if (compression.isString()) { server.compression |= DecompressTable.getWithEql(compression.getZigString(globalObject), ZigString.eqlComptime) orelse { - globalObject.throwInvalidArguments( - "websocket expects a valid decompress option, either \"disable\" \"shared\" \"dedicated\" \"3KB\" \"4KB\" \"8KB\" \"16KB\" \"32KB\" \"64KB\" \"128KB\" or \"256KB\"", - .{}, - ); - return null; + return globalObject.throwInvalidArguments2("websocket expects a valid decompress option, either \"disable\" \"shared\" \"dedicated\" \"3KB\" \"4KB\" \"8KB\" \"16KB\" \"32KB\" \"64KB\" \"128KB\" or \"256KB\"", .{}); }; } else { - globalObject.throwInvalidArguments( - "websocket expects a valid decompress option, either \"disable\" \"shared\" \"dedicated\" \"3KB\" \"4KB\" \"8KB\" \"16KB\" \"32KB\" \"64KB\" \"128KB\" or \"256KB\"", - .{}, - ); - return null; + return globalObject.throwInvalidArguments2("websocket expects a valid decompress option, either \"disable\" \"shared\" \"dedicated\" \"3KB\" \"4KB\" \"8KB\" \"16KB\" \"32KB\" \"64KB\" \"128KB\" or \"256KB\"", .{}); } } } @@ -4410,8 +4353,7 @@ pub const WebSocketServer = struct { if (object.get(globalObject, "maxPayloadLength")) |value| { if (!value.isUndefinedOrNull()) { if (!value.isAnyInt()) { - globalObject.throwInvalidArguments("websocket expects maxPayloadLength to be an integer", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects maxPayloadLength to be an integer", .{}); } server.maxPayloadLength = @truncate(@max(value.toInt64(), 0)); } @@ -4420,14 +4362,12 @@ pub const WebSocketServer = struct { if (object.get(globalObject, "idleTimeout")) |value| { if (!value.isUndefinedOrNull()) { if (!value.isAnyInt()) { - globalObject.throwInvalidArguments("websocket expects idleTimeout to be an integer", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects idleTimeout to be an integer", .{}); } var idleTimeout: u16 = @truncate(@max(value.toInt64(), 0)); if (idleTimeout > 960) { - globalObject.throwInvalidArguments("websocket expects idleTimeout to be 960 or less", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects idleTimeout to be 960 or less", .{}); } else if (idleTimeout > 0) { // uws does not allow idleTimeout to be between (0, 8), // since its timer is not that accurate, therefore round up. @@ -4440,8 +4380,7 @@ pub const WebSocketServer = struct { if (object.get(globalObject, "backpressureLimit")) |value| { if (!value.isUndefinedOrNull()) { if (!value.isAnyInt()) { - globalObject.throwInvalidArguments("websocket expects backpressureLimit to be an integer", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects backpressureLimit to be an integer", .{}); } server.backpressureLimit = @truncate(@max(value.toInt64(), 0)); @@ -4451,8 +4390,7 @@ pub const WebSocketServer = struct { if (object.get(globalObject, "closeOnBackpressureLimit")) |value| { if (!value.isUndefinedOrNull()) { if (!value.isBoolean()) { - globalObject.throwInvalidArguments("websocket expects closeOnBackpressureLimit to be a boolean", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects closeOnBackpressureLimit to be a boolean", .{}); } server.closeOnBackpressureLimit = value.toBoolean(); @@ -4462,8 +4400,7 @@ pub const WebSocketServer = struct { if (object.get(globalObject, "sendPings")) |value| { if (!value.isUndefinedOrNull()) { if (!value.isBoolean()) { - globalObject.throwInvalidArguments("websocket expects sendPings to be a boolean", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects sendPings to be a boolean", .{}); } server.sendPingsAutomatically = value.toBoolean(); @@ -4473,8 +4410,7 @@ pub const WebSocketServer = struct { if (object.get(globalObject, "publishToSelf")) |value| { if (!value.isUndefinedOrNull()) { if (!value.isBoolean()) { - globalObject.throwInvalidArguments("websocket expects publishToSelf to be a boolean", .{}); - return null; + return globalObject.throwInvalidArguments2("websocket expects publishToSelf to be a boolean", .{}); } server.handler.flags.publish_to_self = value.toBoolean(); @@ -5616,7 +5552,8 @@ pub const ServerWebSocket = struct { ) callconv(.C) bool { log("setBinaryType()", .{}); - switch (JSC.BinaryType.fromJSValue(globalThis, value) orelse + const btype = JSC.BinaryType.fromJSValue(globalThis, value) catch return false; + switch (btype orelse // some other value which we don't support .Float64Array) { .ArrayBuffer, .Buffer, .Uint8Array => |val| { diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig index 9a8774a2ff..67f436de8e 100644 --- a/src/bun.js/base.zig +++ b/src/bun.js/base.zig @@ -1417,9 +1417,9 @@ pub const BinaryType = enum(u4) { return Map.get(input); } - pub fn fromJSValue(globalThis: *JSC.JSGlobalObject, input: JSValue) ?BinaryType { + pub fn fromJSValue(globalThis: *JSC.JSGlobalObject, input: JSValue) bun.JSError!?BinaryType { if (input.isString()) { - return Map.getWithEql(input.getZigString(globalThis), ZigString.eqlComptime); + return Map.getWithEql(try input.toBunString2(globalThis), bun.String.eqlComptime); } return null; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 4b0ef4e82b..24c0c2d000 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -221,7 +221,8 @@ enum class AsymmetricMatcherResult : uint8_t { NOT_MATCHER, }; -enum class AsymmetricMatcherConstructorType : uint8_t { +enum class AsymmetricMatcherConstructorType : int8_t { + exception = -1, none = 0, Symbol = 1, String = 2, @@ -242,7 +243,7 @@ enum class AsymmetricMatcherConstructorType : uint8_t { extern "C" bool Expect_readFlagsAndProcessPromise(JSC__JSValue instanceValue, JSC__JSGlobalObject* globalObject, ExpectFlags* flags, JSC__JSValue* value, AsymmetricMatcherConstructorType* constructorType); -extern "C" uint8_t AsymmetricMatcherConstructorType__fromJS(JSC__JSGlobalObject* globalObject, JSC__JSValue encodedValue) +extern "C" int8_t AsymmetricMatcherConstructorType__fromJS(JSC__JSGlobalObject* globalObject, JSC__JSValue encodedValue) { JSValue value = JSValue::decode(encodedValue); if (value.isObject()) { @@ -258,21 +259,21 @@ extern "C" uint8_t AsymmetricMatcherConstructorType__fromJS(JSC__JSGlobalObject* } auto stringConstructorValue = globalObject->stringPrototype()->getIfPropertyExists(globalObject, vm.propertyNames->constructor); - RETURN_IF_EXCEPTION(scope, {}); + RETURN_IF_EXCEPTION(scope, -1); if (stringConstructorValue == object) { return static_cast(AsymmetricMatcherConstructorType::String); } auto symbolConstructorValue = globalObject->symbolPrototype()->getIfPropertyExists(globalObject, vm.propertyNames->constructor); - RETURN_IF_EXCEPTION(scope, {}); + RETURN_IF_EXCEPTION(scope, -1); if (symbolConstructorValue == object) { return static_cast(AsymmetricMatcherConstructorType::Symbol); } auto bigIntConstructorValue = globalObject->bigIntPrototype()->getIfPropertyExists(globalObject, vm.propertyNames->constructor); - RETURN_IF_EXCEPTION(scope, {}); + RETURN_IF_EXCEPTION(scope, -1); if (bigIntConstructorValue == object) { return static_cast(AsymmetricMatcherConstructorType::BigInt); @@ -412,6 +413,7 @@ AsymmetricMatcherResult matchAsymmetricMatcherAndGetFlags(JSGlobalObject* global case AsymmetricMatcherConstructorType::InstanceOf: { break; } + case AsymmetricMatcherConstructorType::exception: case AsymmetricMatcherConstructorType::none: { ASSERT_NOT_REACHED_WITH_MESSAGE("Invalid constructor type"); break; diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 086f73348e..afe79db515 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -1100,9 +1100,7 @@ pub const DOMFormData = opaque { DOMFormData__toQueryString(this, ctx, &Wrapper.run); } - pub fn fromJS( - value: JSValue, - ) ?*DOMFormData { + pub fn fromJS(value: JSValue) ?*DOMFormData { return shim.cppFn("fromJS", .{ value, }); @@ -5181,6 +5179,7 @@ pub const JSValue = enum(i64) { }); } + /// Deprecated: replace with 'toBunString2' pub inline fn getZigString(this: JSValue, global: *JSGlobalObject) ZigString { var str = ZigString.init(""); this.toZigString(&str, global); @@ -7072,14 +7071,18 @@ pub const URL = opaque { /// This percent-encodes the URL, punycode-encodes the hostname, and returns the result /// If it fails, the tag is marked Dead - pub fn hrefFromJS(value: JSValue, globalObject: *JSC.JSGlobalObject) String { + pub fn hrefFromJS(value: JSValue, globalObject: *JSC.JSGlobalObject) bun.JSError!String { JSC.markBinding(@src()); - return URL__getHrefFromJS(value, globalObject); + const result = URL__getHrefFromJS(value, globalObject); + if (globalObject.hasException()) return error.JSError; + return result; } - pub fn fromJS(value: JSValue, globalObject: *JSC.JSGlobalObject) ?*URL { + pub fn fromJS(value: JSValue, globalObject: *JSC.JSGlobalObject) bun.JSError!?*URL { JSC.markBinding(@src()); - return URL__fromJS(value, globalObject); + const result = URL__fromJS(value, globalObject); + if (globalObject.hasException()) return error.JSError; + return result; } pub fn fromUTF8(input: []const u8) ?*URL { diff --git a/src/bun.js/node/node_crypto_binding.zig b/src/bun.js/node/node_crypto_binding.zig index b162be1cbd..3606afa9ce 100644 --- a/src/bun.js/node/node_crypto_binding.zig +++ b/src/bun.js/node/node_crypto_binding.zig @@ -44,10 +44,7 @@ fn pbkdf2( ) bun.JSError!JSC.JSValue { const arguments = callframe.arguments(5); - const data = PBKDF2.fromJS(globalThis, arguments.slice(), true) orelse { - assert(globalThis.hasException()); - return .zero; - }; + const data = try PBKDF2.fromJS(globalThis, arguments.slice(), true); const job = PBKDF2.Job.create(JSC.VirtualMachine.get(), globalThis, &data); return job.promise.value(); @@ -59,10 +56,7 @@ fn pbkdf2Sync( ) bun.JSError!JSC.JSValue { const arguments = callframe.arguments(5); - var data = PBKDF2.fromJS(globalThis, arguments.slice(), false) orelse { - assert(globalThis.hasException()); - return .zero; - }; + var data = try PBKDF2.fromJS(globalThis, arguments.slice(), false); defer data.deinit(); var out_arraybuffer = JSC.JSValue.createBufferFromLength(globalThis, @intCast(data.length)); if (out_arraybuffer == .zero or globalThis.hasException()) { diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index e488eb260c..359773d3f1 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -1283,13 +1283,11 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Rename { const old_path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("oldPath must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("oldPath must be a string or TypedArray", .{}); }; const new_path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("newPath must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("newPath must be a string or TypedArray", .{}); }; return Rename{ .old_path = old_path, .new_path = new_path }; @@ -1316,8 +1314,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Truncate { const path = try PathOrFileDescriptor.fromJS(ctx, arguments, bun.default_allocator) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; const len: JSC.WebCore.Blob.SizeType = brk: { @@ -1359,20 +1356,17 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Writev { const fd_value = arguments.nextEat() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }; const fd = try JSC.Node.fileDescriptorFromJS(ctx, fd_value) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; const buffers = try JSC.Node.VectorArrayBuffer.fromJS( ctx, arguments.protectEatNext() orelse { - ctx.throwInvalidArguments("Expected an ArrayBufferView[]", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Expected an ArrayBufferView[]", .{}); }, arguments.arena.allocator(), ); @@ -1384,8 +1378,7 @@ pub const Arguments = struct { if (pos_value.isNumber()) { position = pos_value.to(u52); } else { - ctx.throwInvalidArguments("position must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("position must be a number", .{}); } } } @@ -1420,20 +1413,17 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Readv { const fd_value = arguments.nextEat() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }; const fd = try JSC.Node.fileDescriptorFromJS(ctx, fd_value) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; const buffers = try JSC.Node.VectorArrayBuffer.fromJS( ctx, arguments.protectEatNext() orelse { - ctx.throwInvalidArguments("Expected an ArrayBufferView[]", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Expected an ArrayBufferView[]", .{}); }, arguments.arena.allocator(), ); @@ -1445,8 +1435,7 @@ pub const Arguments = struct { if (pos_value.isNumber()) { position = pos_value.to(u52); } else { - ctx.throwInvalidArguments("position must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("position must be a number", .{}); } } } @@ -1473,11 +1462,9 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!FTruncate { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; arguments.eat(); @@ -1515,15 +1502,13 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Chown { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); const uid: uid_t = brk: { const uid_value = arguments.next() orelse break :brk { - ctx.throwInvalidArguments("uid is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("uid is required", .{}); }; arguments.eat(); @@ -1536,8 +1521,7 @@ pub const Arguments = struct { const gid: gid_t = brk: { const gid_value = arguments.next() orelse break :brk { - ctx.throwInvalidArguments("gid is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("gid is required", .{}); }; arguments.eat(); @@ -1563,17 +1547,14 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Fchown { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; const uid: uid_t = brk: { const uid_value = arguments.next() orelse break :brk { - ctx.throwInvalidArguments("uid is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("uid is required", .{}); }; arguments.eat(); @@ -1582,8 +1563,7 @@ pub const Arguments = struct { const gid: gid_t = brk: { const gid_value = arguments.next() orelse break :brk { - ctx.throwInvalidArguments("gid is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("gid is required", .{}); }; arguments.eat(); @@ -1615,27 +1595,22 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Lutimes { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); const atime = JSC.Node.timeLikeFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("atime is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("atime is required", .{}); }) orelse { - ctx.throwInvalidArguments("atime must be a number or a Date", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("atime must be a number or a Date", .{}); }; arguments.eat(); const mtime = JSC.Node.timeLikeFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("mtime is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("mtime is required", .{}); }) orelse { - ctx.throwInvalidArguments("mtime must be a number or a Date", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("mtime must be a number or a Date", .{}); }; arguments.eat(); @@ -1662,17 +1637,14 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Chmod { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); const mode: Mode = try JSC.Node.modeFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("mode is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("mode is required", .{}); }) orelse { - ctx.throwInvalidArguments("mode must be a string or integer", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("mode must be a string or integer", .{}); }; arguments.eat(); @@ -1691,21 +1663,17 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!FChmod { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; arguments.eat(); const mode: Mode = try JSC.Node.modeFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("mode is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("mode is required", .{}); }) orelse { - ctx.throwInvalidArguments("mode must be a string or integer", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("mode must be a string or integer", .{}); }; arguments.eat(); @@ -1735,8 +1703,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Stat { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -1774,11 +1741,9 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Fstat { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; const big_int = brk: { @@ -1822,13 +1787,11 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Link { const old_path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("oldPath must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("oldPath must be a string or TypedArray", .{}); }; const new_path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("newPath must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("newPath must be a string or TypedArray", .{}); }; return Link{ .old_path = old_path, .new_path = new_path }; @@ -1868,13 +1831,11 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Symlink { const old_path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("oldPath must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("oldPath must be a string or TypedArray", .{}); }; const new_path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("newPath must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("newPath must be a string or TypedArray", .{}); }; const link_type: LinkType = if (!Environment.isWindows) @@ -1936,8 +1897,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Readlink { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -1979,8 +1939,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Realpath { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -2029,8 +1988,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Unlink { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -2065,8 +2023,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!RmDir { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -2122,8 +2079,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: *JSC.JSGlobalObject, arguments: *ArgumentsSlice) bun.JSError!Mkdir { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -2172,8 +2128,7 @@ pub const Arguments = struct { const prefix_value = arguments.next() orelse return MkdirTemp{}; const prefix = StringOrBuffer.fromJS(ctx, bun.default_allocator, prefix_value) orelse { - ctx.throwInvalidArguments("prefix must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("prefix must be a string or TypedArray", .{}); }; errdefer prefix.deinit(); @@ -2233,8 +2188,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Readdir { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -2285,11 +2239,9 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Close { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; return Close{ .fd = fd }; @@ -2315,8 +2267,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Open { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -2376,29 +2327,23 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Futimes { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; arguments.eat(); const atime = JSC.Node.timeLikeFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("atime is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("atime is required", .{}); }) orelse { - ctx.throwInvalidArguments("atime must be a number or a Date", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("atime must be a number or a Date", .{}); }; arguments.eat(); const mtime = JSC.Node.timeLikeFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("mtime is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("mtime is required", .{}); }) orelse { - ctx.throwInvalidArguments("mtime must be a number or a Date", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("mtime must be a number or a Date", .{}); }; arguments.eat(); @@ -2457,18 +2402,15 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Write { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; arguments.eat(); const buffer_value = arguments.next(); const buffer = StringOrBuffer.fromJS(ctx, bun.default_allocator, buffer_value orelse { - ctx.throwInvalidArguments("data is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("data is required", .{}); }) orelse { _ = ctx.throwInvalidArgumentTypeValue("buffer", "string or TypedArray", buffer_value.?); return error.JSError; @@ -2555,18 +2497,15 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Read { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; arguments.eat(); const buffer_value = arguments.next(); const buffer = Buffer.fromJS(ctx, buffer_value orelse { - ctx.throwInvalidArguments("buffer is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("buffer is required", .{}); }) orelse { _ = ctx.throwInvalidArgumentTypeValue("buffer", "TypedArray", buffer_value.?); return error.JSError; @@ -2664,8 +2603,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!ReadFile { const path = try PathOrFileDescriptor.fromJS(ctx, arguments, bun.default_allocator) orelse { - ctx.throwInvalidArguments("path must be a string or a file descriptor", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or a file descriptor", .{}); }; errdefer path.deinit(); @@ -2681,8 +2619,7 @@ pub const Arguments = struct { if (arg.getTruthy(ctx, "flag")) |flag_| { flag = try FileSystemFlags.fromJS(ctx, flag_) orelse { - ctx.throwInvalidArguments("Invalid flag", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Invalid flag", .{}); }; } } @@ -2727,14 +2664,12 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!WriteFile { const path = try PathOrFileDescriptor.fromJS(ctx, arguments, bun.default_allocator) orelse { - ctx.throwInvalidArguments("path must be a string or a file descriptor", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or a file descriptor", .{}); }; errdefer path.deinit(); const data_value = arguments.nextEat() orelse { - ctx.throwInvalidArguments("data is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("data is required", .{}); }; var encoding = Encoding.buffer; @@ -2754,23 +2689,20 @@ pub const Arguments = struct { if (arg.getTruthy(ctx, "flag")) |flag_| { flag = try FileSystemFlags.fromJS(ctx, flag_) orelse { - ctx.throwInvalidArguments("Invalid flag", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Invalid flag", .{}); }; } if (arg.getTruthy(ctx, "mode")) |mode_| { mode = try JSC.Node.modeFromJS(ctx, mode_) orelse { - ctx.throwInvalidArguments("Invalid mode", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Invalid mode", .{}); }; } } } - const data = StringOrBuffer.fromJSWithEncodingMaybeAsync(ctx, bun.default_allocator, data_value, encoding, arguments.will_be_async) orelse { - ctx.throwInvalidArguments("data must be a string or TypedArray", .{}); - return error.JSError; + const data = try StringOrBuffer.fromJSWithEncodingMaybeAsync(ctx, bun.default_allocator, data_value, encoding, arguments.will_be_async) orelse { + return ctx.throwInvalidArguments2("data must be a string or TypedArray", .{}); }; // Note: Signal is not implemented @@ -2800,8 +2732,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!OpenDir { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -2820,8 +2751,7 @@ pub const Arguments = struct { if (arg.get(ctx, "bufferSize")) |buffer_size_| { buffer_size = buffer_size_.toInt32(); if (buffer_size < 0) { - ctx.throwInvalidArguments("bufferSize must be > 0", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("bufferSize must be > 0", .{}); } } } @@ -2881,8 +2811,7 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Access { const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("path must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("path must be a string or TypedArray", .{}); }; errdefer path.deinit(); @@ -2892,8 +2821,7 @@ pub const Arguments = struct { arguments.eat(); if (arg.isString()) { mode = try FileSystemFlags.fromJS(ctx, arg) orelse { - ctx.throwInvalidArguments("Invalid mode", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Invalid mode", .{}); }; } } @@ -2915,11 +2843,9 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!FdataSync { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; arguments.eat(); @@ -2949,14 +2875,12 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!CopyFile { const src = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("src must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("src must be a string or TypedArray", .{}); }; errdefer src.deinit(); const dest = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("dest must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("dest must be a string or TypedArray", .{}); }; errdefer dest.deinit(); @@ -2998,14 +2922,12 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Cp { const src = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("src must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("src must be a string or TypedArray", .{}); }; errdefer src.deinit(); const dest = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("dest must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("dest must be a string or TypedArray", .{}); }; errdefer dest.deinit(); @@ -3075,11 +2997,9 @@ pub const Arguments = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Fsync { const fd = try JSC.Node.fileDescriptorFromJS(ctx, arguments.next() orelse { - ctx.throwInvalidArguments("file descriptor is required", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor is required", .{}); }) orelse { - ctx.throwInvalidArguments("file descriptor must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("file descriptor must be a number", .{}); }; arguments.eat(); diff --git a/src/bun.js/node/node_fs_stat_watcher.zig b/src/bun.js/node/node_fs_stat_watcher.zig index 2b923a888f..b18414b947 100644 --- a/src/bun.js/node/node_fs_stat_watcher.zig +++ b/src/bun.js/node/node_fs_stat_watcher.zig @@ -237,8 +237,7 @@ pub const StatWatcher = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Arguments { const vm = ctx.vm(); const path = try PathLike.fromJSWithAllocator(ctx, arguments, bun.default_allocator) orelse { - ctx.throwInvalidArguments("filename must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("filename must be a string or TypedArray", .{}); }; var listener: JSC.JSValue = .zero; @@ -257,8 +256,7 @@ pub const StatWatcher = struct { if (options_or_callable.get(ctx, "interval")) |interval_| { if (!interval_.isNumber() and !interval_.isAnyInt()) { - ctx.throwInvalidArguments("interval must be a number", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("interval must be a number", .{}); } interval = interval_.coerce(i32, ctx); } @@ -272,8 +270,7 @@ pub const StatWatcher = struct { } if (listener == .zero) { - ctx.throwInvalidArguments("Expected \"listener\" callback", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Expected \"listener\" callback", .{}); } return Arguments{ diff --git a/src/bun.js/node/node_fs_watcher.zig b/src/bun.js/node/node_fs_watcher.zig index df4025082e..64444cbc39 100644 --- a/src/bun.js/node/node_fs_watcher.zig +++ b/src/bun.js/node/node_fs_watcher.zig @@ -344,8 +344,7 @@ pub const FSWatcher = struct { pub fn fromJS(ctx: JSC.C.JSContextRef, arguments: *ArgumentsSlice) bun.JSError!Arguments { const vm = ctx.vm(); const path = try PathLike.fromJS(ctx, arguments) orelse { - ctx.throwInvalidArguments("filename must be a string or TypedArray", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("filename must be a string or TypedArray", .{}); }; var should_deinit_path = true; defer if (should_deinit_path) path.deinit(); @@ -362,16 +361,14 @@ pub const FSWatcher = struct { if (options_or_callable.isObject()) { if (options_or_callable.getTruthy(ctx, "persistent")) |persistent_| { if (!persistent_.isBoolean()) { - ctx.throwInvalidArguments("persistent must be a boolean", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("persistent must be a boolean", .{}); } persistent = persistent_.toBoolean(); } if (options_or_callable.getTruthy(ctx, "verbose")) |verbose_| { if (!verbose_.isBoolean()) { - ctx.throwInvalidArguments("verbose must be a boolean", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("verbose must be a boolean", .{}); } verbose = verbose_.toBoolean(); } @@ -382,8 +379,7 @@ pub const FSWatcher = struct { if (options_or_callable.getTruthy(ctx, "recursive")) |recursive_| { if (!recursive_.isBoolean()) { - ctx.throwInvalidArguments("recursive must be a boolean", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("recursive must be a boolean", .{}); } recursive = recursive_.toBoolean(); } @@ -395,30 +391,26 @@ pub const FSWatcher = struct { signal_.ensureStillAlive(); signal = signal_obj; } else { - ctx.throwInvalidArguments("signal is not of type AbortSignal", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("signal is not of type AbortSignal", .{}); } } // listener if (arguments.nextEat()) |callable| { if (!callable.isCell() or !callable.isCallable(vm)) { - ctx.throwInvalidArguments("Expected \"listener\" callback to be a function", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Expected \"listener\" callback to be a function", .{}); } listener = callable; } } else { if (!options_or_callable.isCell() or !options_or_callable.isCallable(vm)) { - ctx.throwInvalidArguments("Expected \"listener\" callback to be a function", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Expected \"listener\" callback to be a function", .{}); } listener = options_or_callable; } } if (listener == .zero) { - ctx.throwInvalidArguments("Expected \"listener\" callback", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Expected \"listener\" callback", .{}); } should_deinit_path = false; diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index ec0b6e4b7f..fe364484b8 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -370,15 +370,15 @@ pub const BlobOrStringOrBuffer = union(enum) { return .{ .string_or_buffer = StringOrBuffer.fromJS(global, allocator, value) orelse return null }; } - pub fn fromJSWithEncodingValue(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue) ?BlobOrStringOrBuffer { + pub fn fromJSWithEncodingValue(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue) bun.JSError!?BlobOrStringOrBuffer { return fromJSWithEncodingValueMaybeAsync(global, allocator, value, encoding_value, false); } - pub fn fromJSWithEncodingValueMaybeAsync(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue, is_async: bool) ?BlobOrStringOrBuffer { + pub fn fromJSWithEncodingValueMaybeAsync(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue, is_async: bool) bun.JSError!?BlobOrStringOrBuffer { return fromJSWithEncodingValueMaybeAsyncAllowRequestResponse(global, allocator, value, encoding_value, is_async, false); } - pub fn fromJSWithEncodingValueMaybeAsyncAllowRequestResponse(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue, is_async: bool, allow_request_response: bool) ?BlobOrStringOrBuffer { + pub fn fromJSWithEncodingValueMaybeAsyncAllowRequestResponse(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue, is_async: bool, allow_request_response: bool) bun.JSError!?BlobOrStringOrBuffer { switch (value.jsType()) { .DOMWrapper => { if (value.as(JSC.WebCore.Blob)) |blob| { @@ -397,8 +397,7 @@ pub const BlobOrStringOrBuffer = union(enum) { return .{ .blob = any_blob.toBlob(global) }; } - global.throwInvalidArguments("Only buffered Request/Response bodies are supported for now.", .{}); - return null; + return global.throwInvalidArguments2("Only buffered Request/Response bodies are supported for now.", .{}); } if (value.as(JSC.WebCore.Response)) |response| { @@ -410,15 +409,14 @@ pub const BlobOrStringOrBuffer = union(enum) { return .{ .blob = any_blob.toBlob(global) }; } - global.throwInvalidArguments("Only buffered Request/Response bodies are supported for now.", .{}); - return null; + return global.throwInvalidArguments2("Only buffered Request/Response bodies are supported for now.", .{}); } } }, else => {}, } - return .{ .string_or_buffer = StringOrBuffer.fromJSWithEncodingValueMaybeAsync(global, allocator, value, encoding_value, is_async) orelse return null }; + return .{ .string_or_buffer = try StringOrBuffer.fromJSWithEncodingValueMaybeAsync(global, allocator, value, encoding_value, is_async) orelse return null }; } }; @@ -453,14 +451,14 @@ pub const StringOrBuffer = union(enum) { } } - pub fn fromJSToOwnedSlice(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue, allocator: std.mem.Allocator) ![]u8 { + pub fn fromJSToOwnedSlice(globalObject: *JSC.JSGlobalObject, value: JSC.JSValue, allocator: std.mem.Allocator) bun.JSError![]u8 { if (value.asArrayBuffer(globalObject)) |array_buffer| { defer globalObject.vm().reportExtraMemory(array_buffer.len); return try allocator.dupe(u8, array_buffer.byteSlice()); } - const str = bun.String.tryFromJS(value, globalObject) orelse return error.JSError; + const str = try bun.String.fromJS2(value, globalObject); defer str.deref(); const result = try str.toOwnedSlice(allocator); @@ -579,11 +577,11 @@ pub const StringOrBuffer = union(enum) { return fromJSMaybeAsync(global, allocator, value, false); } - pub fn fromJSWithEncoding(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding: Encoding) ?StringOrBuffer { + pub fn fromJSWithEncoding(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding: Encoding) bun.JSError!?StringOrBuffer { return fromJSWithEncodingMaybeAsync(global, allocator, value, encoding, false); } - pub fn fromJSWithEncodingMaybeAsync(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding: Encoding, is_async: bool) ?StringOrBuffer { + pub fn fromJSWithEncodingMaybeAsync(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding: Encoding, is_async: bool) bun.JSError!?StringOrBuffer { if (value.isCell() and value.jsType().isTypedArray()) { return StringOrBuffer{ .buffer = Buffer.fromTypedArray(global, value), @@ -594,7 +592,7 @@ pub const StringOrBuffer = union(enum) { return fromJSMaybeAsync(global, allocator, value, is_async); } - var str = bun.String.tryFromJS(value, global) orelse return null; + var str = try bun.String.fromJS2(value, global); defer str.deref(); if (str.isEmpty()) { return fromJSMaybeAsync(global, allocator, value, is_async); @@ -608,7 +606,7 @@ pub const StringOrBuffer = union(enum) { }; } - pub fn fromJSWithEncodingValue(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue) ?StringOrBuffer { + pub fn fromJSWithEncodingValue(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue) bun.JSError!?StringOrBuffer { const encoding: Encoding = brk: { if (!encoding_value.isCell()) break :brk .utf8; @@ -618,7 +616,7 @@ pub const StringOrBuffer = union(enum) { return fromJSWithEncoding(global, allocator, value, encoding); } - pub fn fromJSWithEncodingValueMaybeAsync(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue, maybe_async: bool) ?StringOrBuffer { + pub fn fromJSWithEncodingValueMaybeAsync(global: *JSC.JSGlobalObject, allocator: std.mem.Allocator, value: JSC.JSValue, encoding_value: JSC.JSValue, maybe_async: bool) bun.JSError!?StringOrBuffer { const encoding: Encoding = brk: { if (!encoding_value.isCell()) break :brk .utf8; @@ -692,7 +690,7 @@ pub const Encoding = enum(u8) { } pub fn fromJSWithDefaultOnEmpty(value: JSC.JSValue, globalObject: *JSC.JSGlobalObject, default: Encoding) bun.JSError!?Encoding { - const str = bun.String.tryFromJS(value, globalObject) orelse return error.JSError; + const str = try bun.String.fromJS2(value, globalObject); defer str.deref(); if (str.isEmpty()) { return default; @@ -1106,8 +1104,7 @@ pub const VectorArrayBuffer = struct { pub fn fromJS(globalObject: *JSC.JSGlobalObject, val: JSC.JSValue, allocator: std.mem.Allocator) bun.JSError!VectorArrayBuffer { if (!val.jsType().isArrayLike()) { - globalObject.throwInvalidArguments("Expected ArrayBufferView[]", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected ArrayBufferView[]", .{}); } var bufferlist = std.ArrayList(bun.PlatformIOVec).init(allocator); @@ -1119,13 +1116,11 @@ pub const VectorArrayBuffer = struct { const element = val.getIndex(globalObject, @as(u32, @truncate(i))); if (!element.isCell()) { - globalObject.throwInvalidArguments("Expected ArrayBufferView[]", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected ArrayBufferView[]", .{}); } const array_buffer = element.asArrayBuffer(globalObject) orelse { - globalObject.throwInvalidArguments("Expected ArrayBufferView[]", .{}); - return error.JSError; + return globalObject.throwInvalidArguments2("Expected ArrayBufferView[]", .{}); }; const buf = array_buffer.byteSlice(); @@ -1479,13 +1474,11 @@ pub const FileSystemFlags = enum(Mode) { if (jsType.isStringLike()) { const str = val.getZigString(ctx); if (str.isEmpty()) { - ctx.throwInvalidArguments("Expected flags to be a non-empty string. Learn more at https://nodejs.org/api/fs.html#fs_file_system_flags", .{}); - return error.JSError; + return ctx.throwInvalidArguments2("Expected flags to be a non-empty string. Learn more at https://nodejs.org/api/fs.html#fs_file_system_flags", .{}); } // it's definitely wrong when the string is super long else if (str.len > 12) { - ctx.throwInvalidArguments("Invalid flag '{any}'. Learn more at https://nodejs.org/api/fs.html#fs_file_system_flags", .{str}); - return error.JSError; + return ctx.throwInvalidArguments2("Invalid flag '{any}'. Learn more at https://nodejs.org/api/fs.html#fs_file_system_flags", .{str}); } const flags = brk: { @@ -1509,8 +1502,7 @@ pub const FileSystemFlags = enum(Mode) { break :brk map.getWithEql(str, JSC.ZigString.eqlComptime); } orelse { - ctx.throwInvalidArguments("Invalid flag '{any}'. Learn more at https://nodejs.org/api/fs.html#fs_file_system_flags", .{str}); - return error.JSError; + return ctx.throwInvalidArguments2("Invalid flag '{any}'. Learn more at https://nodejs.org/api/fs.html#fs_file_system_flags", .{str}); }; return @as(FileSystemFlags, @enumFromInt(@as(Mode, @intCast(flags)))); diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index 89755654d9..979143b53a 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -107,9 +107,11 @@ pub const Expect = struct { Promise = 8, InstanceOf = 9, - extern fn AsymmetricMatcherConstructorType__fromJS(globalObject: *JSGlobalObject, value: JSValue) u8; - pub fn fromJS(globalObject: *JSGlobalObject, value: JSValue) AsymmetricMatcherConstructorType { - return @enumFromInt(AsymmetricMatcherConstructorType__fromJS(globalObject, value)); + extern fn AsymmetricMatcherConstructorType__fromJS(globalObject: *JSGlobalObject, value: JSValue) i8; + pub fn fromJS(globalObject: *JSGlobalObject, value: JSValue) bun.JSError!AsymmetricMatcherConstructorType { + const result = AsymmetricMatcherConstructorType__fromJS(globalObject, value); + if (result == -1) return error.JSError; + return @enumFromInt(result); } }; @@ -5194,9 +5196,7 @@ pub const ExpectAny = struct { flags: Expect.Flags = .{}, - pub fn finalize( - this: *ExpectAny, - ) callconv(.C) void { + pub fn finalize(this: *ExpectAny) callconv(.C) void { VirtualMachine.get().allocator.destroy(this); } @@ -5205,8 +5205,7 @@ pub const ExpectAny = struct { const arguments: []const JSValue = _arguments.ptr[0.._arguments.len]; if (arguments.len == 0) { - globalThis.throw("any() expects to be passed a constructor function. Please pass one or use anything() to match any object.", .{}); - return .zero; + return globalThis.throw2("any() expects to be passed a constructor function. Please pass one or use anything() to match any object.", .{}); } const constructor = arguments[0]; @@ -5214,19 +5213,19 @@ pub const ExpectAny = struct { if (!constructor.isConstructor()) { const fmt = "expect.any(constructor)\n\nExpected a constructor\n"; globalThis.throwPretty(fmt, .{}); - return .zero; + return error.JSError; } - const asymmetric_matcher_constructor_type = Expect.Flags.AsymmetricMatcherConstructorType.fromJS(globalThis, constructor); + const asymmetric_matcher_constructor_type = try Expect.Flags.AsymmetricMatcherConstructorType.fromJS(globalThis, constructor); // I don't think this case is possible, but just in case! if (globalThis.hasException()) { - return .zero; + return error.JSError; } var any = globalThis.bunVM().allocator.create(ExpectAny) catch { globalThis.throwOutOfMemory(); - return .zero; + return error.JSError; }; any.* = .{ .flags = .{ diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index 83dd25b00d..081c3a5f60 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -1445,15 +1445,16 @@ pub const Blob = struct { }; defer name_value_str.deref(); - blob = get(globalThis, args[0], false, true) catch |err| { - if (!globalThis.hasException()) { - if (err == error.InvalidArguments) { - globalThis.throwInvalidArguments("new File(bits, name) expects iterable as the first argument", .{}); - return null; - } + blob = get(globalThis, args[0], false, true) catch |err| switch (err) { + error.JSError => return null, + error.OutOfMemory => { globalThis.throwOutOfMemory(); - } - return null; + return null; + }, + error.InvalidArguments => { + globalThis.throwInvalidArguments("new Blob() expects an Array", .{}); + return null; + }, }; if (blob.store) |store_| { @@ -3468,18 +3469,15 @@ pub const Blob = struct { var arguments = arguments_.ptr[0..arguments_.len]; if (!arguments.ptr[0].isEmptyOrUndefinedOrNull() and !arguments.ptr[0].isObject()) { - globalThis.throwInvalidArguments("options must be an object or undefined", .{}); - return JSValue.jsUndefined(); + return globalThis.throwInvalidArguments2("options must be an object or undefined", .{}); } var store = this.store orelse { - globalThis.throwInvalidArguments("Blob is detached", .{}); - return JSValue.jsUndefined(); + return globalThis.throwInvalidArguments2("Blob is detached", .{}); }; if (store.data != .file) { - globalThis.throwInvalidArguments("Blob is read-only", .{}); - return JSValue.jsUndefined(); + return globalThis.throwInvalidArguments2("Blob is read-only", .{}); } if (Environment.isWindows) { @@ -3497,8 +3495,7 @@ pub const Blob = struct { break :brk result; }, .err => |err| { - globalThis.throwValue(err.withPath(path).toJSC(globalThis)); - return JSValue.jsUndefined(); + return globalThis.throwValue2(err.withPath(path).toJSC(globalThis)); }, } unreachable; @@ -3530,20 +3527,16 @@ pub const Blob = struct { if (is_stdout_or_stderr) { switch (sink.writer.startSync(fd, false)) { .err => |err| { - globalThis.throwValue(err.toJSC(globalThis)); sink.deref(); - - return JSC.JSValue.zero; + return globalThis.throwValue2(err.toJSC(globalThis)); }, else => {}, } } else { switch (sink.writer.start(fd, true)) { .err => |err| { - globalThis.throwValue(err.toJSC(globalThis)); sink.deref(); - - return JSC.JSValue.zero; + return globalThis.throwValue2(err.toJSC(globalThis)); }, else => {}, } @@ -3576,16 +3569,14 @@ pub const Blob = struct { }; if (arguments.len > 0 and arguments.ptr[0].isObject()) { - stream_start = JSC.WebCore.StreamStart.fromJSWithTag(globalThis, arguments[0], .FileSink); + stream_start = try JSC.WebCore.StreamStart.fromJSWithTag(globalThis, arguments[0], .FileSink); stream_start.FileSink.input_path = input_path; } switch (sink.start(stream_start)) { .err => |err| { - globalThis.vm().throwError(globalThis, err.toJSC(globalThis)); sink.deref(); - - return JSC.JSValue.zero; + return globalThis.vm().throwError2(globalThis, err.toJSC(globalThis)); }, else => {}, } @@ -3959,13 +3950,9 @@ pub const Blob = struct { blob = Blob.init(empty, allocator, globalThis); }, else => { - blob = get(globalThis, args[0], false, true) catch |err| { - if (err == error.InvalidArguments) { - return globalThis.throwInvalidArguments2("new Blob() expects an Array", .{}); - } - if (!globalThis.hasException()) - globalThis.throwOutOfMemory(); - return error.JSError; + blob = get(globalThis, args[0], false, true) catch |err| switch (err) { + error.OutOfMemory, error.JSError => |e| return e, + error.InvalidArguments => return globalThis.throwInvalidArguments2("new Blob() expects an Array", .{}), }; if (args.len > 1) { @@ -4518,24 +4505,26 @@ pub const Blob = struct { return toFormDataWithBytes(this, global, @constCast(view_), lifetime); } + const FromJsError = bun.JSError || error{InvalidArguments}; + pub inline fn get( global: *JSGlobalObject, arg: JSValue, comptime move: bool, comptime require_array: bool, - ) anyerror!Blob { + ) FromJsError!Blob { return fromJSMovable(global, arg, move, require_array); } - pub inline fn fromJSMove(global: *JSGlobalObject, arg: JSValue) anyerror!Blob { + pub inline fn fromJSMove(global: *JSGlobalObject, arg: JSValue) FromJsError!Blob { return fromJSWithoutDeferGC(global, arg, true, false); } - pub inline fn fromJSClone(global: *JSGlobalObject, arg: JSValue) anyerror!Blob { + pub inline fn fromJSClone(global: *JSGlobalObject, arg: JSValue) FromJsError!Blob { return fromJSWithoutDeferGC(global, arg, false, true); } - pub inline fn fromJSCloneOptionalArray(global: *JSGlobalObject, arg: JSValue) anyerror!Blob { + pub inline fn fromJSCloneOptionalArray(global: *JSGlobalObject, arg: JSValue) FromJsError!Blob { return fromJSWithoutDeferGC(global, arg, false, false); } @@ -4544,7 +4533,7 @@ pub const Blob = struct { arg: JSValue, comptime move: bool, comptime require_array: bool, - ) anyerror!Blob { + ) FromJsError!Blob { const FromJSFunction = if (comptime move and !require_array) fromJSMove else if (!require_array) @@ -4560,7 +4549,7 @@ pub const Blob = struct { arg: JSValue, comptime move: bool, comptime require_array: bool, - ) anyerror!Blob { + ) FromJsError!Blob { var current = arg; if (current.isUndefinedOrNull()) { return Blob{ .globalThis = global }; diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig index d336886c8d..e4e9760444 100644 --- a/src/bun.js/webcore/response.zig +++ b/src/bun.js/webcore/response.zig @@ -1900,7 +1900,7 @@ pub const Fetch = struct { return .zero; } - var url_str = JSC.URL.hrefFromJS(arguments[0], globalObject); + var url_str = try JSC.URL.hrefFromJS(arguments[0], globalObject); defer url_str.deref(); if (globalObject.hasException()) { @@ -1941,15 +1941,13 @@ pub const Fetch = struct { } const StringOrURL = struct { - pub fn fromJS(value: JSC.JSValue, globalThis: *JSC.JSGlobalObject) ?bun.String { + pub fn fromJS(value: JSC.JSValue, globalThis: *JSC.JSGlobalObject) bun.JSError!?bun.String { if (value.isString()) { - return bun.String.tryFromJS(value, globalThis); + return try bun.String.fromJS2(value, globalThis); } - const out = JSC.URL.hrefFromJS(value, globalThis); - if (out.tag == .Dead) { - return null; - } + const out = try JSC.URL.hrefFromJS(value, globalThis); + if (out.tag == .Dead) return null; return out; } }; @@ -1972,6 +1970,7 @@ pub const Fetch = struct { // used to clean up dynamically allocated memory on error (a poor man's errdefer) var is_error = false; var allocator = memory_reporter.wrap(bun.default_allocator); + errdefer bun.default_allocator.destroy(memory_reporter); defer { memory_reporter.report(globalThis.vm()); @@ -2035,10 +2034,6 @@ pub const Fetch = struct { sig.unref(); } - if (!is_error and globalThis.hasException()) { - is_error = true; - } - unix_socket_path.deinit(); allocator.free(url_proxy_buffer); @@ -2084,7 +2079,7 @@ pub const Fetch = struct { break :brk null; }; // If it's NOT a Request or a subclass of Request, treat the first argument as a URL. - const url_str_optional = if (first_arg.as(Request) == null) StringOrURL.fromJS(first_arg, globalThis) else null; + const url_str_optional = if (first_arg.as(Request) == null) try StringOrURL.fromJS(first_arg, globalThis) else null; if (globalThis.hasException()) { is_error = true; return .zero; @@ -2108,9 +2103,7 @@ pub const Fetch = struct { if (request_init_object) |request_init| { if (request_init.fastGet(globalThis, .url)) |url_| { if (!url_.isUndefined()) { - if (bun.String.tryFromJS(url_, globalThis)) |str| { - break :extract_url str; - } + break :extract_url try bun.String.fromJS2(url_, globalThis); } } } @@ -2457,7 +2450,7 @@ pub const Fetch = struct { if (objects_to_try[i] != .zero) { if (objects_to_try[i].get(globalThis, "proxy")) |proxy_arg| { if (proxy_arg.isString() and proxy_arg.getLength(ctx) > 0) { - var href = JSC.URL.hrefFromJS(proxy_arg, globalThis); + var href = try JSC.URL.hrefFromJS(proxy_arg, globalThis); if (href.tag == .Dead) { const err = JSC.toTypeError(.ERR_INVALID_ARG_VALUE, "fetch() proxy URL is invalid", .{}, ctx); is_error = true; diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 9f14fd3ed1..c44b25897b 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -526,7 +526,7 @@ pub const StreamStart = union(Tag) { } } - pub fn fromJS(globalThis: *JSGlobalObject, value: JSValue) StreamStart { + pub fn fromJS(globalThis: *JSGlobalObject, value: JSValue) bun.JSError!StreamStart { if (value.isEmptyOrUndefinedOrNull() or !value.isObject()) { return .{ .empty = {} }; } @@ -543,7 +543,7 @@ pub const StreamStart = union(Tag) { globalThis: *JSGlobalObject, value: JSValue, comptime tag: Tag, - ) StreamStart { + ) bun.JSError!StreamStart { if (value.isEmptyOrUndefinedOrNull() or !value.isObject()) { return .{ .empty = {} }; } @@ -1917,11 +1917,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { if (comptime @hasField(StreamStart, name_)) { return this.sink.start( if (callframe.argumentsCount() > 0) - StreamStart.fromJSWithTag( - globalThis, - callframe.argument(0), - comptime @field(StreamStart, name_), - ) + try StreamStart.fromJSWithTag(globalThis, callframe.argument(0), comptime @field(StreamStart, name_)) else StreamStart{ .empty = {} }, ).toJS(globalThis); @@ -1929,7 +1925,7 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { return this.sink.start( if (callframe.argumentsCount() > 0) - StreamStart.fromJS(globalThis, callframe.argument(0)) + try StreamStart.fromJS(globalThis, callframe.argument(0)) else StreamStart{ .empty = {} }, ).toJS(globalThis); diff --git a/src/bun.zig b/src/bun.zig index 0b19824aec..a2a39d1df9 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -130,6 +130,7 @@ pub const patch = @import("./patch.zig"); pub const ini = @import("./ini.zig"); pub const Bitflags = @import("./bitflags.zig").Bitflags; pub const css = @import("./css/css_parser.zig"); +pub const validators = @import("./bun.js/node/util/validators.zig"); pub const shell = struct { pub usingnamespace @import("./shell/shell.zig"); diff --git a/src/install/dependency.zig b/src/install/dependency.zig index 95700a0125..66959bd493 100644 --- a/src/install/dependency.zig +++ b/src/install/dependency.zig @@ -308,7 +308,7 @@ pub const Version = struct { literal: String = .{}, value: Value = .{ .uninitialized = {} }, - pub fn toJS(dep: *const Version, buf: []const u8, globalThis: *JSC.JSGlobalObject) JSC.JSValue { + pub fn toJS(dep: *const Version, buf: []const u8, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { const object = JSC.JSValue.createEmptyObject(globalThis, 2); object.put(globalThis, "type", bun.String.static(@tagName(dep.tag)).toJS(globalThis)); @@ -332,15 +332,8 @@ pub const Version = struct { }, .npm => { object.put(globalThis, "name", dep.value.npm.name.toJS(buf, globalThis)); - var version_str = bun.String.createFormat("{}", .{dep.value.npm.version.fmt(buf)}) catch { - globalThis.throwOutOfMemory(); - return .zero; - }; - object.put( - globalThis, - "version", - version_str.transferToJS(globalThis), - ); + var version_str = try bun.String.createFormat("{}", .{dep.value.npm.version.fmt(buf)}); + object.put(globalThis, "version", version_str.transferToJS(globalThis)); object.put(globalThis, "alias", JSC.JSValue.jsBoolean(dep.value.npm.is_alias)); }, .symlink => { @@ -362,7 +355,7 @@ pub const Version = struct { }, else => { globalThis.throwTODO("Unsupported dependency type"); - return .zero; + return error.JSError; }, } @@ -1237,7 +1230,7 @@ pub fn parseWithTag( pub fn fromJS(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const arguments = callframe.arguments(2).slice(); if (arguments.len == 1) { - return bun.install.PackageManager.UpdateRequest.fromJS(globalThis, arguments[0]); + return try bun.install.PackageManager.UpdateRequest.fromJS(globalThis, arguments[0]); } var arena = std.heap.ArenaAllocator.init(bun.default_allocator); defer arena.deinit(); @@ -1277,16 +1270,14 @@ pub fn fromJS(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JS const dep: Version = Dependency.parse(allocator, SlicedString.init(buf, alias).value(), null, buf, &sliced, &log) orelse { if (log.msgs.items.len > 0) { - globalThis.throwValue(log.toJS(globalThis, bun.default_allocator, "Failed to parse dependency")); - return .zero; + return globalThis.throwValue2(log.toJS(globalThis, bun.default_allocator, "Failed to parse dependency")); } return .undefined; }; if (log.msgs.items.len > 0) { - globalThis.throwValue(log.toJS(globalThis, bun.default_allocator, "Failed to parse dependency")); - return .zero; + return globalThis.throwValue2(log.toJS(globalThis, bun.default_allocator, "Failed to parse dependency")); } log.deinit(); diff --git a/src/install/install.zig b/src/install/install.zig index 0ee8f2893c..6fd768c6dc 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -9993,7 +9993,7 @@ pub const PackageManager = struct { lockfile.packages.items(.name)[this.package_id].slice(this.version_buf); } - pub fn fromJS(globalThis: *JSC.JSGlobalObject, input: JSC.JSValue) JSC.JSValue { + pub fn fromJS(globalThis: *JSC.JSGlobalObject, input: JSC.JSValue) bun.JSError!JSC.JSValue { var arena = std.heap.ArenaAllocator.init(bun.default_allocator); defer arena.deinit(); var stack = std.heap.stackFallback(1024, arena.allocator()); @@ -10029,25 +10029,22 @@ pub const PackageManager = struct { var array = Array{}; const update_requests = parseWithError(allocator, &log, all_positionals.items, &array, .add, false) catch { - globalThis.throwValue(log.toJS(globalThis, bun.default_allocator, "Failed to parse dependencies")); - return .zero; + return globalThis.throwValue2(log.toJS(globalThis, bun.default_allocator, "Failed to parse dependencies")); }; if (update_requests.len == 0) return .undefined; if (log.msgs.items.len > 0) { - globalThis.throwValue(log.toJS(globalThis, bun.default_allocator, "Failed to parse dependencies")); - return .zero; + return globalThis.throwValue2(log.toJS(globalThis, bun.default_allocator, "Failed to parse dependencies")); } if (update_requests[0].failed) { - globalThis.throw("Failed to parse dependencies", .{}); - return .zero; + return globalThis.throw2("Failed to parse dependencies", .{}); } 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, "version", update_requests[0].version.toJS(update_requests[0].version_buf, globalThis)); + object.put(globalThis, "version", try update_requests[0].version.toJS(update_requests[0].version_buf, globalThis)); return object; } diff --git a/src/logger.zig b/src/logger.zig index c1b81145fe..d3ff0999ca 100644 --- a/src/logger.zig +++ b/src/logger.zig @@ -658,8 +658,7 @@ pub const Log = struct { } if (!value.isString()) { - globalThis.throwInvalidArguments("Expected logLevel to be a string", .{}); - return error.JSError; + return globalThis.throwInvalidArguments2("Expected logLevel to be a string", .{}); } return Map.fromJS(globalThis, value); diff --git a/src/options.zig b/src/options.zig index b516e206de..b7faf7f0ca 100644 --- a/src/options.zig +++ b/src/options.zig @@ -396,9 +396,8 @@ pub const Target = enum { }); pub fn fromJS(global: *JSC.JSGlobalObject, value: JSC.JSValue) bun.JSError!?Target { - if (!value.jsType().isStringLike()) { - global.throwInvalidArguments("target must be a string", .{}); - return error.JSError; + if (!value.isString()) { + return global.throwInvalidArguments2("target must be a string", .{}); } return Map.fromJS(global, value); } @@ -614,14 +613,12 @@ pub const Format = enum { pub fn fromJS(global: *JSC.JSGlobalObject, format: JSC.JSValue) bun.JSError!?Format { if (format.isUndefinedOrNull()) return null; - if (!format.jsType().isStringLike()) { - global.throwInvalidArguments("format must be a string", .{}); - return error.JSError; + if (!format.isString()) { + return global.throwInvalidArguments2("format must be a string", .{}); } return Map.fromJS(global, format) orelse { - global.throwInvalidArguments("Invalid format - must be esm, cjs, or iife", .{}); - return error.JSError; + return global.throwInvalidArguments2("Invalid format - must be esm, cjs, or iife", .{}); }; } @@ -733,9 +730,8 @@ pub const Loader = enum(u8) { pub fn fromJS(global: *JSC.JSGlobalObject, loader: JSC.JSValue) bun.JSError!?Loader { if (loader.isUndefinedOrNull()) return null; - if (!loader.jsType().isStringLike()) { - global.throwInvalidArguments("loader must be a string", .{}); - return error.JSError; + if (!loader.isString()) { + return global.throwInvalidArguments2("loader must be a string", .{}); } var zig_str = JSC.ZigString.init(""); @@ -743,8 +739,7 @@ pub const Loader = enum(u8) { if (zig_str.len == 0) return null; return fromString(zig_str.slice()) orelse { - global.throwInvalidArguments("invalid loader - must be js, jsx, tsx, ts, css, file, toml, wasm, bunsh, or json", .{}); - return error.JSError; + return global.throwInvalidArguments2("invalid loader - must be js, jsx, tsx, ts, css, file, toml, wasm, bunsh, or json", .{}); }; } diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index 73b7499b08..496fef2b18 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -476,13 +476,13 @@ pub const PostgresSQLQuery = struct { const arguments = arguments_.slice(); var connection = arguments[0].as(PostgresSQLConnection) orelse { globalObject.throw("connection must be a PostgresSQLConnection", .{}); - return .zero; + return error.JSError; }; var query = arguments[1]; if (!query.isObject()) { globalObject.throwInvalidArgumentType("run", "query", "Query"); - return .zero; + return error.JSError; } this.target.set(globalObject, query); @@ -494,7 +494,7 @@ pub const PostgresSQLQuery = struct { var signature = Signature.generate(globalObject, query_str.slice(), binding_value, columns_value) catch |err| { if (!globalObject.hasException()) globalObject.throwError(err, "failed to generate signature"); - return .zero; + return error.JSError; }; var writer = connection.writer(); @@ -502,7 +502,7 @@ pub const PostgresSQLQuery = struct { const entry = connection.statements.getOrPut(bun.default_allocator, bun.hash(signature.name)) catch |err| { globalObject.throwError(err, "failed to allocate statement"); signature.deinit(); - return .zero; + return error.JSError; }; const has_params = signature.fields.len > 0; @@ -523,7 +523,7 @@ pub const PostgresSQLQuery = struct { if (!globalObject.hasException()) globalObject.throwError(err, "failed to bind and execute query"); - return .zero; + return error.JSError; }; did_write = true; } @@ -537,7 +537,7 @@ pub const PostgresSQLQuery = struct { if (!globalObject.hasException()) globalObject.throwError(err, "failed to prepare and query"); signature.deinit(); - return .zero; + return error.JSError; }; did_write = true; } else { @@ -545,20 +545,20 @@ pub const PostgresSQLQuery = struct { if (!globalObject.hasException()) globalObject.throwError(err, "failed to write query"); signature.deinit(); - return .zero; + return error.JSError; }; writer.write(&protocol.Sync) catch |err| { if (!globalObject.hasException()) globalObject.throwError(err, "failed to flush"); signature.deinit(); - return .zero; + return error.JSError; }; } { const stmt = bun.default_allocator.create(PostgresSQLStatement) catch |err| { globalObject.throwError(err, "failed to allocate statement"); - return .zero; + return error.JSError; }; stmt.* = .{ .signature = signature, .ref_count = 2, .status = PostgresSQLStatement.Status.parsing }; @@ -724,7 +724,7 @@ pub const PostgresRequest = struct { }, else => { - const str = String.fromJSRef(value, globalObject); + const str = try String.fromJSRef(value, globalObject); defer str.deref(); const slice = str.toUTF8WithoutRef(bun.default_allocator); defer slice.deinit(); diff --git a/src/sql/postgres/postgres_types.zig b/src/sql/postgres/postgres_types.zig index 9ace396880..6a595cafb7 100644 --- a/src/sql/postgres/postgres_types.zig +++ b/src/sql/postgres/postgres_types.zig @@ -330,7 +330,7 @@ pub const Tag = enum(short) { return toJSWithType(tag, globalObject, @TypeOf(value), value); } - pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSValue) anyerror!Tag { + pub fn fromJS(globalObject: *JSC.JSGlobalObject, value: JSValue) bun.JSError!Tag { if (value.isEmptyOrUndefinedOrNull()) { return Tag.numeric; } @@ -359,6 +359,7 @@ pub const Tag = enum(short) { if (tag.isArrayLike() and value.getLength(globalObject) > 0) { return Tag.fromJS(globalObject, value.getIndex(globalObject, 0)); } + if (globalObject.hasException()) return error.JSError; // Ban these types: if (tag == .NumberObject) { diff --git a/src/string.zig b/src/string.zig index 3be422ccfc..eba63664aa 100644 --- a/src/string.zig +++ b/src/string.zig @@ -714,14 +714,15 @@ pub const String = extern struct { } } - pub fn fromJSRef(value: bun.JSC.JSValue, globalObject: *JSC.JSGlobalObject) String { + pub fn fromJSRef(value: bun.JSC.JSValue, globalObject: *JSC.JSGlobalObject) bun.JSError!String { JSC.markBinding(@src()); var out: String = String.dead; if (BunString__fromJSRef(globalObject, value, &out)) { return out; } else { - return String.dead; + bun.assert(globalObject.hasException()); + return error.JSError; } }