mirror of
https://github.com/oven-sh/bun
synced 2026-02-17 22:32:06 +00:00
Compare commits
14 Commits
claude/fix
...
jarred/wip
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
750502b330 | ||
|
|
2f0307b3d6 | ||
|
|
12c36a9852 | ||
|
|
7bd828bdf9 | ||
|
|
f2498ffe19 | ||
|
|
e59b34a7b8 | ||
|
|
ae1e6ddcc2 | ||
|
|
a50183ae60 | ||
|
|
aadf38c1c6 | ||
|
|
a00c0d5232 | ||
|
|
b827d3d87c | ||
|
|
aa9c3c1a3e | ||
|
|
bded3385c1 | ||
|
|
142296257e |
@@ -1087,6 +1087,7 @@ async function spawnBun(execPath, { args, cwd, timeout, env, stdout, stderr }) {
|
||||
BUN_JSC_randomIntegrityAuditRate: "1.0",
|
||||
BUN_RUNTIME_TRANSPILER_CACHE_PATH: "0",
|
||||
BUN_INSTALL_CACHE_DIR: tmpdirPath,
|
||||
|
||||
SHELLOPTS: isWindows ? "igncr" : undefined, // ignore "\r" on Windows
|
||||
TEST_TMPDIR: tmpdirPath, // Used in Node.js tests.
|
||||
...(typeof remapPort == "number"
|
||||
|
||||
@@ -84,6 +84,8 @@ pub const Optional = struct {
|
||||
const impl = strong.impl orelse return .zero;
|
||||
const result = impl.get();
|
||||
if (result == .zero) {
|
||||
strong.impl = null;
|
||||
impl.deinit();
|
||||
return .zero;
|
||||
}
|
||||
impl.clear();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { define } from "../../codegen/class-definitions";
|
||||
|
||||
const types = ["PostgresSQL", "MySQL"];
|
||||
const types = ["PostgresSQL", "MySQL"] as const;
|
||||
const classes = [];
|
||||
for (const type of types) {
|
||||
classes.push(
|
||||
@@ -9,7 +9,7 @@ for (const type of types) {
|
||||
construct: true,
|
||||
finalize: true,
|
||||
configurable: false,
|
||||
hasPendingActivity: true,
|
||||
hasPendingActivity: type === "PostgresSQL",
|
||||
klass: {
|
||||
// escapeString: {
|
||||
// fn: "escapeString",
|
||||
|
||||
@@ -15,7 +15,7 @@ pub const JSRef = union(enum) {
|
||||
return .{ .weak = .zero };
|
||||
}
|
||||
|
||||
pub fn get(this: *@This()) jsc.JSValue {
|
||||
pub fn get(this: *const @This()) jsc.JSValue {
|
||||
return switch (this.*) {
|
||||
.weak => this.weak,
|
||||
.strong => this.strong.get() orelse .zero,
|
||||
@@ -23,7 +23,7 @@ pub const JSRef = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn tryGet(this: *@This()) ?jsc.JSValue {
|
||||
pub fn tryGet(this: *const @This()) ?jsc.JSValue {
|
||||
return switch (this.*) {
|
||||
.weak => if (this.weak != .zero) this.weak else null,
|
||||
.strong => this.strong.get(),
|
||||
@@ -64,6 +64,21 @@ pub const JSRef = union(enum) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn downgrade(this: *@This()) void {
|
||||
switch (this.*) {
|
||||
.weak => {},
|
||||
.strong => {
|
||||
if (this.strong.trySwap()) |strong| {
|
||||
bun.debugAssert(strong != .zero);
|
||||
this.* = .{ .weak = strong };
|
||||
}
|
||||
},
|
||||
.finalized => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub const finalize = deinit;
|
||||
|
||||
pub fn deinit(this: *@This()) void {
|
||||
switch (this.*) {
|
||||
.weak => {
|
||||
|
||||
@@ -441,13 +441,19 @@ extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject
|
||||
if (name.isNamedColumn()) {
|
||||
propertyNames.add(Identifier::fromString(vm, name.name.toWTFString()));
|
||||
}
|
||||
if (name.isIndexedColumn()) {
|
||||
return encodedJSValue();
|
||||
}
|
||||
|
||||
nonDuplicateCount += !name.isDuplicateColumn();
|
||||
if (nonDuplicateCount == JSFinalObject::maxInlineCapacity) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(globalObject, globalObject->objectPrototype(), nonDuplicateCount);
|
||||
ASSERT_WITH_MESSAGE(nonDuplicateCount < JSFinalObject::maxInlineCapacity, "expected nonDuplicateCount %u to be less than maxInlineCapacity %u", nonDuplicateCount, JSFinalObject::maxInlineCapacity);
|
||||
Structure* structure = Structure::create(vm, globalObject, globalObject->objectPrototype(), JSFinalObject::typeInfo(), JSFinalObject::info(), NonArray, nonDuplicateCount);
|
||||
|
||||
if (owner) {
|
||||
vm.writeBarrier(owner, structure);
|
||||
} else {
|
||||
|
||||
@@ -21,8 +21,7 @@ poll_ref: bun.Async.KeepAlive = .{},
|
||||
globalObject: *jsc.JSGlobalObject,
|
||||
vm: *jsc.VirtualMachine,
|
||||
|
||||
pending_activity_count: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
|
||||
js_value: JSValue = .js_undefined,
|
||||
js_value: jsc.JSRef = .empty(),
|
||||
|
||||
server_version: bun.ByteList = .{},
|
||||
connection_id: u32 = 0,
|
||||
@@ -122,14 +121,16 @@ pub const AuthState = union(enum) {
|
||||
};
|
||||
};
|
||||
|
||||
pub fn hasPendingActivity(this: *MySQLConnection) bool {
|
||||
return this.pending_activity_count.load(.acquire) > 0;
|
||||
}
|
||||
|
||||
fn updateHasPendingActivity(this: *MySQLConnection) void {
|
||||
if (this.js_value == .finalized) return;
|
||||
const a: u32 = if (this.requests.readableLength() > 0) 1 else 0;
|
||||
const b: u32 = if (this.status != .disconnected) 1 else 0;
|
||||
this.pending_activity_count.store(a + b, .release);
|
||||
const c: u32 = if (this.socket.isClosed()) 0 else 1;
|
||||
if (a + b + c == 0) {
|
||||
this.js_value.downgrade();
|
||||
} else {
|
||||
this.js_value.upgrade(this.globalObject);
|
||||
}
|
||||
}
|
||||
|
||||
fn hasDataToSend(this: *@This()) bool {
|
||||
@@ -265,27 +266,34 @@ fn drainInternal(this: *@This()) void {
|
||||
}
|
||||
}
|
||||
pub fn finalize(this: *MySQLConnection) void {
|
||||
this.stopTimers();
|
||||
debug("MySQLConnection finalize", .{});
|
||||
|
||||
this.js_value.finalize();
|
||||
|
||||
this.stopTimers();
|
||||
|
||||
// Ensure we disconnect before finalizing
|
||||
if (this.status != .disconnected) {
|
||||
this.disconnect();
|
||||
}
|
||||
|
||||
this.js_value = .zero;
|
||||
this.deref();
|
||||
}
|
||||
|
||||
pub fn doRef(this: *@This(), _: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue {
|
||||
this.poll_ref.ref(this.vm);
|
||||
if (!this.socket.isClosed()) {
|
||||
this.poll_ref.ref(this.vm);
|
||||
}
|
||||
|
||||
this.updateHasPendingActivity();
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
pub fn doUnref(this: *@This(), _: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue {
|
||||
this.poll_ref.unref(this.vm);
|
||||
|
||||
this.updateHasPendingActivity();
|
||||
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
@@ -309,6 +317,7 @@ pub fn getConnected(this: *MySQLConnection, _: *jsc.JSGlobalObject) JSValue {
|
||||
pub fn doClose(this: *MySQLConnection, globalObject: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue {
|
||||
_ = globalObject;
|
||||
this.disconnect();
|
||||
|
||||
this.write_buffer.clearAndFree(bun.default_allocator);
|
||||
|
||||
return .js_undefined;
|
||||
@@ -351,8 +360,8 @@ pub fn stopTimers(this: *@This()) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getQueriesArray(this: *const @This()) JSValue {
|
||||
return js.queriesGetCached(this.js_value) orelse .js_undefined;
|
||||
pub fn getQueriesArray(this: *@This()) JSValue {
|
||||
return js.queriesGetCached(this.js_value.tryGet() orelse return .js_undefined) orelse .js_undefined;
|
||||
}
|
||||
pub fn failFmt(this: *@This(), error_code: AnyMySQLError.Error, comptime fmt: [:0]const u8, args: anytype) void {
|
||||
const message = bun.handleOom(std.fmt.allocPrint(bun.default_allocator, fmt, args));
|
||||
@@ -362,77 +371,85 @@ pub fn failFmt(this: *@This(), error_code: AnyMySQLError.Error, comptime fmt: [:
|
||||
this.failWithJSValue(err);
|
||||
}
|
||||
pub fn failWithJSValue(this: *MySQLConnection, value: JSValue) void {
|
||||
this.ref();
|
||||
defer this.deref();
|
||||
|
||||
defer this.updateHasPendingActivity();
|
||||
this.stopTimers();
|
||||
if (this.status == .failed) return;
|
||||
this.setStatus(.failed);
|
||||
|
||||
this.ref();
|
||||
defer this.deref();
|
||||
this.setStatus(.failed);
|
||||
const js_value = this.js_value.tryGet() orelse return;
|
||||
const globalObject = this.globalObject;
|
||||
// we defer the refAndClose so the on_close will be called first before we reject the pending requests
|
||||
defer this.refAndClose(value);
|
||||
const on_close = this.consumeOnCloseCallback(this.globalObject) orelse return;
|
||||
|
||||
const on_close = this.consumeOnCloseCallback(globalObject) orelse return;
|
||||
|
||||
const loop = this.vm.eventLoop();
|
||||
loop.enter();
|
||||
defer loop.exit();
|
||||
_ = on_close.call(
|
||||
this.globalObject,
|
||||
this.js_value,
|
||||
globalObject,
|
||||
js_value,
|
||||
&[_]JSValue{
|
||||
value,
|
||||
this.getQueriesArray(),
|
||||
},
|
||||
) catch |e| this.globalObject.reportActiveExceptionAsUnhandled(e);
|
||||
) catch |e| globalObject.reportActiveExceptionAsUnhandled(e);
|
||||
this.closeWithReason(js_value);
|
||||
}
|
||||
|
||||
const FinalizeRequests = struct {
|
||||
connection: *MySQLConnection,
|
||||
task: jsc.AnyTask,
|
||||
pub fn run(this: *FinalizeRequests) void {
|
||||
defer {
|
||||
this.connection.deref();
|
||||
bun.destroy(this);
|
||||
}
|
||||
this.connection.cleanUpRequests(null);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn fail(this: *MySQLConnection, message: []const u8, err: AnyMySQLError.Error) void {
|
||||
debug("failed: {s}: {s}", .{ message, @errorName(err) });
|
||||
if (this.js_value == .finalized) {
|
||||
if (!this.flags.is_finalizing_requests and this.requests.readableLength() > 0) {
|
||||
this.flags.is_finalizing_requests = true;
|
||||
const finalize_requests = bun.new(FinalizeRequests, .{
|
||||
.connection = this,
|
||||
.task = undefined,
|
||||
});
|
||||
finalize_requests.task = jsc.AnyTask.New(FinalizeRequests, FinalizeRequests.run).init(finalize_requests);
|
||||
this.vm.eventLoop().enqueueTask(jsc.Task.init(&finalize_requests.task));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const instance = AnyMySQLError.mysqlErrorToJS(this.globalObject, message, err);
|
||||
this.failWithJSValue(instance);
|
||||
}
|
||||
|
||||
pub fn onClose(this: *MySQLConnection) void {
|
||||
var vm = this.vm;
|
||||
defer vm.drainMicrotasks();
|
||||
this.poll_ref.disable();
|
||||
|
||||
this.setStatus(.disconnected);
|
||||
this.fail("Connection closed", error.ConnectionClosed);
|
||||
this.updateHasPendingActivity();
|
||||
}
|
||||
|
||||
fn refAndClose(this: *@This(), js_reason: ?jsc.JSValue) void {
|
||||
// refAndClose is always called when we wanna to disconnect or when we are closed
|
||||
|
||||
if (!this.socket.isClosed()) {
|
||||
// event loop need to be alive to close the socket
|
||||
this.poll_ref.ref(this.vm);
|
||||
// will unref on socket close
|
||||
this.socket.close();
|
||||
}
|
||||
|
||||
// cleanup requests
|
||||
fn closeWithReason(this: *@This(), js_reason: ?jsc.JSValue) void {
|
||||
this.cleanUpRequests(js_reason);
|
||||
this.socket.close();
|
||||
}
|
||||
|
||||
pub fn disconnect(this: *@This()) void {
|
||||
this.poll_ref.disable();
|
||||
this.stopTimers();
|
||||
if (this.status == .connected) {
|
||||
this.setStatus(.disconnected);
|
||||
this.poll_ref.disable();
|
||||
|
||||
const requests = this.requests.readableSlice(0);
|
||||
this.requests.head = 0;
|
||||
this.requests.count = 0;
|
||||
|
||||
// Fail any pending requests
|
||||
for (requests) |request| {
|
||||
this.finishRequest(request);
|
||||
request.onError(.{
|
||||
.error_code = 2013, // CR_SERVER_LOST
|
||||
.error_message = .{ .temporary = "Lost connection to MySQL server" },
|
||||
}, this.globalObject);
|
||||
}
|
||||
|
||||
this.socket.close();
|
||||
}
|
||||
this.cleanUpRequests(null);
|
||||
this.socket.close();
|
||||
this.updateRef();
|
||||
}
|
||||
|
||||
fn finishRequest(this: *@This(), item: *MySQLQuery) void {
|
||||
@@ -705,6 +722,7 @@ fn SocketHandler(comptime ssl: bool) type {
|
||||
return Socket{ .SocketTCP = s };
|
||||
}
|
||||
pub fn onOpen(this: *MySQLConnection, socket: SocketType) void {
|
||||
this.socket = _socket(socket);
|
||||
this.onOpen(_socket(socket));
|
||||
}
|
||||
|
||||
@@ -715,32 +733,32 @@ fn SocketHandler(comptime ssl: bool) type {
|
||||
pub const onHandshake = if (ssl) onHandshake_ else null;
|
||||
|
||||
pub fn onClose(this: *MySQLConnection, socket: SocketType, _: i32, _: ?*anyopaque) void {
|
||||
_ = socket;
|
||||
this.socket = _socket(socket);
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
pub fn onEnd(this: *MySQLConnection, socket: SocketType) void {
|
||||
_ = socket;
|
||||
this.onClose();
|
||||
this.socket = _socket(socket);
|
||||
socket.close(.normal);
|
||||
}
|
||||
|
||||
pub fn onConnectError(this: *MySQLConnection, socket: SocketType, _: i32) void {
|
||||
_ = socket;
|
||||
this.socket = _socket(socket);
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
pub fn onTimeout(this: *MySQLConnection, socket: SocketType) void {
|
||||
_ = socket;
|
||||
this.socket = _socket(socket);
|
||||
this.onTimeout();
|
||||
}
|
||||
|
||||
pub fn onData(this: *MySQLConnection, socket: SocketType, data: []const u8) void {
|
||||
_ = socket;
|
||||
this.socket = _socket(socket);
|
||||
this.onData(data);
|
||||
}
|
||||
|
||||
pub fn onWritable(this: *MySQLConnection, socket: SocketType) void {
|
||||
_ = socket;
|
||||
this.socket = _socket(socket);
|
||||
this.onDrain();
|
||||
}
|
||||
};
|
||||
@@ -937,13 +955,16 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
|
||||
};
|
||||
}
|
||||
}
|
||||
ptr.setStatus(.connecting);
|
||||
ptr.updateHasPendingActivity();
|
||||
ptr.resetConnectionTimeout();
|
||||
|
||||
ptr.poll_ref.ref(vm);
|
||||
const js_value = ptr.toJS(globalObject);
|
||||
js_value.ensureStillAlive();
|
||||
ptr.js_value = js_value;
|
||||
ptr.js_value.setStrong(js_value, globalObject);
|
||||
|
||||
ptr.setStatus(.connecting);
|
||||
ptr.updateHasPendingActivity();
|
||||
ptr.resetConnectionTimeout();
|
||||
|
||||
js.onconnectSetCached(js_value, globalObject, on_connect);
|
||||
js.oncloseSetCached(js_value, globalObject, on_close);
|
||||
|
||||
@@ -1270,18 +1291,20 @@ fn handleHandshakeDecodePublicKey(this: *MySQLConnection, comptime Context: type
|
||||
|
||||
pub fn consumeOnConnectCallback(this: *const @This(), globalObject: *jsc.JSGlobalObject) ?jsc.JSValue {
|
||||
debug("consumeOnConnectCallback", .{});
|
||||
const on_connect = js.onconnectGetCached(this.js_value) orelse return null;
|
||||
const this_value = this.js_value.tryGet() orelse return null;
|
||||
const on_connect = js.onconnectGetCached(this_value) orelse return null;
|
||||
debug("consumeOnConnectCallback exists", .{});
|
||||
|
||||
js.onconnectSetCached(this.js_value, globalObject, .zero);
|
||||
js.onconnectSetCached(this_value, globalObject, .zero);
|
||||
return on_connect;
|
||||
}
|
||||
|
||||
pub fn consumeOnCloseCallback(this: *const @This(), globalObject: *jsc.JSGlobalObject) ?jsc.JSValue {
|
||||
debug("consumeOnCloseCallback", .{});
|
||||
const on_close = js.oncloseGetCached(this.js_value) orelse return null;
|
||||
const this_value = this.js_value.tryGet() orelse return null;
|
||||
const on_close = js.oncloseGetCached(this_value) orelse return null;
|
||||
debug("consumeOnCloseCallback exists", .{});
|
||||
js.oncloseSetCached(this.js_value, globalObject, .zero);
|
||||
js.oncloseSetCached(this_value, globalObject, .zero);
|
||||
return on_close;
|
||||
}
|
||||
|
||||
@@ -1291,15 +1314,20 @@ pub fn setStatus(this: *@This(), status: ConnectionState) void {
|
||||
|
||||
this.status = status;
|
||||
this.resetConnectionTimeout();
|
||||
if (this.vm.isShuttingDown()) return;
|
||||
if (this.vm.isShuttingDown()) {
|
||||
this.poll_ref.disable();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
.connected => {
|
||||
const on_connect = this.consumeOnConnectCallback(this.globalObject) orelse return;
|
||||
const js_value = this.js_value;
|
||||
const js_value = this.js_value.tryGet() orelse return;
|
||||
js_value.ensureStillAlive();
|
||||
this.globalObject.queueMicrotask(on_connect, &[_]JSValue{ JSValue.jsNull(), js_value });
|
||||
this.poll_ref.unref(this.vm);
|
||||
},
|
||||
.disconnected, .failed => {
|
||||
this.poll_ref.disable();
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
@@ -1307,11 +1335,6 @@ pub fn setStatus(this: *@This(), status: ConnectionState) void {
|
||||
|
||||
pub fn updateRef(this: *@This()) void {
|
||||
this.updateHasPendingActivity();
|
||||
if (this.pending_activity_count.raw > 0) {
|
||||
this.poll_ref.ref(this.vm);
|
||||
} else {
|
||||
this.poll_ref.unref(this.vm);
|
||||
}
|
||||
}
|
||||
pub fn handleAuth(this: *MySQLConnection, comptime Context: type, reader: NewReader(Context), header_length: u24) !void {
|
||||
const first_byte = try reader.int(u8);
|
||||
@@ -1765,7 +1788,7 @@ fn handleResultSetOK(this: *MySQLConnection, request: *MySQLQuery, statement: *M
|
||||
request.onResult(
|
||||
statement.result_count,
|
||||
this.globalObject,
|
||||
this.js_value,
|
||||
this.js_value.tryGet() orelse return,
|
||||
this.flags.is_ready_for_query,
|
||||
last_insert_id,
|
||||
affected_rows,
|
||||
@@ -1871,10 +1894,10 @@ pub fn handleResultSet(this: *MySQLConnection, comptime Context: type, reader: N
|
||||
.bigint = request.flags.bigint,
|
||||
};
|
||||
var structure: JSValue = .js_undefined;
|
||||
var cached_structure: ?CachedStructure = null;
|
||||
var cached_structure: ?*CachedStructure = null;
|
||||
switch (request.flags.result_mode) {
|
||||
.objects => {
|
||||
cached_structure = statement.structure(this.js_value, this.globalObject);
|
||||
cached_structure = statement.structure(this.js_value.tryGet() orelse return, this.globalObject);
|
||||
structure = cached_structure.?.jsValue() orelse .js_undefined;
|
||||
},
|
||||
.raw, .values => {
|
||||
|
||||
@@ -66,11 +66,7 @@ pub fn finalize(this: *@This()) void {
|
||||
this.statement = null;
|
||||
}
|
||||
|
||||
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.thisValue.finalize();
|
||||
this.deref();
|
||||
}
|
||||
|
||||
@@ -82,7 +78,7 @@ pub fn onWriteFail(
|
||||
) void {
|
||||
this.status = .fail;
|
||||
const thisValue = this.thisValue.get();
|
||||
defer this.thisValue.deinit();
|
||||
defer this.thisValue.downgrade();
|
||||
const targetValue = this.getTarget(globalObject, true);
|
||||
if (thisValue == .zero or targetValue == .zero) {
|
||||
return;
|
||||
@@ -168,7 +164,7 @@ pub fn onJSError(this: *@This(), err: jsc.JSValue, globalObject: *jsc.JSGlobalOb
|
||||
defer this.deref();
|
||||
this.status = .fail;
|
||||
const thisValue = this.thisValue.get();
|
||||
defer this.thisValue.deinit();
|
||||
defer this.thisValue.downgrade();
|
||||
const targetValue = this.getTarget(globalObject, true);
|
||||
if (thisValue == .zero or targetValue == .zero) {
|
||||
return;
|
||||
@@ -227,8 +223,7 @@ pub fn onResult(this: *@This(), result_count: u64, globalObject: *jsc.JSGlobalOb
|
||||
this.status = .partial_response;
|
||||
}
|
||||
defer if (is_last) {
|
||||
allowGC(thisValue, globalObject);
|
||||
this.thisValue.deinit();
|
||||
this.thisValue.downgrade();
|
||||
};
|
||||
if (thisValue == .zero or targetValue == .zero) {
|
||||
return;
|
||||
@@ -324,9 +319,9 @@ pub fn call(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSEr
|
||||
|
||||
return this_value;
|
||||
}
|
||||
pub fn setPendingValue(this: *@This(), globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue {
|
||||
pub fn setPendingValue(_: *@This(), globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue {
|
||||
const result = callframe.argument(0);
|
||||
const thisValue = this.thisValue.tryGet() orelse return .js_undefined;
|
||||
const thisValue = callframe.this();
|
||||
js.pendingValueSetCached(thisValue, globalObject, result);
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
@@ -103,9 +103,9 @@ pub fn checkForDuplicateFields(this: *@This()) void {
|
||||
this.fields_flags = flags;
|
||||
}
|
||||
|
||||
pub fn structure(this: *MySQLStatement, owner: JSValue, globalObject: *jsc.JSGlobalObject) CachedStructure {
|
||||
pub fn structure(this: *MySQLStatement, owner: JSValue, globalObject: *jsc.JSGlobalObject) *CachedStructure {
|
||||
if (this.cached_structure.has()) {
|
||||
return this.cached_structure;
|
||||
return &this.cached_structure;
|
||||
}
|
||||
this.checkForDuplicateFields();
|
||||
|
||||
@@ -155,7 +155,7 @@ pub fn structure(this: *MySQLStatement, owner: JSValue, globalObject: *jsc.JSGlo
|
||||
), null);
|
||||
}
|
||||
|
||||
return this.cached_structure;
|
||||
return &this.cached_structure;
|
||||
}
|
||||
pub const Param = struct {
|
||||
type: types.FieldType,
|
||||
|
||||
@@ -8,7 +8,7 @@ pub const Row = struct {
|
||||
bigint: bool = false,
|
||||
globalObject: *jsc.JSGlobalObject,
|
||||
|
||||
pub fn toJS(this: *Row, globalObject: *jsc.JSGlobalObject, array: JSValue, structure: JSValue, flags: SQLDataCell.Flags, result_mode: SQLQueryResultMode, cached_structure: ?CachedStructure) JSValue {
|
||||
pub fn toJS(this: *Row, globalObject: *jsc.JSGlobalObject, array: JSValue, structure: JSValue, flags: SQLDataCell.Flags, result_mode: SQLQueryResultMode, cached_structure: ?*const CachedStructure) JSValue {
|
||||
var names: ?[*]jsc.JSObject.ExternColumnIdentifier = null;
|
||||
var names_count: u32 = 0;
|
||||
if (cached_structure) |c| {
|
||||
|
||||
@@ -902,7 +902,7 @@ pub const Putter = struct {
|
||||
count: usize = 0,
|
||||
globalObject: *jsc.JSGlobalObject,
|
||||
|
||||
pub fn toJS(this: *Putter, globalObject: *jsc.JSGlobalObject, array: JSValue, structure: JSValue, flags: SQLDataCell.Flags, result_mode: PostgresSQLQueryResultMode, cached_structure: ?PostgresCachedStructure) JSValue {
|
||||
pub fn toJS(this: *Putter, globalObject: *jsc.JSGlobalObject, array: JSValue, structure: JSValue, flags: SQLDataCell.Flags, result_mode: PostgresSQLQueryResultMode, cached_structure: ?*PostgresCachedStructure) JSValue {
|
||||
var names: ?[*]jsc.JSObject.ExternColumnIdentifier = null;
|
||||
var names_count: u32 = 0;
|
||||
if (cached_structure) |c| {
|
||||
|
||||
@@ -1362,7 +1362,7 @@ pub fn on(this: *PostgresSQLConnection, comptime MessageType: @Type(.enum_litera
|
||||
|
||||
var statement = request.statement orelse return error.ExpectedStatement;
|
||||
var structure: JSValue = .js_undefined;
|
||||
var cached_structure: ?PostgresCachedStructure = null;
|
||||
var cached_structure: ?*PostgresCachedStructure = null;
|
||||
// explicit use switch without else so if new modes are added, we don't forget to check for duplicate fields
|
||||
switch (request.flags.result_mode) {
|
||||
.objects => {
|
||||
|
||||
@@ -67,11 +67,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.thisValue.finalize();
|
||||
this.deref();
|
||||
}
|
||||
|
||||
@@ -85,7 +81,7 @@ pub fn onWriteFail(
|
||||
defer this.deref();
|
||||
this.status = .fail;
|
||||
const thisValue = this.thisValue.get();
|
||||
defer this.thisValue.deinit();
|
||||
defer this.thisValue.downgrade();
|
||||
const targetValue = this.getTarget(globalObject, true);
|
||||
if (thisValue == .zero or targetValue == .zero) {
|
||||
return;
|
||||
@@ -106,7 +102,7 @@ pub fn onJSError(this: *@This(), err: jsc.JSValue, globalObject: *jsc.JSGlobalOb
|
||||
defer this.deref();
|
||||
this.status = .fail;
|
||||
const thisValue = this.thisValue.get();
|
||||
defer this.thisValue.deinit();
|
||||
defer this.thisValue.downgrade();
|
||||
const targetValue = this.getTarget(globalObject, true);
|
||||
if (thisValue == .zero or targetValue == .zero) {
|
||||
return;
|
||||
@@ -154,8 +150,7 @@ pub fn onResult(this: *@This(), command_tag_str: []const u8, globalObject: *jsc.
|
||||
this.status = .partial_response;
|
||||
}
|
||||
defer if (is_last) {
|
||||
allowGC(thisValue, globalObject);
|
||||
this.thisValue.deinit();
|
||||
this.thisValue.downgrade();
|
||||
};
|
||||
if (thisValue == .zero or targetValue == .zero) {
|
||||
return;
|
||||
@@ -257,9 +252,9 @@ pub fn doDone(this: *@This(), globalObject: *jsc.JSGlobalObject, _: *jsc.CallFra
|
||||
this.flags.is_done = true;
|
||||
return .js_undefined;
|
||||
}
|
||||
pub fn setPendingValue(this: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue {
|
||||
pub fn setPendingValue(_: *PostgresSQLQuery, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue {
|
||||
const result = callframe.argument(0);
|
||||
const thisValue = this.thisValue.tryGet() orelse return .js_undefined;
|
||||
const thisValue = callframe.this();
|
||||
js.pendingValueSetCached(thisValue, globalObject, result);
|
||||
return .js_undefined;
|
||||
}
|
||||
|
||||
@@ -107,9 +107,9 @@ pub fn deinit(this: *PostgresSQLStatement) void {
|
||||
bun.default_allocator.destroy(this);
|
||||
}
|
||||
|
||||
pub fn structure(this: *PostgresSQLStatement, owner: JSValue, globalObject: *jsc.JSGlobalObject) PostgresCachedStructure {
|
||||
pub fn structure(this: *PostgresSQLStatement, owner: JSValue, globalObject: *jsc.JSGlobalObject) *PostgresCachedStructure {
|
||||
if (this.cached_structure.has()) {
|
||||
return this.cached_structure;
|
||||
return &this.cached_structure;
|
||||
}
|
||||
this.checkForDuplicateFields();
|
||||
|
||||
@@ -157,7 +157,7 @@ pub fn structure(this: *PostgresSQLStatement, owner: JSValue, globalObject: *jsc
|
||||
), null);
|
||||
}
|
||||
|
||||
return this.cached_structure;
|
||||
return &this.cached_structure;
|
||||
}
|
||||
|
||||
const debug = bun.Output.scoped(.Postgres, .visible);
|
||||
|
||||
@@ -4,4 +4,5 @@ pub const ConnectionFlags = packed struct {
|
||||
use_unnamed_prepared_statements: bool = false,
|
||||
waiting_to_prepare: bool = false,
|
||||
has_backpressure: bool = false,
|
||||
is_finalizing_requests: bool = false,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user