diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index bf75c92b1a..a29342e6a1 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -1426,7 +1426,7 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d pub fn finalize(this: *ThisServer) void { httplog("finalize", .{}); - this.js_value.deinit(); + this.js_value.finalize(); this.flags.has_js_deinited = true; this.deinitIfWeCan(); } diff --git a/src/bun.js/bindings/JSRef.zig b/src/bun.js/bindings/JSRef.zig index 46555db798..ee8f697f38 100644 --- a/src/bun.js/bindings/JSRef.zig +++ b/src/bun.js/bindings/JSRef.zig @@ -100,6 +100,11 @@ pub const JSRef = union(enum) { .finalized => {}, } } + + pub fn finalize(this: *@This()) void { + this.deinit(); + this.* = .{ .finalized = {} }; + } }; const bun = @import("bun"); diff --git a/src/sql/mysql/MySQLConnection.zig b/src/sql/mysql/MySQLConnection.zig index f6d73664d4..8dddb303e8 100644 --- a/src/sql/mysql/MySQLConnection.zig +++ b/src/sql/mysql/MySQLConnection.zig @@ -269,7 +269,7 @@ pub fn finalize(this: *MySQLConnection) void { this.stopTimers(); debug("MySQLConnection finalize", .{}); - this.js_value.deinit(); + this.js_value.finalize(); this.deref(); } diff --git a/src/sql/mysql/MySQLQuery.zig b/src/sql/mysql/MySQLQuery.zig index 2388240c9d..45e6d4936d 100644 --- a/src/sql/mysql/MySQLQuery.zig +++ b/src/sql/mysql/MySQLQuery.zig @@ -43,7 +43,6 @@ pub const Status = enum(u8) { }; pub fn deinit(this: *@This()) void { - this.thisValue.deinit(); if (this.statement) |statement| { statement.deref(); } @@ -62,7 +61,7 @@ pub fn finalize(this: *@This()) void { this.statement = null; } - this.thisValue.deinit(); + this.thisValue.finalize(); this.deref(); } @@ -74,18 +73,23 @@ pub fn onWriteFail( ) void { this.status = .fail; const thisValue = this.thisValue.tryGet() orelse return; - defer this.thisValue.deinit(); + defer this.thisValue.downgrade(); const targetValue = this.getTarget(globalObject, true) orelse return; const instance = AnyMySQLError.mysqlErrorToJS(globalObject, "Failed to bind query", err); - + const js_err = instance.toError() orelse instance; + bun.assertf(js_err != .zero, "js_err is zero", .{}); + js_err.ensureStillAlive(); const vm = jsc.VirtualMachine.get(); - const function = vm.rareData().mysql_context.onQueryRejectFn.get().?; + const function = vm.rareData().mysql_context.onQueryRejectFn.get() orelse return; + bun.assertf(function.isCallable(), "onQueryRejectFn is not callable"); const event_loop = vm.eventLoop(); + const js_array = if (queries_array == .zero) .js_undefined else queries_array; + js_array.ensureStillAlive(); event_loop.runCallback(function, globalObject, thisValue, &.{ targetValue, - instance.toError() orelse instance, - queries_array, + js_err, + js_array, }); } @@ -155,11 +159,12 @@ pub fn onJSError(this: *@This(), err: jsc.JSValue, globalObject: *jsc.JSGlobalOb defer this.deref(); this.status = .fail; const thisValue = this.thisValue.tryGet() orelse return; - defer this.thisValue.deinit(); + defer this.thisValue.downgrade(); const targetValue = this.getTarget(globalObject, true) orelse return; var vm = jsc.VirtualMachine.get(); - const function = vm.rareData().mysql_context.onQueryRejectFn.get().?; + const function = vm.rareData().mysql_context.onQueryRejectFn.get() orelse return; + bun.assertf(function.isCallable(), "onQueryRejectFn is not callable", .{}); const event_loop = vm.eventLoop(); var js_error = err.toError() orelse err; if (js_error == .zero) { @@ -217,12 +222,14 @@ pub fn onResult(this: *@This(), result_count: u64, globalObject: *jsc.JSGlobalOb defer if (is_last) { allowGC(thisValue, globalObject); - this.thisValue.deinit(); + this.thisValue.downgrade(); }; const targetValue = this.getTarget(globalObject, is_last) orelse return; const vm = jsc.VirtualMachine.get(); - const function = vm.rareData().mysql_context.onQueryResolveFn.get().?; + const function = vm.rareData().mysql_context.onQueryResolveFn.get() orelse return; + bun.assertf(function.isCallable(), "onQueryResolveFn is not callable", .{}); + const event_loop = vm.eventLoop(); const tag: CommandTag = .{ .SELECT = result_count }; var queries_array = if (connection == .zero) .js_undefined else MySQLConnection.js.queriesGetCached(connection) orelse .js_undefined; diff --git a/src/sql/postgres/PostgresSQLQuery.zig b/src/sql/postgres/PostgresSQLQuery.zig index 12e3dd4fb3..a8a399362f 100644 --- a/src/sql/postgres/PostgresSQLQuery.zig +++ b/src/sql/postgres/PostgresSQLQuery.zig @@ -52,7 +52,6 @@ pub const Status = enum(u8) { }; pub fn deinit(this: *@This()) void { - this.thisValue.deinit(); if (this.statement) |statement| { statement.deref(); } @@ -63,11 +62,7 @@ pub fn deinit(this: *@This()) void { pub fn finalize(this: *@This()) void { debug("PostgresSQLQuery finalize", .{}); - if (this.thisValue == .weak) { - // clean up if is a weak reference, if is a strong reference we need to wait until the query is done - // if we are a strong reference, here is probably a bug because GC'd should not happen - this.thisValue.weak = .zero; - } + this.finalize(); this.deref(); } @@ -81,7 +76,7 @@ pub fn onWriteFail( defer this.deref(); this.status = .fail; const thisValue = this.thisValue.tryGet() orelse return; - defer this.thisValue.deinit(); + defer this.thisValue.downgrade(); const targetValue = this.getTarget(globalObject, true) orelse return; const vm = jsc.VirtualMachine.get(); @@ -99,7 +94,7 @@ pub fn onJSError(this: *@This(), err: jsc.JSValue, globalObject: *jsc.JSGlobalOb defer this.deref(); this.status = .fail; const thisValue = this.thisValue.tryGet() orelse return; - defer this.thisValue.deinit(); + defer this.thisValue.downgrade(); const targetValue = this.getTarget(globalObject, true) orelse return; var vm = jsc.VirtualMachine.get(); @@ -143,7 +138,7 @@ pub fn onResult(this: *@This(), command_tag_str: []const u8, globalObject: *jsc. const thisValue = this.thisValue.tryGet() orelse return; defer if (is_last) { allowGC(thisValue, globalObject); - this.thisValue.deinit(); + this.thisValue.downgrade(); }; const targetValue = this.getTarget(globalObject, is_last) orelse return;