mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
doesnt fix it
This commit is contained in:
@@ -676,8 +676,8 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2,
|
||||
if ((url2 == nullptr) != (url1 == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (url2 && url1) {
|
||||
// toEqual or toStrictEqual should return false when the URLs' href is not equal
|
||||
// But you could have added additional properties onto the
|
||||
@@ -4690,6 +4690,11 @@ CPP_DECL double JSC__JSValue__getUnixTimestamp(JSC__JSValue timeValue)
|
||||
return date->internalNumber();
|
||||
}
|
||||
|
||||
extern "C" double WTF__parseDateFromNullTerminatedCharacters(const char* nullTerminatedChars)
|
||||
{
|
||||
return WTF::parseDateFromNullTerminatedCharacters(nullTerminatedChars);
|
||||
}
|
||||
|
||||
extern "C" EncodedJSValue JSC__JSValue__dateInstanceFromNullTerminatedString(JSC::JSGlobalObject* globalObject, const char* nullTerminatedChars)
|
||||
{
|
||||
double dateSeconds = WTF::parseDateFromNullTerminatedCharacters(nullTerminatedChars);
|
||||
|
||||
@@ -5102,6 +5102,13 @@ pub const VM = extern struct {
|
||||
cppFn("holdAPILock", .{ this, ctx, callback });
|
||||
}
|
||||
|
||||
extern fn JSC__runInDeferralContext(this: *VM, ctx: ?*anyopaque, callback: *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);
|
||||
}
|
||||
|
||||
pub fn deferGC(this: *VM, ctx: ?*anyopaque, callback: *const fn (ctx: ?*anyopaque) callconv(.C) void) void {
|
||||
cppFn("deferGC", .{ this, ctx, callback });
|
||||
}
|
||||
|
||||
@@ -4,9 +4,124 @@
|
||||
#include "headers-handwritten.h"
|
||||
#include <JavaScriptCore/JSCJSValueInlines.h>
|
||||
#include <JavaScriptCore/ObjectConstructor.h>
|
||||
#include <JavaScriptCore/JSObjectInlines.h>
|
||||
#include <JavaScriptCore/JSBigInt.h>
|
||||
#include <JavaScriptCore/DateInstance.h>
|
||||
#include "ZigGlobalObject.h"
|
||||
#include <JavaScriptCore/JSONObject.h>
|
||||
#include <JavaScriptCore/GCDeferralContext.h>
|
||||
#include "GCDefferalContext.h"
|
||||
|
||||
namespace Bun {
|
||||
using namespace JSC;
|
||||
|
||||
typedef union DataCellValue {
|
||||
uint8_t null_value;
|
||||
WTF::StringImpl* string;
|
||||
double number;
|
||||
int32_t integer;
|
||||
int64_t bigint;
|
||||
bool boolean;
|
||||
double date;
|
||||
size_t bytea[2];
|
||||
WTF::StringImpl* json;
|
||||
} DataCellValue;
|
||||
|
||||
enum class DataCellTag : uint8_t {
|
||||
Null = 0,
|
||||
String = 1,
|
||||
Integer = 2,
|
||||
Bigint = 3,
|
||||
Boolean = 4,
|
||||
Date = 5,
|
||||
Bytea = 6,
|
||||
Json = 7,
|
||||
};
|
||||
|
||||
typedef struct DataCell {
|
||||
DataCellTag tag;
|
||||
DataCellValue value;
|
||||
} DataCell;
|
||||
|
||||
static JSC::JSValue toJS(JSC::Structure* structure, DataCell* cells, unsigned count, JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto* object = JSC::constructEmptyObject(vm, structure);
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
auto& cell = cells[i];
|
||||
switch (cell.tag) {
|
||||
case DataCellTag::Null:
|
||||
object->putDirectOffset(vm, i, jsNull());
|
||||
break;
|
||||
case DataCellTag::String: {
|
||||
object->putDirectOffset(vm, i, jsString(vm, WTF::String(cell.value.string)));
|
||||
cell.value.string->deref();
|
||||
break;
|
||||
}
|
||||
case DataCellTag::Integer:
|
||||
object->putDirectOffset(vm, i, jsNumber(cell.value.integer));
|
||||
break;
|
||||
case DataCellTag::Bigint:
|
||||
object->putDirectOffset(vm, i, JSC::JSBigInt::createFrom(globalObject, cell.value.bigint));
|
||||
break;
|
||||
case DataCellTag::Boolean:
|
||||
object->putDirectOffset(vm, i, jsBoolean(cell.value.boolean));
|
||||
break;
|
||||
case DataCellTag::Date:
|
||||
object->putDirectOffset(vm, i, JSC::DateInstance::create(vm, globalObject->dateStructure(), cell.value.date));
|
||||
break;
|
||||
case DataCellTag::Bytea: {
|
||||
Zig::GlobalObject* zigGlobal = jsCast<Zig::GlobalObject*>(globalObject);
|
||||
auto* subclassStructure = zigGlobal->JSBufferSubclassStructure();
|
||||
auto* uint8Array = JSC::JSUint8Array::createUninitialized(globalObject, subclassStructure, cell.value.bytea[1]);
|
||||
memcpy(uint8Array->vector(), reinterpret_cast<void*>(cell.value.bytea[0]), cell.value.bytea[1]);
|
||||
object->putDirectOffset(vm, i, uint8Array);
|
||||
break;
|
||||
}
|
||||
case DataCellTag::Json: {
|
||||
auto str = WTF::String(cell.value.string);
|
||||
JSC::JSValue json = JSC::JSONParse(globalObject, str);
|
||||
cell.value.string->deref();
|
||||
|
||||
object->putDirectOffset(vm, i, json);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static JSC::JSValue toJS(JSC::JSArray* array, JSC::Structure* structure, DataCell* cells, unsigned count, JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
|
||||
if (array) {
|
||||
array->push(globalObject, toJS(structure, cells, count, globalObject));
|
||||
return array;
|
||||
}
|
||||
|
||||
auto* newArray = JSC::constructEmptyArray(globalObject, nullptr);
|
||||
|
||||
newArray->putDirectIndex(globalObject, 0, toJS(structure, cells, count, globalObject));
|
||||
return newArray;
|
||||
}
|
||||
|
||||
extern "C" EncodedJSValue JSC__constructObjectFromDataCell(
|
||||
JSC::JSGlobalObject* globalObject,
|
||||
EncodedJSValue arrayValue,
|
||||
EncodedJSValue structureValue, DataCell* cells, unsigned count)
|
||||
{
|
||||
auto* array = arrayValue ? jsDynamicCast<JSC::JSArray*>(JSC::JSValue::decode(arrayValue)) : nullptr;
|
||||
auto* structure = jsDynamicCast<JSC::Structure*>(JSC::JSValue::decode(structureValue));
|
||||
|
||||
return JSValue::encode(toJS(array, structure, cells, count, globalObject));
|
||||
}
|
||||
|
||||
extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject, JSC::JSCell* owner, unsigned int inlineCapacity, BunString* names)
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
@@ -45,6 +160,7 @@ extern "C" EncodedJSValue JSC__createEmptyObjectWithStructure(JSC::JSGlobalObjec
|
||||
extern "C" void JSC__runInDeferralContext(JSC::VM* vm, void* ptr, void (*callback)(void*))
|
||||
{
|
||||
GCDeferralContext context(*vm);
|
||||
JSC::DisallowGC disallowGC;
|
||||
callback(ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -1600,9 +1600,12 @@ pub const PostgresSQLQuery = struct {
|
||||
}
|
||||
this.query.deref();
|
||||
this.cursor_name.deref();
|
||||
|
||||
bun.default_allocator.destroy(this);
|
||||
}
|
||||
|
||||
pub fn finalize(this: *@This()) callconv(.C) void {
|
||||
debug("PostgresSQLQuery finalize", .{});
|
||||
this.thisValue = .zero;
|
||||
this.target = .zero;
|
||||
this.deref();
|
||||
@@ -1614,7 +1617,6 @@ pub const PostgresSQLQuery = struct {
|
||||
|
||||
if (ref_count == 1) {
|
||||
this.deinit();
|
||||
bun.default_allocator.destroy(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2169,6 +2171,7 @@ pub const PostgresSQLConnection = struct {
|
||||
}
|
||||
|
||||
pub fn finalize(this: *PostgresSQLConnection) callconv(.C) void {
|
||||
debug("PostgresSQLConnection finalize", .{});
|
||||
this.js_value = .zero;
|
||||
this.deref();
|
||||
}
|
||||
@@ -2236,6 +2239,19 @@ pub const PostgresSQLConnection = struct {
|
||||
}
|
||||
|
||||
pub fn onData(this: *PostgresSQLConnection, data: []const u8) void {
|
||||
const Deferrer = struct {
|
||||
data: []const u8,
|
||||
this: *PostgresSQLConnection,
|
||||
|
||||
pub fn run(d: *@This()) callconv(.C) void {
|
||||
_onData(d.this, d.data);
|
||||
}
|
||||
};
|
||||
var deferrer = Deferrer{ .data = data, .this = this };
|
||||
this.globalObject.vm().runInDeferralContext(&deferrer, @ptrCast(&Deferrer.run));
|
||||
}
|
||||
|
||||
fn _onData(this: *PostgresSQLConnection, data: []const u8) void {
|
||||
var vm = this.globalObject.bunVM();
|
||||
defer vm.drainMicrotasks();
|
||||
if (this.read_buffer.remaining().len == 0) {
|
||||
@@ -2633,6 +2649,106 @@ pub const PostgresSQLConnection = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const DataCell = extern struct {
|
||||
tag: Tag,
|
||||
|
||||
value: Value,
|
||||
|
||||
pub const Tag = enum(u8) {
|
||||
null = 0,
|
||||
string = 1,
|
||||
double = 2,
|
||||
int32 = 3,
|
||||
int64 = 4,
|
||||
boolean = 5,
|
||||
date = 6,
|
||||
bytea = 7,
|
||||
json = 8,
|
||||
};
|
||||
|
||||
pub const Value = extern union {
|
||||
null: u8,
|
||||
string: bun.WTF.StringImpl,
|
||||
double: f64,
|
||||
int32: i32,
|
||||
int64: i64,
|
||||
boolean: bool,
|
||||
date: f64,
|
||||
bytea: [2]usize,
|
||||
json: bun.WTF.StringImpl,
|
||||
};
|
||||
|
||||
pub fn deinit(this: *DataCell) void {
|
||||
switch (this.tag) {
|
||||
.string => {
|
||||
this.value.string.deref();
|
||||
},
|
||||
.json => {
|
||||
this.value.json.deref();
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
extern fn WTF__parseDateFromNullTerminatedCharacters([*:0]const u8) f64;
|
||||
|
||||
pub const Putter = struct {
|
||||
list: []DataCell,
|
||||
fields: []const protocol.FieldDescription,
|
||||
|
||||
extern fn JSC__constructObjectFromDataCell(*JSC.JSGlobalObject, JSC.JSValue, JSC.JSValue, [*]DataCell, u32) JSC.JSValue;
|
||||
pub fn toJS(this: *Putter, globalObject: *JSC.JSGlobalObject, array: JSC.JSValue, structure: JSC.JSValue) JSC.JSValue {
|
||||
return JSC__constructObjectFromDataCell(globalObject, array, structure, this.list.ptr, @truncate(this.fields.len));
|
||||
}
|
||||
|
||||
pub fn put(this: *Putter, index: u32, optional_bytes: ?*Data) anyerror!bool {
|
||||
var bytes_ = optional_bytes orelse {
|
||||
this.list[index] = DataCell{ .tag = .null, .value = .{ .null = 0 } };
|
||||
return true;
|
||||
};
|
||||
const bytes = bytes_.slice();
|
||||
|
||||
switch (@as(types.Tag, @enumFromInt(this.fields[index].type_oid))) {
|
||||
.number => {
|
||||
switch (bytes.len) {
|
||||
0 => {
|
||||
this.list[index] = DataCell{ .tag = .null, .value = .{ .null = 0 } };
|
||||
},
|
||||
2 => {
|
||||
this.list[index] = DataCell{ .tag = .int32, .value = .{ .int32 = @as(i32, @as(short, @bitCast(bytes[0..2].*))) } };
|
||||
},
|
||||
4 => {
|
||||
this.list[index] = DataCell{ .tag = .int32, .value = .{ .int32 = @as(i32, @bitCast(bytes[0..4].*)) } };
|
||||
},
|
||||
else => {
|
||||
var eight: i64 = 0;
|
||||
@memcpy(@as(*[8]u8, @ptrCast(&eight))[0..bytes.len], bytes[0..@min(8, bytes.len)]);
|
||||
eight = @byteSwap(eight);
|
||||
this.list[index] = DataCell{ .tag = .int64, .value = .{ .int64 = eight } };
|
||||
},
|
||||
}
|
||||
},
|
||||
.json => {
|
||||
this.list[index] = DataCell{ .tag = .json, .value = .{ .json = bun.String.create(bytes).value.WTFStringImpl } };
|
||||
},
|
||||
.boolean => {
|
||||
this.list[index] = DataCell{ .tag = .boolean, .value = .{ .boolean = bytes.len > 0 and bytes[0] == 't' } };
|
||||
},
|
||||
.time, .datetime, .date => {
|
||||
this.list[index] = DataCell{ .tag = .date, .value = .{ .date = WTF__parseDateFromNullTerminatedCharacters(bytes_.sliceZ().ptr) } };
|
||||
},
|
||||
.bytea => {
|
||||
this.list[index] = DataCell{ .tag = .bytea, .value = .{ .bytea = .{ @intFromPtr(bytes_.slice().ptr), bytes.len } } };
|
||||
},
|
||||
else => {
|
||||
this.list[index] = DataCell{ .tag = .string, .value = .{ .string = bun.String.create(bytes).value.WTFStringImpl } };
|
||||
},
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
pub fn on(this: *PostgresSQLConnection, comptime MessageType: @Type(.EnumLiteral), comptime Context: type, reader: protocol.NewReader(Context)) !void {
|
||||
debug("on({s})", .{@tagName(MessageType)});
|
||||
if (comptime MessageType != .ReadyForQuery) {
|
||||
@@ -2644,18 +2760,21 @@ pub const PostgresSQLConnection = struct {
|
||||
var request = this.current() orelse return error.ExpectedRequest;
|
||||
var statement = request.statement orelse return error.ExpectedStatement;
|
||||
|
||||
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();
|
||||
var stack_buf: [64]DataCell = undefined;
|
||||
var cells: []DataCell = stack_buf[0..@min(statement.fields.len, stack_buf.len)];
|
||||
|
||||
var putter = CellPutter{
|
||||
.object = row,
|
||||
.vm = this.globalObject.vm(),
|
||||
.globalObject = this.globalObject,
|
||||
var free_cells = false;
|
||||
defer if (free_cells) bun.default_allocator.free(cells);
|
||||
if (statement.fields.len >= 64) {
|
||||
cells = try bun.default_allocator.alloc(DataCell, statement.fields.len);
|
||||
free_cells = true;
|
||||
}
|
||||
|
||||
var putter = DataCell.Putter{
|
||||
.list = cells,
|
||||
.fields = statement.fields,
|
||||
};
|
||||
|
||||
@@ -2663,9 +2782,15 @@ pub const PostgresSQLConnection = struct {
|
||||
&putter,
|
||||
Context,
|
||||
reader,
|
||||
CellPutter.put,
|
||||
DataCell.Putter.put,
|
||||
);
|
||||
request.push(this.globalObject, row);
|
||||
|
||||
const pending_value = PostgresSQLQuery.pendingValueGetCached(request.thisValue) orelse .zero;
|
||||
const result = putter.toJS(this.globalObject, pending_value, structure);
|
||||
|
||||
if (pending_value == .zero) {
|
||||
PostgresSQLQuery.pendingValueSetCached(request.thisValue, this.globalObject, result);
|
||||
}
|
||||
},
|
||||
.CopyData => {
|
||||
var copy_data: protocol.CopyData = undefined;
|
||||
@@ -2855,6 +2980,8 @@ pub const PostgresSQLStatement = struct {
|
||||
}
|
||||
|
||||
pub fn deinit(this: *PostgresSQLStatement) void {
|
||||
debug("PostgresSQLStatement deinit", .{});
|
||||
|
||||
std.debug.assert(this.ref_count == 0);
|
||||
|
||||
for (this.fields) |*field| {
|
||||
|
||||
Reference in New Issue
Block a user