From e2198b95ef69ee735a550a55efd15cf438e43b1f Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Wed, 18 Oct 2023 21:23:29 -0700 Subject: [PATCH] try some things --- src/bun.js/bindings/bindings.zig | 44 ++++++++--- .../bindings/sqlite/JSSQLiteStatement.cpp | 4 +- src/bun.js/bindings/structure.cpp | 24 +++++- src/js/bun/sql.ts | 16 +++- src/js/out/InternalModuleRegistryConstants.h | 6 +- src/sql/postgres.zig | 79 +++++++++++++------ 6 files changed, 128 insertions(+), 45 deletions(-) diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 2019f21b77..58fcb65916 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -45,13 +45,13 @@ pub const JSObject = extern struct { }); } - extern fn JSC__createStructure(*JSC.JSGlobalObject, u32, names: [*]bun.String) JSC.JSValue; + extern fn JSC__createStructure(*JSC.JSGlobalObject, *JSC.JSCell, u32, names: [*]bun.String) JSC.JSValue; extern fn JSC__createEmptyObjectWithStructure(*JSC.JSGlobalObject, *anyopaque) JSC.JSValue; extern fn JSC__putDirectOffset(*JSC.VM, JSC.JSValue, offset: u32, JSC.JSValue) void; - pub fn createStructure(global: *JSGlobalObject, length: u32, names: [*]bun.String) JSValue { + pub fn createStructure(global: *JSGlobalObject, owner: JSC.JSValue, length: u32, names: [*]bun.String) JSValue { JSC.markBinding(@src()); - return JSC__createStructure(global, length, names); + return JSC__createStructure(global, owner.asCell(), length, names); } pub fn uninitialized(global: *JSGlobalObject, structure: JSC.JSValue) JSValue { @@ -4300,6 +4300,7 @@ pub const JSValue = enum(JSValueReprInt) { method, headers, status, + statusText, url, body, data, @@ -4969,6 +4970,34 @@ pub const JSValue = enum(JSValueReprInt) { pub inline fn deserialize(bytes: []const u8, global: *JSGlobalObject) JSValue { return Bun__JSValue__deserialize(global, bytes.ptr, @intCast(bytes.len)); } + + extern fn Bun__serializeJSValue(global: *JSC.JSGlobalObject, value: JSValue) SerializedScriptValue.External; + extern fn Bun__SerializedScriptSlice__free(*anyopaque) void; + + pub const SerializedScriptValue = struct { + data: []const u8, + handle: *anyopaque, + + const External = extern struct { + bytes: ?[*]const u8, + size: isize, + handle: ?*anyopaque, + }; + + pub inline fn deinit(self: @This()) void { + Bun__SerializedScriptSlice__free(self.handle); + } + }; + + /// Throws a JS exception and returns null if the serialization fails, otherwise returns a SerializedScriptValue. + /// Must be freed when you are done with the bytes. + pub inline fn serialize(this: JSValue, global: *JSGlobalObject) ?SerializedScriptValue { + const value = Bun__serializeJSValue(global, this); + return if (value.bytes) |bytes| + .{ .data = bytes[0..@intCast(value.size)], .handle = value.handle.? } + else + null; + } }; extern "c" fn AsyncContextFrame__withAsyncContextIfNeeded(global: *JSGlobalObject, callback: JSValue) JSValue; @@ -5076,13 +5105,6 @@ pub const VM = extern struct { pub fn deferGC(this: *VM, ctx: ?*anyopaque, callback: *const fn (ctx: ?*anyopaque) callconv(.C) void) void { cppFn("deferGC", .{ this, ctx, callback }); } - - extern fn JSC__runInDeferralContext(this: *VM, *anyopaque, *const fn (ctx: ?*anyopaque) callconv(.C) void) void; - pub fn runInDeferralContext(this: *VM, ctx: ?*anyopaque, callback: *const fn (ctx: ?*anyopaque) callconv(.C) void) void { - JSC.markBinding(@src()); - JSC__runInDeferralContext(this, ctx, callback); - } - extern fn JSC__VM__reportExtraMemory(*VM, usize) void; pub fn reportExtraMemory(this: *VM, size: usize) void { JSC.markBinding(@src()); @@ -5876,7 +5898,7 @@ pub fn initialize() void { \\ \\ https://github.com/oven-sh/webkit/blob/main/Source/JavaScriptCore/runtime/OptionsList.h \\ - \\Environment variables must be prefixed with "BUN_JSC_". This code runs before .env files are loaded, so those won't work here. + \\Environment variables must be prefixed with "BUN_JSC_". This code runs before .env files are loaded, so those won't work here. \\ \\Warning: options change between releases of Bun and WebKit without notice. This is not a stable API, you should not rely on it beyond debugging something, and it may be removed entirely in a future version of Bun. , diff --git a/src/bun.js/bindings/sqlite/JSSQLiteStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLiteStatement.cpp index 4c2b0caaf8..47effa087e 100644 --- a/src/bun.js/bindings/sqlite/JSSQLiteStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLiteStatement.cpp @@ -1060,7 +1060,7 @@ static const HashTableValue JSSQLiteStatementConstructorTableValues[] = { { "deserialize"_s, static_cast(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSQLStatementDeserialize, 2 } }, }; -const ClassInfo JSSQLStatementConstructor::s_info = { "SQLStatement"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSQLStatementConstructor) }; +const ClassInfo JSSQLiteStatementConstructor::s_info = { "SQLStatement"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSQLiteStatementConstructor) }; void JSSQLiteStatementConstructor::finishCreation(VM& vm) { @@ -1632,7 +1632,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementFunctionFinalize, (JSC::JSGlobalObject * RELEASE_AND_RETURN(scope, JSValue::encode(jsUndefined())); } -const ClassInfo JSSQLStatement::s_info = { "SQLStatement"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSQLStatement) }; +const ClassInfo JSSQLiteStatement::s_info = { "SQLStatement"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSQLiteStatement) }; /* Hash table for prototype */ static const HashTableValue JSSQLiteStatementTableValues[] = { diff --git a/src/bun.js/bindings/structure.cpp b/src/bun.js/bindings/structure.cpp index 4db9141c07..3d09db9378 100644 --- a/src/bun.js/bindings/structure.cpp +++ b/src/bun.js/bindings/structure.cpp @@ -7,14 +7,25 @@ namespace Bun { using namespace JSC; -extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject, unsigned int inlineCapacity, BunString* names) +extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject, JSC::JSCell* owner, unsigned int inlineCapacity, BunString* names) { auto& vm = globalObject->vm(); Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(globalObject, globalObject->objectPrototype(), inlineCapacity); + if (owner) { + vm.writeBarrier(owner, structure); + } else { + vm.writeBarrier(structure); + } + ensureStillAliveHere(structure); + + PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + for (unsigned i = 0; i < inlineCapacity; i++) { + propertyNames.add(Identifier::fromString(vm, Bun::toWTFString(names[i]))); + } + PropertyOffset offset = 0; for (unsigned i = 0; i < inlineCapacity; i++) { - JSC::PropertyName ident = JSC::PropertyName(JSC::Identifier::fromString(vm, Bun::toWTFString(names[i]).isolatedCopy())); - structure = structure->addPropertyTransition(vm, structure, ident, 0, offset); + structure = structure->addPropertyTransition(vm, structure, propertyNames[i], 0, offset); } return JSValue::encode(structure); @@ -23,7 +34,12 @@ extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject extern "C" EncodedJSValue JSC__createEmptyObjectWithStructure(JSC::JSGlobalObject* globalObject, JSC::Structure* structure) { auto& vm = globalObject->vm(); - return JSValue::encode(JSC::constructEmptyObject(vm, structure)); + auto* object = JSC::constructEmptyObject(vm, structure); + + ensureStillAliveHere(object); + vm.writeBarrier(object); + + return JSValue::encode(object); } extern "C" void JSC__runInDeferralContext(JSC::VM* vm, void* ptr, void (*callback)(void*)) diff --git a/src/js/bun/sql.ts b/src/js/bun/sql.ts index fa2a13c5a2..7391ea9733 100644 --- a/src/js/bun/sql.ts +++ b/src/js/bun/sql.ts @@ -127,8 +127,20 @@ class Query extends PublicPromise { Object.defineProperty(Query, Symbol.species, { value: PublicPromise }); Object.defineProperty(Query, Symbol.toStringTag, { value: "Query" }); init( - (query, result) => query.resolve(result), - (query, reject) => query.reject(reject), + (query, result) => { + try { + query.resolve(result); + } catch (e) { + console.log(e); + } + }, + (query, reject) => { + try { + query.reject(reject); + } catch (e) { + console.log(e); + } + }, ); function createConnection({ hostname, port, username, password, tls, query, database }, onConnected, onClose) { diff --git a/src/js/out/InternalModuleRegistryConstants.h b/src/js/out/InternalModuleRegistryConstants.h index f7f47288cc..3ee91530c0 100644 --- a/src/js/out/InternalModuleRegistryConstants.h +++ b/src/js/out/InternalModuleRegistryConstants.h @@ -10,7 +10,7 @@ static constexpr ASCIILiteral BunFFICode = ASCIILiteral::fromLiteralUnsafe("(fun // // -static constexpr ASCIILiteral BunSqlCode = ASCIILiteral::fromLiteralUnsafe("(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return _createConnection(hostname, Number(port), username || \"\", password || \"\", database || \"\", tls || null, query || \"\", onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", port = Number(port), !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err, result) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err, @undefined);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), connectedHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { createConnection: _createConnection, createQuery, PostgresSQLConnection, init } = @lazy(\"bun:sql\");\n\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_reject](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.@then.@apply(this, arguments);\n }\n catch() {\n return this[_run](), super.@catch.@apply(this, arguments);\n }\n finally() {\n return this[_run](), super.@finally.@apply(this, arguments);\n }\n}\nObject.defineProperty(Query, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query, Symbol.toStringTag, { value: \"Query\" });\ninit((query, result) => query.resolve(result), (query, reject) => query.reject(reject));\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"); +static constexpr ASCIILiteral BunSqlCode = ASCIILiteral::fromLiteralUnsafe("(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return _createConnection(hostname, Number(port), username || \"\", password || \"\", database || \"\", tls || null, query || \"\", onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", port = Number(port), !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err, result) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err, @undefined);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), connectedHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { createConnection: _createConnection, createQuery, PostgresSQLConnection, init } = @lazy(\"bun:sql\");\n\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_reject](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.@then.@apply(this, arguments);\n }\n catch() {\n return this[_run](), super.@catch.@apply(this, arguments);\n }\n finally() {\n return this[_run](), super.@finally.@apply(this, arguments);\n }\n}\nObject.defineProperty(Query, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query, Symbol.toStringTag, { value: \"Query\" });\ninit((query, result) => {\n try {\n query.resolve(result);\n } catch (e) {\n console.log(e);\n }\n}, (query, reject) => {\n try {\n query.reject(reject);\n } catch (e) {\n console.log(e);\n }\n});\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"); // // @@ -263,7 +263,7 @@ static constexpr ASCIILiteral BunFFICode = ASCIILiteral::fromLiteralUnsafe("(fun // // -static constexpr ASCIILiteral BunSqlCode = ASCIILiteral::fromLiteralUnsafe("(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return _createConnection(hostname, Number(port), username || \"\", password || \"\", database || \"\", tls || null, query || \"\", onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", port = Number(port), !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err, result) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err, @undefined);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), connectedHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { createConnection: _createConnection, createQuery, PostgresSQLConnection, init } = @lazy(\"bun:sql\");\n\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_reject](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.@then.@apply(this, arguments);\n }\n catch() {\n return this[_run](), super.@catch.@apply(this, arguments);\n }\n finally() {\n return this[_run](), super.@finally.@apply(this, arguments);\n }\n}\nObject.defineProperty(Query, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query, Symbol.toStringTag, { value: \"Query\" });\ninit((query, result) => query.resolve(result), (query, reject) => query.reject(reject));\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"); +static constexpr ASCIILiteral BunSqlCode = ASCIILiteral::fromLiteralUnsafe("(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return _createConnection(hostname, Number(port), username || \"\", password || \"\", database || \"\", tls || null, query || \"\", onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", port = Number(port), !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err, result) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err, @undefined);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), connectedHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { createConnection: _createConnection, createQuery, PostgresSQLConnection, init } = @lazy(\"bun:sql\");\n\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_reject](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.@then.@apply(this, arguments);\n }\n catch() {\n return this[_run](), super.@catch.@apply(this, arguments);\n }\n finally() {\n return this[_run](), super.@finally.@apply(this, arguments);\n }\n}\nObject.defineProperty(Query, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query, Symbol.toStringTag, { value: \"Query\" });\ninit((query, result) => {\n try {\n query.resolve(result);\n } catch (e) {\n console.log(e);\n }\n}, (query, reject) => {\n try {\n query.reject(reject);\n } catch (e) {\n console.log(e);\n }\n});\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"); // // @@ -517,7 +517,7 @@ static constexpr ASCIILiteral BunFFICode = ASCIILiteral::fromLiteralUnsafe("(fun // // -static constexpr ASCIILiteral BunSqlCode = ASCIILiteral::fromLiteralUnsafe("(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return _createConnection(hostname, Number(port), username || \"\", password || \"\", database || \"\", tls || null, query || \"\", onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", port = Number(port), !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err, result) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err, @undefined);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), connectedHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { createConnection: _createConnection, createQuery, PostgresSQLConnection, init } = @lazy(\"bun:sql\");\n\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_reject](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.@then.@apply(this, arguments);\n }\n catch() {\n return this[_run](), super.@catch.@apply(this, arguments);\n }\n finally() {\n return this[_run](), super.@finally.@apply(this, arguments);\n }\n}\nObject.defineProperty(Query, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query, Symbol.toStringTag, { value: \"Query\" });\ninit((query, result) => query.resolve(result), (query, reject) => query.reject(reject));\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"); +static constexpr ASCIILiteral BunSqlCode = ASCIILiteral::fromLiteralUnsafe("(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return _createConnection(hostname, Number(port), username || \"\", password || \"\", database || \"\", tls || null, query || \"\", onConnected, onClose);\n}, normalizeStrings = function(strings) {\n if (@isJSArray(strings))\n return strings.join(\"\?\");\n return strings + \"\";\n}, loadOptions = function(o) {\n var hostname, port, username, password, database, tls, url, query, adapter;\n const env = Bun.env;\n if (typeof o === \"undefined\" || typeof o === \"string\" && o.length === 0) {\n const urlString = env.POSTGRES_URL || env.DATABASE_URL || env.PGURL || env.PG_URL;\n if (urlString)\n url = new URL(urlString), o = {};\n } else if (o && typeof o === \"object\") {\n if (o instanceof URL)\n url = o;\n else if (o\?.url) {\n const _url = o.url;\n if (typeof _url === \"string\")\n url = new URL(_url);\n else if (_url && typeof _url === \"object\" && _url instanceof URL)\n url = _url;\n }\n } else if (typeof o === \"string\")\n url = new URL(o);\n if (url) {\n if ({ hostname, port, username, password, protocol: adapter } = o = url, adapter[adapter.length - 1] === \":\")\n adapter = adapter.slice(0, -1);\n const queryObject = url.searchParams.toJSON();\n query = \"\";\n for (let key in queryObject)\n query += `${encodeURIComponent(key)}=${encodeURIComponent(queryObject[key])} `;\n query = query.trim();\n }\n if (!o)\n o = {};\n if (hostname ||= o.hostname || o.host || env.PGHOST || \"localhost\", port ||= Number(o.port || env.PGPORT || 5432), username ||= o.username || o.user || env.PGUSERNAME || env.PGUSER || env.USER || env.USERNAME || \"postgres\", database ||= o.database || o.db || (url\?.pathname \?\? \"\").slice(1) || env.PGDATABASE || username, password ||= o.password || o.pass || env.PGPASSWORD || \"\", tls ||= o.tls || o.ssl, adapter ||= o.adapter || \"postgres\", port = Number(port), !Number.isSafeInteger(port) || port < 1 || port > 65535)\n throw new Error(`Invalid port: ${port}`);\n if (adapter && !(adapter === \"postgres\" || adapter === \"postgresql\"))\n throw new Error(`Unsupported adapter: ${adapter}. Only \\\"postgres\\\" is supported for now`);\n return { hostname, port, username, password, database, tls, query };\n}, SQL = function(o) {\n var connection, connected = !1, connecting = !1, closed = !1, onConnect = [], connectionInfo = loadOptions(o);\n function connectedHandler(query, handle, err) {\n if (err)\n return query.reject(err);\n if (!connected)\n return query.reject(new Error(\"Not connected\"));\n if (query.cancelled)\n return query.reject(new Error(\"Query cancelled\"));\n handle.run(connection, query);\n }\n function pendingConnectionHandler(query, handle) {\n if (onConnect.push((err) => connectedHandler(query, handle, err)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n }\n function closedConnectionHandler(query, handle) {\n query.reject(new Error(\"Connection closed\"));\n }\n function onConnected(err, result) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err, @undefined);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), connectedHandler);\n }\n function closedSQL(strings, values) {\n return new Query(@undefined, closedConnectionHandler);\n }\n function pendingSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), pendingConnectionHandler);\n }\n function sql(strings, ...values) {\n if (closed)\n return closedSQL(strings, values);\n if (connected)\n return connectedSQL(strings, values);\n return pendingSQL(strings, values);\n }\n return sql.connect = () => {\n if (closed)\n return @Promise.reject(new Error(\"Connection closed\"));\n if (connected)\n return @Promise.resolve(sql);\n var { resolve, reject, promise } = @Promise.withResolvers();\n if (onConnect.push((err) => err \? reject(err) : resolve(sql)), !connecting)\n connecting = !0, connection = createConnection(connectionInfo, onConnected, onClose);\n return promise;\n }, sql.close = () => {\n if (closed)\n return @Promise.resolve();\n var { resolve, promise } = @Promise.withResolvers();\n return onConnect.push(resolve), connection.close(), promise;\n }, sql.flush = () => {\n if (closed || !connected)\n return;\n connection.flush();\n }, sql;\n}, queryStatus_active = 1 << 1, queryStatus_cancelled = 1 << 2, queryStatus_error = 1 << 3, queryStatus_executed = 1 << 4;\nvar _resolve = Symbol(\"resolve\"), _reject = Symbol(\"reject\"), _handle = Symbol(\"handle\"), _run = Symbol(\"run\"), _queryStatus = Symbol(\"status\"), _handler = Symbol(\"handler\"), PublicPromise = @Promise, { createConnection: _createConnection, createQuery, PostgresSQLConnection, init } = @lazy(\"bun:sql\");\n\nclass Query extends PublicPromise {\n [_resolve];\n [_reject];\n [_handle];\n [_handler];\n [_queryStatus] = 0;\n constructor(handle, handler) {\n var resolve_, reject_;\n super((resolve, reject) => {\n resolve_ = resolve, reject_ = reject;\n });\n this[_resolve] = resolve_, this[_reject] = reject_, this[_handle] = handle, this[_handler] = handler, this[_queryStatus] = handle \? 0 : queryStatus_cancelled;\n }\n async[_run]() {\n const { [_handle]: handle, [_handler]: handler, [_queryStatus]: status } = this;\n if (status & (queryStatus_executed | queryStatus_cancelled))\n return;\n return this[_queryStatus] |= queryStatus_executed, await 1, handler(this, handle);\n }\n get active() {\n return (this[_queryStatus] & queryStatus_active) !== 0;\n }\n set active(value) {\n if (this[_queryStatus] & (queryStatus_cancelled | queryStatus_error))\n return;\n if (value)\n this[_queryStatus] |= queryStatus_active;\n else\n this[_queryStatus] &= ~queryStatus_active;\n }\n get cancelled() {\n return (this[_queryStatus] & queryStatus_cancelled) !== 0;\n }\n resolve(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_resolve](x);\n }\n reject(x) {\n return this[_queryStatus] &= ~queryStatus_active, this[_queryStatus] |= queryStatus_error, this[_reject](x);\n }\n cancel() {\n var status = this[_queryStatus];\n if (status & queryStatus_cancelled)\n return this;\n if (this[_queryStatus] |= queryStatus_cancelled, status & queryStatus_executed)\n this[_handle].cancel();\n return this;\n }\n execute() {\n return this[_run](), this;\n }\n raw() {\n return this[_handle].raw = 2, this;\n }\n values() {\n return this[_handle].raw = 1, this;\n }\n then() {\n return this[_run](), super.@then.@apply(this, arguments);\n }\n catch() {\n return this[_run](), super.@catch.@apply(this, arguments);\n }\n finally() {\n return this[_run](), super.@finally.@apply(this, arguments);\n }\n}\nObject.defineProperty(Query, Symbol.species, { value: PublicPromise });\nObject.defineProperty(Query, Symbol.toStringTag, { value: \"Query\" });\ninit((query, result) => {\n try {\n query.resolve(result);\n } catch (e) {\n console.log(e);\n }\n}, (query, reject) => {\n try {\n query.reject(reject);\n } catch (e) {\n console.log(e);\n }\n});\nvar lazyDefaultSQL, defaultSQLObject = function sql(strings, ...values) {\n if (!lazyDefaultSQL)\n lazyDefaultSQL = SQL(@undefined), Object.assign(defaultSQLObject, lazyDefaultSQL), exportsObject.default = exportsObject.sql = lazyDefaultSQL;\n return lazyDefaultSQL(strings, ...values);\n}, exportsObject = {\n sql: defaultSQLObject,\n default: defaultSQLObject,\n SQL,\n Query\n};\nreturn exportsObject})\n"); // // diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index 51e42646d0..5fa2430f0d 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -1737,13 +1737,15 @@ pub const PostgresSQLQuery = struct { } pub fn push(this: *PostgresSQLQuery, globalThis: *JSC.JSGlobalObject, value: JSC.JSValue) void { - var pending_value = PostgresSQLQuery.pendingValueGetCached(this.thisValue) orelse JSC.JSValue.zero; + const thisValue = this.thisValue; + var pending_value = PostgresSQLQuery.pendingValueGetCached(thisValue) orelse JSC.JSValue.zero; if (pending_value.isEmptyOrUndefinedOrNull()) { - pending_value = JSC.JSValue.createEmptyArray(globalThis, 0); - PostgresSQLQuery.pendingValueSetCached(this.thisValue, globalThis, pending_value); + pending_value = JSC.JSValue.createEmptyArray(globalThis, 1); + pending_value.putIndex(globalThis, 0, value); + PostgresSQLQuery.pendingValueSetCached(thisValue, globalThis, pending_value); + } else { + pending_value.push(globalThis, value); } - - pending_value.push(globalThis, value); } pub fn doRun(this: *PostgresSQLQuery, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { @@ -1837,6 +1839,7 @@ pub const PostgresRequest = struct { cursor_name: bun.String, globalObject: *JSC.JSGlobalObject, values_array: JSC.JSValue, + result_fields: []const protocol.FieldDescription, comptime Context: type, writer: protocol.NewWriter(Context), ) !void { @@ -1935,7 +1938,30 @@ pub const PostgresRequest = struct { } } - try writer.short(0); + var any_non_text_fields: bool = false; + for (result_fields) |field| { + if (switch (@as(types.Tag, @enumFromInt(field.type_oid))) { + .bigint, .number => true, + else => false, + }) { + any_non_text_fields = true; + break; + } + } + + if (any_non_text_fields) { + try writer.short(@truncate(result_fields.len)); + for (result_fields) |field| { + try writer.short( + switch (@as(types.Tag, @enumFromInt(field.type_oid))) { + .bigint, .number => 1, + else => 0, + }, + ); + } + } else { + try writer.short(0); + } try length.write(); } @@ -1977,7 +2003,7 @@ pub const PostgresRequest = struct { signature: *Signature, ) !void { try writeQuery(query, signature.name, signature.fields, Context, writer); - try writeBind(signature.name, bun.String.empty, globalObject, array_value, Context, writer); + try writeBind(signature.name, bun.String.empty, globalObject, array_value, &.{}, Context, writer); var exec = protocol.Execute{ .p = .{ .prepared_statement = signature.name, @@ -2015,7 +2041,7 @@ pub const PostgresRequest = struct { comptime Context: type, writer: protocol.NewWriter(Context), ) !void { - try writeBind(statement.signature.name, bun.String.empty, globalObject, array_value, Context, writer); + try writeBind(statement.signature.name, bun.String.empty, globalObject, array_value, &.{}, Context, writer); var exec = protocol.Execute{ .p = .{ .prepared_statement = statement.signature.name, @@ -2560,45 +2586,47 @@ pub const PostgresSQLConnection = struct { }; defer bytes_.deinit(); const bytes = bytes_.slice(); + const object = this.object; + object.ensureStillAlive(); switch (@as(types.Tag, @enumFromInt(this.fields[index].type_oid))) { .number => { switch (bytes.len) { 0 => { - putDirectOffset(this.object, this.vm, index, JSC.JSValue.jsNull()); + putDirectOffset(object, this.vm, index, JSC.JSValue.jsNull()); }, 2 => { - putDirectOffset(this.object, this.vm, index, JSC.JSValue.jsNumber(@as(int32, @as(short, @bitCast(bytes[0..2].*))))); + putDirectOffset(object, this.vm, index, JSC.JSValue.jsNumber(@as(int32, @as(short, @bitCast(bytes[0..2].*))))); }, 4 => { - putDirectOffset(this.object, this.vm, index, JSC.JSValue.jsNumber(@as(int32, @bitCast(bytes[0..4].*)))); + putDirectOffset(object, this.vm, index, JSC.JSValue.jsNumber(@as(int32, @bitCast(bytes[0..4].*)))); }, else => { var eight: usize = 0; @memcpy(@as(*[8]u8, @ptrCast(&eight))[0..bytes.len], bytes[0..@min(8, bytes.len)]); eight = @byteSwap(eight); - putDirectOffset(this.object, this.vm, index, JSC.JSValue.jsNumber(@as(f64, @bitCast(eight)))); + putDirectOffset(object, this.vm, index, JSC.JSValue.jsNumber(@as(f64, @bitCast(eight)))); }, } }, .json => { - var str = bun.String.fromUTF8(bytes); + var str = bun.String.create(bytes); defer str.deref(); - putDirectOffset(this.object, this.vm, index, str.toJSForParseJSON(this.globalObject)); + putDirectOffset(object, this.vm, index, str.toJSForParseJSON(this.globalObject)); }, .boolean => { - putDirectOffset(this.object, this.vm, index, JSC.JSValue.jsBoolean(bytes.len > 0 and bytes[0] == 't')); + putDirectOffset(object, this.vm, index, JSC.JSValue.jsBoolean(bytes.len > 0 and bytes[0] == 't')); }, .time, .datetime, .date => { - putDirectOffset(this.object, this.vm, index, JSC.JSValue.fromDateString(this.globalObject, bytes_.sliceZ())); + putDirectOffset(object, this.vm, index, JSC.JSValue.fromDateString(this.globalObject, bytes_.sliceZ())); }, .bytea => { - putDirectOffset(this.object, this.vm, index, JSC.ArrayBuffer.createBuffer(this.globalObject, bytes)); + putDirectOffset(object, this.vm, index, JSC.ArrayBuffer.createBuffer(this.globalObject, bytes)); }, else => { - var str = bun.String.fromUTF8(bytes); + var str = bun.String.create(bytes); defer str.deref(); - putDirectOffset(this.object, this.vm, index, str.toJS(this.globalObject)); + putDirectOffset(object, this.vm, index, str.toJS(this.globalObject)); }, } return true; @@ -2615,12 +2643,14 @@ pub const PostgresSQLConnection = struct { .DataRow => { var request = this.current() orelse return error.ExpectedRequest; var statement = request.statement orelse return error.ExpectedStatement; - var structure = statement.structure(this.globalObject); + + statement.cached_structure.clear(); + + var structure = statement.structure(this.js_value, this.globalObject); std.debug.assert(!structure.isEmptyOrUndefinedOrNull()); var row = JSC.JSObject.uninitialized(this.globalObject, structure); row.ensureStillAlive(); - request.push(this.globalObject, row); var putter = CellPutter{ .object = row, @@ -2628,12 +2658,14 @@ pub const PostgresSQLConnection = struct { .globalObject = this.globalObject, .fields = statement.fields, }; + try protocol.DataRow.decode( &putter, Context, reader, CellPutter.put, ); + request.push(this.globalObject, row); }, .CopyData => { var copy_data: protocol.CopyData = undefined; @@ -2835,7 +2867,7 @@ pub const PostgresSQLStatement = struct { bun.default_allocator.destroy(this); } - pub fn structure(this: *PostgresSQLStatement, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + pub fn structure(this: *PostgresSQLStatement, owner: JSC.JSValue, globalObject: *JSC.JSGlobalObject) JSC.JSValue { return this.cached_structure.get() orelse { var names = bun.default_allocator.alloc(bun.String, this.fields.len) catch return .undefined; defer { @@ -2845,10 +2877,11 @@ pub const PostgresSQLStatement = struct { bun.default_allocator.free(names); } for (this.fields, names) |*field, *name| { - name.* = String.createAtomIfPossible(field.name.slice()); + name.* = String.fromUTF8(field.name.slice()); } var structure_ = JSC.JSObject.createStructure( globalObject, + owner, @truncate(this.fields.len), names.ptr, );