diff options
-rw-r--r-- | src/bun.js/api/postgres.classes.ts | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.cpp | 8 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.h | 27 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.cpp | 5 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes.zig | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/structure.cpp | 2 | ||||
-rw-r--r-- | src/js/bun/sql.ts | 2 | ||||
-rw-r--r-- | src/js/out/InternalModuleRegistryConstants.h | 6 | ||||
-rw-r--r-- | src/sql/postgres.zig | 151 |
9 files changed, 150 insertions, 53 deletions
diff --git a/src/bun.js/api/postgres.classes.ts b/src/bun.js/api/postgres.classes.ts index 0a6f209fe..1185f8389 100644 --- a/src/bun.js/api/postgres.classes.ts +++ b/src/bun.js/api/postgres.classes.ts @@ -42,6 +42,7 @@ export default [ construct: true, finalize: true, configurable: false, + hasPendingActivity: true, JSType: "0b11101110", klass: {}, proto: { diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index 47532a98c..aeba3881c 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -17913,6 +17913,12 @@ extern "C" EncodedJSValue PostgresSQLQuery__getConstructor(Zig::GlobalObject* gl return JSValue::encode(globalObject->JSPostgresSQLQueryConstructor()); } +extern "C" bool PostgresSQLQuery__hasPendingActivity(void* ptr); +bool JSPostgresSQLQuery::hasPendingActivity(void* ctx) +{ + return PostgresSQLQuery__hasPendingActivity(ctx); +} + JSPostgresSQLQuery::~JSPostgresSQLQuery() { if (m_ctx) { @@ -18016,6 +18022,8 @@ void JSPostgresSQLQuery::visitAdditionalChildren(Visitor& visitor) ASSERT_GC_OBJECT_INHERITS(thisObject, info()); visitor.append(thisObject->m_pendingValue); visitor.append(thisObject->m_binding); + + visitor.addOpaqueRoot(this->wrapped()); } DEFINE_VISIT_ADDITIONAL_CHILDREN(JSPostgresSQLQuery); diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h index 7080146df..31ea8ef47 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.h +++ b/src/bun.js/bindings/ZigGeneratedClasses.h @@ -1928,10 +1928,37 @@ public: : Base(vm, structure) { m_ctx = sinkPtr; + m_weakThis = JSC::Weak<JSPostgresSQLQuery>(this, getOwner()); } void finishCreation(JSC::VM&); + JSC::Weak<JSPostgresSQLQuery> m_weakThis; + + static bool hasPendingActivity(void* ctx); + + class Owner final : public JSC::WeakHandleOwner { + public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor& visitor, const char** reason) final + { + auto* controller = JSC::jsCast<JSPostgresSQLQuery*>(handle.slot()->asCell()); + if (JSPostgresSQLQuery::hasPendingActivity(controller->wrapped())) { + if (UNLIKELY(reason)) + *reason = "has pending activity"; + return true; + } + + return visitor.containsOpaqueRoot(context); + } + void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} + }; + + static JSC::WeakHandleOwner* getOwner() + { + static NeverDestroyed<Owner> m_owner; + return &m_owner.get(); + } + DECLARE_VISIT_CHILDREN; template<typename Visitor> void visitAdditionalChildren(Visitor&); DECLARE_VISIT_OUTPUT_CONSTRAINTS; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index a61a0221a..dd0e440af 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -4690,8 +4690,9 @@ extern "C" EncodedJSValue JSC__JSValue__dateInstanceFromNullTerminatedString(JSC } // this is largely copied from dateProtoFuncToISOString -extern "C" int JSC__JSValue__toISOString(JSC::JSGlobalObject* globalObject, EncodedJSValue dateValue, char buffer[28]) +extern "C" int JSC__JSValue__toISOString(JSC::JSGlobalObject* globalObject, EncodedJSValue dateValue, char* buf) { + char buffer[28]; JSC::DateInstance* thisDateObj = JSC::jsDynamicCast<JSC::DateInstance*>(JSC::JSValue::decode(dateValue)); if (!thisDateObj) return -1; @@ -4716,6 +4717,8 @@ extern "C" int JSC__JSValue__toISOString(JSC::JSGlobalObject* globalObject, Enco else charactersWritten = snprintf(buffer, sizeof(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms); + memcpy(buf, buffer, charactersWritten); + ASSERT(charactersWritten > 0 && static_cast<unsigned>(charactersWritten) < sizeof(buffer)); if (static_cast<unsigned>(charactersWritten) >= sizeof(buffer)) return -1; diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index 7e76611b4..53be7b778 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -4532,6 +4532,7 @@ pub const JSPostgresSQLQuery = struct { @export(PostgresSQLQuery.doRun, .{ .name = "PostgresSQLQueryPrototype__doRun" }); @export(PostgresSQLQuery.estimatedSize, .{ .name = "PostgresSQLQuery__estimatedSize" }); @export(PostgresSQLQuery.finalize, .{ .name = "PostgresSQLQueryClass__finalize" }); + @export(PostgresSQLQuery.hasPendingActivity, .{ .name = "PostgresSQLQuery__hasPendingActivity" }); } } }; diff --git a/src/bun.js/bindings/structure.cpp b/src/bun.js/bindings/structure.cpp index 9e1fb6dc2..82358abf8 100644 --- a/src/bun.js/bindings/structure.cpp +++ b/src/bun.js/bindings/structure.cpp @@ -10,7 +10,7 @@ using namespace JSC; extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject, unsigned int inlineCapacity, BunString* names) { auto& vm = globalObject->vm(); - JSC::Structure* structure = JSC::Structure::create(vm, globalObject, globalObject->objectPrototype(), JSC::TypeInfo(ObjectType, JSC::JSObject::StructureFlags), JSC::JSFinalObject::info(), inlineCapacity); + JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureConcurrently(globalObject->objectPrototype(), inlineCapacity); PropertyOffset offset = 0; for (unsigned i = 0; i < inlineCapacity; i++) { const Identifier& ident = JSC::Identifier::fromString(vm, Bun::toWTFString(names[i])); diff --git a/src/js/bun/sql.ts b/src/js/bun/sql.ts index 8286b1fc7..f142162f4 100644 --- a/src/js/bun/sql.ts +++ b/src/js/bun/sql.ts @@ -77,7 +77,7 @@ class Query extends PublicPromise { reject(x) { this[_queryStatus] &= ~queryStatus_active; this[_queryStatus] |= queryStatus_error; - return this[_resolve](x); + return this[_reject](x); } cancel() { diff --git a/src/js/out/InternalModuleRegistryConstants.h b/src/js/out/InternalModuleRegistryConstants.h index e01c81190..119beaef5 100644 --- a/src/js/out/InternalModuleRegistryConstants.h +++ b/src/js/out/InternalModuleRegistryConstants.h @@ -10,7 +10,7 @@ static constexpr ASCIILiteral BunFFICode = "(function (){\"use strict\";// src/j // // -static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return new PostgresSQLConnection(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) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), closedConnectionHandler);\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, { 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[_resolve](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.prototype.resolve, Query.prototype.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"_s; +static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return new PostgresSQLConnection(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) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), closedConnectionHandler);\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, { 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.prototype.resolve, Query.prototype.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"_s; // // @@ -263,7 +263,7 @@ static constexpr ASCIILiteral BunFFICode = "(function (){\"use strict\";// src/j // // -static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return new PostgresSQLConnection(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) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), closedConnectionHandler);\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, { 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[_resolve](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.prototype.resolve, Query.prototype.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"_s; +static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return new PostgresSQLConnection(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) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), closedConnectionHandler);\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, { 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.prototype.resolve, Query.prototype.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"_s; // // @@ -517,7 +517,7 @@ static constexpr ASCIILiteral BunFFICode = "(function (){\"use strict\";// src/j // // -static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return new PostgresSQLConnection(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) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), closedConnectionHandler);\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, { 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[_resolve](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.prototype.resolve, Query.prototype.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"_s; +static constexpr ASCIILiteral BunSqlCode = "(function (){\"use strict\";// src/js/out/tmp/bun/sql.ts\nvar createConnection = function({ hostname, port, username, password, tls, query, database }, onConnected, onClose) {\n return new PostgresSQLConnection(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) {\n connected = !err;\n for (let handler of onConnect)\n handler(err);\n onConnect = [];\n }\n function onClose(err) {\n closed = !0, onConnected(err);\n }\n function connectedSQL(strings, values) {\n return new Query(createQuery(normalizeStrings(strings), values), closedConnectionHandler);\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, { 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.prototype.resolve, Query.prototype.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"_s; // // diff --git a/src/sql/postgres.zig b/src/sql/postgres.zig index 4352f7db3..7c561cf7e 100644 --- a/src/sql/postgres.zig +++ b/src/sql/postgres.zig @@ -140,10 +140,30 @@ pub const protocol = struct { const offsetFn = offsetFn_; pub const Ctx = Context; + pub const WrappedWriter = @This(); + pub inline fn write(this: @This(), data: []const u8) anyerror!void { try writeFn(this.wrapped, data); } + pub const LengthWriter = struct { + index: usize, + context: WrappedWriter, + + pub fn write(this: LengthWriter) anyerror!void { + try this.context.pwrite(&Int32(this.context.offset() - this.index), this.index); + } + }; + + pub inline fn length(this: @This()) anyerror!LengthWriter { + const i = this.offset(); + try this.int32(0); + return LengthWriter{ + .index = i, + .context = this, + }; + } + pub inline fn offset(this: @This()) usize { return offsetFn(this.wrapped); } @@ -802,7 +822,7 @@ pub const protocol = struct { .name = .{ .owned = try name.toOwned() }, }; - try reader.skip(12); + try reader.skip(2 + 4 + 2); } pub const decode = decoderWrap(FieldDescription, decodeInternal).decode; @@ -936,7 +956,7 @@ pub const protocol = struct { writer: NewWriter(Context), ) !void { const parameters = this.params; - const count: usize = @sizeOf((u32)) + @sizeOf(u16) + (parameters.len * @sizeOf(u32)) + zCount(this.name) + zCount(this.query); + const count: usize = @sizeOf((u32)) + @sizeOf(u16) + (parameters.len * @sizeOf(u32)) + @max(zCount(this.name), 1) + @max(zCount(this.query), 1); const header = [_]u8{ 'P', } ++ toBytes(Int32(count)); @@ -1125,7 +1145,7 @@ pub const protocol = struct { } pub const Execute = struct { - max_rows: int32 = std.math.maxInt(int32), + max_rows: int32 = 0, p: PortalOrPreparedStatement, pub fn writeInternal( @@ -1133,14 +1153,14 @@ pub const protocol = struct { comptime Context: type, writer: NewWriter(Context), ) !void { - const message = this.p.slice(); - const count: usize = @sizeOf((u32)) + @sizeOf((u32)) + message.len + 1; - const header = [_]u8{ - 'E', - } ++ toBytes(Int32(count)); - try writer.write(&header); - try writer.string(message); + try writer.write("E"); + const length = try writer.length(); + if (this.p == .portal) + try writer.string(this.p.portal) + else + try writer.write(&[_]u8{0}); try writer.int32(this.max_rows); + try length.write(); } pub const write = writeWrap(@This(), writeInternal).write; @@ -1155,16 +1175,15 @@ pub const protocol = struct { writer: NewWriter(Context), ) !void { const message = this.p.slice(); - const count: usize = @sizeOf((u32)) + @sizeOf((u32)) + message.len + 2; - const header = [_]u8{ + try writer.write(&[_]u8{ 'D', - } ++ toBytes(Int32(count)); - try writer.write(&header); + }); + const length = try writer.length(); try writer.write(&[_]u8{ this.p.tag(), - 0, }); try writer.string(message); + try length.write(); } pub const write = writeWrap(@This(), writeInternal).write; @@ -1564,13 +1583,17 @@ pub const PostgresSQLQuery = struct { pub usingnamespace JSC.Codegen.JSPostgresSQLQuery; - pub const Status = enum { + pub const Status = enum(u8) { pending, running, success, fail, }; + pub fn hasPendingActivity(this: *@This()) callconv(.C) bool { + return this.status == .running; + } + pub fn deinit(this: *@This()) void { if (this.statement) |statement| { statement.deref(); @@ -1601,7 +1624,9 @@ pub const PostgresSQLQuery = struct { } pub fn onNoData(this: *@This(), globalObject: *JSC.JSGlobalObject) void { - if (this.thisValue == .zero) { + const thisValue = this.thisValue; + const targetValue = this.target; + if (thisValue == .zero) { this.deref(); return; } @@ -1611,14 +1636,16 @@ pub const PostgresSQLQuery = struct { // TODO: error handling _ = vm.rareData().postgresql_context.onQueryResolveFn.get().?.callWithThis( globalObject, - this.thisValue, + targetValue, &[_]JSC.JSValue{ JSC.JSValue.undefined, }, ); } pub fn onError(this: *@This(), err: protocol.ErrorResponse, globalObject: *JSC.JSGlobalObject) void { - if (this.thisValue == .zero) { + const thisValue = this.thisValue; + const targetValue = this.target; + if (thisValue == .zero) { this.deref(); return; } @@ -1638,14 +1665,15 @@ pub const PostgresSQLQuery = struct { _ = b.append(str.slice()); _ = b.append("\n"); } - const instance = globalObject.createSyntaxErrorInstance("Postgres error occurred\n{s}", .{b.allocatedSlice()}); + const instance = globalObject.createSyntaxErrorInstance("Postgres error occurred\n{s}", .{b.allocatedSlice()[0..b.len]}); + this.status = .fail; b.deinit(bun.default_allocator); this.deref(); // TODO: error handling _ = JSC.VirtualMachine.get().rareData().postgresql_context.onQueryRejectFn.get().?.callWithThis( globalObject, - this.thisValue, + targetValue, &[_]JSC.JSValue{ instance, }, @@ -1653,17 +1681,21 @@ pub const PostgresSQLQuery = struct { } pub fn onSuccess(this: *@This(), _: []const u8, globalObject: *JSC.JSGlobalObject) void { - if (this.thisValue == .zero) { + const thisValue = this.thisValue; + const targetValue = this.target; + if (thisValue == .zero) { this.deref(); return; } - const pending_value = PostgresSQLQuery.pendingValueGetCached(this.thisValue) orelse JSC.JSValue.undefined; + const pending_value = PostgresSQLQuery.pendingValueGetCached(thisValue) orelse JSC.JSValue.undefined; + this.status = .success; this.deref(); + // TODO: error handling _ = JSC.VirtualMachine.get().rareData().postgresql_context.onQueryResolveFn.get().?.callWithThis( globalObject, - this.thisValue, + targetValue, &[_]JSC.JSValue{ pending_value, }, @@ -1768,6 +1800,7 @@ pub const PostgresSQLQuery = struct { connection.requests.writeItem(this) catch {}; this.ref(); + this.status = .running; return .undefined; } @@ -1796,40 +1829,44 @@ pub const PostgresRequest = struct { comptime Context: type, writer: protocol.NewWriter(Context), ) !void { - try writer.bytes("B"); - const length_offset = writer.offset(); - try writer.int32(0); + try writer.write("B"); + const length = try writer.length(); - try writer.string(name); try writer.String(cursor_name); + try writer.string(name); var iter = JSC.JSArrayIterator.init(values_array, globalObject); - try writer.short(@intCast(iter.len)); + if (iter.len > 0) { + try writer.short(@intCast(iter.len)); - while (iter.next()) |value| { - if (value.isUndefinedOrNull()) { - try writer.short(0); - continue; - } + while (iter.next()) |value| { + if (value.isUndefinedOrNull()) { + try writer.short(0); + continue; + } - const tag = try types.Tag.fromJS(globalObject, value); + const tag = try types.Tag.fromJS(globalObject, value); - switch (tag) { - .bytea, .number => { - try writer.short(0); - }, - else => { - try writer.short(1); - }, + switch (tag) { + .bytea, .number => { + try writer.short(0); + }, + else => { + try writer.short(1); + }, + } } - } - try writer.short(@intCast(iter.len)); + try writer.short(@intCast(iter.len)); + } else { + try writer.short(0); + try writer.short(0); + } iter = JSC.JSArrayIterator.init(values_array, globalObject); - debug("Bind: {} ({d})", .{ bun.strings.QuotedFormatter{ .text = name }, iter.len }); + debug("Bind: {} ({d} args)", .{ bun.strings.QuotedFormatter{ .text = name }, iter.len }); while (iter.next()) |value| { if (value.isUndefinedOrNull()) { @@ -1887,7 +1924,9 @@ pub const PostgresRequest = struct { } } - try writer.pwrite(&std.mem.toBytes(@byteSwap(@as(int32, @intCast(writer.offset())))), length_offset); + try writer.short(0); + + try length.write(); } pub fn writeQuery( @@ -2069,6 +2108,8 @@ pub const PostgresSQLConnection = struct { .connected => { const on_connect = this.on_connect.swap(); if (on_connect == .zero) return; + this.poll_ref.unref(this.globalObject.bunVM()); + this.updateHasPendingActivity(); _ = on_connect.callWithThis( this.globalObject, this.js_value, @@ -2123,6 +2164,7 @@ pub const PostgresSQLConnection = struct { this.socket = socket; this.poll_ref.ref(this.globalObject.bunVM()); + this.updateHasPendingActivity(); var msg = protocol.StartupMessage{ .user = Data{ .temporary = this.user }, .database = Data{ .temporary = this.database }, .options = Data{ .temporary = this.options } }; msg.writeInternal(Writer, this.writer()) catch |err| { @@ -2400,7 +2442,7 @@ pub const PostgresSQLConnection = struct { } pub fn offset(this: Writer) usize { - return this.connection.write_buffer.head; + return this.connection.write_buffer.len(); } }; @@ -2586,6 +2628,7 @@ pub const PostgresSQLConnection = struct { } debug("-> {s}", .{cmd.command_tag.slice()}); _ = this.requests.discard(1); + this.updateRef(); request.onSuccess(cmd.command_tag.slice(), this.globalObject); }, .BindComplete => { @@ -2621,6 +2664,8 @@ pub const PostgresSQLConnection = struct { try reader.eatMessage(protocol.NoData); var request = this.current() orelse return error.ExpectedRequest; _ = this.requests.discard(1); + this.updateRef(); + request.onNoData(this.globalObject); }, .BackendKeyData => { @@ -2634,6 +2679,8 @@ pub const PostgresSQLConnection = struct { } var request = this.current() orelse return error.ExpectedRequest; _ = this.requests.discard(1); + this.updateRef(); + request.onError(err, this.globalObject); }, .PortalSuspended => { @@ -2663,6 +2710,7 @@ pub const PostgresSQLConnection = struct { try reader.eatMessage(protocol.EmptyQueryResponse); var request = this.current() orelse return error.ExpectedRequest; _ = this.requests.discard(1); + this.updateRef(); request.onSuccess("", this.globalObject); }, .CopyOutResponse => { @@ -2678,6 +2726,15 @@ pub const PostgresSQLConnection = struct { } } + pub fn updateRef(this: *PostgresSQLConnection) void { + this.updateHasPendingActivity(); + if (this.has_pending_activity.loadUnchecked()) { + this.poll_ref.ref(this.globalObject.bunVM()); + } else { + this.poll_ref.unref(this.globalObject.bunVM()); + } + } + pub fn doFlush(this: *PostgresSQLConnection, globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue { _ = callframe; _ = globalObject; |