From a37f86e89dc01f884a1b4474c27c79d5932093a0 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Mon, 16 May 2022 15:46:20 -0700 Subject: `bun:sqlite` (#167) * :scissors: * Add the slow version * draw the rest of the owl * Fix crash when allocating lots of memory * [Bun.Transipiler] Support passing objects * [JS Parser] Support passing objects to macros via Bun.Transpiler * Update JSSQLStatement.cpp * Embed SQLite * Add SQLite to Dockerfile * [sqlite] Add quick one-off queries without creating a whole object * [sqlite] Add `columnsCount`, rename raw() to `values()`, remove `rebind` * Implement `bun:sqlite` * return null * Fix updating query * Update bun.d.ts * more tests * Support variadic arguments, write tests and add types * Update sqlite.d.ts * Update sqlite.d.ts * latest * Implement `Database.loadExtension` and `Database.setCustomSQLite` * Support `require.resolve` * [napi] Improve string performance * [bun.js] Support some of `node:module` * another test * [sqlite] Support serialize & deserialize * [`bun:ffi`] Implement `CFunction` and `linkSymbols` * [bun.js] Fix crash in `Buffer.from` * Update sqlite.test.js * Document linkSymbols * docs * Update README.md --- src/javascript/jsc/bindings/ZigGlobalObject.cpp | 110 ++++++++++++++++++------ 1 file changed, 84 insertions(+), 26 deletions(-) (limited to 'src/javascript/jsc/bindings/ZigGlobalObject.cpp') diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp index 45f4533c2..9498d6b14 100644 --- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp +++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp @@ -96,6 +96,7 @@ #include "JavaScriptCore/FunctionPrototype.h" #include "napi.h" #include "JSZigGlobalObjectBuiltins.h" +#include "JSSQLStatement.h" using JSGlobalObject = JSC::JSGlobalObject; using Exception = JSC::Exception; @@ -769,7 +770,18 @@ static JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolveSync, JSC__JSValue from; if (callFrame->argumentCount() > 1) { - from = JSC::JSValue::encode(callFrame->argument(1)); + JSC::JSValue fromValue = callFrame->argument(1); + + // require.resolve also supports a paths array + // we only support a single path + if (!fromValue.isUndefinedOrNull() && fromValue.isObject()) { + if (JSC::JSArray* array = JSC::jsDynamicCast(fromValue.getObject()->getIfPropertyExists(globalObject, JSC::Identifier::fromString(vm, "paths"_s)))) { + if (array->length() > 0) { + fromValue = array->getIndex(globalObject, 0); + } + } + } + from = JSC::JSValue::encode(fromValue); } else { JSC::JSObject* thisObject = JSC::jsDynamicCast(callFrame->thisValue()); if (UNLIKELY(!thisObject)) { @@ -815,6 +827,42 @@ static JSC_DEFINE_HOST_FUNCTION(functionReportError, return JSC::JSValue::encode(JSC::jsUndefined()); } +// we're trying out a new way to do this lazy loading +static JSC_DECLARE_HOST_FUNCTION(functionLazyLoad); +static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, + (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ +JSC: + VM& vm = globalObject->vm(); + switch (callFrame->argumentCount()) { + case 0: { + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + JSC::throwTypeError(globalObject, scope, "lazyLoad needs 1 argument (a string)"_s); + scope.release(); + return JSC::JSValue::encode(JSC::JSValue {}); + } + default: { + static NeverDestroyed sqliteString(MAKE_STATIC_STRING_IMPL("sqlite")); + JSC::JSValue moduleName = callFrame->argument(0); + auto string = moduleName.toWTFString(globalObject); + if (string.isNull()) { + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + JSC::throwTypeError(globalObject, scope, "lazyLoad expects a string"_s); + scope.release(); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + if (string == sqliteString) { + return JSC::JSValue::encode(JSSQLStatementConstructor::create(vm, globalObject, JSSQLStatementConstructor::createStructure(vm, globalObject, globalObject->m_functionPrototype.get()))); + } + + return JSC::JSValue::encode(JSC::jsUndefined()); + + break; + } + } +} + // This is not a publicly exposed API currently. // This is used by the bundler to make Response, Request, FetchEvent, // and any other objects available globally. @@ -824,7 +872,7 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm size_t constructor_count = 0; JSC__JSValue const* constructors = Zig__getAPIConstructors(&constructor_count, this); WTF::Vector extraStaticGlobals; - extraStaticGlobals.reserveCapacity((size_t)count + constructor_count + 3 + 10); + extraStaticGlobals.reserveCapacity((size_t)count + constructor_count + 3 + 11); int i = 0; for (; i < constructor_count; i++) { auto* object = JSC::jsDynamicCast(JSC::JSValue::decode(constructors[i]).asCell()->getObject()); @@ -871,49 +919,49 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm GlobalPropertyInfo { queueMicrotaskIdentifier, JSC::JSFunction::create(vm, JSC::jsCast(globalObject()), 0, "queueMicrotask"_s, functionQueueMicrotask), - JSC::PropertyAttribute::DontDelete | 0 }); + JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); JSC::Identifier setTimeoutIdentifier = JSC::Identifier::fromString(vm, "setTimeout"_s); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { setTimeoutIdentifier, JSC::JSFunction::create(vm, JSC::jsCast(globalObject()), 0, "setTimeout"_s, functionSetTimeout), - JSC::PropertyAttribute::DontDelete | 0 }); + JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); JSC::Identifier clearTimeoutIdentifier = JSC::Identifier::fromString(vm, "clearTimeout"_s); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { clearTimeoutIdentifier, JSC::JSFunction::create(vm, JSC::jsCast(globalObject()), 0, "clearTimeout"_s, functionClearTimeout), - JSC::PropertyAttribute::DontDelete | 0 }); + JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); JSC::Identifier setIntervalIdentifier = JSC::Identifier::fromString(vm, "setInterval"_s); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { setIntervalIdentifier, JSC::JSFunction::create(vm, JSC::jsCast(globalObject()), 0, "setInterval"_s, functionSetInterval), - JSC::PropertyAttribute::DontDelete | 0 }); + JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); JSC::Identifier clearIntervalIdentifier = JSC::Identifier::fromString(vm, "clearInterval"_s); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { clearIntervalIdentifier, JSC::JSFunction::create(vm, JSC::jsCast(globalObject()), 0, "clearInterval"_s, functionClearInterval), - JSC::PropertyAttribute::DontDelete | 0 }); + JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); JSC::Identifier atobIdentifier = JSC::Identifier::fromString(vm, "atob"_s); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { atobIdentifier, JSC::JSFunction::create(vm, JSC::jsCast(globalObject()), 0, "atob"_s, functionATOB), - JSC::PropertyAttribute::DontDelete | 0 }); + JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); JSC::Identifier btoaIdentifier = JSC::Identifier::fromString(vm, "btoa"_s); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { btoaIdentifier, JSC::JSFunction::create(vm, JSC::jsCast(globalObject()), 0, "btoa"_s, functionBTOA), - JSC::PropertyAttribute::DontDelete | 0 }); + JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); JSC::Identifier reportErrorIdentifier = JSC::Identifier::fromString(vm, "reportError"_s); extraStaticGlobals.uncheckedAppend( GlobalPropertyInfo { reportErrorIdentifier, @@ -921,6 +969,14 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm "reportError"_s, functionReportError), JSC::PropertyAttribute::DontDelete | 0 }); + static NeverDestroyed BunLazyString(MAKE_STATIC_STRING_IMPL("Bun.lazy")); + JSC::Identifier BunLazyIdentifier = JSC::Identifier::fromUid(vm.symbolRegistry().symbolForKey(BunLazyString)); + extraStaticGlobals.uncheckedAppend( + GlobalPropertyInfo { BunLazyIdentifier, + JSC::JSFunction::create(vm, JSC::jsCast(globalObject()), 0, + BunLazyString, functionLazyLoad), + JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function | 0 }); + this->addStaticGlobals(extraStaticGlobals.data(), extraStaticGlobals.size()); m_NapiClassStructure.initLater( @@ -969,6 +1025,9 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Buffer"_s), JSC::CustomGetterSetter::create(vm, JSBuffer_getter, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + // putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "SQL"_s), JSC::CustomGetterSetter::create(vm, JSSQLStatement_getter, nullptr), + // JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + extraStaticGlobals.releaseBuffer(); this->setRemoteDebuggingEnabled(true); @@ -1177,25 +1236,24 @@ JSC::JSObject* GlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObje metaProperties->putDirect( vm, clientData->builtinNames().filePublicName(), JSC::jsSubstring(globalObject, keyString, index + 1, keyString->length() - index - 1)); - - metaProperties->putDirect( - vm, clientData->builtinNames().filePublicName(), - JSC::jsSubstring(globalObject, keyString, index + 1, keyString->length() - index - 1)); - - metaProperties->putDirect(vm, clientData->builtinNames().resolvePublicName(), - JSC::JSFunction::create(vm, JSC::jsCast(globalObject), 0, - WTF::String("resolve"_s), functionImportMeta__resolve), - JSC::PropertyAttribute::Function | 0); - metaProperties->putDirect(vm, clientData->builtinNames().resolveSyncPublicName(), - JSC::JSFunction::create(vm, JSC::jsCast(globalObject), 0, - WTF::String("resolveSync"_s), functionImportMeta__resolveSync), - JSC::PropertyAttribute::Function | 0); - - metaProperties->putDirectBuiltinFunction(vm, globalObject, clientData->builtinNames().requirePublicName(), - jsZigGlobalObjectRequireCodeGenerator(vm), - JSC::PropertyAttribute::Builtin | 0); + } else { + metaProperties->putDirect(vm, clientData->builtinNames().filePublicName(), keyString); + metaProperties->putDirect(vm, clientData->builtinNames().dirPublicName(), jsEmptyString(vm)); } + metaProperties->putDirect(vm, clientData->builtinNames().resolvePublicName(), + JSC::JSFunction::create(vm, JSC::jsCast(globalObject), 0, + clientData->builtinNames().resolvePublicName().string(), functionImportMeta__resolve), + JSC::PropertyAttribute::Function | 0); + metaProperties->putDirect(vm, clientData->builtinNames().resolveSyncPublicName(), + JSC::JSFunction::create(vm, JSC::jsCast(globalObject), 0, + clientData->builtinNames().resolveSyncPublicName().string(), functionImportMeta__resolveSync), + JSC::PropertyAttribute::Function | 0); + + metaProperties->putDirectBuiltinFunction(vm, globalObject, clientData->builtinNames().requirePublicName(), + jsZigGlobalObjectRequireCodeGenerator(vm), + JSC::PropertyAttribute::Builtin | 0); + metaProperties->putDirect(vm, clientData->builtinNames().pathPublicName(), key); metaProperties->putDirect(vm, clientData->builtinNames().urlPublicName(), JSC::JSValue(JSC::jsString(vm, WTF::URL::fileURLWithFileSystemPath(view).string()))); -- cgit v1.2.3