From 284de53f26367c796c14c42c88ef940bcd45b085 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Sat, 31 May 2025 19:05:02 -0800 Subject: [PATCH] safety: audit and add missing exception checks to JSC::constructArray+constructEmptyArray (#20119) --- src/bake/DevServer.zig | 24 +++--- src/bake/FrameworkRouter.zig | 24 +++--- src/bake/production.zig | 28 +++--- src/bun.js/BuildMessage.zig | 2 +- src/bun.js/Counters.zig | 5 +- src/bun.js/api/BunObject.zig | 8 +- src/bun.js/api/JSTranspiler.zig | 15 ++-- src/bun.js/api/bun/dns_resolver.zig | 34 ++++---- src/bun.js/api/bun/h2_frame_parser.zig | 59 ++++++------- src/bun.js/api/bun/socket.zig | 21 ++--- src/bun.js/api/bun/socket/SocketAddress.zig | 4 +- src/bun.js/api/bun/subprocess.zig | 17 +--- src/bun.js/api/crypto/CryptoHasher.zig | 6 +- src/bun.js/api/ffi.zig | 4 +- src/bun.js/api/glob.zig | 4 +- src/bun.js/api/html_rewriter.zig | 2 +- src/bun.js/api/server.zig | 8 +- src/bun.js/bindgen_test.zig | 6 +- src/bun.js/bindings/BunProcess.cpp | 1 + src/bun.js/bindings/JSArray.zig | 8 +- src/bun.js/bindings/JSCommonJSModule.cpp | 1 + src/bun.js/bindings/JSGlobalObject.zig | 6 +- src/bun.js/bindings/JSMockFunction.cpp | 5 ++ src/bun.js/bindings/JSObject.zig | 8 +- src/bun.js/bindings/JSPromise.zig | 4 +- src/bun.js/bindings/JSValue.zig | 13 ++- src/bun.js/bindings/JSX509Certificate.cpp | 1 + src/bun.js/bindings/NodeHTTP.cpp | 5 ++ src/bun.js/bindings/NodeVMModule.cpp | 10 +++ .../bindings/NodeVMSourceTextModule.cpp | 1 + src/bun.js/bindings/Path.cpp | 7 ++ src/bun.js/bindings/ProcessBindingUV.cpp | 1 + src/bun.js/bindings/ZigGlobalObject.cpp | 1 + src/bun.js/bindings/sqlite/JSSQLStatement.cpp | 11 +++ src/bun.js/bindings/v8/V8Array.cpp | 1 + .../bindings/webcore/JSDOMConvertSequences.h | 4 +- src/bun.js/bindings/webcore/JSDOMFormData.cpp | 1 + .../bindings/webcore/JSEventEmitter.cpp | 12 ++- src/bun.js/ipc.zig | 10 +-- src/bun.js/jsc.zig | 1 + src/bun.js/jsc/host_fn.zig | 5 ++ src/bun.js/modules/NodeModuleModule.cpp | 3 + src/bun.js/node/net/BlockList.zig | 2 +- src/bun.js/node/node_assert.zig | 6 +- src/bun.js/node/node_assert_binding.zig | 4 +- src/bun.js/node/node_crypto_binding.zig | 2 +- src/bun.js/node/node_fs.zig | 53 +++++------- src/bun.js/node/node_fs_binding.zig | 2 +- src/bun.js/node/node_os.zig | 16 ++-- src/bun.js/node/node_process.zig | 6 +- src/bun.js/node/util/parse_args.zig | 10 +-- src/bun.js/test/expect.zig | 2 +- src/bun.js/webcore/blob/Store.zig | 3 +- src/bundler/bundle_v2.zig | 4 +- src/cli/pack_command.zig | 2 +- src/crash_handler.zig | 2 +- src/css/values/color_js.zig | 4 +- src/deps/c_ares.zig | 85 +++++++++---------- src/deps/uws.zig | 4 +- src/dns.zig | 13 ++- src/ini.zig | 4 +- src/js/node/http2.ts | 8 +- src/js/node/net.ts | 9 +- src/js/node/tls.ts | 2 +- src/js_ast.zig | 3 +- src/logger.zig | 6 +- src/napi/napi.zig | 4 +- src/resolver/resolver.zig | 2 +- src/s3/list_objects.zig | 6 +- src/sql/postgres.zig | 4 +- src/string.zig | 5 +- src/valkey/valkey_protocol.zig | 6 +- 72 files changed, 341 insertions(+), 329 deletions(-) diff --git a/src/bake/DevServer.zig b/src/bake/DevServer.zig index 60606afde6..d5457488c4 100644 --- a/src/bake/DevServer.zig +++ b/src/bake/DevServer.zig @@ -1303,7 +1303,7 @@ fn ensureRouteIsBundled( kind: DeferredRequest.Handler.Kind, req: *Request, resp: AnyResponse, -) bun.OOM!void { +) bun.JSError!void { assert(dev.magic == .valid); assert(dev.server != null); sw: switch (dev.routeBundlePtr(route_bundle_index).server_state) { @@ -1416,7 +1416,7 @@ fn ensureRouteIsBundled( ); }, .loaded => switch (kind) { - .server_handler => dev.onFrameworkRequestWithBundle(route_bundle_index, .{ .stack = req }, resp), + .server_handler => try dev.onFrameworkRequestWithBundle(route_bundle_index, .{ .stack = req }, resp), .bundled_html_page => dev.onHtmlRequestWithBundle(route_bundle_index, resp, bun.http.Method.which(req.method()) orelse .POST), }, } @@ -1525,7 +1525,7 @@ fn onFrameworkRequestWithBundle( route_bundle_index: RouteBundle.Index, req: bun.JSC.API.SavedRequest.Union, resp: AnyResponse, -) void { +) bun.JSError!void { const route_bundle = dev.routeBundlePtr(route_bundle_index); assert(route_bundle.data == .framework); const bundle = &route_bundle.data.framework; @@ -1559,7 +1559,7 @@ fn onFrameworkRequestWithBundle( if (route.file_layout != .none) n += 1; route = dev.router.routePtr(route.parent.unwrap() orelse break); } - const arr = JSValue.createEmptyArray(global, n); + const arr = try JSValue.createEmptyArray(global, n); route = dev.router.routePtr(bundle.route_index); var route_name = bun.String.createUTF8(dev.relativePath(keys[fromOpaqueFileId(.server, route.file_page.unwrap().?).get()])); arr.putIndex(global, 0, route_name.transferToJS(global)); @@ -2123,7 +2123,7 @@ fn generateClientBundle(dev: *DevServer, route_bundle: *RouteBundle) bun.OOM![]u return client_bundle; } -fn generateCssJSArray(dev: *DevServer, route_bundle: *RouteBundle) bun.OOM!JSC.JSValue { +fn generateCssJSArray(dev: *DevServer, route_bundle: *RouteBundle) bun.JSError!JSC.JSValue { assert(route_bundle.data == .framework); // a JSC.JSValue has no purpose, and therefore isn't implemented. if (Environment.allow_assert) assert(!route_bundle.data.framework.cached_css_file_array.has()); assert(route_bundle.server_state == .loaded); // page is unfit to load @@ -2143,7 +2143,7 @@ fn generateCssJSArray(dev: *DevServer, route_bundle: *RouteBundle) bun.OOM!JSC.J try dev.traceAllRouteImports(route_bundle, >s, .find_css); const names = dev.client_graph.current_css_files.items; - const arr = JSC.JSArray.createEmpty(dev.vm.global, names.len); + const arr = try JSC.JSArray.createEmpty(dev.vm.global, names.len); for (names, 0..) |item, i| { var buf: [asset_prefix.len + @sizeOf(u64) * 2 + "/.css".len]u8 = undefined; const path = std.fmt.bufPrint(&buf, asset_prefix ++ "/{s}.css", .{ @@ -2187,9 +2187,9 @@ fn traceAllRouteImports(dev: *DevServer, route_bundle: *RouteBundle, gts: *Graph } } -fn makeArrayForServerComponentsPatch(dev: *DevServer, global: *JSC.JSGlobalObject, items: []const IncrementalGraph(.server).FileIndex) JSValue { +fn makeArrayForServerComponentsPatch(dev: *DevServer, global: *JSC.JSGlobalObject, items: []const IncrementalGraph(.server).FileIndex) bun.JSError!JSValue { if (items.len == 0) return .null; - const arr = JSC.JSArray.createEmpty(global, items.len); + const arr = try JSC.JSArray.createEmpty(global, items.len); const names = dev.server_graph.bundled_files.keys(); for (items, 0..) |item, i| { const str = bun.String.createUTF8(dev.relativePath(names[item.get()])); @@ -2248,7 +2248,7 @@ pub fn finalizeBundle( dev: *DevServer, bv2: *bun.bundle_v2.BundleV2, result: *const bun.bundle_v2.DevServerOutput, -) bun.OOM!void { +) bun.JSError!void { assert(dev.magic == .valid); var had_sent_hmr_event = false; defer { @@ -2539,8 +2539,8 @@ pub fn finalizeBundle( dev.vm.global.toJSValue(), &.{ server_modules, - dev.makeArrayForServerComponentsPatch(dev.vm.global, dev.incremental_result.client_components_added.items), - dev.makeArrayForServerComponentsPatch(dev.vm.global, dev.incremental_result.client_components_removed.items), + try dev.makeArrayForServerComponentsPatch(dev.vm.global, dev.incremental_result.client_components_added.items), + try dev.makeArrayForServerComponentsPatch(dev.vm.global, dev.incremental_result.client_components_removed.items), }, ) catch |err| { // One module replacement error should NOT prevent follow-up @@ -2902,7 +2902,7 @@ pub fn finalizeBundle( switch (req.handler) { .aborted => continue, - .server_handler => |saved| dev.onFrameworkRequestWithBundle(req.route_bundle_index, .{ .saved = saved }, saved.response), + .server_handler => |saved| try dev.onFrameworkRequestWithBundle(req.route_bundle_index, .{ .saved = saved }, saved.response), .bundled_html_page => |ram| dev.onHtmlRequestWithBundle(req.route_bundle_index, ram.response, ram.method), } } diff --git a/src/bake/FrameworkRouter.zig b/src/bake/FrameworkRouter.zig index 7b6b71b8ca..a342db0317 100644 --- a/src/bake/FrameworkRouter.zig +++ b/src/bake/FrameworkRouter.zig @@ -1094,14 +1094,14 @@ pub const JSFrameworkRouter = struct { const validators = bun.JSC.Node.validators; - pub fn getBindings(global: *JSC.JSGlobalObject) JSC.JSValue { - return JSC.JSObject.create(.{ + pub fn getBindings(global: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { + return (try JSC.JSObject.create(.{ .parseRoutePattern = global.createHostFunction("parseRoutePattern", parseRoutePattern, 1), .FrameworkRouter = js.getConstructor(global), - }, global).toJS(); + }, global)).toJS(); } - pub fn constructor(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) !*JSFrameworkRouter { + pub fn constructor(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!*JSFrameworkRouter { const opts = callframe.argumentsAsArray(1)[0]; if (!opts.isObject()) return global.throwInvalidArguments("FrameworkRouter needs an object as it's first argument", .{}); @@ -1144,7 +1144,7 @@ pub const JSFrameworkRouter = struct { InsertionContext.wrap(JSFrameworkRouter, jsfr), ); if (jsfr.stored_parse_errors.items.len > 0) { - const arr = JSValue.createEmptyArray(global, jsfr.stored_parse_errors.items.len); + const arr = try JSValue.createEmptyArray(global, jsfr.stored_parse_errors.items.len); for (jsfr.stored_parse_errors.items, 0..) |*item, i| { arr.putIndex( global, @@ -1176,7 +1176,7 @@ pub const JSFrameworkRouter = struct { var sfb = std.heap.stackFallback(4096, bun.default_allocator); const alloc = sfb.get(); - return JSC.JSObject.create(.{ + return (try JSC.JSObject.create(.{ .params = if (params_out.params.len > 0) params: { const obj = JSValue.createEmptyObject(global, params_out.params.len); for (params_out.params.slice()) |param| { @@ -1187,7 +1187,7 @@ pub const JSFrameworkRouter = struct { break :params obj; } else .null, .route = try jsfr.routeToJsonInverse(global, index, alloc), - }, global).toJS(); + }, global)).toJS(); } return .null; @@ -1204,7 +1204,7 @@ pub const JSFrameworkRouter = struct { fn routeToJson(jsfr: *JSFrameworkRouter, global: *JSGlobalObject, route_index: Route.Index, allocator: Allocator) !JSValue { const route = jsfr.router.routePtr(route_index); - return JSC.JSObject.create(.{ + return (try JSC.JSObject.create(.{ .part = try partToJS(global, route.part, allocator), .page = jsfr.fileIdToJS(global, route.file_page), .layout = jsfr.fileIdToJS(global, route.file_layout), @@ -1214,7 +1214,7 @@ pub const JSFrameworkRouter = struct { var next = route.first_child.unwrap(); while (next) |r| : (next = jsfr.router.routePtr(r).next_sibling.unwrap()) len += 1; - const arr = JSValue.createEmptyArray(global, len); + const arr = try JSValue.createEmptyArray(global, len); next = route.first_child.unwrap(); var i: u32 = 0; while (next) |r| : (next = jsfr.router.routePtr(r).next_sibling.unwrap()) { @@ -1223,12 +1223,12 @@ pub const JSFrameworkRouter = struct { } break :brk arr; }, - }, global).toJS(); + }, global)).toJS(); } fn routeToJsonInverse(jsfr: *JSFrameworkRouter, global: *JSGlobalObject, route_index: Route.Index, allocator: Allocator) !JSValue { const route = jsfr.router.routePtr(route_index); - return JSC.JSObject.create(.{ + return (try JSC.JSObject.create(.{ .part = try partToJS(global, route.part, allocator), .page = jsfr.fileIdToJS(global, route.file_page), .layout = jsfr.fileIdToJS(global, route.file_layout), @@ -1237,7 +1237,7 @@ pub const JSFrameworkRouter = struct { try routeToJsonInverse(jsfr, global, parent, allocator) else .null, - }, global).toJS(); + }, global)).toJS(); } pub fn finalize(this: *JSFrameworkRouter) void { diff --git a/src/bake/production.zig b/src/bake/production.zig index 9828812d1f..5d3d3e569c 100644 --- a/src/bake/production.zig +++ b/src/bake/production.zig @@ -356,9 +356,9 @@ pub fn buildWithVm(ctx: bun.CLI.Command.Context, cwd: []const u8, vm: *VirtualMa pt.attach(); // Static site generator - const server_render_funcs = JSValue.createEmptyArray(global, router.types.len); - const server_param_funcs = JSValue.createEmptyArray(global, router.types.len); - const client_entry_urls = JSValue.createEmptyArray(global, router.types.len); + const server_render_funcs = try JSValue.createEmptyArray(global, router.types.len); + const server_param_funcs = try JSValue.createEmptyArray(global, router.types.len); + const client_entry_urls = try JSValue.createEmptyArray(global, router.types.len); for (router.types, 0..) |router_type, i| { if (router_type.client_file.unwrap()) |client_file| { @@ -421,12 +421,12 @@ pub fn buildWithVm(ctx: bun.CLI.Command.Context, cwd: []const u8, vm: *VirtualMa str.* = (try bun.String.createFormat("{s}{s}", .{ public_path, output_file.dest_path })).toJS(global); } - const route_patterns = JSValue.createEmptyArray(global, navigatable_routes.items.len); - const route_nested_files = JSValue.createEmptyArray(global, navigatable_routes.items.len); - const route_type_and_flags = JSValue.createEmptyArray(global, navigatable_routes.items.len); - const route_source_files = JSValue.createEmptyArray(global, navigatable_routes.items.len); - const route_param_info = JSValue.createEmptyArray(global, navigatable_routes.items.len); - const route_style_references = JSValue.createEmptyArray(global, navigatable_routes.items.len); + const route_patterns = try JSValue.createEmptyArray(global, navigatable_routes.items.len); + const route_nested_files = try JSValue.createEmptyArray(global, navigatable_routes.items.len); + const route_type_and_flags = try JSValue.createEmptyArray(global, navigatable_routes.items.len); + const route_source_files = try JSValue.createEmptyArray(global, navigatable_routes.items.len); + const route_param_info = try JSValue.createEmptyArray(global, navigatable_routes.items.len); + const route_style_references = try JSValue.createEmptyArray(global, navigatable_routes.items.len); var params_buf: std.ArrayListUnmanaged([]const u8) = .{}; for (navigatable_routes.items, 0..) |route_index, nav_index| { @@ -476,8 +476,8 @@ pub fn buildWithVm(ctx: bun.CLI.Command.Context, cwd: []const u8, vm: *VirtualMa } // Fill styles and file_list - const styles = JSValue.createEmptyArray(global, css_chunks_count); - const file_list = JSValue.createEmptyArray(global, file_count); + const styles = try JSValue.createEmptyArray(global, css_chunks_count); + const file_list = try JSValue.createEmptyArray(global, file_count); next = route.parent.unwrap(); file_count = 1; @@ -523,7 +523,7 @@ pub fn buildWithVm(ctx: bun.CLI.Command.Context, cwd: []const u8, vm: *VirtualMa }))); if (params_buf.items.len > 0) { - const param_info_array = JSValue.createEmptyArray(global, params_buf.items.len); + const param_info_array = try JSValue.createEmptyArray(global, params_buf.items.len); for (params_buf.items, 0..) |param, i| { param_info_array.putIndex(global, @intCast(params_buf.items.len - i - 1), bun.String.createUTF8ForJS(global, param)); } @@ -766,10 +766,10 @@ pub const PerThread = struct { /// After initializing, call `attach` pub fn init(vm: *VirtualMachine, opts: Options) !PerThread { - const loaded_files = try bun.bit_set.AutoBitSet.initEmpty(vm.allocator, opts.output_indexes.len); + var loaded_files = try bun.bit_set.AutoBitSet.initEmpty(vm.allocator, opts.output_indexes.len); errdefer loaded_files.deinit(vm.allocator); - const all_server_files = JSValue.createEmptyArray(vm.global, opts.output_indexes.len); + const all_server_files = try JSValue.createEmptyArray(vm.global, opts.output_indexes.len); all_server_files.protect(); return .{ diff --git a/src/bun.js/BuildMessage.zig b/src/bun.js/BuildMessage.zig index 85097271c0..fcc14d0f55 100644 --- a/src/bun.js/BuildMessage.zig +++ b/src/bun.js/BuildMessage.zig @@ -26,7 +26,7 @@ pub const BuildMessage = struct { pub fn getNotes(this: *BuildMessage, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { const notes = this.msg.notes; - const array = JSC.JSValue.createEmptyArray(globalThis, notes.len); + const array = try JSC.JSValue.createEmptyArray(globalThis, notes.len); for (notes, 0..) |note, i| { const cloned = try note.clone(bun.default_allocator); array.putIndex( diff --git a/src/bun.js/Counters.zig b/src/bun.js/Counters.zig index ca85c58d57..9d3d187b4f 100644 --- a/src/bun.js/Counters.zig +++ b/src/bun.js/Counters.zig @@ -5,9 +5,8 @@ pub fn mark(this: *Counters, comptime tag: Field) void { @field(this, @tagName(tag)) +|= 1; } -pub fn toJS(this: *const Counters, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - const obj = JSC.JSObject.create(this.*, globalObject); - return obj.toJS(); +pub fn toJS(this: *const Counters, globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { + return (try JSC.JSObject.create(this.*, globalObject)).toJS(); } pub fn createCountersObject(globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSC.JSValue { diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 451dc92e43..dc8ee6f85b 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -95,7 +95,7 @@ pub const BunObject = struct { fn toJSGetter(comptime getter: anytype) LazyPropertyCallback { return struct { pub fn callback(this: *JSC.JSGlobalObject, object: *JSC.JSObject) callconv(JSC.conv) JSValue { - return @call(.always_inline, getter, .{ this, object }); + return bun.jsc.toJSHostValue(this, getter(this, object)); } }.callback; } @@ -1303,9 +1303,9 @@ pub fn getValkeyClientConstructor(globalThis: *JSC.JSGlobalObject, _: *JSC.JSObj return JSC.API.Valkey.js.getConstructor(globalThis); } -pub fn getEmbeddedFiles(globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject) JSC.JSValue { +pub fn getEmbeddedFiles(globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject) bun.JSError!JSC.JSValue { const vm = globalThis.bunVM(); - const graph = vm.standalone_module_graph orelse return JSC.JSValue.createEmptyArray(globalThis, 0); + const graph = vm.standalone_module_graph orelse return try JSC.JSValue.createEmptyArray(globalThis, 0); const unsorted_files = graph.files.values(); var sort_indices = std.ArrayList(u32).initCapacity(bun.default_allocator, unsorted_files.len) catch bun.outOfMemory(); @@ -1320,7 +1320,7 @@ pub fn getEmbeddedFiles(globalThis: *JSC.JSGlobalObject, _: *JSC.JSObject) JSC.J } var i: u32 = 0; - var array = JSC.JSValue.createEmptyArray(globalThis, sort_indices.items.len); + var array = try JSC.JSValue.createEmptyArray(globalThis, sort_indices.items.len); std.mem.sort(u32, sort_indices.items, unsorted_files, bun.StandaloneModuleGraph.File.lessThanByIndex); for (sort_indices.items) |index| { const file = &unsorted_files[index]; diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 98c8f47fbe..d7f2ac4cb4 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -852,12 +852,12 @@ pub fn scan(this: *JSTranspiler, globalThis: *JSC.JSGlobalObject, callframe: *JS const exports_label = JSC.ZigString.static("exports"); const imports_label = JSC.ZigString.static("imports"); - const named_imports_value = namedImportsToJS( + const named_imports_value = try namedImportsToJS( globalThis, parse_result.ast.import_records.slice(), ); - const named_exports_value = namedExportsToJS( + const named_exports_value = try namedExportsToJS( globalThis, &parse_result.ast.named_exports, ); @@ -1027,7 +1027,7 @@ pub fn transformSync( return out.toJS(globalThis); } -fn namedExportsToJS(global: *JSGlobalObject, named_exports: *JSAst.Ast.NamedExports) JSC.JSValue { +fn namedExportsToJS(global: *JSGlobalObject, named_exports: *JSAst.Ast.NamedExports) bun.JSError!JSC.JSValue { if (named_exports.count() == 0) return JSValue.createEmptyArray(global, 0); @@ -1052,14 +1052,11 @@ fn namedExportsToJS(global: *JSGlobalObject, named_exports: *JSAst.Ast.NamedExpo const ImportRecord = @import("../../import_record.zig").ImportRecord; -fn namedImportsToJS( - global: *JSGlobalObject, - import_records: []const ImportRecord, -) JSC.JSValue { +fn namedImportsToJS(global: *JSGlobalObject, import_records: []const ImportRecord) bun.JSError!JSC.JSValue { const path_label = JSC.ZigString.static("path"); const kind_label = JSC.ZigString.static("kind"); - const array = JSC.JSValue.createEmptyArray(global, import_records.len); + const array = try JSC.JSValue.createEmptyArray(global, import_records.len); array.ensureStillAlive(); for (import_records, 0..) |record, i| { @@ -1157,7 +1154,7 @@ pub fn scanImports(this: *JSTranspiler, globalThis: *JSC.JSGlobalObject, callfra return globalThis.throwValue(try log.toJS(globalThis, globalThis.allocator(), "Failed to scan imports")); } - const named_imports_value = namedImportsToJS( + const named_imports_value = try namedImportsToJS( globalThis, this.scan_pass_result.import_records.items, ); diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig index 3a2761c636..0f65a9d69e 100644 --- a/src/bun.js/api/bun/dns_resolver.zig +++ b/src/bun.js/api/bun/dns_resolver.zig @@ -526,7 +526,7 @@ pub const CAresNameInfo = struct { return; } var name_info = result.?; - const array = name_info.toJSResponse(this.globalThis.allocator(), this.globalThis); + const array = name_info.toJSResponse(this.globalThis.allocator(), this.globalThis) catch .zero; // TODO: properly propagate exception upwards this.onComplete(array); return; } @@ -942,7 +942,7 @@ pub const CAresReverse = struct { return; } var node = result.?; - const array = node.toJSResponse(this.globalThis.allocator(), this.globalThis, ""); + const array = node.toJSResponse(this.globalThis.allocator(), this.globalThis, "") catch .zero; // TODO: properly propagate exception upwards this.onComplete(array); return; } @@ -1023,7 +1023,7 @@ pub fn CAresLookup(comptime cares_type: type, comptime type_name: []const u8) ty } var node = result.?; - const array = node.toJSResponse(this.globalThis.allocator(), this.globalThis, type_name); + const array = node.toJSResponse(this.globalThis.allocator(), this.globalThis, type_name) catch .zero; // TODO: properly propagate exception upwards this.onComplete(array); return; } @@ -1084,7 +1084,7 @@ pub const DNSLookup = struct { pub fn onCompleteNative(this: *DNSLookup, result: GetAddrInfo.Result.Any) void { log("onCompleteNative", .{}); - const array = result.toJS(this.globalThis).?; + const array = (result.toJS(this.globalThis) catch .zero).?; // TODO: properly propagate exception upwards this.onCompleteWithArray(array); } @@ -1117,7 +1117,7 @@ pub const DNSLookup = struct { pub fn onComplete(this: *DNSLookup, result: *c_ares.AddrInfo) void { log("onComplete", .{}); - const array = result.toJSArray(this.globalThis); + const array = result.toJSArray(this.globalThis) catch .zero; // TODO: properly propagate exception upwards this.onCompleteWithArray(array); } @@ -2012,7 +2012,7 @@ pub const DNSResolver = struct { const key = this.getKey(index, cache_name, request_type); - var addr = result orelse { + var addr: *cares_type = result orelse { var pending: ?*CAresLookup(cares_type, lookup_name) = key.lookup.head.next; key.lookup.head.processResolve(err, timeout, null); bun.default_allocator.destroy(key.lookup); @@ -2026,7 +2026,7 @@ pub const DNSResolver = struct { var pending: ?*CAresLookup(cares_type, lookup_name) = key.lookup.head.next; var prev_global = key.lookup.head.globalThis; - var array = addr.toJSResponse(this.vm.allocator, prev_global, lookup_name); + var array = addr.toJSResponse(this.vm.allocator, prev_global, lookup_name) catch .zero; // TODO: properly propagate exception upwards defer addr.deinit(); array.ensureStillAlive(); key.lookup.head.onComplete(array); @@ -2037,7 +2037,7 @@ pub const DNSResolver = struct { while (pending) |value| { const new_global = value.globalThis; if (prev_global != new_global) { - array = addr.toJSResponse(this.vm.allocator, new_global, lookup_name); + array = addr.toJSResponse(this.vm.allocator, new_global, lookup_name) catch .zero; // TODO: properly propagate exception upwards prev_global = new_global; } pending = value.next; @@ -2070,7 +2070,7 @@ pub const DNSResolver = struct { var pending: ?*DNSLookup = key.lookup.head.next; var prev_global = key.lookup.head.globalThis; - var array = addr.toJSArray(prev_global); + var array = addr.toJSArray(prev_global) catch .zero; // TODO: properly propagate exception upwards defer addr.deinit(); array.ensureStillAlive(); key.lookup.head.onCompleteWithArray(array); @@ -2082,7 +2082,7 @@ pub const DNSResolver = struct { while (pending) |value| { const new_global = value.globalThis; if (prev_global != new_global) { - array = addr.toJSArray(new_global); + array = addr.toJSArray(new_global) catch .zero; // TODO: properly propagate exception upwards prev_global = new_global; } pending = value.next; @@ -2102,7 +2102,7 @@ pub const DNSResolver = struct { this.ref(); defer this.deref(); - var array = result.toJS(globalObject) orelse { + var array = (result.toJS(globalObject) catch .zero) orelse { // TODO: properly propagate exception upwards var pending: ?*DNSLookup = key.lookup.head.next; var head = key.lookup.head; head.processGetAddrInfoNative(err, null); @@ -2131,7 +2131,7 @@ pub const DNSResolver = struct { const new_global = value.globalThis; pending = value.next; if (prev_global != new_global) { - array = result.toJS(new_global).?; + array = (result.toJS(new_global) catch .zero).?; // TODO: properly propagate exception upwards prev_global = new_global; } @@ -2166,7 +2166,7 @@ pub const DNSResolver = struct { // The callback need not and should not attempt to free the memory // pointed to by hostent; the ares library will free it when the // callback returns. - var array = addr.toJSResponse(this.vm.allocator, prev_global, ""); + var array = addr.toJSResponse(this.vm.allocator, prev_global, "") catch .zero; // TODO: properly propagate exception upwards array.ensureStillAlive(); key.lookup.head.onComplete(array); bun.default_allocator.destroy(key.lookup); @@ -2176,7 +2176,7 @@ pub const DNSResolver = struct { while (pending) |value| { const new_global = value.globalThis; if (prev_global != new_global) { - array = addr.toJSResponse(this.vm.allocator, new_global, ""); + array = addr.toJSResponse(this.vm.allocator, new_global, "") catch .zero; // TODO: properly propagate exception upwards prev_global = new_global; } pending = value.next; @@ -2210,7 +2210,7 @@ pub const DNSResolver = struct { var pending: ?*CAresNameInfo = key.lookup.head.next; var prev_global = key.lookup.head.globalThis; - var array = name_info.toJSResponse(this.vm.allocator, prev_global); + var array = name_info.toJSResponse(this.vm.allocator, prev_global) catch .zero; // TODO: properly propagate exception upwards array.ensureStillAlive(); key.lookup.head.onComplete(array); bun.default_allocator.destroy(key.lookup); @@ -2220,7 +2220,7 @@ pub const DNSResolver = struct { while (pending) |value| { const new_global = value.globalThis; if (prev_global != new_global) { - array = name_info.toJSResponse(this.vm.allocator, new_global); + array = name_info.toJSResponse(this.vm.allocator, new_global) catch .zero; // TODO: properly propagate exception upwards prev_global = new_global; } pending = value.next; @@ -3088,7 +3088,7 @@ pub const DNSResolver = struct { } defer c_ares.ares_free_data(servers); - const values = JSC.JSValue.createEmptyArray(globalThis, 0); + const values = try JSC.JSValue.createEmptyArray(globalThis, 0); var i: u32 = 0; var cur = servers; diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index 408c2c6072..32d2d90d74 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -290,7 +290,7 @@ const SingleValueHeaders = bun.ComptimeStringMap(void, .{ .{"x-content-type-options"}, }); -fn jsGetUnpackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { +pub fn jsGetUnpackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); var settings: FullSettingsPayload = .{}; @@ -323,7 +323,7 @@ fn jsGetUnpackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.Call } } -fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { +pub fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { const args_list = callframe.arguments_old(1); if (args_list.len < 1) { return globalObject.throw("Expected settings to be a object", .{}); @@ -410,7 +410,7 @@ fn jsAssertSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame return .undefined; } -fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { +pub fn jsGetPackedSettings(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { var settings: FullSettingsPayload = .{}; const args_list = callframe.arguments_old(1); @@ -646,6 +646,8 @@ const Handlers = struct { } }; +pub const H2FrameParserConstructor = H2FrameParser.js.getConstructor; + pub const H2FrameParser = struct { pub const log = Output.scoped(.H2FrameParser, false); const Self = @This(); @@ -1774,14 +1776,14 @@ pub const H2FrameParser = struct { return data.len; } - pub fn decodeHeaderBlock(this: *H2FrameParser, payload: []const u8, stream: *Stream, flags: u8) ?*Stream { + pub fn decodeHeaderBlock(this: *H2FrameParser, payload: []const u8, stream: *Stream, flags: u8) bun.JSError!?*Stream { log("decodeHeaderBlock isSever: {}", .{this.isServer}); var offset: usize = 0; const globalObject = this.handlers.globalObject; const stream_id = stream.id; - const headers = JSC.JSValue.createEmptyArray(globalObject, 0); + const headers = try JSC.JSValue.createEmptyArray(globalObject, 0); headers.ensureStillAlive(); var sensitiveHeaders = JSC.JSValue.jsUndefined(); @@ -1817,7 +1819,7 @@ pub const H2FrameParser = struct { headers.push(globalObject, js_header_value); if (header.never_index) { if (sensitiveHeaders.isUndefined()) { - sensitiveHeaders = JSC.JSValue.createEmptyArray(globalObject, 0); + sensitiveHeaders = try JSC.JSValue.createEmptyArray(globalObject, 0); sensitiveHeaders.ensureStillAlive(); } sensitiveHeaders.push(globalObject, js_header_name); @@ -1836,7 +1838,7 @@ pub const H2FrameParser = struct { if (header.never_index) { if (sensitiveHeaders.isUndefined()) { - sensitiveHeaders = JSC.JSValue.createEmptyArray(globalObject, 0); + sensitiveHeaders = try JSC.JSValue.createEmptyArray(globalObject, 0); sensitiveHeaders.ensureStillAlive(); } sensitiveHeaders.push(globalObject, js_header_name); @@ -1960,7 +1962,7 @@ pub const H2FrameParser = struct { return bun.String.createUTF8ForJS(this.handlers.globalObject, payload); } - pub fn handleOriginFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, _: ?*Stream) usize { + pub fn handleOriginFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, _: ?*Stream) bun.JSError!usize { log("handleOriginFrame {s}", .{data}); if (this.isServer) { this.sendGoAway(frame.streamIdentifier, ErrorCode.PROTOCOL_ERROR, "ORIGIN frame on server", this.lastStreamID, true); @@ -1995,7 +1997,7 @@ pub const H2FrameParser = struct { originValue.ensureStillAlive(); } else if (count == 1) { // need to create an array - const array = JSC.JSValue.createEmptyArray(this.handlers.globalObject, 0); + const array = try JSC.JSValue.createEmptyArray(this.handlers.globalObject, 0); array.ensureStillAlive(); array.push(this.handlers.globalObject, originValue); array.push(this.handlers.globalObject, this.stringOrEmptyToJS(origin_str)); @@ -2141,7 +2143,7 @@ pub const H2FrameParser = struct { } return data.len; } - pub fn handleContinuationFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, stream_: ?*Stream) usize { + pub fn handleContinuationFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, stream_: ?*Stream) bun.JSError!usize { log("handleContinuationFrame", .{}); var stream = stream_ orelse { this.sendGoAway(frame.streamIdentifier, ErrorCode.PROTOCOL_ERROR, "Continuation on connection stream", this.lastStreamID, true); @@ -2156,7 +2158,7 @@ pub const H2FrameParser = struct { const payload = content.data; this.readBuffer.reset(); stream.endAfterHeaders = frame.flags & @intFromEnum(HeadersFrameFlags.END_STREAM) != 0; - stream = this.decodeHeaderBlock(payload[0..payload.len], stream, frame.flags) orelse { + stream = (try this.decodeHeaderBlock(payload[0..payload.len], stream, frame.flags)) orelse { return content.end; }; if (stream.endAfterHeaders) { @@ -2182,7 +2184,7 @@ pub const H2FrameParser = struct { return data.len; } - pub fn handleHeadersFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, stream_: ?*Stream) usize { + pub fn handleHeadersFrame(this: *H2FrameParser, frame: FrameHeader, data: []const u8, stream_: ?*Stream) bun.JSError!usize { log("handleHeadersFrame {s}", .{if (this.isServer) "server" else "client"}); var stream = stream_ orelse { this.sendGoAway(frame.streamIdentifier, ErrorCode.PROTOCOL_ERROR, "Headers frame on connection stream", this.lastStreamID, true); @@ -2221,7 +2223,7 @@ pub const H2FrameParser = struct { return content.end; } stream.endAfterHeaders = frame.flags & @intFromEnum(HeadersFrameFlags.END_STREAM) != 0; - stream = this.decodeHeaderBlock(payload[offset..end], stream, frame.flags) orelse { + stream = (try this.decodeHeaderBlock(payload[offset..end], stream, frame.flags)) orelse { return content.end; }; stream.isWaitingMoreHeaders = frame.flags & @intFromEnum(HeadersFrameFlags.END_HEADERS) == 0; @@ -2330,7 +2332,7 @@ pub const H2FrameParser = struct { return entry.value_ptr; } - fn readBytes(this: *H2FrameParser, bytes: []const u8) usize { + fn readBytes(this: *H2FrameParser, bytes: []const u8) bun.JSError!usize { log("read {}", .{bytes.len}); if (this.isServer and this.prefaceReceivedLen < 24) { // Handle Server Preface @@ -2403,15 +2405,15 @@ pub const H2FrameParser = struct { return switch (header.type) { @intFromEnum(FrameType.HTTP_FRAME_SETTINGS) => this.handleSettingsFrame(header, bytes[needed..]) + needed, @intFromEnum(FrameType.HTTP_FRAME_WINDOW_UPDATE) => this.handleWindowUpdateFrame(header, bytes[needed..], stream) + needed, - @intFromEnum(FrameType.HTTP_FRAME_HEADERS) => this.handleHeadersFrame(header, bytes[needed..], stream) + needed, + @intFromEnum(FrameType.HTTP_FRAME_HEADERS) => (try this.handleHeadersFrame(header, bytes[needed..], stream)) + needed, @intFromEnum(FrameType.HTTP_FRAME_DATA) => this.handleDataFrame(header, bytes[needed..], stream) + needed, - @intFromEnum(FrameType.HTTP_FRAME_CONTINUATION) => this.handleContinuationFrame(header, bytes[needed..], stream) + needed, + @intFromEnum(FrameType.HTTP_FRAME_CONTINUATION) => (try this.handleContinuationFrame(header, bytes[needed..], stream)) + needed, @intFromEnum(FrameType.HTTP_FRAME_PRIORITY) => this.handlePriorityFrame(header, bytes[needed..], stream) + needed, @intFromEnum(FrameType.HTTP_FRAME_PING) => this.handlePingFrame(header, bytes[needed..], stream) + needed, @intFromEnum(FrameType.HTTP_FRAME_GOAWAY) => this.handleGoAwayFrame(header, bytes[needed..], stream) + needed, @intFromEnum(FrameType.HTTP_FRAME_RST_STREAM) => this.handleRSTStreamFrame(header, bytes[needed..], stream) + needed, @intFromEnum(FrameType.HTTP_FRAME_ALTSVC) => this.handleAltsvcFrame(header, bytes[needed..], stream) + needed, - @intFromEnum(FrameType.HTTP_FRAME_ORIGIN) => this.handleOriginFrame(header, bytes[needed..], stream) + needed, + @intFromEnum(FrameType.HTTP_FRAME_ORIGIN) => (try this.handleOriginFrame(header, bytes[needed..], stream)) + needed, else => { this.sendGoAway(header.streamIdentifier, ErrorCode.PROTOCOL_ERROR, "Unknown frame type", this.lastStreamID, true); return bytes.len; @@ -2439,15 +2441,15 @@ pub const H2FrameParser = struct { return switch (header.type) { @intFromEnum(FrameType.HTTP_FRAME_SETTINGS) => this.handleSettingsFrame(header, bytes[FrameHeader.byteSize..]) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_WINDOW_UPDATE) => this.handleWindowUpdateFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, - @intFromEnum(FrameType.HTTP_FRAME_HEADERS) => this.handleHeadersFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, + @intFromEnum(FrameType.HTTP_FRAME_HEADERS) => (try this.handleHeadersFrame(header, bytes[FrameHeader.byteSize..], stream)) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_DATA) => this.handleDataFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, - @intFromEnum(FrameType.HTTP_FRAME_CONTINUATION) => this.handleContinuationFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, + @intFromEnum(FrameType.HTTP_FRAME_CONTINUATION) => (try this.handleContinuationFrame(header, bytes[FrameHeader.byteSize..], stream)) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_PRIORITY) => this.handlePriorityFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_PING) => this.handlePingFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_GOAWAY) => this.handleGoAwayFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_RST_STREAM) => this.handleRSTStreamFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, @intFromEnum(FrameType.HTTP_FRAME_ALTSVC) => this.handleAltsvcFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, - @intFromEnum(FrameType.HTTP_FRAME_ORIGIN) => this.handleOriginFrame(header, bytes[FrameHeader.byteSize..], stream) + FrameHeader.byteSize, + @intFromEnum(FrameType.HTTP_FRAME_ORIGIN) => (try this.handleOriginFrame(header, bytes[FrameHeader.byteSize..], stream)) + FrameHeader.byteSize, else => { this.sendGoAway(header.streamIdentifier, ErrorCode.PROTOCOL_ERROR, "Unknown frame type", this.lastStreamID, true); return bytes.len; @@ -3537,7 +3539,7 @@ pub const H2FrameParser = struct { pub fn getAllStreams(this: *H2FrameParser, globalObject: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); - const array = JSC.JSValue.createEmptyArray(globalObject, this.streams.count()); + const array = try JSC.JSValue.createEmptyArray(globalObject, this.streams.count()); var count: u32 = 0; var it = this.streams.valueIterator(); while (it.next()) |stream| { @@ -4018,7 +4020,7 @@ pub const H2FrameParser = struct { var bytes = array_buffer.byteSlice(); // read all the bytes while (bytes.len > 0) { - const result = this.readBytes(bytes); + const result = try this.readBytes(bytes); bytes = bytes[result..]; } return .undefined; @@ -4026,13 +4028,13 @@ pub const H2FrameParser = struct { return globalObject.throw("Expected data to be a Buffer or ArrayBuffer", .{}); } - pub fn onNativeRead(this: *H2FrameParser, data: []const u8) void { + pub fn onNativeRead(this: *H2FrameParser, data: []const u8) bun.JSError!void { log("onNativeRead", .{}); this.ref(); defer this.deref(); var bytes = data; while (bytes.len > 0) { - const result = this.readBytes(bytes); + const result = try this.readBytes(bytes); bytes = bytes[result..]; } } @@ -4295,12 +4297,3 @@ pub const H2FrameParser = struct { }; extern fn Bun__wrapAbortError(globalObject: *JSC.JSGlobalObject, cause: JSC.JSValue) JSC.JSValue; - -pub fn createNodeHttp2Binding(global: *JSC.JSGlobalObject) JSC.JSValue { - return JSC.JSArray.create(global, &.{ - H2FrameParser.js.getConstructor(global), - JSC.JSFunction.create(global, "assertSettings", jsAssertSettings, 1, .{}), - JSC.JSFunction.create(global, "getPackedSettings", jsGetPackedSettings, 1, .{}), - JSC.JSFunction.create(global, "getUnpackedSettings", jsGetUnpackedSettings, 1, .{}), - }); -} diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index eb627f79b0..af2fb6c7c5 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -1402,7 +1402,7 @@ fn NewSocket(comptime ssl: bool) type { pub fn onData(this: NativeCallbacks, data: []const u8) bool { switch (this) { .h2 => |h2| { - h2.onNativeRead(data); + h2.onNativeRead(data) catch return false; // TODO: properly propagate exception upwards return true; }, .none => return false, @@ -3101,7 +3101,7 @@ fn NewSocket(comptime ssl: bool) type { const nsig = BoringSSL.SSL_get_shared_sigalgs(ssl_ptr, 0, null, null, null, null, null); - const array = JSC.JSValue.createEmptyArray(globalObject, @as(usize, @intCast(nsig))); + const array = try JSC.JSValue.createEmptyArray(globalObject, @as(usize, @intCast(nsig))); for (0..@as(usize, @intCast(nsig))) |i| { var hash_nid: c_int = 0; @@ -3580,7 +3580,7 @@ fn NewSocket(comptime ssl: bool) type { this.has_pending_activity.store(false, .release); } - const array = JSC.JSValue.createEmptyArray(globalObject, 2); + const array = try JSC.JSValue.createEmptyArray(globalObject, 2); array.putIndex(globalObject, 0, raw_js_value); array.putIndex(globalObject, 1, tls_js_value); @@ -4331,10 +4331,10 @@ pub fn jsUpgradeDuplexToTLS(globalObject: *JSC.JSGlobalObject, callframe: *JSC.C duplexContext.startTLS(); - const array = JSC.JSValue.createEmptyArray(globalObject, 2); + const array = try JSC.JSValue.createEmptyArray(globalObject, 2); array.putIndex(globalObject, 0, tls_js_value); // data, end, drain and close events must be reported - array.putIndex(globalObject, 1, duplexContext.upgrade.getJSHandlers(globalObject)); + array.putIndex(globalObject, 1, try duplexContext.upgrade.getJSHandlers(globalObject)); return array; } @@ -4371,15 +4371,6 @@ pub fn jsGetBufferedAmount(global: *JSC.JSGlobalObject, callframe: *JSC.CallFram return JSC.JSValue.jsNumber(0); } -pub fn createNodeTLSBinding(global: *JSC.JSGlobalObject) JSC.JSValue { - return JSC.JSArray.create(global, &.{ - JSC.JSFunction.create(global, "addServerName", jsAddServerName, 3, .{}), - JSC.JSFunction.create(global, "upgradeDuplexToTLS", jsUpgradeDuplexToTLS, 2, .{}), - JSC.JSFunction.create(global, "isNamedPipeSocket", jsIsNamedPipeSocket, 1, .{}), - JSC.JSFunction.create(global, "getBufferedAmount", jsGetBufferedAmount, 1, .{}), - }); -} - pub fn jsCreateSocketPair(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSValue { JSC.markBinding(@src()); @@ -4397,7 +4388,7 @@ pub fn jsCreateSocketPair(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JS _ = bun.FD.fromNative(fds_[0]).updateNonblocking(true); _ = bun.FD.fromNative(fds_[1]).updateNonblocking(true); - const array = JSC.JSValue.createEmptyArray(global, 2); + const array = try JSC.JSValue.createEmptyArray(global, 2); array.putIndex(global, 0, JSC.jsNumber(fds_[0])); array.putIndex(global, 1, JSC.jsNumber(fds_[1])); return array; diff --git a/src/bun.js/api/bun/socket/SocketAddress.zig b/src/bun.js/api/bun/socket/SocketAddress.zig index c9c2249390..5291152eee 100644 --- a/src/bun.js/api/bun/socket/SocketAddress.zig +++ b/src/bun.js/api/bun/socket/SocketAddress.zig @@ -448,12 +448,12 @@ pub fn estimatedSize(this: *SocketAddress) usize { } pub fn toJSON(this: *SocketAddress, global: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSC.JSValue { - return JSC.JSObject.create(.{ + return (try JSC.JSObject.create(.{ .address = this.getAddress(global), .family = this.getFamily(global), .port = this.port(), .flowlabel = this.flowLabel() orelse 0, - }, global).toJS(); + }, global)).toJS(); } fn pton(global: *JSC.JSGlobalObject, comptime af: c_int, addr: [:0]const u8, dst: *anyopaque) bun.JSError!void { diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 523c5ade19..b651b4d52d 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -775,25 +775,16 @@ pub fn pid(this: *const Subprocess) i32 { return @intCast(this.process.pid); } -pub fn getPid( - this: *Subprocess, - _: *JSGlobalObject, -) JSValue { +pub fn getPid(this: *Subprocess, _: *JSGlobalObject) JSValue { return JSValue.jsNumber(this.pid()); } -pub fn getKilled( - this: *Subprocess, - _: *JSGlobalObject, -) JSValue { +pub fn getKilled(this: *Subprocess, _: *JSGlobalObject) JSValue { return JSValue.jsBoolean(this.hasKilled()); } -pub fn getStdio( - this: *Subprocess, - global: *JSGlobalObject, -) JSValue { - const array = JSValue.createEmptyArray(global, 0); +pub fn getStdio(this: *Subprocess, global: *JSGlobalObject) bun.JSError!JSValue { + const array = try JSValue.createEmptyArray(global, 0); array.push(global, .null); array.push(global, .null); // TODO: align this with options array.push(global, .null); // TODO: align this with options diff --git a/src/bun.js/api/crypto/CryptoHasher.zig b/src/bun.js/api/crypto/CryptoHasher.zig index 404c387e69..f7bd57e3ee 100644 --- a/src/bun.js/api/crypto/CryptoHasher.zig +++ b/src/bun.js/api/crypto/CryptoHasher.zig @@ -154,11 +154,7 @@ pub const CryptoHasher = union(enum) { }; } - pub fn getAlgorithms( - globalThis_: *JSC.JSGlobalObject, - _: JSValue, - _: JSValue, - ) JSC.JSValue { + pub fn getAlgorithms(globalThis_: *JSC.JSGlobalObject, _: JSValue, _: JSValue) bun.JSError!JSC.JSValue { return bun.String.toJSArray(globalThis_, &EVP.Algorithm.names.values); } diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index b6d3ddf6bd..6b0f2320dd 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -922,7 +922,7 @@ pub const FFI = struct { return ZigString.init(arraylist.items).toJS(global); } - pub fn print(global: *JSGlobalObject, object: JSC.JSValue, is_callback_val: ?JSC.JSValue) JSValue { + pub fn print(global: *JSGlobalObject, object: JSC.JSValue, is_callback_val: ?JSC.JSValue) bun.JSError!JSValue { const allocator = bun.default_allocator; if (is_callback_val) |is_callback| { if (is_callback.toBoolean()) { @@ -968,7 +968,7 @@ pub const FFI = struct { strs.appendAssumeCapacity(bun.String.createUTF8(arraylist.items)); } - const ret = bun.String.toJSArray(global, strs.items); + const ret = try bun.String.toJSArray(global, strs.items); for (symbols.keys()) |key| { allocator.free(@constCast(key)); diff --git a/src/bun.js/api/glob.zig b/src/bun.js/api/glob.zig index 2ac9fe61bc..151c7c1f54 100644 --- a/src/bun.js/api/glob.zig +++ b/src/bun.js/api/glob.zig @@ -199,7 +199,7 @@ pub const WalkTask = struct { return; } - const jsStrings = globWalkResultToJS(this.walker, this.global); + const jsStrings = globWalkResultToJS(this.walker, this.global) catch return promise.reject(this.global, error.JSError); promise.resolve(this.global, jsStrings); } @@ -209,7 +209,7 @@ pub const WalkTask = struct { } }; -fn globWalkResultToJS(globWalk: *GlobWalker, globalThis: *JSGlobalObject) JSValue { +fn globWalkResultToJS(globWalk: *GlobWalker, globalThis: *JSGlobalObject) bun.JSError!JSValue { if (globWalk.matchedPaths.keys().len == 0) { return JSC.JSValue.createEmptyArray(globalThis, 0); } diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index c252e280e2..805abb8fde 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -1632,7 +1632,7 @@ pub const AttributeIterator = struct { const value = attribute.value(); const name = attribute.name(); - return JSValue.createObject2(globalObject, done_label, value_label, JSValue.jsBoolean(false), bun.String.toJSArray( + return JSValue.createObject2(globalObject, done_label, value_label, JSValue.jsBoolean(false), try bun.String.toJSArray( globalObject, &[_]bun.String{ name.toString(), diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index b47b5380c3..f47f911967 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -5043,10 +5043,10 @@ const ServePlugins = struct { bun.destroy(this); } - pub fn getOrStartLoad(this: *ServePlugins, global: *JSC.JSGlobalObject, cb: Callback) bun.OOM!GetOrStartLoadResult { + pub fn getOrStartLoad(this: *ServePlugins, global: *JSC.JSGlobalObject, cb: Callback) bun.JSError!GetOrStartLoadResult { sw: switch (this.state) { .unqueued => { - this.loadAndResolvePlugins(global); + try this.loadAndResolvePlugins(global); continue :sw this.state; // could jump to any branch if synchronously resolved }, .pending => |*pending| { @@ -5073,7 +5073,7 @@ const ServePlugins = struct { bunfig_folder: JSC.JSValue, ) JSValue; - fn loadAndResolvePlugins(this: *ServePlugins, global: *JSC.JSGlobalObject) void { + fn loadAndResolvePlugins(this: *ServePlugins, global: *JSC.JSGlobalObject) bun.JSError!void { bun.assert(this.state == .unqueued); const plugin_list = this.state.unqueued; const bunfig_folder = bun.path.dirname(global.bunVM().transpiler.options.bunfig_path, .auto); @@ -5089,7 +5089,7 @@ const ServePlugins = struct { for (plugin_list, bunstring_array) |raw_plugin, *out| { out.* = bun.String.init(raw_plugin); } - const plugin_js_array = bun.String.toJSArray(global, bunstring_array); + const plugin_js_array = try bun.String.toJSArray(global, bunstring_array); const bunfig_folder_bunstr = bun.String.createUTF8ForJS(global, bunfig_folder); this.state = .{ .pending = .{ diff --git a/src/bun.js/bindgen_test.zig b/src/bun.js/bindgen_test.zig index 3f3f636d8a..7793c4dae1 100644 --- a/src/bun.js/bindgen_test.zig +++ b/src/bun.js/bindgen_test.zig @@ -1,11 +1,11 @@ //! This namespace is used to test binding generator const gen = bun.gen.bindgen_test; -pub fn getBindgenTestFunctions(global: *JSC.JSGlobalObject) JSC.JSValue { - return JSC.JSObject.create(.{ +pub fn getBindgenTestFunctions(global: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { + return (try JSC.JSObject.create(.{ .add = gen.createAddCallback(global), .requiredAndOptionalArg = gen.createRequiredAndOptionalArgCallback(global), - }, global).toJS(); + }, global)).toJS(); } // This example should be kept in sync with bindgen's documentation diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 8b94e81231..26fd7b78fe 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -2367,6 +2367,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functiongetgroups, (JSGlobalObject * globalObje return {}; } JSArray* groups = constructEmptyArray(globalObject, nullptr, ngroups); + RETURN_IF_EXCEPTION(throwScope, {}); Vector groupVector(ngroups); getgroups(ngroups, groupVector.data()); for (unsigned i = 0; i < ngroups; i++) { diff --git a/src/bun.js/bindings/JSArray.zig b/src/bun.js/bindings/JSArray.zig index 206d52a27e..1f5d23c385 100644 --- a/src/bun.js/bindings/JSArray.zig +++ b/src/bun.js/bindings/JSArray.zig @@ -8,14 +8,14 @@ pub const JSArray = opaque { // TODO(@paperclover): this can throw extern fn JSArray__constructArray(*JSGlobalObject, [*]const JSValue, usize) JSValue; - pub fn create(global: *JSGlobalObject, items: []const JSValue) JSValue { - return JSArray__constructArray(global, items.ptr, items.len); + pub fn create(global: *JSGlobalObject, items: []const JSValue) bun.JSError!JSValue { + return bun.jsc.fromJSHostValue(JSArray__constructArray(global, items.ptr, items.len)); } extern fn JSArray__constructEmptyArray(*JSGlobalObject, usize) JSValue; - pub fn createEmpty(global: *JSGlobalObject, len: usize) JSValue { - return JSArray__constructEmptyArray(global, len); + pub fn createEmpty(global: *JSGlobalObject, len: usize) bun.JSError!JSValue { + return bun.jsc.fromJSHostValue(JSArray__constructEmptyArray(global, len)); } pub fn iterator(array: *JSArray, global: *JSGlobalObject) JSArrayIterator { diff --git a/src/bun.js/bindings/JSCommonJSModule.cpp b/src/bun.js/bindings/JSCommonJSModule.cpp index e376461d9d..0c92ffd957 100644 --- a/src/bun.js/bindings/JSCommonJSModule.cpp +++ b/src/bun.js/bindings/JSCommonJSModule.cpp @@ -560,6 +560,7 @@ JSC_DEFINE_CUSTOM_GETTER(getterChildren, (JSC::JSGlobalObject * globalObject, JS // Construct the array JSArray* array = JSC::constructArray(globalObject, static_cast(nullptr), children); + RETURN_IF_EXCEPTION(throwScope, {}); mod->m_childrenValue.set(globalObject->vm(), mod, array); mod->m_children.clear(); diff --git a/src/bun.js/bindings/JSGlobalObject.zig b/src/bun.js/bindings/JSGlobalObject.zig index 5555d979d6..d747d1f6dc 100644 --- a/src/bun.js/bindings/JSGlobalObject.zig +++ b/src/bun.js/bindings/JSGlobalObject.zig @@ -64,8 +64,8 @@ pub const JSGlobalObject = opaque { return this.ERR(.INVALID_ARG_TYPE, comptime std.fmt.comptimePrint("Expected {s} to be a {s} for '{s}'.", .{ field, typename, name_ }), .{}).toJS(); } - pub fn toJS(this: *JSC.JSGlobalObject, value: anytype, comptime lifetime: JSC.JSValue.FromAnyLifetime) JSC.JSValue { - return .fromAny(this, @TypeOf(value), value, lifetime); + pub fn toJS(this: *JSC.JSGlobalObject, value: anytype) bun.JSError!JSC.JSValue { + return .fromAny(this, @TypeOf(value), value); } /// "Expected {field} to be a {typename} for '{name}'." @@ -373,7 +373,7 @@ pub const JSGlobalObject = opaque { const err = createErrorInstance(this, message, args); err.put(this, ZigString.static("code"), ZigString.init(@tagName(opts.code)).toJS(this)); if (opts.name) |name| err.put(this, ZigString.static("name"), ZigString.init(name).toJS(this)); - if (opts.errno) |errno| err.put(this, ZigString.static("errno"), JSC.toJS(this, i32, errno, .temporary)); + if (opts.errno) |errno| err.put(this, ZigString.static("errno"), try JSC.toJS(this, i32, errno)); return this.throwValue(err); } diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index 372346a2cc..d10befc1ba 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -387,6 +387,7 @@ public: JSArray* val = calls.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); + // RETURN_IF_EXCEPTION this->calls.set(vm(), this, val); } return val; @@ -396,6 +397,7 @@ public: JSArray* val = contexts.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); + // RETURN_IF_EXCEPTION this->contexts.set(vm(), this, val); } return val; @@ -405,6 +407,7 @@ public: JSArray* val = instances.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); + // RETURN_IF_EXCEPTION this->instances.set(vm(), this, val); } return val; @@ -414,6 +417,7 @@ public: JSArray* val = returnValues.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); + // RETURN_IF_EXCEPTION this->returnValues.set(vm(), this, val); } return val; @@ -423,6 +427,7 @@ public: JSArray* val = invocationCallOrder.get(); if (!val) { val = JSC::constructEmptyArray(globalObject(), nullptr, 0); + // RETURN_IF_EXCEPTION this->invocationCallOrder.set(vm(), this, val); } return val; diff --git a/src/bun.js/bindings/JSObject.zig b/src/bun.js/bindings/JSObject.zig index 62688560fa..748b5322e4 100644 --- a/src/bun.js/bindings/JSObject.zig +++ b/src/bun.js/bindings/JSObject.zig @@ -30,7 +30,7 @@ pub const JSObject = opaque { /// /// This method is equivalent to `Object.create(...)` + setting properties, /// and is only intended for creating POJOs. - pub fn create(pojo: anytype, global: *JSGlobalObject) *JSObject { + pub fn create(pojo: anytype, global: *JSGlobalObject) bun.JSError!*JSObject { return createFromStructWithPrototype(@TypeOf(pojo), pojo, global, false); } /// Marshall a struct into a JSObject, copying its properties. It's @@ -41,7 +41,7 @@ pub const JSObject = opaque { /// /// This is roughly equivalent to creating an object with /// `Object.create(null)` and adding properties to it. - pub fn createNullProto(pojo: anytype, global: *JSGlobalObject) *JSObject { + pub fn createNullProto(pojo: anytype, global: *JSGlobalObject) bun.JSError!*JSObject { return createFromStructWithPrototype(@TypeOf(pojo), pojo, global, true); } @@ -57,7 +57,7 @@ pub const JSObject = opaque { /// depending on whether `null_prototype` is set. Prefer using the object /// prototype (`null_prototype = false`) unless you have a good reason not /// to. - fn createFromStructWithPrototype(comptime T: type, pojo: T, global: *JSGlobalObject, comptime null_prototype: bool) *JSObject { + fn createFromStructWithPrototype(comptime T: type, pojo: T, global: *JSGlobalObject, comptime null_prototype: bool) bun.JSError!*JSObject { const info: std.builtin.Type.Struct = @typeInfo(T).@"struct"; const obj = obj: { @@ -76,7 +76,7 @@ pub const JSObject = opaque { cell.put( global, field.name, - JSC.toJS(global, @TypeOf(property), property, .temporary), + try JSC.toJS(global, @TypeOf(property), property), ); } diff --git a/src/bun.js/bindings/JSPromise.zig b/src/bun.js/bindings/JSPromise.zig index bc71367d6e..69bf262144 100644 --- a/src/bun.js/bindings/JSPromise.zig +++ b/src/bun.js/bindings/JSPromise.zig @@ -111,8 +111,8 @@ pub const JSPromise = opaque { pub const empty: Strong = .{ .strong = .empty }; - pub fn reject(this: *Strong, globalThis: *JSC.JSGlobalObject, val: JSC.JSValue) void { - this.swap().reject(globalThis, val); + pub fn reject(this: *Strong, globalThis: *JSC.JSGlobalObject, val: JSError!JSC.JSValue) void { + this.swap().reject(globalThis, val catch globalThis.tryTakeException().?); } /// Like `reject`, except it drains microtasks at the end of the current event loop iteration. diff --git a/src/bun.js/bindings/JSValue.zig b/src/bun.js/bindings/JSValue.zig index 62e6e56c94..1cc63b1fb5 100644 --- a/src/bun.js/bindings/JSValue.zig +++ b/src/bun.js/bindings/JSValue.zig @@ -690,8 +690,8 @@ pub const JSValue = enum(i64) { } extern fn JSC__JSValue__createEmptyArray(global: *JSGlobalObject, len: usize) JSValue; - pub fn createEmptyArray(global: *JSGlobalObject, len: usize) JSValue { - return JSC__JSValue__createEmptyArray(global, len); + pub fn createEmptyArray(global: *JSGlobalObject, len: usize) bun.JSError!JSValue { + return bun.jsc.fromJSHostValue(JSC__JSValue__createEmptyArray(global, len)); } extern fn JSC__JSValue__putRecord(value: JSValue, global: *JSGlobalObject, key: *ZigString, values_array: [*]ZigString, values_len: usize) void; @@ -2652,8 +2652,7 @@ pub const JSValue = enum(i64) { globalObject: *JSC.JSGlobalObject, comptime T: type, value: T, - comptime lifetime: FromAnyLifetime, - ) JSC.JSValue { + ) bun.JSError!JSC.JSValue { const Type = comptime brk: { var CurrentType = T; if (@typeInfo(T) == .optional) { @@ -2688,7 +2687,7 @@ pub const JSValue = enum(i64) { JSC.JSValue => return if (Type != T) value.* else value, inline []const u16, []const u32, []const i16, []const i8, []const i32, []const f32 => { - var array = JSC.JSValue.createEmptyArray(globalObject, value.len); + var array = try JSC.JSValue.createEmptyArray(globalObject, value.len); for (value, 0..) |item, i| { array.putIndex( globalObject, @@ -2705,9 +2704,9 @@ pub const JSValue = enum(i64) { if (bun.trait.isSlice(Type)) { const Child = comptime std.meta.Child(Type); - var array = JSC.JSValue.createEmptyArray(globalObject, value.len); + var array = try JSC.JSValue.createEmptyArray(globalObject, value.len); for (value, 0..) |*item, i| { - const res = fromAny(globalObject, *Child, item, lifetime); + const res = try fromAny(globalObject, *Child, item); if (res == .zero) return .zero; array.putIndex( globalObject, diff --git a/src/bun.js/bindings/JSX509Certificate.cpp b/src/bun.js/bindings/JSX509Certificate.cpp index 8720e599f0..86afb980f0 100644 --- a/src/bun.js/bindings/JSX509Certificate.cpp +++ b/src/bun.js/bindings/JSX509Certificate.cpp @@ -1084,6 +1084,7 @@ JSValue JSX509Certificate::computeInfoAccess(ncrypto::X509View view, JSGlobalObj array->push(globalObject, jsString(vm, value)); } else { JSArray* array = constructEmptyArray(globalObject, static_cast(nullptr), 1); + RETURN_IF_EXCEPTION(scope, {}); array->putDirectIndex(globalObject, 0, jsString(vm, value)); object->putDirect(vm, identifier, array); } diff --git a/src/bun.js/bindings/NodeHTTP.cpp b/src/bun.js/bindings/NodeHTTP.cpp index 3565d214cc..39b4bad591 100644 --- a/src/bun.js/bindings/NodeHTTP.cpp +++ b/src/bun.js/bindings/NodeHTTP.cpp @@ -665,6 +665,7 @@ static void assignHeadersFromUWebSocketsForCall(uWS::HttpRequest* request, JSVal if (name == WebCore::HTTPHeaderName::SetCookie) { if (!setCookiesHeaderArray) { setCookiesHeaderArray = constructEmptyArray(globalObject, nullptr); + RETURN_IF_EXCEPTION(scope, ); setCookiesHeaderString = nameString; headersObject->putDirect(vm, nameIdentifier, setCookiesHeaderArray, 0); RETURN_IF_EXCEPTION(scope, void()); @@ -692,7 +693,9 @@ static void assignHeadersFromUWebSocketsForCall(uWS::HttpRequest* request, JSVal array->initializeIndex(initializationScope, i, JSValue::decode(data[i])); } } else { + RETURN_IF_EXCEPTION(scope, ); array = constructArray(globalObject, static_cast(nullptr), arrayValues); + RETURN_IF_EXCEPTION(scope, ); } } @@ -809,6 +812,7 @@ static EncodedJSValue assignHeadersFromUWebSockets(uWS::HttpRequest* request, JS JSC::JSObject* headersObject = JSC::constructEmptyObject(globalObject, prototype, std::min(size, static_cast(JSFinalObject::maxInlineCapacity))); RETURN_IF_EXCEPTION(scope, {}); JSC::JSArray* array = constructEmptyArray(globalObject, nullptr, size * 2); + RETURN_IF_EXCEPTION(scope, {}); JSC::JSArray* setCookiesHeaderArray = nullptr; JSC::JSString* setCookiesHeaderString = nullptr; @@ -843,6 +847,7 @@ static EncodedJSValue assignHeadersFromUWebSockets(uWS::HttpRequest* request, JS if (name == WebCore::HTTPHeaderName::SetCookie) { if (!setCookiesHeaderArray) { setCookiesHeaderArray = constructEmptyArray(globalObject, nullptr); + RETURN_IF_EXCEPTION(scope, {}); setCookiesHeaderString = jsString(vm, nameString); headersObject->putDirect(vm, Identifier::fromString(vm, lowercasedNameString), setCookiesHeaderArray, 0); RETURN_IF_EXCEPTION(scope, {}); diff --git a/src/bun.js/bindings/NodeVMModule.cpp b/src/bun.js/bindings/NodeVMModule.cpp index 66ce7c94b2..2e2383a5e0 100644 --- a/src/bun.js/bindings/NodeVMModule.cpp +++ b/src/bun.js/bindings/NodeVMModule.cpp @@ -19,10 +19,15 @@ void NodeVMModuleRequest::addImportAttribute(WTF::String key, WTF::String value) JSArray* NodeVMModuleRequest::toJS(JSGlobalObject* globalObject) const { + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSArray* array = JSC::constructEmptyArray(globalObject, nullptr, 2); + RETURN_IF_EXCEPTION(scope, {}); array->putDirectIndex(globalObject, 0, JSC::jsString(globalObject->vm(), m_specifier)); JSObject* attributes = JSC::constructEmptyObject(globalObject); + RETURN_IF_EXCEPTION(scope, {}); for (const auto& [key, value] : m_importAttributes) { attributes->putDirect(globalObject->vm(), JSC::Identifier::fromString(globalObject->vm(), key), JSC::jsString(globalObject->vm(), value), PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete); @@ -224,6 +229,9 @@ JSC_DEFINE_HOST_FUNCTION(jsNodeVmModuleGetError, (JSC::JSGlobalObject * globalOb JSC_DEFINE_HOST_FUNCTION(jsNodeVmModuleGetModuleRequests, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + auto* thisObject = jsCast(callFrame->thisValue()); if (auto* sourceTextModule = jsDynamicCast(callFrame->thisValue())) { @@ -233,9 +241,11 @@ JSC_DEFINE_HOST_FUNCTION(jsNodeVmModuleGetModuleRequests, (JSC::JSGlobalObject * const WTF::Vector& requests = thisObject->moduleRequests(); JSArray* array = constructEmptyArray(globalObject, nullptr, requests.size()); + RETURN_IF_EXCEPTION(scope, {}); for (unsigned i = 0; const NodeVMModuleRequest& request : requests) { array->putDirectIndex(globalObject, i++, request.toJS(globalObject)); + RETURN_IF_EXCEPTION(scope, {}); } return JSValue::encode(array); diff --git a/src/bun.js/bindings/NodeVMSourceTextModule.cpp b/src/bun.js/bindings/NodeVMSourceTextModule.cpp index 69a9032b41..5d47f47dd7 100644 --- a/src/bun.js/bindings/NodeVMSourceTextModule.cpp +++ b/src/bun.js/bindings/NodeVMSourceTextModule.cpp @@ -170,6 +170,7 @@ JSValue NodeVMSourceTextModule::createModuleRecord(JSGlobalObject* globalObject) } JSArray* requestsArray = constructEmptyArray(globalObject, nullptr, requests.size()); + RETURN_IF_EXCEPTION(scope, {}); const auto& builtinNames = WebCore::clientData(vm)->builtinNames(); const Identifier& specifierIdentifier = builtinNames.specifierPublicName(); diff --git a/src/bun.js/bindings/Path.cpp b/src/bun.js/bindings/Path.cpp index fd05ec5c6a..d8b110a425 100644 --- a/src/bun.js/bindings/Path.cpp +++ b/src/bun.js/bindings/Path.cpp @@ -78,7 +78,9 @@ DEFINE_PATH_FUNCTION(jsFunctionPath_toNamespacedPathWindows, Bun__Path__toNamesp static JSC::JSObject* createPath(JSGlobalObject* globalThis, bool isWindows) { auto& vm = JSC::getVM(globalThis); + auto scope = DECLARE_THROW_SCOPE(vm); auto* path = JSC::constructEmptyObject(globalThis); + RETURN_IF_EXCEPTION(scope, {}); auto builtinNames = WebCore::builtinNames(vm); if (!isWindows) { @@ -116,15 +118,20 @@ namespace Bun { JSC::JSValue createNodePathBinding(Zig::GlobalObject* globalObject) { + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); auto binding = constructEmptyArray(globalObject, nullptr, 2); + RETURN_IF_EXCEPTION(scope, {}); binding->putDirectIndex( globalObject, (unsigned)0, Zig::createPath(globalObject, false)); + RETURN_IF_EXCEPTION(scope, {}); binding->putDirectIndex( globalObject, (unsigned)1, Zig::createPath(globalObject, true)); + RETURN_IF_EXCEPTION(scope, {}); return binding; } diff --git a/src/bun.js/bindings/ProcessBindingUV.cpp b/src/bun.js/bindings/ProcessBindingUV.cpp index 1d6c6ac9cd..72ae576b4a 100644 --- a/src/bun.js/bindings/ProcessBindingUV.cpp +++ b/src/bun.js/bindings/ProcessBindingUV.cpp @@ -384,6 +384,7 @@ JSC_DEFINE_HOST_FUNCTION(jsGetErrorMap, (JSGlobalObject * globalObject, JSC::Cal // Inlining each of these via macros costs like 300 KB. const auto putProperty = [](JSC::VM& vm, JSC::JSMap* map, JSC::JSGlobalObject* globalObject, ASCIILiteral name, int value, ASCIILiteral desc) -> void { auto arr = JSC::constructEmptyArray(globalObject, static_cast(nullptr), 2); + // RETURN_IF_EXCEPTION arr->putDirectIndex(globalObject, 0, JSC::jsString(vm, String(name))); arr->putDirectIndex(globalObject, 1, JSC::jsString(vm, String(desc))); map->set(globalObject, JSC::jsNumber(value), arr); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index b8be9b186d..787ddbbe7e 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -750,6 +750,7 @@ static JSValue computeErrorInfoWithPrepareStackTrace(JSC::VM& vm, Zig::GlobalObj } JSArray* callSitesArray = JSC::constructArray(globalObject, globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous), callSites); + RETURN_IF_EXCEPTION(scope, {}); return formatStackTraceToJSValue(vm, globalObject, lexicalGlobalObject, errorObject, callSitesArray, prepareStackTrace); } diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index 4218eca000..ad399bf868 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -1889,6 +1889,7 @@ static inline JSC::JSArray* constructResultRow(JSC::VM& vm, JSC::JSGlobalObject* } else { RETURN_IF_EXCEPTION(throwScope, nullptr); result = JSC::constructArray(lexicalGlobalObject, arrayStructure, arguments); + RETURN_IF_EXCEPTION(throwScope, {}); } return result; @@ -1995,6 +1996,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionIterate, (JSC::JS result = useBigInt64 ? constructResultObject(lexicalGlobalObject, castedThis) : constructResultObject(lexicalGlobalObject, castedThis); + RETURN_IF_EXCEPTION(scope, {}); } if (status == SQLITE_DONE || status == SQLITE_OK || status == SQLITE_ROW) { @@ -2052,15 +2054,18 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionAll, (JSC::JSGlob } else { bool useBigInt64 = castedThis->useBigInt64; JSC::JSArray* resultArray = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); + RETURN_IF_EXCEPTION(scope, {}); if (useBigInt64) { do { JSC::JSValue result = constructResultObject(lexicalGlobalObject, castedThis); + RETURN_IF_EXCEPTION(scope, {}); resultArray->push(lexicalGlobalObject, result); status = sqlite3_step(stmt); } while (status == SQLITE_ROW); } else { do { JSC::JSValue result = constructResultObject(lexicalGlobalObject, castedThis); + RETURN_IF_EXCEPTION(scope, {}); resultArray->push(lexicalGlobalObject, result); status = sqlite3_step(stmt); } while (status == SQLITE_ROW); @@ -2069,6 +2074,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionAll, (JSC::JSGlob } } else if (status == SQLITE_DONE) { result = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); + RETURN_IF_EXCEPTION(scope, {}); } if (status != SQLITE_DONE && status != SQLITE_OK) [[unlikely]] { @@ -2123,6 +2129,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionGet, (JSC::JSGlob result = useBigInt64 ? constructResultObject(lexicalGlobalObject, castedThis) : constructResultObject(lexicalGlobalObject, castedThis); + RETURN_IF_EXCEPTION(scope, {}); while (status == SQLITE_ROW) { status = sqlite3_step(stmt); } @@ -2185,6 +2192,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionRows, (JSC::JSGlo } else { JSC::JSArray* resultArray = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); + RETURN_IF_EXCEPTION(scope, {}); { size_t columnCount = sqlite3_column_count(stmt); @@ -2204,6 +2212,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionRows, (JSC::JSGlo } else if (status == SQLITE_DONE && columnCount != 0) { // breaking change in Bun v0.6.8 result = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); + RETURN_IF_EXCEPTION(scope, {}); } if (status != SQLITE_DONE && status != SQLITE_OK) [[unlikely]] { @@ -2318,6 +2327,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnNames, (JSGlobalObject * lexical array = ownPropertyKeys(lexicalGlobalObject, castedThis->_prototype.get(), PropertyNameMode::Strings, DontEnumPropertiesMode::Exclude); } else { array = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, columnNames->size()); + RETURN_IF_EXCEPTION(scope, {}); unsigned int i = 0; for (const auto& column : *columnNames) { array->putDirectIndex(lexicalGlobalObject, i++, jsString(vm, column.string())); @@ -2325,6 +2335,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnNames, (JSGlobalObject * lexical } } else { array = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); + RETURN_IF_EXCEPTION(scope, {}); } return JSC::JSValue::encode(array); } diff --git a/src/bun.js/bindings/v8/V8Array.cpp b/src/bun.js/bindings/v8/V8Array.cpp index 27f4265ee0..089b445808 100644 --- a/src/bun.js/bindings/v8/V8Array.cpp +++ b/src/bun.js/bindings/v8/V8Array.cpp @@ -20,6 +20,7 @@ Local Array::New(Isolate* isolate, Local* elements, size_t length) static_cast(nullptr), reinterpret_cast(elements), (unsigned int)length); + // RETURN_IF_EXCEPTION return isolate->currentHandleScope()->createLocal(isolate->vm(), array); } diff --git a/src/bun.js/bindings/webcore/JSDOMConvertSequences.h b/src/bun.js/bindings/webcore/JSDOMConvertSequences.h index 0f57bf691e..fdc14839c8 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertSequences.h +++ b/src/bun.js/bindings/webcore/JSDOMConvertSequences.h @@ -484,7 +484,9 @@ template struct JSConverter> { throwOutOfMemoryError(&lexicalGlobalObject, scope); return {}; } - RELEASE_AND_RETURN(scope, JSC::constructArray(&globalObject, static_cast(nullptr), list)); + auto* array = JSC::constructArray(&globalObject, static_cast(nullptr), list); + RETURN_IF_EXCEPTION(scope, {}); + RELEASE_AND_RETURN(scope, array); } }; diff --git a/src/bun.js/bindings/webcore/JSDOMFormData.cpp b/src/bun.js/bindings/webcore/JSDOMFormData.cpp index 168f7b2328..966c990b0c 100644 --- a/src/bun.js/bindings/webcore/JSDOMFormData.cpp +++ b/src/bun.js/bindings/webcore/JSDOMFormData.cpp @@ -401,6 +401,7 @@ static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_getAllBody(JSC: RETURN_IF_EXCEPTION(throwScope, {}); auto entries = impl.getAll(name); JSC::JSArray* result = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); + RETURN_IF_EXCEPTION(throwScope, {}); for (auto entry : entries) { if (auto string = std::get_if(&entry)) { result->push(lexicalGlobalObject, jsString(vm, *string)); diff --git a/src/bun.js/bindings/webcore/JSEventEmitter.cpp b/src/bun.js/bindings/webcore/JSEventEmitter.cpp index ecb5e0dfa5..679832e39c 100644 --- a/src/bun.js/bindings/webcore/JSEventEmitter.cpp +++ b/src/bun.js/bindings/webcore/JSEventEmitter.cpp @@ -456,7 +456,9 @@ static inline JSC::EncodedJSValue jsEventEmitterPrototypeFunction_eventNamesBody for (auto& name : impl.getEventNames()) { args.append(JSC::identifierToSafePublicJSValue(vm, name)); } - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::constructArray(lexicalGlobalObject, static_cast(nullptr), WTFMove(args)))); + auto array = JSC::constructArray(lexicalGlobalObject, static_cast(nullptr), WTFMove(args)); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(array)); } JSC_DEFINE_HOST_FUNCTION(jsEventEmitterPrototypeFunction_eventNames, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) @@ -494,7 +496,9 @@ static inline JSC::EncodedJSValue jsEventEmitterPrototypeFunction_listenersBody( for (auto* listener : impl.getListeners(eventType)) { args.append(listener); } - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::constructArray(lexicalGlobalObject, static_cast(nullptr), WTFMove(args)))); + auto array = JSC::constructArray(lexicalGlobalObject, static_cast(nullptr), WTFMove(args)); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(array)); } JSC_DEFINE_HOST_FUNCTION(jsEventEmitterPrototypeFunction_listeners, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) @@ -582,7 +586,9 @@ JSC_DEFINE_HOST_FUNCTION(Events_functionGetEventListeners, for (auto* listener : impl.getListeners(eventType)) { args.append(listener); } - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::constructArray(lexicalGlobalObject, static_cast(nullptr), WTFMove(args)))); + auto array = JSC::constructArray(lexicalGlobalObject, static_cast(nullptr), WTFMove(args)); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(array)); } JSC_DEFINE_HOST_FUNCTION(Events_functionListenerCount, diff --git a/src/bun.js/ipc.zig b/src/bun.js/ipc.zig index 2ca9f3c9b2..caaec23e3c 100644 --- a/src/bun.js/ipc.zig +++ b/src/bun.js/ipc.zig @@ -335,7 +335,7 @@ pub const CallbackList = union(enum) { } /// protects the callback - pub fn push(self: *@This(), callback: JSC.JSValue, global: *JSC.JSGlobalObject) void { + pub fn push(self: *@This(), callback: JSC.JSValue, global: *JSC.JSGlobalObject) bun.JSError!void { switch (self.*) { .ack_nack => unreachable, .none => { @@ -344,7 +344,7 @@ pub const CallbackList = union(enum) { }, .callback => { const prev = self.callback; - const arr = JSC.JSValue.createEmptyArray(global, 2); + const arr = try JSC.JSValue.createEmptyArray(global, 2); arr.protect(); arr.putIndex(global, 0, prev); // add the old callback to the array arr.putIndex(global, 1, callback); // add the new callback to the array @@ -581,7 +581,7 @@ pub const SendQueue = struct { } /// returned pointer is invalidated if the queue is modified - pub fn startMessage(self: *SendQueue, global: *JSC.JSGlobalObject, callback: JSC.JSValue, handle: ?Handle) *SendHandle { + pub fn startMessage(self: *SendQueue, global: *JSC.JSGlobalObject, callback: JSC.JSValue, handle: ?Handle) bun.JSError!*SendHandle { log("SendQueue#startMessage", .{}); if (Environment.allow_assert) bun.debugAssert(self.has_written_version == 1); @@ -591,7 +591,7 @@ pub const SendQueue = struct { const last = &self.queue.items[self.queue.items.len - 1]; if (last.handle == null and !last.isAckNack() and !(self.queue.items.len == 1 and self.write_in_progress)) { if (callback.isCallable()) { - last.callbacks.push(callback, global); + try last.callbacks.push(callback, global); } // caller can append now return last; @@ -771,7 +771,7 @@ pub const SendQueue = struct { pub fn serializeAndSend(self: *SendQueue, global: *JSGlobalObject, value: JSValue, is_internal: IsInternal, callback: JSC.JSValue, handle: ?Handle) SerializeAndSendResult { log("SendQueue#serializeAndSend", .{}); const indicate_backoff = self.waiting_for_ack != null and self.queue.items.len > 0; - const msg = self.startMessage(global, callback, handle); + const msg = self.startMessage(global, callback, handle) catch return .failure; const start_offset = msg.data.list.items.len; const payload_length = serialize(self.mode, &msg.data, global, value, is_internal) catch return .failure; diff --git a/src/bun.js/jsc.zig b/src/bun.js/jsc.zig index cf1ce90b8f..242d878e66 100644 --- a/src/bun.js/jsc.zig +++ b/src/bun.js/jsc.zig @@ -34,6 +34,7 @@ pub const JSHostFunctionTypeWithContext = host_fn.JSHostFunctionTypeWithContext; pub const toJSHostFn = host_fn.toJSHostFn; pub const toJSHostFnWithContext = host_fn.toJSHostFnWithContext; pub const toJSHostValue = host_fn.toJSHostValue; +pub const fromJSHostValue = host_fn.fromJSHostValue; pub const createCallback = host_fn.createCallback; // JSC Classes Bindings diff --git a/src/bun.js/jsc/host_fn.zig b/src/bun.js/jsc/host_fn.zig index a35f67363d..74c5167e99 100644 --- a/src/bun.js/jsc/host_fn.zig +++ b/src/bun.js/jsc/host_fn.zig @@ -92,6 +92,11 @@ pub fn toJSHostValue(globalThis: *JSGlobalObject, value: error{ OutOfMemory, JSE return normal; } +pub fn fromJSHostValue(value: JSValue) bun.JSError!JSValue { + if (value == .zero) return error.JSError; + return value; +} + const ParsedHostFunctionErrorSet = struct { OutOfMemory: bool = false, JSError: bool = false, diff --git a/src/bun.js/modules/NodeModuleModule.cpp b/src/bun.js/modules/NodeModuleModule.cpp index 8b9abda5a9..20dce1e733 100644 --- a/src/bun.js/modules/NodeModuleModule.cpp +++ b/src/bun.js/modules/NodeModuleModule.cpp @@ -476,6 +476,7 @@ JSC::JSValue resolveLookupPaths(JSC::JSGlobalObject* globalObject, String reques )) { if (parent.paths) { auto array = JSC::constructArray(globalObject, (ArrayAllocationProfile*)nullptr, nullptr, 0); + RETURN_IF_EXCEPTION(scope, {}); auto len = parent.paths->length(); for (size_t i = 0; i < len; i++) { auto path = parent.paths->getIndex(globalObject, i); @@ -490,6 +491,7 @@ JSC::JSValue resolveLookupPaths(JSC::JSGlobalObject* globalObject, String reques RELEASE_AND_RETURN(scope, paths); } else { auto array = JSC::constructEmptyArray(globalObject, nullptr, 0); + RETURN_IF_EXCEPTION(scope, {}); RELEASE_AND_RETURN(scope, array); } } @@ -510,6 +512,7 @@ JSC::JSValue resolveLookupPaths(JSC::JSGlobalObject* globalObject, String reques JSValue values[] = { dirname }; auto array = JSC::constructArray(globalObject, (ArrayAllocationProfile*)nullptr, values, 1); + RETURN_IF_EXCEPTION(scope, {}); RELEASE_AND_RETURN(scope, array); } diff --git a/src/bun.js/node/net/BlockList.zig b/src/bun.js/node/net/BlockList.zig index cacc198e61..b61bd270de 100644 --- a/src/bun.js/node/net/BlockList.zig +++ b/src/bun.js/node/net/BlockList.zig @@ -161,7 +161,7 @@ pub fn check(this: *@This(), globalThis: *JSC.JSGlobalObject, callframe: *JSC.Ca return .jsBoolean(false); } -pub fn rules(this: *@This(), globalThis: *JSC.JSGlobalObject) JSC.JSValue { +pub fn rules(this: *@This(), globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { this.mutex.lock(); defer this.mutex.unlock(); var list = std.ArrayList(JSC.JSValue).initCapacity(bun.default_allocator, this.da_rules.items.len) catch bun.outOfMemory(); diff --git a/src/bun.js/node/node_assert.zig b/src/bun.js/node/node_assert.zig index 067efb087d..619c00997c 100644 --- a/src/bun.js/node/node_assert.zig +++ b/src/bun.js/node/node_assert.zig @@ -37,7 +37,7 @@ pub fn myersDiff( // moot since BunStrings with non-zero reference counds should never be // dead. if (actual.length() == 0 and expected.length() == 0) { - return JSC.JSValue.createEmptyArray(global, 0); + return try JSC.JSValue.createEmptyArray(global, 0); } const actual_encoding = actual.encoding(); @@ -112,9 +112,9 @@ fn diffLines( } fn diffListToJS(comptime T: type, global: *JSC.JSGlobalObject, diff_list: MyersDiff.DiffList(T)) bun.JSError!JSC.JSValue { - var array = JSC.JSValue.createEmptyArray(global, diff_list.items.len); + var array = try JSC.JSValue.createEmptyArray(global, diff_list.items.len); for (diff_list.items, 0..) |*line, i| { - array.putIndex(global, @truncate(i), JSC.JSObject.createNullProto(line.*, global).toJS()); + array.putIndex(global, @truncate(i), (try JSC.JSObject.createNullProto(line.*, global)).toJS()); } return array; } diff --git a/src/bun.js/node/node_assert_binding.zig b/src/bun.js/node/node_assert_binding.zig index 42354aad25..01dcf7e4cb 100644 --- a/src/bun.js/node/node_assert_binding.zig +++ b/src/bun.js/node/node_assert_binding.zig @@ -59,12 +59,12 @@ pub fn myersDiff(global: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE const StrDiffList = DiffList([]const u8); fn diffListToJS(global: *JSC.JSGlobalObject, diff_list: StrDiffList) bun.JSError!JSC.JSValue { // todo: replace with toJS - var array = JSC.JSValue.createEmptyArray(global, diff_list.items.len); + var array = try JSC.JSValue.createEmptyArray(global, diff_list.items.len); for (diff_list.items, 0..) |*line, i| { var obj = JSC.JSValue.createEmptyObjectWithNullPrototype(global); if (obj == .zero) return global.throwOutOfMemory(); obj.put(global, bun.String.static("kind"), JSC.JSValue.jsNumber(@as(u32, @intFromEnum(line.kind)))); - obj.put(global, bun.String.static("value"), JSC.toJS(global, []const u8, line.value, .allocated)); + obj.put(global, bun.String.static("value"), JSC.toJS(global, []const u8, line.value)); array.putIndex(global, @truncate(i), obj); } return array; diff --git a/src/bun.js/node/node_crypto_binding.zig b/src/bun.js/node/node_crypto_binding.zig index b57eaecb5d..b75c51de1e 100644 --- a/src/bun.js/node/node_crypto_binding.zig +++ b/src/bun.js/node/node_crypto_binding.zig @@ -509,7 +509,7 @@ fn getHashes(global: *JSGlobalObject, _: *JSC.CallFrame) JSError!JSValue { // TODO(dylan-conway): cache the names BoringSSL.EVP_MD_do_all_sorted(&forEachHash, @alignCast(@ptrCast(&hashes))); - const array = JSValue.createEmptyArray(global, hashes.count()); + const array = try JSValue.createEmptyArray(global, hashes.count()); for (hashes.keys(), 0..) |hash, i| { const str = String.createUTF8ForJS(global, hash); diff --git a/src/bun.js/node/node_fs.zig b/src/bun.js/node/node_fs.zig index 0b2965edc2..1b4b472e0c 100644 --- a/src/bun.js/node/node_fs.zig +++ b/src/bun.js/node/node_fs.zig @@ -292,18 +292,15 @@ pub const Async = struct { pub fn runFromJSThread(this: *Task) void { const globalObject = this.globalObject; - var success = @as(JSC.Maybe(ReturnType).Tag, this.result) == .result; + const success = @as(JSC.Maybe(ReturnType).Tag, this.result) == .result; + var promise_value = this.promise.value(); + var promise = this.promise.get(); const result = switch (this.result) { .err => |err| err.toJSC(globalObject), .result => |*res| brk: { - const out = globalObject.toJS(res, .temporary); - success = out != .zero; - - break :brk out; + break :brk globalObject.toJS(res) catch return promise.reject(globalObject, error.JSError); }, }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); promise_value.ensureStillAlive(); const tracker = this.tracker; @@ -394,17 +391,15 @@ pub const Async = struct { pub fn runFromJSThread(this: *Task) void { const globalObject = this.globalObject; - var success = @as(JSC.Maybe(ReturnType).Tag, this.result) == .result; + const success = @as(JSC.Maybe(ReturnType).Tag, this.result) == .result; + var promise_value = this.promise.value(); + var promise = this.promise.get(); const result = switch (this.result) { .err => |err| err.toJSC(globalObject), .result => |*res| brk: { - const out = globalObject.toJS(res, .temporary); - success = out != .zero; - break :brk out; + break :brk globalObject.toJS(res) catch return promise.reject(globalObject, error.JSError); }, }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); promise_value.ensureStillAlive(); const tracker = this.tracker; @@ -671,18 +666,15 @@ pub fn NewAsyncCpTask(comptime is_shell: bool) type { const globalObject = this.evtloop.globalObject() orelse { @panic("No global object, this indicates a bug in Bun. Please file a GitHub issue."); }; - var success = @as(JSC.Maybe(Return.Cp).Tag, this.result) == .result; + const success = @as(JSC.Maybe(Return.Cp).Tag, this.result) == .result; + var promise_value = this.promise.value(); + var promise = this.promise.get(); const result = switch (this.result) { .err => |err| err.toJSC(globalObject), .result => |*res| brk: { - const out = globalObject.toJS(res, .temporary); - success = out != .zero; - - break :brk out; + break :brk globalObject.toJS(res) catch return promise.reject(globalObject, error.JSError); }, }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); promise_value.ensureStillAlive(); const tracker = this.tracker; @@ -1225,22 +1217,17 @@ pub const AsyncReaddirRecursiveTask = struct { pub fn runFromJSThread(this: *AsyncReaddirRecursiveTask) void { const globalObject = this.globalObject; - var success = this.pending_err == null; + const success = this.pending_err == null; + var promise_value = this.promise.value(); + var promise = this.promise.get(); const result = if (this.pending_err) |*err| err.toJSC(globalObject) else brk: { const res = switch (this.result_list) { .with_file_types => |*res| Return.Readdir{ .with_file_types = res.moveToUnmanaged().items }, .buffers => |*res| Return.Readdir{ .buffers = res.moveToUnmanaged().items }, .files => |*res| Return.Readdir{ .files = res.moveToUnmanaged().items }, }; - const out = res.toJS(globalObject); - if (out == .zero) { - success = false; - } - - break :brk out; + break :brk res.toJS(globalObject) catch return promise.reject(globalObject, error.JSError); }; - var promise_value = this.promise.value(); - var promise = this.promise.get(); promise_value.ensureStillAlive(); const tracker = this.tracker; @@ -3289,11 +3276,11 @@ const Return = struct { files, }; - pub fn toJS(this: Readdir, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + pub fn toJS(this: Readdir, globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { switch (this) { .with_file_types => { defer bun.default_allocator.free(this.with_file_types); - var array = JSC.JSValue.createEmptyArray(globalObject, this.with_file_types.len); + var array = try JSC.JSValue.createEmptyArray(globalObject, this.with_file_types.len); var previous_jsstring: ?*JSC.JSString = null; for (this.with_file_types, 0..) |*item, i| { const res = item.toJSNewlyCreated(globalObject, &previous_jsstring); @@ -3308,11 +3295,11 @@ const Return = struct { }, .buffers => { defer bun.default_allocator.free(this.buffers); - return JSC.toJS(globalObject, []Buffer, this.buffers, .temporary); + return JSC.toJS(globalObject, []Buffer, this.buffers); }, .files => { // automatically freed - return JSC.toJS(globalObject, []const bun.String, this.files, .temporary); + return JSC.toJS(globalObject, []const bun.String, this.files); }, } } diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index 9a2b16fe15..538bcf7661 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -35,7 +35,7 @@ fn Bindings(comptime function_name: NodeFSFunctionEnum) type { var result = function(&this.node_fs, args, .sync); return switch (result) { .err => |err| globalObject.throwValue(JSC.JSValue.c(err.toJS(globalObject))), - .result => |*res| globalObject.toJS(res, .temporary), + .result => |*res| globalObject.toJS(res), }; } diff --git a/src/bun.js/node/node_os.zig b/src/bun.js/node/node_os.zig index 1d5372948a..2dedf0cc5d 100644 --- a/src/bun.js/node/node_os.zig +++ b/src/bun.js/node/node_os.zig @@ -9,8 +9,8 @@ const gen = bun.gen.node_os; const sys = bun.sys; const c = bun.c; -pub fn createNodeOsBinding(global: *JSC.JSGlobalObject) JSC.JSValue { - return JSC.JSObject.create(.{ +pub fn createNodeOsBinding(global: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { + return (try JSC.JSObject.create(.{ .cpus = gen.createCpusCallback(global), .freemem = gen.createFreememCallback(global), .getPriority = gen.createGetPriorityCallback(global), @@ -24,7 +24,7 @@ pub fn createNodeOsBinding(global: *JSC.JSGlobalObject) JSC.JSValue { .userInfo = gen.createUserInfoCallback(global), .version = gen.createVersionCallback(global), .setPriority = gen.createSetPriorityCallback(global), - }, global).toJS(); + }, global)).toJS(); } const CPUTimes = struct { @@ -63,7 +63,7 @@ pub fn cpus(global: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { fn cpusImplLinux(globalThis: *JSC.JSGlobalObject) !JSC.JSValue { // Create the return array - const values = JSC.JSValue.createEmptyArray(globalThis, 0); + const values = try JSC.JSValue.createEmptyArray(globalThis, 0); var num_cpus: u32 = 0; var stack_fallback = std.heap.stackFallback(1024 * 8, bun.default_allocator); @@ -235,7 +235,7 @@ fn cpusImplDarwin(globalThis: *JSC.JSGlobalObject) !JSC.JSValue { const multiplier = 1000 / @as(u64, @intCast(ticks)); // Set up each CPU value in the return - const values = JSC.JSValue.createEmptyArray(globalThis, @as(u32, @intCast(num_cpus))); + const values = try JSC.JSValue.createEmptyArray(globalThis, @as(u32, @intCast(num_cpus))); var cpu_index: u32 = 0; while (cpu_index < num_cpus) : (cpu_index += 1) { const times = CPUTimes{ @@ -265,7 +265,7 @@ pub fn cpusImplWindows(globalThis: *JSC.JSGlobalObject) !JSC.JSValue { } defer libuv.uv_free_cpu_info(cpu_infos, count); - const values = JSC.JSValue.createEmptyArray(globalThis, @intCast(count)); + const values = try JSC.JSValue.createEmptyArray(globalThis, @intCast(count)); for (cpu_infos[0..@intCast(count)], 0..@intCast(count)) |cpu_info, i| { const times = CPUTimes{ @@ -639,7 +639,7 @@ fn networkInterfacesPosix(globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSVal } else { // Add it as an array with this interface as an element const member_name = JSC.ZigString.init(interface_name); - var array = JSC.JSValue.createEmptyArray(globalThis, 1); + var array = try JSC.JSValue.createEmptyArray(globalThis, 1); array.putIndex(globalThis, 0, interface); ret.put(globalThis, &member_name, array); } @@ -753,7 +753,7 @@ fn networkInterfacesWindows(globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSV } else { // Add it as an array with this interface as an element const member_name = JSC.ZigString.init(interface_name); - var array = JSC.JSValue.createEmptyArray(globalThis, 1); + var array = try JSC.JSValue.createEmptyArray(globalThis, 1); array.putIndex(globalThis, 0, interface); ret.put(globalThis, &member_name, array); } diff --git a/src/bun.js/node/node_process.zig b/src/bun.js/node/node_process.zig index 9065543802..bb6c23d898 100644 --- a/src/bun.js/node/node_process.zig +++ b/src/bun.js/node/node_process.zig @@ -50,7 +50,7 @@ fn createExecArgv(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { if (vm.worker) |worker| { // was explicitly overridden for the worker? if (worker.execArgv) |execArgv| { - const array = JSC.JSValue.createEmptyArray(globalObject, execArgv.len); + const array = JSC.JSValue.createEmptyArray(globalObject, execArgv.len) catch return .zero; for (0..execArgv.len) |i| { array.putIndex(globalObject, @intCast(i), bun.String.init(execArgv[i]).toJS(globalObject)); } @@ -114,7 +114,7 @@ fn createExecArgv(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { break; } - return bun.String.toJSArray(globalObject, args.items); + return bun.String.toJSArray(globalObject, args.items) catch .zero; } fn createArgv(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { @@ -180,7 +180,7 @@ fn createArgv(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue { } } - return bun.String.toJSArray(globalObject, args_list.items); + return bun.String.toJSArray(globalObject, args_list.items) catch .zero; } extern fn Bun__Process__getArgv(global: *JSGlobalObject) JSValue; diff --git a/src/bun.js/node/util/parse_args.zig b/src/bun.js/node/util/parse_args.zig index a696a6935b..3384e12438 100644 --- a/src/bun.js/node/util/parse_args.zig +++ b/src/bun.js/node/util/parse_args.zig @@ -267,7 +267,7 @@ fn checkOptionUsage(globalThis: *JSGlobalObject, options: []const OptionDefiniti /// - `option_value`: value from user args /// - `options`: option configs, from `parseArgs({ options })` /// - `values`: option values returned in `values` by parseArgs -fn storeOption(globalThis: *JSGlobalObject, option_name: ValueRef, option_value: ValueRef, option_idx: ?usize, negative: bool, options: []const OptionDefinition, values: JSValue) void { +fn storeOption(globalThis: *JSGlobalObject, option_name: ValueRef, option_value: ValueRef, option_idx: ?usize, negative: bool, options: []const OptionDefinition, values: JSValue) bun.JSError!void { var key = option_name.asBunString(globalThis); if (key.eqlComptime("__proto__")) { return; @@ -288,7 +288,7 @@ fn storeOption(globalThis: *JSGlobalObject, option_name: ValueRef, option_value: if (values.getOwn(globalThis, key)) |value_list| { value_list.push(globalThis, new_value); } else { - var value_list = JSValue.createEmptyArray(globalThis, 1); + var value_list = try JSValue.createEmptyArray(globalThis, 1); value_list.putIndex(globalThis, 0, new_value); values.putMayBeIndex(globalThis, &key, value_list); } @@ -590,7 +590,7 @@ const ParseArgsState = struct { try checkOptionUsage(globalThis, this.option_defs, this.allow_positionals, token); try checkOptionLikeValue(globalThis, token); } - storeOption(globalThis, token.name, token.value, token.option_idx, token.negative, this.option_defs, this.values); + try storeOption(globalThis, token.name, token.value, token.option_idx, token.negative, this.option_defs, this.values); }, .positional => |token| { if (!this.allow_positionals) { @@ -713,8 +713,8 @@ pub fn parseArgs(globalThis: *JSGlobalObject, callframe: *JSC.CallFrame) bun.JSE // note that "values" needs to have a null prototype instead of Object, to avoid issues such as "values.toString"` being defined const values = JSValue.createEmptyObjectWithNullPrototype(globalThis); - const positionals = JSC.JSValue.createEmptyArray(globalThis, 0); - const tokens = if (return_tokens) JSC.JSValue.createEmptyArray(globalThis, 0) else JSValue.undefined; + const positionals = try JSC.JSValue.createEmptyArray(globalThis, 0); + const tokens = if (return_tokens) try JSC.JSValue.createEmptyArray(globalThis, 0) else JSValue.undefined; var state = ParseArgsState{ .globalThis = globalThis, diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index f204094879..ce8e15d419 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -5409,7 +5409,7 @@ pub const ExpectCustomAsymmetricMatcher = struct { // capture the args as a JS array saved in the instance, so the matcher can be executed later on with them const args = callFrame.arguments(); - const array = JSValue.createEmptyArray(globalThis, args.len); + const array = try JSValue.createEmptyArray(globalThis, args.len); for (args, 0..) |arg, i| { array.putIndex(globalThis, @truncate(i), arg); } diff --git a/src/bun.js/webcore/blob/Store.zig b/src/bun.js/webcore/blob/Store.zig index d447d2abe0..e08e8fb9ed 100644 --- a/src/bun.js/webcore/blob/Store.zig +++ b/src/bun.js/webcore/blob/Store.zig @@ -388,7 +388,8 @@ pub const S3 = struct { switch (result) { .success => |list_result| { defer list_result.deinit(); - self.promise.resolve(globalObject, list_result.toJS(globalObject)); + const list_result_js = list_result.toJS(globalObject) catch return self.promise.reject(globalObject, error.JSError); + self.promise.resolve(globalObject, list_result_js); }, inline .not_found, .failure => |err| { diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index 8a61f62cb5..284fdb9895 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -2068,7 +2068,7 @@ pub const BundleV2 = struct { } const root_obj = JSC.JSValue.createEmptyObject(globalThis, 3); - root_obj.put(globalThis, JSC.ZigString.static("outputs"), JSC.JSValue.createEmptyArray(globalThis, 0)); + root_obj.put(globalThis, JSC.ZigString.static("outputs"), JSC.JSValue.createEmptyArray(globalThis, 0) catch return promise.reject(globalThis, error.JSError)); root_obj.put( globalThis, JSC.ZigString.static("success"), @@ -2086,7 +2086,7 @@ pub const BundleV2 = struct { .value => |*build| { const root_obj = JSC.JSValue.createEmptyObject(globalThis, 3); const output_files: []options.OutputFile = build.output_files.items; - const output_files_js = JSC.JSValue.createEmptyArray(globalThis, output_files.len); + const output_files_js = JSC.JSValue.createEmptyArray(globalThis, output_files.len) catch return promise.reject(globalThis, error.JSError); if (output_files_js == .zero) { @panic("Unexpected pending JavaScript exception in JSBundleCompletionTask.onComplete. This is a bug in Bun."); } diff --git a/src/cli/pack_command.zig b/src/cli/pack_command.zig index 2a21defb20..6f90649f6f 100644 --- a/src/cli/pack_command.zig +++ b/src/cli/pack_command.zig @@ -2664,7 +2664,7 @@ pub const bindings = struct { else => {}, } - const entries = JSArray.createEmpty(global, entries_info.items.len); + const entries = try JSArray.createEmpty(global, entries_info.items.len); for (entries_info.items, 0..) |entry, i| { const obj = JSValue.createEmptyObject(global, 4); diff --git a/src/crash_handler.zig b/src/crash_handler.zig index 3746d94eb9..8ffdc60d88 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -1826,7 +1826,7 @@ pub const js_bindings = struct { pub fn jsGetFeatureData(global: *JSC.JSGlobalObject, _: *JSC.CallFrame) bun.JSError!JSC.JSValue { const obj = JSValue.createEmptyObject(global, 5); const list = bun.Analytics.packed_features_list; - const array = JSValue.createEmptyArray(global, list.len); + const array = try JSValue.createEmptyArray(global, list.len); for (list, 0..) |feature, i| { array.putIndex(global, @intCast(i), bun.String.static(feature).toJS(global)); } diff --git a/src/css/values/color_js.zig b/src/css/values/color_js.zig index 3168174fc9..1d7c7f3d7d 100644 --- a/src/css/values/color_js.zig +++ b/src/css/values/color_js.zig @@ -303,14 +303,14 @@ pub fn jsFunctionColor(globalThis: *JSC.JSGlobalObject, callFrame: *JSC.CallFram return object; }, .@"[rgb]" => { - const object = JSC.JSValue.createEmptyArray(globalThis, 3); + const object = try JSC.JSValue.createEmptyArray(globalThis, 3); object.putIndex(globalThis, 0, JSC.JSValue.jsNumber(rgba.red)); object.putIndex(globalThis, 1, JSC.JSValue.jsNumber(rgba.green)); object.putIndex(globalThis, 2, JSC.JSValue.jsNumber(rgba.blue)); return object; }, .@"[rgba]" => { - const object = JSC.JSValue.createEmptyArray(globalThis, 4); + const object = try JSC.JSValue.createEmptyArray(globalThis, 4); object.putIndex(globalThis, 0, JSC.JSValue.jsNumber(rgba.red)); object.putIndex(globalThis, 1, JSC.JSValue.jsNumber(rgba.green)); object.putIndex(globalThis, 2, JSC.JSValue.jsNumber(rgba.blue)); diff --git a/src/deps/c_ares.zig b/src/deps/c_ares.zig index f9513c3ed7..3b6096d7fd 100644 --- a/src/deps/c_ares.zig +++ b/src/deps/c_ares.zig @@ -203,17 +203,17 @@ pub const struct_hostent = extern struct { // hostent in glibc uses int for h_addrtype and h_length, whereas hostent in winsock2.h uses short. const hostent_int = if (bun.Environment.isWindows) c_short else c_int; - pub fn toJSResponse(this: *struct_hostent, _: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime lookup_name: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *struct_hostent, _: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime lookup_name: []const u8) bun.JSError!JSC.JSValue { if (comptime strings.eqlComptime(lookup_name, "cname")) { // A cname lookup always returns a single record but we follow the common API here. if (this.h_name == null) { - return JSC.JSValue.createEmptyArray(globalThis, 0); + return try JSC.JSValue.createEmptyArray(globalThis, 0); } return bun.String.toJSArray(globalThis, &[_]bun.String{bun.String.fromUTF8(this.h_name.?[0..bun.len(this.h_name.?)])}); } if (this.h_aliases == null) { - return JSC.JSValue.createEmptyArray(globalThis, 0); + return try JSC.JSValue.createEmptyArray(globalThis, 0); } var count: u32 = 0; @@ -221,7 +221,7 @@ pub const struct_hostent = extern struct { count += 1; } - const array = JSC.JSValue.createEmptyArray(globalThis, count); + const array = try JSC.JSValue.createEmptyArray(globalThis, count); count = 0; while (this.h_aliases.?[count]) |alias| { @@ -308,10 +308,10 @@ pub const hostent_with_ttls = struct { hostent: *struct_hostent, ttls: [256]c_int = [_]c_int{-1} ** 256, - pub fn toJSResponse(this: *hostent_with_ttls, _: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime lookup_name: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *hostent_with_ttls, _: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime lookup_name: []const u8) bun.JSError!JSC.JSValue { if (comptime strings.eqlComptime(lookup_name, "a") or strings.eqlComptime(lookup_name, "aaaa")) { if (this.hostent.h_addr_list == null) { - return JSC.JSValue.createEmptyArray(globalThis, 0); + return try JSC.JSValue.createEmptyArray(globalThis, 0); } var count: u32 = 0; @@ -319,7 +319,7 @@ pub const hostent_with_ttls = struct { count += 1; } - const array = JSC.JSValue.createEmptyArray(globalThis, count); + const array = try JSC.JSValue.createEmptyArray(globalThis, count); count = 0; const addressKey = JSC.ZigString.static("address").withEncoding(); @@ -431,8 +431,8 @@ pub const struct_nameinfo = extern struct { node: [*c]u8, service: [*c]u8, - pub fn toJSResponse(this: *struct_nameinfo, _: std.mem.Allocator, globalThis: *JSC.JSGlobalObject) JSC.JSValue { - const array = JSC.JSValue.createEmptyArray(globalThis, 2); // [node, service] + pub fn toJSResponse(this: *struct_nameinfo, _: std.mem.Allocator, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { + const array = try JSC.JSValue.createEmptyArray(globalThis, 2); // [node, service] if (this.node != null) { const node_len = bun.len(this.node); @@ -508,12 +508,9 @@ pub const AddrInfo = extern struct { node: ?*AddrInfo_node = null, name_: ?[*:0]u8 = null, - pub fn toJSArray( - addr_info: *AddrInfo, - globalThis: *JSC.JSGlobalObject, - ) JSC.JSValue { - var node = addr_info.node orelse return JSC.JSValue.createEmptyArray(globalThis, 0); - const array = JSC.JSValue.createEmptyArray(globalThis, node.count()); + pub fn toJSArray(addr_info: *AddrInfo, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { + var node = addr_info.node orelse return try JSC.JSValue.createEmptyArray(globalThis, 0); + const array = try JSC.JSValue.createEmptyArray(globalThis, node.count()); { var j: u32 = 0; @@ -872,7 +869,7 @@ pub const struct_ares_caa_reply = extern struct { value: [*c]u8, length: usize, - pub fn toJSResponse(this: *struct_ares_caa_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *struct_ares_caa_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) bun.JSError!JSC.JSValue { var stack = std.heap.stackFallback(2048, parent_allocator); var arena = bun.ArenaAllocator.init(stack.get()); defer arena.deinit(); @@ -884,7 +881,7 @@ pub const struct_ares_caa_reply = extern struct { count += 1; } - const array = JSC.JSValue.createEmptyArray(globalThis, count); + const array = try JSC.JSValue.createEmptyArray(globalThis, count); caa = this; var i: u32 = 0; @@ -950,7 +947,7 @@ pub const struct_ares_srv_reply = extern struct { weight: c_ushort, port: c_ushort, - pub fn toJSResponse(this: *struct_ares_srv_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *struct_ares_srv_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) bun.JSError!JSC.JSValue { var stack = std.heap.stackFallback(2048, parent_allocator); var arena = bun.ArenaAllocator.init(stack.get()); defer arena.deinit(); @@ -962,7 +959,7 @@ pub const struct_ares_srv_reply = extern struct { count += 1; } - const array = JSC.JSValue.createEmptyArray(globalThis, count); + const array = try JSC.JSValue.createEmptyArray(globalThis, count); srv = this; var i: u32 = 0; @@ -1033,7 +1030,7 @@ pub const struct_ares_mx_reply = extern struct { host: [*c]u8, priority: c_ushort, - pub fn toJSResponse(this: *struct_ares_mx_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *struct_ares_mx_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) bun.JSError!JSC.JSValue { var stack = std.heap.stackFallback(2048, parent_allocator); var arena = bun.ArenaAllocator.init(stack.get()); defer arena.deinit(); @@ -1045,7 +1042,7 @@ pub const struct_ares_mx_reply = extern struct { count += 1; } - const array = JSC.JSValue.createEmptyArray(globalThis, count); + const array = try JSC.JSValue.createEmptyArray(globalThis, count); mx = this; var i: u32 = 0; @@ -1107,7 +1104,7 @@ pub const struct_ares_txt_reply = extern struct { txt: [*c]u8, length: usize, - pub fn toJSResponse(this: *struct_ares_txt_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *struct_ares_txt_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) bun.JSError!JSC.JSValue { var stack = std.heap.stackFallback(2048, parent_allocator); var arena = bun.ArenaAllocator.init(stack.get()); defer arena.deinit(); @@ -1119,13 +1116,13 @@ pub const struct_ares_txt_reply = extern struct { count += 1; } - const array = JSC.JSValue.createEmptyArray(globalThis, count); + const array = try JSC.JSValue.createEmptyArray(globalThis, count); txt = this; var i: u32 = 0; while (txt != null) { var node = txt.?; - array.putIndex(globalThis, i, node.toJS(globalThis, allocator)); + array.putIndex(globalThis, i, try node.toJS(globalThis, allocator)); txt = node.next; i += 1; } @@ -1133,21 +1130,21 @@ pub const struct_ares_txt_reply = extern struct { return array; } - pub fn toJS(this: *struct_ares_txt_reply, globalThis: *JSC.JSGlobalObject, _: std.mem.Allocator) JSC.JSValue { - const array = JSC.JSValue.createEmptyArray(globalThis, 1); + pub fn toJS(this: *struct_ares_txt_reply, globalThis: *JSC.JSGlobalObject, _: std.mem.Allocator) bun.JSError!JSC.JSValue { + const array = try JSC.JSValue.createEmptyArray(globalThis, 1); const value = this.txt[0..this.length]; array.putIndex(globalThis, 0, JSC.ZigString.fromUTF8(value).toJS(globalThis)); return array; } - pub fn toJSForAny(this: *struct_ares_txt_reply, _: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) JSC.JSValue { + pub fn toJSForAny(this: *struct_ares_txt_reply, _: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) bun.JSError!JSC.JSValue { var count: usize = 0; var txt: ?*struct_ares_txt_reply = this; while (txt != null) : (txt = txt.?.next) { count += 1; } - const array = JSC.JSValue.createEmptyArray(globalThis, count); + const array = try JSC.JSValue.createEmptyArray(globalThis, count); txt = this; var i: u32 = 0; @@ -1157,9 +1154,9 @@ pub const struct_ares_txt_reply = extern struct { i += 1; } - return JSC.JSObject.create(.{ + return (try JSC.JSObject.create(.{ .entries = array, - }, globalThis).toJS(); + }, globalThis)).toJS(); } pub fn Callback(comptime Type: type) type { @@ -1209,7 +1206,7 @@ pub const struct_ares_naptr_reply = extern struct { order: c_ushort, preference: c_ushort, - pub fn toJSResponse(this: *struct_ares_naptr_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *struct_ares_naptr_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) bun.JSError!JSC.JSValue { var stack = std.heap.stackFallback(2048, parent_allocator); var arena = bun.ArenaAllocator.init(stack.get()); defer arena.deinit(); @@ -1221,7 +1218,7 @@ pub const struct_ares_naptr_reply = extern struct { count += 1; } - const array = JSC.JSValue.createEmptyArray(globalThis, count); + const array = try JSC.JSValue.createEmptyArray(globalThis, count); naptr = this; var i: u32 = 0; @@ -1301,7 +1298,7 @@ pub const struct_ares_soa_reply = extern struct { expire: c_uint, minttl: c_uint, - pub fn toJSResponse(this: *struct_ares_soa_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *struct_ares_soa_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) bun.JSError!JSC.JSValue { var stack = std.heap.stackFallback(2048, parent_allocator); var arena = bun.ArenaAllocator.init(stack.get()); defer arena.deinit(); @@ -1384,7 +1381,7 @@ pub const struct_any_reply = struct { soa_reply: ?*struct_ares_soa_reply = null, caa_reply: ?*struct_ares_caa_reply = null, - pub fn toJSResponse(this: *struct_any_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) JSC.JSValue { + pub fn toJSResponse(this: *struct_any_reply, parent_allocator: std.mem.Allocator, globalThis: *JSC.JSGlobalObject, comptime _: []const u8) bun.JSError!JSC.JSValue { var stack = std.heap.stackFallback(2048, parent_allocator); var arena = bun.ArenaAllocator.init(stack.get()); defer arena.deinit(); @@ -1394,11 +1391,11 @@ pub const struct_any_reply = struct { return this.toJS(globalThis, allocator); } - fn append(globalThis: *JSC.JSGlobalObject, array: JSC.JSValue, i: *u32, response: JSC.JSValue, comptime lookup_name: []const u8) void { + fn append(globalThis: *JSC.JSGlobalObject, array: JSC.JSValue, i: *u32, response: JSC.JSValue, comptime lookup_name: []const u8) bun.JSError!void { const transformed = if (response.isString()) - JSC.JSObject.create(.{ + (try JSC.JSObject.create(.{ .value = response, - }, globalThis).toJS() + }, globalThis)).toJS() else blk: { bun.assert(response.isObject()); break :blk response; @@ -1414,8 +1411,8 @@ pub const struct_any_reply = struct { i.* += 1; } - fn appendAll(globalThis: *JSC.JSGlobalObject, allocator: std.mem.Allocator, array: JSC.JSValue, i: *u32, reply: anytype, comptime lookup_name: []const u8) void { - const response: JSC.JSValue = if (comptime @hasDecl(@TypeOf(reply.*), "toJSForAny")) + fn appendAll(globalThis: *JSC.JSGlobalObject, allocator: std.mem.Allocator, array: JSC.JSValue, i: *u32, reply: anytype, comptime lookup_name: []const u8) bun.JSError!void { + const response: JSC.JSValue = try if (comptime @hasDecl(@TypeOf(reply.*), "toJSForAny")) reply.toJSForAny(allocator, globalThis, lookup_name) else reply.toJSResponse(allocator, globalThis, lookup_name); @@ -1423,15 +1420,15 @@ pub const struct_any_reply = struct { if (response.isArray()) { var iterator = response.arrayIterator(globalThis); while (iterator.next()) |item| { - append(globalThis, array, i, item, lookup_name); + try append(globalThis, array, i, item, lookup_name); } } else { - append(globalThis, array, i, response, lookup_name); + try append(globalThis, array, i, response, lookup_name); } } - pub fn toJS(this: *struct_any_reply, globalThis: *JSC.JSGlobalObject, allocator: std.mem.Allocator) JSC.JSValue { - const array = JSC.JSValue.createEmptyArray(globalThis, blk: { + pub fn toJS(this: *struct_any_reply, globalThis: *JSC.JSGlobalObject, allocator: std.mem.Allocator) bun.JSError!JSC.JSValue { + const array = try JSC.JSValue.createEmptyArray(globalThis, blk: { var len: usize = 0; inline for (comptime @typeInfo(struct_any_reply).@"struct".fields) |field| { if (comptime std.mem.endsWith(u8, field.name, "_reply")) { @@ -1447,7 +1444,7 @@ pub const struct_any_reply = struct { if (comptime std.mem.endsWith(u8, field.name, "_reply")) { if (@field(this, field.name)) |reply| { const lookup_name = comptime field.name[0 .. field.name.len - "_reply".len]; - appendAll(globalThis, allocator, array, &i, reply, lookup_name); + try appendAll(globalThis, allocator, array, &i, reply, lookup_name); } } } diff --git a/src/deps/uws.zig b/src/deps/uws.zig index 065066c308..c8357ae8cc 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -330,8 +330,8 @@ pub const UpgradedDuplex = struct { }; } - pub fn getJSHandlers(this: *UpgradedDuplex, globalThis: *JSC.JSGlobalObject) JSC.JSValue { - const array = JSC.JSValue.createEmptyArray(globalThis, 4); + pub fn getJSHandlers(this: *UpgradedDuplex, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { + const array = try JSC.JSValue.createEmptyArray(globalThis, 4); array.ensureStillAlive(); { diff --git a/src/dns.zig b/src/dns.zig index 1d33bbe43b..f43455d59b 100644 --- a/src/dns.zig +++ b/src/dns.zig @@ -329,11 +329,11 @@ pub const GetAddrInfo = struct { addrinfo: ?*std.c.addrinfo, list: List, - pub fn toJS(this: *const Any, globalThis: *JSC.JSGlobalObject) ?JSC.JSValue { + pub fn toJS(this: *const Any, globalThis: *JSC.JSGlobalObject) bun.JSError!?JSC.JSValue { return switch (this.*) { - .addrinfo => |addrinfo| addrInfoToJSArray(addrinfo orelse return null, globalThis), + .addrinfo => |addrinfo| try addrInfoToJSArray(addrinfo orelse return null, globalThis), .list => |list| brk: { - const array = JSC.JSValue.createEmptyArray(globalThis, @as(u32, @truncate(list.items.len))); + const array = try JSC.JSValue.createEmptyArray(globalThis, @as(u32, @truncate(list.items.len))); var i: u32 = 0; const items: []const Result = list.items; for (items) |item| { @@ -444,11 +444,8 @@ fn addrInfoCount(addrinfo: *std.c.addrinfo) u32 { return count; } -pub fn addrInfoToJSArray( - addr_info: *std.c.addrinfo, - globalThis: *JSC.JSGlobalObject, -) JSC.JSValue { - const array = JSC.JSValue.createEmptyArray( +pub fn addrInfoToJSArray(addr_info: *std.c.addrinfo, globalThis: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { + const array = try JSC.JSValue.createEmptyArray( globalThis, addrInfoCount(addr_info), ); diff --git a/src/ini.zig b/src/ini.zig index fb2ca0213c..e3f8f2b46a 100644 --- a/src/ini.zig +++ b/src/ini.zig @@ -591,12 +591,12 @@ pub const IniTestingAPIs = struct { default_registry_password.deref(); } - return JSC.JSObject.create(.{ + return (try JSC.JSObject.create(.{ .default_registry_url = default_registry_url, .default_registry_token = default_registry_token, .default_registry_username = default_registry_username, .default_registry_password = default_registry_password, - }, globalThis).toJS(); + }, globalThis)).toJS(); } pub fn parse(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) bun.JSError!JSC.JSValue { diff --git a/src/js/node/http2.ts b/src/js/node/http2.ts index 5ba440a8c8..ddd07604b6 100644 --- a/src/js/node/http2.ts +++ b/src/js/node/http2.ts @@ -66,10 +66,10 @@ const ObjectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty; const DatePrototypeToUTCString = Date.prototype.toUTCString; const DatePrototypeGetMilliseconds = Date.prototype.getMilliseconds; -const [H2FrameParser, assertSettings, getPackedSettings, getUnpackedSettings] = $zig( - "h2_frame_parser.zig", - "createNodeHttp2Binding", -); +const H2FrameParser = $zig("h2_frame_parser.zig", "H2FrameParserConstructor"); +const assertSettings = $newZigFunction("h2_frame_parser.zig", "jsAssertSettings", 1); +const getPackedSettings = $newZigFunction("h2_frame_parser.zig", "jsGetPackedSettings", 1); +const getUnpackedSettings = $newZigFunction("h2_frame_parser.zig", "jsGetUnpackedSettings", 1); const sensitiveHeaders = Symbol.for("nodejs.http2.sensitiveHeaders"); const bunHTTP2Native = Symbol.for("::bunhttp2native::"); diff --git a/src/js/node/net.ts b/src/js/node/net.ts index d7c7665ac1..749af39f41 100644 --- a/src/js/node/net.ts +++ b/src/js/node/net.ts @@ -25,10 +25,6 @@ const { getDefaultHighWaterMark } = require("internal/streams/state"); const EventEmitter = require("node:events"); let dns: typeof import("node:dns"); -const [addServerName, upgradeDuplexToTLS, isNamedPipeSocket, getBufferedAmount] = $zig( - "socket.zig", - "createNodeTLSBinding", -); const normalizedArgsSymbol = Symbol("normalizedArgs"); const { ExceptionWithHostPort } = require("internal/shared"); import type { Socket, SocketHandler, SocketListener } from "bun"; @@ -53,6 +49,11 @@ const BlockList = $zig("node_net_binding.zig", "BlockList"); const newDetachedSocket = $newZigFunction("node_net_binding.zig", "newDetachedSocket", 1); const doConnect = $newZigFunction("node_net_binding.zig", "doConnect", 2); +const addServerName = $newZigFunction("socket.zig", "jsAddServerName", 3); +const upgradeDuplexToTLS = $newZigFunction("socket.zig", "jsUpgradeDuplexToTLS", 2); +const isNamedPipeSocket = $newZigFunction("socket.zig", "jsIsNamedPipeSocket", 1); +const getBufferedAmount = $newZigFunction("socket.zig", "jsGetBufferedAmount", 1); + // IPv4 Segment const v4Seg = "(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])"; const v4Str = `(?:${v4Seg}\\.){3}${v4Seg}`; diff --git a/src/js/node/tls.ts b/src/js/node/tls.ts index 92b898092f..c603536f02 100644 --- a/src/js/node/tls.ts +++ b/src/js/node/tls.ts @@ -2,7 +2,7 @@ const { isArrayBufferView, isTypedArray } = require("node:util/types"); const net = require("node:net"); const { Duplex } = require("node:stream"); -const [addServerName] = $zig("socket.zig", "createNodeTLSBinding"); +const addServerName = $newZigFunction("socket.zig", "jsAddServerName", 3); const { throwNotImplemented } = require("internal/shared"); const { throwOnInvalidTLSArray, DEFAULT_CIPHERS, validateCiphers } = require("internal/tls"); diff --git a/src/js_ast.zig b/src/js_ast.zig index 34c3ccd26e..e5cb2a5ad5 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -1520,7 +1520,7 @@ pub const E = struct { pub fn toJS(this: @This(), allocator: std.mem.Allocator, globalObject: *JSC.JSGlobalObject) ToJSError!JSC.JSValue { const items = this.items.slice(); - var array = JSC.JSValue.createEmptyArray(globalObject, items.len); + var array = try JSC.JSValue.createEmptyArray(globalObject, items.len); array.protect(); defer array.unprotect(); for (items, 0..) |expr, j| { @@ -9126,6 +9126,7 @@ const ToJSError = error{ @"Cannot convert identifier to JS. Try a statically-known value", MacroError, OutOfMemory, + JSError, }; const writeAnyToHasher = bun.writeAnyToHasher; diff --git a/src/logger.zig b/src/logger.zig index 6bc3a78663..09802a763b 100644 --- a/src/logger.zig +++ b/src/logger.zig @@ -771,14 +771,14 @@ pub const Log = struct { } /// unlike toJS, this always produces an AggregateError object - pub fn toJSAggregateError(this: Log, global: *JSC.JSGlobalObject, message: bun.String) bun.OOM!JSC.JSValue { + pub fn toJSAggregateError(this: Log, global: *JSC.JSGlobalObject, message: bun.String) bun.JSError!JSC.JSValue { return global.createAggregateErrorWithArray(message, try this.toJSArray(global, bun.default_allocator)); } - pub fn toJSArray(this: Log, global: *JSC.JSGlobalObject, allocator: std.mem.Allocator) bun.OOM!JSC.JSValue { + pub fn toJSArray(this: Log, global: *JSC.JSGlobalObject, allocator: std.mem.Allocator) bun.JSError!JSC.JSValue { const msgs: []const Msg = this.msgs.items; - const arr = JSC.JSValue.createEmptyArray(global, msgs.len); + const arr = try JSC.JSValue.createEmptyArray(global, msgs.len); for (msgs, 0..) |msg, i| { arr.putIndex(global, @as(u32, @intCast(i)), try msg.toJS(global, allocator)); } diff --git a/src/napi/napi.zig b/src/napi/napi.zig index e20f0a68e2..2fdfe7b16f 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -307,7 +307,7 @@ pub export fn napi_create_array(env_: napi_env, result_: ?*napi_value) napi_stat const result = result_ orelse { return env.invalidArg(); }; - result.set(env, JSValue.createEmptyArray(env.toJS(), 0)); + result.set(env, JSValue.createEmptyArray(env.toJS(), 0) catch return env.setLastError(.pending_exception)); return env.ok(); } pub export fn napi_create_array_with_length(env_: napi_env, length: usize, result_: ?*napi_value) napi_status { @@ -324,7 +324,7 @@ pub export fn napi_create_array_with_length(env_: napi_env, length: usize, resul // Node and V8 convert out-of-bounds array sizes to 0 const len = std.math.cast(u32, length) orelse 0; - const array = JSC.JSValue.createEmptyArray(env.toJS(), len); + const array = JSC.JSValue.createEmptyArray(env.toJS(), len) catch return env.setLastError(.pending_exception); array.ensureStillAlive(); result.set(env, array); return env.ok(); diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 6b7346de1d..27b2fe9d14 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -3491,7 +3491,7 @@ pub const Resolver = struct { .{root_path}, ) catch bun.outOfMemory()) catch bun.outOfMemory(); - return bun.String.toJSArray(globalObject, list.items); + return bun.String.toJSArray(globalObject, list.items) catch .zero; } pub fn loadAsIndex(r: *ThisResolver, dir_info: *DirInfo, extension_order: []const string) ?MatchResult { diff --git a/src/s3/list_objects.zig b/src/s3/list_objects.zig index 9286b7aa57..fff2cad804 100644 --- a/src/s3/list_objects.zig +++ b/src/s3/list_objects.zig @@ -74,7 +74,7 @@ pub const S3ListObjectsV2Result = struct { } } - pub fn toJS(this: @This(), globalObject: *JSGlobalObject) JSValue { + pub fn toJS(this: @This(), globalObject: *JSGlobalObject) bun.JSError!JSValue { const jsResult = JSValue.createEmptyObject(globalObject, 12); if (this.name) |name| { @@ -117,7 +117,7 @@ pub const S3ListObjectsV2Result = struct { } if (this.contents) |contents| { - const jsContents = JSValue.createEmptyArray(globalObject, contents.items.len); + const jsContents = try JSValue.createEmptyArray(globalObject, contents.items.len); for (contents.items, 0..) |item, i| { const objectInfo = JSValue.createEmptyObject(globalObject, 1); @@ -167,7 +167,7 @@ pub const S3ListObjectsV2Result = struct { } if (this.common_prefixes) |common_prefixes| { - const jsCommonPrefixes = JSValue.createEmptyArray(globalObject, common_prefixes.items.len); + const jsCommonPrefixes = try JSValue.createEmptyArray(globalObject, common_prefixes.items.len); for (common_prefixes.items, 0..) |prefix, i| { const jsPrefix = JSValue.createEmptyObject(globalObject, 1); diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index 1e6af437e1..bb5c0ddb11 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -1394,12 +1394,12 @@ pub const PostgresSQLConnection = struct { this.globalObject.bunVM().timer.insert(&this.timer); } - pub fn getQueries(_: *PostgresSQLConnection, thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + pub fn getQueries(_: *PostgresSQLConnection, thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject) bun.JSError!JSC.JSValue { if (js.queriesGetCached(thisValue)) |value| { return value; } - const array = JSC.JSValue.createEmptyArray(globalObject, 0); + const array = try JSC.JSValue.createEmptyArray(globalObject, 0); js.queriesSetCached(thisValue, globalObject, array); return array; diff --git a/src/string.zig b/src/string.zig index af4c10c70b..2025afe79a 100644 --- a/src/string.zig +++ b/src/string.zig @@ -547,10 +547,9 @@ pub const String = extern struct { ) JSC.JSValue; /// calls toJS on all elements of `array`. - pub fn toJSArray(globalObject: *bun.JSC.JSGlobalObject, array: []const bun.String) JSC.JSValue { + pub fn toJSArray(globalObject: *bun.JSC.JSGlobalObject, array: []const bun.String) bun.JSError!JSC.JSValue { JSC.markBinding(@src()); - - return BunString__createArray(globalObject, array.ptr, array.len); + return bun.jsc.fromJSHostValue(BunString__createArray(globalObject, array.ptr, array.len)); } pub fn toZigString(this: String) ZigString { diff --git a/src/valkey/valkey_protocol.zig b/src/valkey/valkey_protocol.zig index 73a92780e9..f7f3e76e87 100644 --- a/src/valkey/valkey_protocol.zig +++ b/src/valkey/valkey_protocol.zig @@ -275,7 +275,7 @@ pub const RESPValue = union(RESPType) { } }, .Array => |array| { - var js_array = JSC.JSValue.createEmptyArray(globalObject, array.len); + var js_array = try JSC.JSValue.createEmptyArray(globalObject, array.len); for (array, 0..) |*item, i| { const js_item = try item.toJSWithOptions(globalObject, options); js_array.putIndex(globalObject, @intCast(i), js_item); @@ -300,7 +300,7 @@ pub const RESPValue = union(RESPType) { return js_obj; }, .Set => |set| { - var js_array = JSC.JSValue.createEmptyArray(globalObject, set.len); + var js_array = try JSC.JSValue.createEmptyArray(globalObject, set.len); for (set, 0..) |*item, i| { const js_item = try item.toJSWithOptions(globalObject, options); js_array.putIndex(globalObject, @intCast(i), js_item); @@ -320,7 +320,7 @@ pub const RESPValue = union(RESPType) { js_obj.put(globalObject, "type", kind_str); // Add the data as an array - var data_array = JSC.JSValue.createEmptyArray(globalObject, push.data.len); + var data_array = try JSC.JSValue.createEmptyArray(globalObject, push.data.len); for (push.data, 0..) |*item, i| { const js_item = try item.toJSWithOptions(globalObject, options); data_array.putIndex(globalObject, @intCast(i), js_item);