#include "root.h" #include #include #include "headers-handwritten.h" #include #include #include #include #include #include "ZigGlobalObject.h" #include #include #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(globalObject); auto* subclassStructure = zigGlobal->JSBufferSubclassStructure(); auto* uint8Array = JSC::JSUint8Array::createUninitialized(globalObject, subclassStructure, cell.value.bytea[1]); memcpy(uint8Array->vector(), reinterpret_cast(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::JSValue::decode(arrayValue)) : nullptr; auto* structure = jsDynamicCast(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(); 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++) { structure = structure->addPropertyTransition(vm, structure, propertyNames[i], 0, offset); } return JSValue::encode(structure); } extern "C" EncodedJSValue JSC__createEmptyObjectWithStructure(JSC::JSGlobalObject* globalObject, JSC::Structure* structure) { auto& vm = globalObject->vm(); 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*)) { GCDeferralContext context(*vm); JSC::DisallowGC disallowGC; callback(ptr); } extern "C" void JSC__putDirectOffset(JSC::VM* vm, JSC::EncodedJSValue object, unsigned int offset, JSC::EncodedJSValue value) { JSValue::decode(object).getObject()->putDirectOffset(*vm, offset, JSValue::decode(value)); } }