try some things

This commit is contained in:
Jarred Sumner
2023-10-18 21:23:29 -07:00
parent 0cb4e9919b
commit e2198b95ef
6 changed files with 128 additions and 45 deletions

View File

@@ -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.
,

View File

@@ -1060,7 +1060,7 @@ static const HashTableValue JSSQLiteStatementConstructorTableValues[] = {
{ "deserialize"_s, static_cast<unsigned>(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[] = {

View File

@@ -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*))

View File

@@ -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) {

File diff suppressed because one or more lines are too long

View File

@@ -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,
);