diff options
author | 2023-10-17 14:10:25 -0700 | |
---|---|---|
committer | 2023-10-17 14:10:25 -0700 | |
commit | 7458b969c5d9971e89d187b687e1924e78da427e (patch) | |
tree | ee3dbf95c728cf407bf49a27826b541e9264a8bd /src/bun.js/bindings | |
parent | d4a2c29131ec154f5e4db897d4deedab2002cbc4 (diff) | |
parent | e91436e5248d947b50f90b4a7402690be8a41f39 (diff) | |
download | bun-7458b969c5d9971e89d187b687e1924e78da427e.tar.gz bun-7458b969c5d9971e89d187b687e1924e78da427e.tar.zst bun-7458b969c5d9971e89d187b687e1924e78da427e.zip |
Merge branch 'main' into postinstall_3
Diffstat (limited to 'src/bun.js/bindings')
116 files changed, 7226 insertions, 2139 deletions
diff --git a/src/bun.js/bindings/AsyncContextFrame.cpp b/src/bun.js/bindings/AsyncContextFrame.cpp index 1c541b2a8..7b715d3d7 100644 --- a/src/bun.js/bindings/AsyncContextFrame.cpp +++ b/src/bun.js/bindings/AsyncContextFrame.cpp @@ -22,7 +22,7 @@ AsyncContextFrame* AsyncContextFrame::create(VM& vm, JSC::Structure* structure, AsyncContextFrame* AsyncContextFrame::create(JSGlobalObject* global, JSValue callback, JSValue context) { auto& vm = global->vm(); - AsyncContextFrame* asyncContextData = new (NotNull, allocateCell<AsyncContextFrame>(vm)) AsyncContextFrame(vm, static_cast<Zig::GlobalObject*>(global)->AsyncContextFrameStructure()); + AsyncContextFrame* asyncContextData = new (NotNull, allocateCell<AsyncContextFrame>(vm)) AsyncContextFrame(vm, jsCast<Zig::GlobalObject*>(global)->AsyncContextFrameStructure()); asyncContextData->finishCreation(vm); asyncContextData->callback.set(vm, asyncContextData, callback); asyncContextData->context.set(vm, asyncContextData, context); @@ -47,7 +47,7 @@ JSValue AsyncContextFrame::withAsyncContextIfNeeded(JSGlobalObject* globalObject auto& vm = globalObject->vm(); return AsyncContextFrame::create( vm, - static_cast<Zig::GlobalObject*>(globalObject)->AsyncContextFrameStructure(), + jsCast<Zig::GlobalObject*>(globalObject)->AsyncContextFrameStructure(), callback, context); } diff --git a/src/bun.js/bindings/BunDebugger.cpp b/src/bun.js/bindings/BunDebugger.cpp index 046739923..55942d2f6 100644 --- a/src/bun.js/bindings/BunDebugger.cpp +++ b/src/bun.js/bindings/BunDebugger.cpp @@ -452,12 +452,13 @@ extern "C" void Bun__ensureDebugger(ScriptExecutionContextIdentifier scriptId, b } } -extern "C" void BunDebugger__willHotReload() { +extern "C" void BunDebugger__willHotReload() +{ if (debuggerScriptExecutionContext == nullptr) { return; } - debuggerScriptExecutionContext->postTaskConcurrently([](ScriptExecutionContext &context){ + debuggerScriptExecutionContext->postTaskConcurrently([](ScriptExecutionContext& context) { WTF::LockHolder locker(inspectorConnectionsLock); for (auto& connections : *inspectorConnections) { for (auto* connection : connections.value) { diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 0b78d1367..498b83b45 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -190,7 +190,7 @@ static JSValue constructPluginObject(VM& vm, JSObject* bunObject) auto* globalObject = bunObject->globalObject(); JSFunction* pluginFunction = JSFunction::create(vm, globalObject, 1, String("plugin"_s), jsFunctionBunPlugin, ImplementationVisibility::Public, NoIntrinsic); pluginFunction->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "clearAll"_s), 1, jsFunctionBunPluginClear, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); return pluginFunction; } @@ -215,37 +215,40 @@ extern "C" EncodedJSValue Bun__DNSResolver__resolvePtr(JSGlobalObject*, JSC::Cal extern "C" EncodedJSValue Bun__DNSResolver__resolveCname(JSGlobalObject*, JSC::CallFrame*); extern "C" EncodedJSValue Bun__DNSResolver__getServers(JSGlobalObject*, JSC::CallFrame*); extern "C" EncodedJSValue Bun__DNSResolver__reverse(JSGlobalObject*, JSC::CallFrame*); +extern "C" EncodedJSValue Bun__DNSResolver__lookupService(JSGlobalObject*, JSC::CallFrame*); static JSValue constructDNSObject(VM& vm, JSObject* bunObject) { JSGlobalObject* globalObject = bunObject->globalObject(); JSC::JSObject* dnsObject = JSC::constructEmptyObject(globalObject); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "lookup"_s), 2, Bun__DNSResolver__lookup, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolve"_s), 2, Bun__DNSResolver__resolve, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveSrv"_s), 2, Bun__DNSResolver__resolveSrv, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveTxt"_s), 2, Bun__DNSResolver__resolveTxt, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveSoa"_s), 2, Bun__DNSResolver__resolveSoa, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveNaptr"_s), 2, Bun__DNSResolver__resolveNaptr, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveMx"_s), 2, Bun__DNSResolver__resolveMx, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveCaa"_s), 2, Bun__DNSResolver__resolveCaa, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveNs"_s), 2, Bun__DNSResolver__resolveNs, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolvePtr"_s), 2, Bun__DNSResolver__resolvePtr, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "resolveCname"_s), 2, Bun__DNSResolver__resolveCname, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "getServers"_s), 2, Bun__DNSResolver__getServers, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "reverse"_s), 2, Bun__DNSResolver__reverse, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::PropertyAttribute::DontDelete | 0); + dnsObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "lookupService"_s), 2, Bun__DNSResolver__lookupService, ImplementationVisibility::Public, NoIntrinsic, + JSC::PropertyAttribute::DontDelete | 0); return dnsObject; } @@ -255,7 +258,7 @@ static JSValue constructBunPeekObject(VM& vm, JSObject* bunObject) JSC::Identifier identifier = JSC::Identifier::fromString(vm, "peek"_s); JSFunction* peekFunction = JSFunction::create(vm, globalObject, 2, WTF::String("peek"_s), functionBunPeek, ImplementationVisibility::Public, NoIntrinsic); JSFunction* peekStatus = JSFunction::create(vm, globalObject, 1, WTF::String("status"_s), functionBunPeekStatus, ImplementationVisibility::Public, NoIntrinsic); - peekFunction->putDirect(vm, PropertyName(JSC::Identifier::fromString(vm, "status"_s)), peekStatus, JSC::PropertyAttribute::Function | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); + peekFunction->putDirect(vm, PropertyName(JSC::Identifier::fromString(vm, "status"_s)), peekStatus, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); return peekFunction; } @@ -602,7 +605,7 @@ JSC_DEFINE_HOST_FUNCTION(functionHashCode, hash BunObject_getter_wrap_hash DontDelete|PropertyCallback indexOfLine BunObject_callback_indexOfLine DontDelete|Function 1 inflateSync BunObject_callback_inflateSync DontDelete|Function 1 - inspect BunObject_getter_wrap_inspect DontDelete|PropertyCallback + inspect BunObject_getter_wrap_inspect DontDelete|PropertyCallback isMainThread constructIsMainThread ReadOnly|DontDelete|PropertyCallback jest BunObject_callback_jest DontEnum|DontDelete|Function 1 listen BunObject_callback_listen DontDelete|Function 1 @@ -660,6 +663,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBunObject, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -670,15 +674,14 @@ public: void finishCreation(JSC::VM& vm) { Base::finishCreation(vm); - JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } static JSBunObject* create(JSC::VM& vm, JSGlobalObject* globalObject) { - auto* object = new (NotNull, JSC::allocateCell<JSBunObject>(vm)) JSBunObject(vm, createStructure(vm, globalObject, globalObject->objectPrototype())); + auto structure = createStructure(vm, globalObject, globalObject->objectPrototype()); + auto* object = new (NotNull, JSC::allocateCell<JSBunObject>(vm)) JSBunObject(vm, structure); object->finishCreation(vm); - return object; } }; @@ -699,11 +702,11 @@ public: #undef bunObjectReadableStreamToJSONCodeGenerator #undef bunObjectReadableStreamToTextCodeGenerator -const JSC::ClassInfo JSBunObject::s_info = { "Bun"_s, &JSNonFinalObject::s_info, &bunObjectTable, nullptr, CREATE_METHOD_TABLE(JSBunObject) }; +const JSC::ClassInfo JSBunObject::s_info = { "Bun"_s, &Base::s_info, &bunObjectTable, nullptr, CREATE_METHOD_TABLE(JSBunObject) }; -JSValue createBunObject(Zig::GlobalObject* globalObject) +JSC::JSObject* createBunObject(VM& vm, JSObject* globalObject) { - return JSBunObject::create(globalObject->vm(), globalObject); + return JSBunObject::create(vm, jsCast<Zig::GlobalObject*>(globalObject)); } } diff --git a/src/bun.js/bindings/BunObject.h b/src/bun.js/bindings/BunObject.h index c2abfe06f..f527f5729 100644 --- a/src/bun.js/bindings/BunObject.h +++ b/src/bun.js/bindings/BunObject.h @@ -13,5 +13,5 @@ JSC_DECLARE_HOST_FUNCTION(functionBunNanoseconds); JSC_DECLARE_HOST_FUNCTION(functionPathToFileURL); JSC_DECLARE_HOST_FUNCTION(functionFileURLToPath); -JSC::JSValue createBunObject(Zig::GlobalObject* globalObject); +JSC::JSObject* createBunObject(VM& vm, JSObject* globalObject); } diff --git a/src/bun.js/bindings/BunObject.lut.h b/src/bun.js/bindings/BunObject.lut.h index 1971cb8da..a2aa95fda 100644 --- a/src/bun.js/bindings/BunObject.lut.h +++ b/src/bun.js/bindings/BunObject.lut.h @@ -1,4 +1,4 @@ -// File generated via `make generate-builtins` +// File generated via `make static-hash-table` / `make cpp` static const struct CompactHashIndex bunObjectTableIndex[269] = { { 75, -1 }, { -1, -1 }, diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index 129d7816b..e0527c724 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -11,14 +11,17 @@ #include "JavaScriptCore/JSObjectInlines.h" #include "wtf/text/WTFString.h" #include "JavaScriptCore/JSCInlines.h" +#include "JavaScriptCore/StrongInlines.h" #include "JavaScriptCore/ObjectConstructor.h" #include "JavaScriptCore/SubspaceInlines.h" #include "JavaScriptCore/RegExpObject.h" #include "JavaScriptCore/JSPromise.h" #include "BunClientData.h" - +#include "isBuiltinModule.h" #include "JavaScriptCore/RegularExpression.h" +#include "JavaScriptCore/JSMap.h" +#include "JavaScriptCore/JSMapInlines.h" namespace Zig { @@ -86,6 +89,76 @@ static EncodedJSValue jsFunctionAppendOnLoadPluginBody(JSC::JSGlobalObject* glob return JSValue::encode(jsUndefined()); } +static EncodedJSValue jsFunctionAppendVirtualModulePluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) +{ + JSC::VM& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (callframe->argumentCount() < 2) { + throwException(globalObject, scope, createError(globalObject, "module() needs 2 arguments: a module ID and a function to call"_s)); + return JSValue::encode(jsUndefined()); + } + + JSValue moduleIdValue = callframe->uncheckedArgument(0); + JSValue functionValue = callframe->uncheckedArgument(1); + + if (!moduleIdValue.isString()) { + throwException(globalObject, scope, createError(globalObject, "module() expects first argument to be a string for the module ID"_s)); + return JSValue::encode(jsUndefined()); + } + + if (!functionValue.isCallable()) { + throwException(globalObject, scope, createError(globalObject, "module() expects second argument to be a function"_s)); + return JSValue::encode(jsUndefined()); + } + + String moduleId = moduleIdValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + + if (moduleId.isEmpty()) { + throwException(globalObject, scope, createError(globalObject, "virtual module cannot be blank"_s)); + return JSValue::encode(jsUndefined()); + } + + if (Bun::isBuiltinModule(moduleId)) { + throwException(globalObject, scope, createError(globalObject, makeString("module() cannot be used to override builtin module \""_s, moduleId, "\""_s))); + return JSValue::encode(jsUndefined()); + } + + if (moduleId.startsWith("."_s)) { + throwException(globalObject, scope, createError(globalObject, "virtual module cannot start with \".\""_s)); + return JSValue::encode(jsUndefined()); + } + + Zig::GlobalObject* global = Zig::jsCast<Zig::GlobalObject*>(globalObject); + if (global->onLoadPlugins.virtualModules == nullptr) { + global->onLoadPlugins.virtualModules = new BunPlugin::VirtualModuleMap; + } + auto* virtualModules = global->onLoadPlugins.virtualModules; + + virtualModules->set(moduleId, JSC::Strong<JSC::JSObject> { vm, jsCast<JSC::JSObject*>(functionValue) }); + + JSMap* esmRegistry; + + if (auto loaderValue = global->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "Loader"_s))) { + if (auto registryValue = loaderValue.getObject()->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "registry"_s))) { + esmRegistry = jsCast<JSC::JSMap*>(registryValue); + } + } + + global->requireMap()->remove(globalObject, moduleIdValue); + esmRegistry && esmRegistry->remove(globalObject, moduleIdValue); + + // bool hasBeenRequired = global->requireMap()->has(globalObject, moduleIdValue); + // bool hasBeenImported = esmRegistry && esmRegistry->has(globalObject, moduleIdValue); + // if (hasBeenRequired || hasBeenImported) { + // // callAndReplaceModule(global, moduleIdValue, functionValue, global->requireMap(), esmRegistry, hasBeenRequired, hasBeenImported); + // // RETURN_IF_EXCEPTION(scope, encodedJSValue()); + // } + + return JSValue::encode(jsUndefined()); +} + static EncodedJSValue jsFunctionAppendOnResolvePluginBody(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target, BunPlugin::Base& plugin, void* ctx, OnAppendPluginCallback callback) { JSC::VM& vm = globalObject->vm(); @@ -143,7 +216,7 @@ static EncodedJSValue jsFunctionAppendOnResolvePluginGlobal(JSC::JSGlobalObject* { Zig::GlobalObject* global = Zig::jsCast<Zig::GlobalObject*>(globalObject); - auto& plugins = global->onResolvePlugins[target]; + auto& plugins = global->onResolvePlugins; auto callback = Bun__onDidAppendPlugin; return jsFunctionAppendOnResolvePluginBody(globalObject, callframe, target, plugins, global->bunVM(), callback); } @@ -152,7 +225,7 @@ static EncodedJSValue jsFunctionAppendOnLoadPluginGlobal(JSC::JSGlobalObject* gl { Zig::GlobalObject* global = Zig::jsCast<Zig::GlobalObject*>(globalObject); - auto& plugins = global->onLoadPlugins[target]; + auto& plugins = global->onLoadPlugins; auto callback = Bun__onDidAppendPlugin; return jsFunctionAppendOnLoadPluginBody(globalObject, callframe, target, plugins, global->bunVM(), callback); } @@ -182,6 +255,11 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolvePluginBun, (JSC::JSGlobalObjec return jsFunctionAppendOnResolvePluginGlobal(globalObject, callframe, BunPluginTargetBun); } +JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendVirtualModule, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) +{ + return jsFunctionAppendVirtualModulePluginBody(globalObject, callframe); +} + JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolvePluginBrowser, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callframe)) { return jsFunctionAppendOnResolvePluginGlobal(globalObject, callframe, BunPluginTargetBrowser); @@ -190,12 +268,12 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionAppendOnResolvePluginBrowser, (JSC::JSGlobalO extern "C" EncodedJSValue jsFunctionBunPluginClear(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) { Zig::GlobalObject* global = reinterpret_cast<Zig::GlobalObject*>(globalObject); - for (uint8_t i = 0; i < BunPluginTargetMax + 1; i++) { - global->onLoadPlugins[i].fileNamespace.clear(); - global->onResolvePlugins[i].fileNamespace.clear(); - global->onLoadPlugins[i].groups.clear(); - global->onResolvePlugins[i].namespaces.clear(); - } + global->onLoadPlugins.fileNamespace.clear(); + global->onResolvePlugins.fileNamespace.clear(); + global->onLoadPlugins.groups.clear(); + global->onResolvePlugins.namespaces.clear(); + + delete global->onLoadPlugins.virtualModules; return JSValue::encode(jsUndefined()); } @@ -239,76 +317,37 @@ extern "C" EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, JSC: } JSFunction* setupFunction = jsCast<JSFunction*>(setupFunctionValue); - JSObject* builderObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 3); - - switch (target) { - case BunPluginTargetNode: { - builderObject->putDirect(vm, Identifier::fromString(vm, "target"_s), jsString(vm, String("node"_s)), 0); - builderObject->putDirectNativeFunction( - vm, - globalObject, - JSC::Identifier::fromString(vm, "onLoad"_s), - 1, - jsFunctionAppendOnLoadPluginNode, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::DontDelete | 0); - builderObject->putDirectNativeFunction( - vm, - globalObject, - JSC::Identifier::fromString(vm, "onResolve"_s), - 1, - jsFunctionAppendOnResolvePluginNode, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::DontDelete | 0); - break; - } - case BunPluginTargetBun: { - builderObject->putDirect(vm, Identifier::fromString(vm, "target"_s), jsString(vm, String("bun"_s)), 0); - builderObject->putDirectNativeFunction( - vm, - globalObject, - JSC::Identifier::fromString(vm, "onLoad"_s), - 1, - jsFunctionAppendOnLoadPluginBun, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::DontDelete | 0); - builderObject->putDirectNativeFunction( - vm, - globalObject, - JSC::Identifier::fromString(vm, "onResolve"_s), - 1, - jsFunctionAppendOnResolvePluginBun, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::DontDelete | 0); - break; - } - case BunPluginTargetBrowser: { - builderObject->putDirect(vm, Identifier::fromString(vm, "target"_s), jsString(vm, String("browser"_s)), 0); - builderObject->putDirectNativeFunction( - vm, - globalObject, - JSC::Identifier::fromString(vm, "onLoad"_s), - 1, - jsFunctionAppendOnLoadPluginBrowser, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::DontDelete | 0); - builderObject->putDirectNativeFunction( - vm, - globalObject, - JSC::Identifier::fromString(vm, "onResolve"_s), - 1, - jsFunctionAppendOnResolvePluginBrowser, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::DontDelete | 0); - break; - } - } + JSObject* builderObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 4); + + builderObject->putDirect(vm, Identifier::fromString(vm, "target"_s), jsString(vm, String("bun"_s)), 0); + builderObject->putDirectNativeFunction( + vm, + globalObject, + JSC::Identifier::fromString(vm, "onLoad"_s), + 1, + jsFunctionAppendOnLoadPluginBun, + ImplementationVisibility::Public, + NoIntrinsic, + JSC::PropertyAttribute::DontDelete | 0); + builderObject->putDirectNativeFunction( + vm, + globalObject, + JSC::Identifier::fromString(vm, "onResolve"_s), + 1, + jsFunctionAppendOnResolvePluginBun, + ImplementationVisibility::Public, + NoIntrinsic, + JSC::PropertyAttribute::DontDelete | 0); + + builderObject->putDirectNativeFunction( + vm, + globalObject, + JSC::Identifier::fromString(vm, "module"_s), + 1, + jsFunctionAppendVirtualModule, + ImplementationVisibility::Public, + NoIntrinsic, + JSC::PropertyAttribute::DontDelete | 0); JSC::MarkedArgumentBuffer args; args.append(builderObject); @@ -329,9 +368,7 @@ extern "C" EncodedJSValue setupBunPlugin(JSC::JSGlobalObject* globalObject, JSC: extern "C" EncodedJSValue jsFunctionBunPlugin(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe) { Zig::GlobalObject* global = reinterpret_cast<Zig::GlobalObject*>(globalObject); - BunPluginTarget target = global->defaultBunPluginTarget; - - return setupBunPlugin(globalObject, callframe, target); + return setupBunPlugin(globalObject, callframe, BunPluginTargetBun); } void BunPlugin::Group::append(JSC::VM& vm, JSC::RegExp* filter, JSC::JSFunction* func) @@ -513,10 +550,60 @@ EncodedJSValue BunPlugin::OnResolve::run(JSC::JSGlobalObject* globalObject, BunS extern "C" JSC::EncodedJSValue Bun__runOnResolvePlugins(Zig::GlobalObject* globalObject, BunString* namespaceString, BunString* path, BunString* from, BunPluginTarget target) { - return globalObject->onResolvePlugins[target].run(globalObject, namespaceString, path, from); + return globalObject->onResolvePlugins.run(globalObject, namespaceString, path, from); } extern "C" JSC::EncodedJSValue Bun__runOnLoadPlugins(Zig::GlobalObject* globalObject, BunString* namespaceString, BunString* path, BunPluginTarget target) { - return globalObject->onLoadPlugins[target].run(globalObject, namespaceString, path); + return globalObject->onLoadPlugins.run(globalObject, namespaceString, path); +} + +namespace Bun { +JSC::JSValue runVirtualModule(Zig::GlobalObject* globalObject, BunString* specifier) +{ + auto fallback = [&]() -> JSC::JSValue { + return JSValue::decode(Bun__runVirtualModule(globalObject, specifier)); + }; + + if (!globalObject->onLoadPlugins.virtualModules) { + return fallback(); + } + auto& virtualModules = *globalObject->onLoadPlugins.virtualModules; + WTF::String specifierString = Bun::toWTFString(*specifier); + if (auto virtualModuleFn = virtualModules.get(specifierString)) { + auto& vm = globalObject->vm(); + JSC::JSObject* function = virtualModuleFn.get(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + JSC::MarkedArgumentBuffer arguments; + JSC::CallData callData = JSC::getCallData(function); + RELEASE_ASSERT(callData.type != JSC::CallData::Type::None); + + auto result = call(globalObject, function, callData, JSC::jsUndefined(), arguments); + RETURN_IF_EXCEPTION(throwScope, JSC::jsUndefined()); + + if (auto* promise = JSC::jsDynamicCast<JSPromise*>(result)) { + switch (promise->status(vm)) { + case JSPromise::Status::Rejected: + case JSPromise::Status::Pending: { + return promise; + } + case JSPromise::Status::Fulfilled: { + result = promise->result(vm); + break; + } + } + } + + if (!result.isObject()) { + JSC::throwTypeError(globalObject, throwScope, "virtual module expects an object returned"_s); + return JSC::jsUndefined(); + } + + return result; + } + + return fallback(); } + +}
\ No newline at end of file diff --git a/src/bun.js/bindings/BunPlugin.h b/src/bun.js/bindings/BunPlugin.h index cf37b739b..f4d09883d 100644 --- a/src/bun.js/bindings/BunPlugin.h +++ b/src/bun.js/bindings/BunPlugin.h @@ -15,6 +15,8 @@ using namespace JSC; class BunPlugin { public: + using VirtualModuleMap = WTF::HashMap<String, JSC::Strong<JSC::JSObject>>; + // This is a list of pairs of regexps and functions to match against class Group { @@ -67,7 +69,15 @@ public: { } - EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path); + VirtualModuleMap* virtualModules = nullptr; + JSC::EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path); + + ~OnLoad() + { + if (virtualModules) { + delete virtualModules; + } + } }; class OnResolve final : public Base { @@ -78,8 +88,14 @@ public: { } - EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path, BunString* importer); + JSC::EncodedJSValue run(JSC::JSGlobalObject* globalObject, BunString* namespaceString, BunString* path, BunString* importer); }; }; -} // namespace Zig
\ No newline at end of file +class GlobalObject; + +} // namespace Zig + +namespace Bun { +JSC::JSValue runVirtualModule(Zig::GlobalObject*, BunString* specifier); +}
\ No newline at end of file diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index 416d5d334..99fd02175 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -3,12 +3,13 @@ #include "JavaScriptCore/JSCJSValueInlines.h" #include "helpers.h" #include "simdutf.h" -#include "wtf/text/ExternalStringImpl.h" +#include "wtf/Seconds.h" #include "GCDefferalContext.h" #include <JavaScriptCore/JSONObject.h> #include <wtf/text/AtomString.h> using namespace JSC; +extern "C" BunString BunString__fromBytes(const char* bytes, size_t length); extern "C" bool Bun__WTFStringImpl__hasPrefix(const WTF::StringImpl* impl, const char* bytes, size_t length) { @@ -74,7 +75,10 @@ JSC::JSValue toJS(JSC::JSGlobalObject* globalObject, BunString bunString, size_t #endif return jsSubstring(globalObject, jsUndefined(), Bun::toWTFString(bunString), 0, length); } - +BunString toString(const char* bytes, size_t length) +{ + return BunString__fromBytes(bytes, length); +} WTF::String toWTFString(const BunString& bunString) { if (bunString.tag == BunStringTag::ZigString) { @@ -190,22 +194,6 @@ BunString toStringRef(WTF::StringImpl* wtfString) return { BunStringTag::WTFStringImpl, { .wtf = wtfString } }; } -BunString fromString(WTF::String& wtfString) -{ - if (wtfString.isEmpty()) - return { BunStringTag::Empty }; - - return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } }; -} - -BunString fromString(WTF::StringImpl* wtfString) -{ - if (wtfString->isEmpty()) - return { BunStringTag::Empty }; - - return { BunStringTag::WTFStringImpl, { .wtf = wtfString } }; -} - } extern "C" JSC::EncodedJSValue BunString__toJS(JSC::JSGlobalObject* globalObject, BunString* bunString) @@ -252,7 +240,7 @@ extern "C" BunString BunString__fromUTF8(const char* bytes, size_t length) auto str = WTF::String::fromUTF8ReplacingInvalidSequences(reinterpret_cast<const LChar*>(bytes), length); str.impl()->ref(); - return Bun::fromString(str); + return Bun::toString(str); } extern "C" BunString BunString__fromLatin1(const char* bytes, size_t length) @@ -381,7 +369,17 @@ extern "C" BunString URL__getHref(BunString* input) return Bun::toStringRef(url.string()); } -extern "C" BunString URL__getHrefJoin(BunString* baseStr, BunString *relativeStr) +extern "C" BunString URL__pathFromFileURL(BunString* input) +{ + auto&& str = Bun::toWTFString(*input); + auto url = WTF::URL(str); + if (!url.isValid() || url.isEmpty()) + return { BunStringTag::Dead }; + + return Bun::toStringRef(url.fileSystemPath()); +} + +extern "C" BunString URL__getHrefJoin(BunString* baseStr, BunString* relativeStr) { auto base = Bun::toWTFString(*baseStr); auto relative = Bun::toWTFString(*relativeStr); @@ -455,4 +453,4 @@ extern "C" uint32_t URL__port(WTF::URL* url) extern "C" BunString URL__pathname(WTF::URL* url) { return Bun::toStringRef(url->path().toStringWithoutCopying()); -}
\ No newline at end of file +} diff --git a/src/bun.js/bindings/CallSite.cpp b/src/bun.js/bindings/CallSite.cpp index 48fe82275..7667d9606 100644 --- a/src/bun.js/bindings/CallSite.cpp +++ b/src/bun.js/bindings/CallSite.cpp @@ -45,7 +45,7 @@ void CallSite::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSCStac m_function.set(vm, this, JSC::jsUndefined()); m_flags |= static_cast<unsigned int>(Flags::IsStrict); } else { - if (callFrame) { + if (callFrame && callFrame->thisValue()) { // We know that we're not in strict mode m_thisValue.set(vm, this, callFrame->thisValue().toThis(globalObject, JSC::ECMAMode::sloppy())); } else { diff --git a/src/bun.js/bindings/CallSitePrototype.h b/src/bun.js/bindings/CallSitePrototype.h index 000bce2de..8aa543fd3 100644 --- a/src/bun.js/bindings/CallSitePrototype.h +++ b/src/bun.js/bindings/CallSitePrototype.h @@ -26,6 +26,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(CallSitePrototype, Base); return &vm.plainObjectSpace(); } diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp index b94386ab3..f47c57559 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.cpp +++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp @@ -8,7 +8,7 @@ * Then, at runtime, we create a JSCommonJSModule object. * * On this special object, we override the setter for the "exports" property in - * a non-observable way (`static bool put ...`) + * a non-observable way using a CustomGetterSetter. * * When the setter is called, we set the internal "exports" property to the * value passed in and we also update the requireMap with the new value. @@ -20,17 +20,13 @@ * * If an exception occurs, we remove the entry from the requireMap. * - * We tried using a CustomGetterSetter instead of overriding `put`, but it led - * to returning the getter itself - * - * How cyclical dependencies are handled + * How cyclical dependencies are handled: * * Before executing the CommonJS module, we set the exports object in the * requireMap to an empty object. When the CommonJS module is required again, we * return the exports object from the requireMap. The values should be in sync * while the module is being executed, unless module.exports is re-assigned to a * different value. In that case, it will have a stale value. - * */ #include "root.h" @@ -71,6 +67,8 @@ #include <JavaScriptCore/JSSourceCode.h> #include <JavaScriptCore/LazyPropertyInlines.h> +extern "C" bool Bun__isBunMain(JSC::JSGlobalObject* global, const char* input_ptr, uint64_t input_len); + namespace Bun { using namespace JSC; @@ -96,28 +94,36 @@ static bool canPerformFastEnumeration(Structure* s) static bool evaluateCommonJSModuleOnce(JSC::VM& vm, Zig::GlobalObject* globalObject, JSCommonJSModule* moduleObject, JSString* dirname, JSValue filename, WTF::NakedPtr<Exception>& exception) { JSC::Structure* thisObjectStructure = globalObject->commonJSFunctionArgumentsStructure(); - JSC::JSObject* thisObject = JSC::constructEmptyObject( - vm, - thisObjectStructure); - thisObject->putDirectOffset( - vm, - 0, - moduleObject); - thisObject->putDirectOffset( - vm, - 1, - dirname); + JSFunction* resolveFunction = JSC::JSBoundFunction::create(vm, + globalObject, + globalObject->requireResolveFunctionUnbound(), + moduleObject->id(), + ArgList(), 1, jsString(vm, String("resolve"_s))); + JSFunction* requireFunction = JSC::JSBoundFunction::create(vm, + globalObject, + globalObject->requireFunctionUnbound(), + moduleObject, + ArgList(), 1, jsString(vm, String("require"_s))); + requireFunction->putDirect(vm, vm.propertyNames->resolve, resolveFunction, 0); + moduleObject->putDirect(vm, WebCore::clientData(vm)->builtinNames().requirePublicName(), requireFunction, 0); - thisObject->putDirectOffset( - vm, - 2, - filename); + JSC::JSObject* thisObject = JSC::constructEmptyObject(vm, thisObjectStructure); + thisObject->putDirectOffset(vm, 0, moduleObject); + thisObject->putDirectOffset(vm, 1, requireFunction); + thisObject->putDirectOffset(vm, 2, resolveFunction); + thisObject->putDirectOffset(vm, 3, dirname); + thisObject->putDirectOffset(vm, 4, filename); moduleObject->hasEvaluated = true; + // TODO: try to not use this write barrier. it needs some extensive testing. + // there is some possible GC issue where `thisObject` is gc'd before it should be globalObject->m_BunCommonJSModuleValue.set(vm, globalObject, thisObject); JSValue empty = JSC::evaluate(globalObject, moduleObject->sourceCode.get()->sourceCode(), thisObject, exception); + + ensureStillAliveHere(thisObject); + globalObject->m_BunCommonJSModuleValue.clear(); moduleObject->sourceCode.clear(); return exception.get() == nullptr; @@ -190,11 +196,25 @@ static const HashTableValue RequireFunctionPrototypeValues[] = { { "cache"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsRequireCacheGetter, jsRequireCacheSetter } }, }; +Structure* RequireFunctionPrototype::createStructure( + JSC::VM& vm, + JSC::JSGlobalObject* globalObject) +{ + return Structure::create(vm, globalObject, globalObject->functionPrototype(), TypeInfo(JSFunctionType, StructureFlags), info()); +} + +Structure* RequireResolveFunctionPrototype::createStructure( + JSC::VM& vm, + JSC::JSGlobalObject* globalObject) +{ + return Structure::create(vm, globalObject, globalObject->functionPrototype(), TypeInfo(JSFunctionType, StructureFlags), info()); +} + RequireResolveFunctionPrototype* RequireResolveFunctionPrototype::create(JSC::JSGlobalObject* globalObject) { auto& vm = globalObject->vm(); - auto* structure = RequireResolveFunctionPrototype::createStructure(vm, globalObject, globalObject->functionPrototype()); + auto* structure = RequireResolveFunctionPrototype::createStructure(vm, globalObject); RequireResolveFunctionPrototype* prototype = new (NotNull, JSC::allocateCell<RequireResolveFunctionPrototype>(vm)) RequireResolveFunctionPrototype(vm, structure); prototype->finishCreation(vm); return prototype; @@ -205,11 +225,11 @@ RequireFunctionPrototype* RequireFunctionPrototype::create( { auto& vm = globalObject->vm(); - auto* structure = RequireFunctionPrototype::createStructure(vm, globalObject, globalObject->functionPrototype()); + auto* structure = RequireFunctionPrototype::createStructure(vm, globalObject); RequireFunctionPrototype* prototype = new (NotNull, JSC::allocateCell<RequireFunctionPrototype>(vm)) RequireFunctionPrototype(vm, structure); prototype->finishCreation(vm); - prototype->putDirect(vm, JSC::Identifier::fromString(vm, "resolve"_s), static_cast<Zig::GlobalObject*>(globalObject)->requireResolveFunctionUnbound(), PropertyAttribute::Function | 0); + prototype->putDirect(vm, JSC::Identifier::fromString(vm, "resolve"_s), jsCast<Zig::GlobalObject*>(globalObject)->requireResolveFunctionUnbound(), 0); return prototype; } @@ -217,7 +237,7 @@ RequireFunctionPrototype* RequireFunctionPrototype::create( void RequireFunctionPrototype::finishCreation(JSC::VM& vm) { Base::finishCreation(vm); - ASSERT(inherits(vm, info())); + ASSERT(inherits(info())); reifyStaticProperties(vm, info(), RequireFunctionPrototypeValues, *this); JSC::JSFunction* requireDotMainFunction = JSFunction::create( @@ -225,11 +245,11 @@ void RequireFunctionPrototype::finishCreation(JSC::VM& vm) moduleMainCodeGenerator(vm), globalObject()->globalScope()); - this->putDirect( - vm, + this->putDirectAccessor( + globalObject(), JSC::Identifier::fromString(vm, "main"_s), - JSC::GetterSetter::create(vm, globalObject(), requireDotMainFunction, JSValue()), - PropertyAttribute::Builtin | PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | 0); + JSC::GetterSetter::create(vm, globalObject(), requireDotMainFunction, requireDotMainFunction), + PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | 0); auto extensions = constructEmptyObject(globalObject()); extensions->putDirect(vm, JSC::Identifier::fromString(vm, ".js"_s), jsBoolean(true), 0); @@ -265,6 +285,31 @@ JSC_DEFINE_CUSTOM_GETTER(getterPath, (JSC::JSGlobalObject * globalObject, JSC::E return JSValue::encode(thisObject->m_id.get()); } +JSC_DEFINE_CUSTOM_GETTER(getterParent, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) +{ + JSCommonJSModule* thisObject = jsDynamicCast<JSCommonJSModule*>(JSValue::decode(thisValue)); + if (UNLIKELY(!thisObject)) { + return JSValue::encode(jsUndefined()); + } + auto v = thisObject->m_parent.get(); + if (v) + return JSValue::encode(thisObject->m_parent.get()); + + // initialize parent by checking if it is the main module. we do this lazily because most people + // dont need `module.parent` and creating commonjs module records is done a ton. + auto idValue = thisObject->m_id.get(); + if (idValue) { + auto id = idValue->value(globalObject).utf8(); + if (Bun__isBunMain(globalObject, id.data(), id.length())) { + thisObject->m_parent.set(globalObject->vm(), thisObject, jsNull()); + return JSValue::encode(jsNull()); + } + } + + thisObject->m_parent.set(globalObject->vm(), thisObject, jsUndefined()); + return JSValue::encode(jsUndefined()); +} + JSC_DEFINE_CUSTOM_SETTER(setterPath, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, JSC::PropertyName propertyName)) @@ -294,6 +339,16 @@ JSC_DEFINE_CUSTOM_GETTER(getterPaths, (JSC::JSGlobalObject * globalObject, JSC:: return JSValue::encode(thisObject->m_paths.get()); } +JSC_DEFINE_CUSTOM_GETTER(getterLoaded, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) +{ + JSCommonJSModule* thisObject = jsDynamicCast<JSCommonJSModule*>(JSValue::decode(thisValue)); + if (UNLIKELY(!thisObject)) { + return JSValue::encode(jsUndefined()); + } + + return JSValue::encode(jsBoolean(thisObject->hasEvaluated)); +} + JSC_DEFINE_CUSTOM_SETTER(setterPaths, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, JSC::PropertyName propertyName)) @@ -329,27 +384,100 @@ JSC_DEFINE_CUSTOM_SETTER(setterId, thisObject->m_id.set(globalObject->vm(), thisObject, JSValue::decode(value).toString(globalObject)); return true; } - -static JSValue createLoaded(VM& vm, JSObject* object) +JSC_DEFINE_CUSTOM_SETTER(setterParent, + (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, + JSC::EncodedJSValue value, JSC::PropertyName propertyName)) { - JSCommonJSModule* cjs = jsCast<JSCommonJSModule*>(object); - return jsBoolean(cjs->hasEvaluated); + JSCommonJSModule* thisObject = jsDynamicCast<JSCommonJSModule*>(JSValue::decode(thisValue)); + if (!thisObject) + return false; + + thisObject->m_parent.set(globalObject->vm(), thisObject, JSValue::decode(value)); + + return true; } -static JSValue createParent(VM& vm, JSObject* object) +JSC_DEFINE_CUSTOM_SETTER(setterLoaded, + (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, + JSC::EncodedJSValue value, JSC::PropertyName propertyName)) { - return jsUndefined(); + JSCommonJSModule* thisObject = jsDynamicCast<JSCommonJSModule*>(JSValue::decode(thisValue)); + if (!thisObject) + return false; + + thisObject->hasEvaluated = JSValue::decode(value).toBoolean(globalObject); + + return true; } + static JSValue createChildren(VM& vm, JSObject* object) { return constructEmptyArray(object->globalObject(), nullptr, 0); } +JSC_DEFINE_HOST_FUNCTION(functionCommonJSModuleRecord_compile, (JSGlobalObject * globalObject, CallFrame* callframe)) +{ + auto* moduleObject = jsDynamicCast<JSCommonJSModule*>(callframe->thisValue()); + if (!moduleObject) { + return JSValue::encode(jsUndefined()); + } + + auto& vm = globalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + String sourceString = callframe->argument(0).toWTFString(globalObject); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode({})); + + String filenameString = callframe->argument(1).toWTFString(globalObject); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode({})); + + String wrappedString = makeString( + "(function(exports,require,module,__filename,__dirname){"_s, + sourceString, + "\n}).call(this.module.exports,this.module.exports,this.require,this.module,this.__filename,this.__dirname)"_s); + + SourceCode sourceCode = makeSource( + WTFMove(wrappedString), + SourceOrigin(URL::fileURLWithFileSystemPath(filenameString)), + JSC::SourceTaintedOrigin::Untainted, + filenameString, + WTF::TextPosition(), + JSC::SourceProviderSourceType::Program); + JSSourceCode* jsSourceCode = JSSourceCode::create(vm, WTFMove(sourceCode)); + moduleObject->sourceCode.set(vm, moduleObject, jsSourceCode); + + auto index = filenameString.reverseFind('/', filenameString.length()); + String dirnameString; + if (index != WTF::notFound) { + dirnameString = filenameString.substring(0, index); + } else { + dirnameString = "/"_s; + } + + WTF::NakedPtr<JSC::Exception> exception; + evaluateCommonJSModuleOnce( + vm, + jsCast<Zig::GlobalObject*>(globalObject), + moduleObject, + jsString(vm, dirnameString), + jsString(vm, filenameString), + exception); + + if (exception) { + throwException(globalObject, throwScope, exception.get()); + exception.clear(); + return JSValue::encode({}); + } + + return JSValue::encode(jsUndefined()); +} + static const struct HashTableValue JSCommonJSModulePrototypeTableValues[] = { - { "children"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback | PropertyAttribute::DontEnum | 0), NoIntrinsic, { HashTableValue::LazyPropertyType, createChildren } }, + { "_compile"_s, static_cast<unsigned>(PropertyAttribute::Function | PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::NativeFunctionType, functionCommonJSModuleRecord_compile, 2 } }, + { "children"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, createChildren } }, { "filename"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterFilename, setterFilename } }, { "id"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterId, setterId } }, - { "loaded"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback | PropertyAttribute::DontEnum | 0), NoIntrinsic, { HashTableValue::LazyPropertyType, createLoaded } }, - { "parent"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback | PropertyAttribute::DontEnum | 0), NoIntrinsic, { HashTableValue::LazyPropertyType, createParent } }, + { "loaded"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterLoaded, setterLoaded } }, + { "parent"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor | PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, getterParent, setterParent } }, { "path"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterPath, setterPath } }, { "paths"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, getterPaths, setterPaths } }, }; @@ -367,6 +495,14 @@ public: return prototype; } + static JSC::Structure* createStructure( + JSC::VM& vm, + JSC::JSGlobalObject* globalObject, + JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + DECLARE_INFO; JSCommonJSModulePrototype( @@ -379,36 +515,36 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCommonJSModulePrototype, Base); return &vm.plainObjectSpace(); } void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) { Base::finishCreation(vm); - ASSERT(inherits(vm, info())); - reifyStaticProperties(vm, JSCommonJSModule::info(), JSCommonJSModulePrototypeTableValues, *this); - - this->putDirect(vm, clientData(vm)->builtinNames().requirePublicName(), (static_cast<Zig::GlobalObject*>(globalObject))->requireFunctionUnbound(), PropertyAttribute::Builtin | PropertyAttribute::Function | 0); + ASSERT(inherits(info())); + reifyStaticProperties(vm, info(), JSCommonJSModulePrototypeTableValues, *this); this->putDirectNativeFunction( vm, globalObject, clientData(vm)->builtinNames().requirePrivateName(), 2, - jsFunctionRequireCommonJS, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); + jsFunctionRequireCommonJS, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete); } }; -const JSC::ClassInfo JSCommonJSModulePrototype::s_info = { "Module"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCommonJSModulePrototype) }; +const JSC::ClassInfo JSCommonJSModulePrototype::s_info = { "ModulePrototype"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCommonJSModulePrototype) }; void JSCommonJSModule::finishCreation(JSC::VM& vm, JSC::JSString* id, JSValue filename, JSC::JSString* dirname, JSC::JSSourceCode* sourceCode) { Base::finishCreation(vm); - ASSERT(inherits(vm, info())); + ASSERT(inherits(info())); m_id.set(vm, this, id); m_filename.set(vm, this, filename); m_dirname.set(vm, this, dirname); - this->sourceCode.set(vm, this, sourceCode); + if (sourceCode) + this->sourceCode.set(vm, this, sourceCode); } JSC::Structure* JSCommonJSModule::createStructure( @@ -439,23 +575,23 @@ JSCommonJSModule* JSCommonJSModule::create( JSC_DEFINE_HOST_FUNCTION(jsFunctionCreateCommonJSModule, (JSGlobalObject * globalObject, CallFrame* callframe)) { auto& vm = globalObject->vm(); + RELEASE_ASSERT(callframe->argumentCount() == 4); - auto id = callframe->argument(0).toWTFString(globalObject); + auto id = callframe->uncheckedArgument(0).toWTFString(globalObject); + JSValue object = callframe->uncheckedArgument(1); + JSValue hasEvaluated = callframe->uncheckedArgument(2); + ASSERT(hasEvaluated.isBoolean()); + JSValue parent = callframe->uncheckedArgument(3); - JSValue object = callframe->argument(1); - - return JSValue::encode( - JSCommonJSModule::create( - jsCast<Zig::GlobalObject*>(globalObject), - id, - object, callframe->argument(2).isBoolean() && callframe->argument(2).asBoolean())); + return JSValue::encode(JSCommonJSModule::create(jsCast<Zig::GlobalObject*>(globalObject), id, object, hasEvaluated.isTrue(), parent)); } JSCommonJSModule* JSCommonJSModule::create( Zig::GlobalObject* globalObject, const WTF::String& key, JSValue exportsObject, - bool hasEvaluated) + bool hasEvaluated, + JSValue parent) { auto& vm = globalObject->vm(); JSString* requireMapKey = JSC::jsStringWithCache(vm, key); @@ -470,8 +606,14 @@ JSCommonJSModule* JSCommonJSModule::create( globalObject->CommonJSModuleObjectStructure(), requireMapKey, requireMapKey, dirname, nullptr); - out->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), exportsObject, exportsObject.isCell() && exportsObject.isCallable() ? JSC::PropertyAttribute::Function | 0 : 0); + out->putDirect( + vm, + WebCore::clientData(vm)->builtinNames().exportsPublicName(), + exportsObject, + 0); out->hasEvaluated = hasEvaluated; + out->m_parent.set(vm, out, parent); + return out; } @@ -543,7 +685,7 @@ void JSCommonJSModule::toSyntheticSource(JSC::JSGlobalObject* globalObject, bool needsToAssignDefault = true; if (result.isObject()) { - auto* exports = asObject(result); + auto* exports = result.getObject(); auto* structure = exports->structure(); uint32_t size = structure->inlineSize() + structure->outOfLineSize(); @@ -673,33 +815,6 @@ JSValue JSCommonJSModule::id() return m_id.get(); } -bool JSCommonJSModule::put( - JSC::JSCell* cell, - JSC::JSGlobalObject* globalObject, - JSC::PropertyName propertyName, - JSC::JSValue value, - JSC::PutPropertySlot& slot) -{ - - auto& vm = globalObject->vm(); - auto* clientData = WebCore::clientData(vm); - auto throwScope = DECLARE_THROW_SCOPE(vm); - - RELEASE_AND_RETURN(throwScope, Base::put(cell, globalObject, propertyName, value, slot)); -} - -template<typename, SubspaceAccess mode> JSC::GCClient::IsoSubspace* JSCommonJSModule::subspaceFor(JSC::VM& vm) -{ - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSCommonJSModule, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForCommonJSModuleRecord.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCommonJSModuleRecord = std::forward<decltype(space)>(space); }, - [](auto& spaces) { return spaces.m_subspaceForCommonJSModuleRecord.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForCommonJSModuleRecord = std::forward<decltype(space)>(space); }); -} - Structure* createCommonJSModuleStructure( Zig::GlobalObject* globalObject) { @@ -740,7 +855,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlo // Special-case for "process" to just return the process object directly. if (UNLIKELY(specifier == "process"_s || specifier == "node:process"_s)) { - jsDynamicCast<JSCommonJSModule*>(callframe->argument(1))->putDirect(vm, builtinNames(vm).exportsPublicName(), globalObject->processObject(), 0); + jsCast<JSCommonJSModule*>(callframe->argument(1))->putDirect(vm, builtinNames(vm).exportsPublicName(), globalObject->processObject(), 0); return JSValue::encode(globalObject->processObject()); } @@ -752,7 +867,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlo JSValue fetchResult = Bun::fetchCommonJSModule( globalObject, - jsDynamicCast<JSCommonJSModule*>(callframe->argument(1)), + jsCast<JSCommonJSModule*>(callframe->argument(1)), specifierValue, &specifierStr, &referrerStr); @@ -763,9 +878,9 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlo void RequireResolveFunctionPrototype::finishCreation(JSC::VM& vm) { Base::finishCreation(vm); - ASSERT(inherits(vm, info())); + ASSERT(inherits(info())); - reifyStaticProperties(vm, RequireResolveFunctionPrototype::info(), RequireResolveFunctionPrototypeValues, *this); + reifyStaticProperties(vm, info(), RequireResolveFunctionPrototypeValues, *this); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } @@ -909,8 +1024,6 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l globalObject->CommonJSModuleObjectStructure(), filename, filename, dirname, nullptr); - auto& builtinNames = WebCore::builtinNames(vm); - JSFunction* requireFunction = JSC::JSBoundFunction::create(vm, globalObject, globalObject->requireFunctionUnbound(), @@ -921,9 +1034,9 @@ JSObject* JSCommonJSModule::createBoundRequireFunction(VM& vm, JSGlobalObject* l globalObject, globalObject->requireResolveFunctionUnbound(), moduleObject, - ArgList(), 1, jsString(vm, String("require"_s))); + ArgList(), 1, jsString(vm, String("resolve"_s))); - requireFunction->putDirect(vm, builtinNames.resolvePublicName(), resolveFunction, PropertyAttribute::Function | 0); + requireFunction->putDirect(vm, vm.propertyNames->resolve, resolveFunction, 0); return requireFunction; } diff --git a/src/bun.js/bindings/CommonJSModuleRecord.h b/src/bun.js/bindings/CommonJSModuleRecord.h index e38d2e083..37353978e 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.h +++ b/src/bun.js/bindings/CommonJSModuleRecord.h @@ -20,13 +20,14 @@ JSC_DECLARE_HOST_FUNCTION(jsFunctionLoadModule); class JSCommonJSModule final : public JSC::JSDestructibleObject { public: using Base = JSC::JSDestructibleObject; - static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesPut; + static constexpr unsigned StructureFlags = Base::StructureFlags; - mutable JSC::WriteBarrier<JSC::JSString> m_id; - mutable JSC::WriteBarrier<JSC::Unknown> m_filename; - mutable JSC::WriteBarrier<JSC::JSString> m_dirname; + mutable JSC::WriteBarrier<JSString> m_id; + mutable JSC::WriteBarrier<Unknown> m_filename; + mutable JSC::WriteBarrier<JSString> m_dirname; mutable JSC::WriteBarrier<Unknown> m_paths; - mutable JSC::WriteBarrier<JSC::JSSourceCode> sourceCode; + mutable JSC::WriteBarrier<Unknown> m_parent; + mutable JSC::WriteBarrier<JSSourceCode> sourceCode; bool ignoreESModuleAnnotation { false }; static void destroy(JSC::JSCell*); @@ -54,8 +55,7 @@ public: static JSCommonJSModule* create( Zig::GlobalObject* globalObject, const WTF::String& key, - JSValue exportsObject, - bool hasEvaluated = false); + JSValue exportsObject, bool hasEvaluated, JSValue parent); static JSCommonJSModule* create( Zig::GlobalObject* globalObject, @@ -72,15 +72,21 @@ public: JSValue exportsObject(); JSValue id(); + DECLARE_INFO; DECLARE_VISIT_CHILDREN; - static bool put(JSC::JSCell* cell, JSC::JSGlobalObject* globalObject, - JSC::PropertyName propertyName, JSC::JSValue value, - JSC::PutPropertySlot& slot); - - DECLARE_INFO; template<typename, SubspaceAccess mode> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm); + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSCommonJSModule, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForCommonJSModuleRecord.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForCommonJSModuleRecord = std::forward<decltype(space)>(space); }, + [](auto& spaces) { return spaces.m_subspaceForCommonJSModuleRecord.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForCommonJSModuleRecord = std::forward<decltype(space)>(space); }); + } bool hasEvaluated = false; @@ -114,7 +120,9 @@ inline std::optional<JSC::SourceCode> createCommonJSModule( class RequireResolveFunctionPrototype final : public JSC::JSNonFinalObject { public: using Base = JSC::JSNonFinalObject; + static RequireResolveFunctionPrototype* create(JSC::JSGlobalObject* globalObject); + static Structure* createStructure(VM& vm, JSC::JSGlobalObject* globalObject); DECLARE_INFO; @@ -128,6 +136,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(RequireResolveFunctionPrototype, Base); return &vm.plainObjectSpace(); } @@ -137,7 +146,11 @@ public: class RequireFunctionPrototype final : public JSC::JSNonFinalObject { public: using Base = JSC::JSNonFinalObject; + static RequireFunctionPrototype* create(JSC::JSGlobalObject* globalObject); + static Structure* createStructure(VM& vm, JSC::JSGlobalObject* globalObject); + + DECLARE_INFO; RequireFunctionPrototype( JSC::VM& vm, @@ -149,12 +162,11 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(RequireFunctionPrototype, Base); return &vm.plainObjectSpace(); } - DECLARE_INFO; - - void finishCreation(JSC::VM& vm); + void finishCreation(JSC::VM&); }; } // namespace Bun diff --git a/src/bun.js/bindings/DOMURL.cpp b/src/bun.js/bindings/DOMURL.cpp index 31381b867..b88161a4d 100644 --- a/src/bun.js/bindings/DOMURL.cpp +++ b/src/bun.js/bindings/DOMURL.cpp @@ -36,26 +36,45 @@ namespace WebCore { +static inline String redact(const String& input) +{ + if (input.contains("@"_s)) + return "<redacted>"_s; + + return makeString('"', input, '"'); +} + inline DOMURL::DOMURL(URL&& completeURL, const URL& baseURL) : m_baseURL(baseURL) , m_url(WTFMove(completeURL)) { } +DOMURL::~DOMURL() = default; + +bool DOMURL::canParse(const String& url, const String& base) +{ + URL baseURL { base }; + if (!base.isNull() && !baseURL.isValid()) + return false; + URL completeURL { baseURL, url }; + return completeURL.isValid(); +} + ExceptionOr<Ref<DOMURL>> DOMURL::create(const String& url, const URL& base) { ASSERT(base.isValid() || base.isNull()); URL completeURL { base, url }; if (!completeURL.isValid()) - return Exception { TypeError }; + return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL.") }; return adoptRef(*new DOMURL(WTFMove(completeURL), base)); } ExceptionOr<Ref<DOMURL>> DOMURL::create(const String& url, const String& base) { - URL baseURL { URL {}, base }; + URL baseURL { base }; if (!base.isNull() && !baseURL.isValid()) - return Exception { TypeError }; + return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL against "_s, redact(base)) }; return create(url, baseURL); } @@ -64,13 +83,13 @@ ExceptionOr<Ref<DOMURL>> DOMURL::create(const String& url, const DOMURL& base) return create(url, base.href()); } -DOMURL::~DOMURL() = default; - ExceptionOr<void> DOMURL::setHref(const String& url) { URL completeURL { URL {}, url }; - if (!completeURL.isValid()) - return Exception { TypeError }; + if (!completeURL.isValid()) { + + return Exception { TypeError, makeString(redact(url), " cannot be parsed as a URL.") }; + } m_url = WTFMove(completeURL); if (m_searchParams) m_searchParams->updateFromAssociatedURL(); diff --git a/src/bun.js/bindings/DOMURL.h b/src/bun.js/bindings/DOMURL.h index 0a6210690..0f19510b6 100644 --- a/src/bun.js/bindings/DOMURL.h +++ b/src/bun.js/bindings/DOMURL.h @@ -43,6 +43,7 @@ public: static ExceptionOr<Ref<DOMURL>> create(const String& url, const DOMURL& base); ~DOMURL(); + static bool canParse(const String& url, const String& base); const URL& href() const { return m_url; } ExceptionOr<void> setHref(const String&); void setQuery(const String&); diff --git a/src/bun.js/bindings/ErrorStackTrace.cpp b/src/bun.js/bindings/ErrorStackTrace.cpp index a8c5b65d8..f7013c9c4 100644 --- a/src/bun.js/bindings/ErrorStackTrace.cpp +++ b/src/bun.js/bindings/ErrorStackTrace.cpp @@ -12,6 +12,7 @@ #include <JavaScriptCore/JSCInlines.h> #include <JavaScriptCore/ErrorInstance.h> #include <JavaScriptCore/StackVisitor.h> +#include <JavaScriptCore/NativeCallee.h> #include <wtf/IterationStatus.h> using namespace JSC; @@ -130,8 +131,8 @@ JSCStackFrame::JSCStackFrame(JSC::VM& vm, JSC::StackVisitor& visitor) : m_vm(vm) , m_codeBlock(nullptr) , m_bytecodeIndex(JSC::BytecodeIndex()) - , m_sourceURL(nullptr) - , m_functionName(nullptr) + , m_sourceURL() + , m_functionName() , m_isWasmFrame(false) , m_sourcePositionsState(SourcePositionsState::NotCalculated) { @@ -139,9 +140,18 @@ JSCStackFrame::JSCStackFrame(JSC::VM& vm, JSC::StackVisitor& visitor) m_callFrame = visitor->callFrame(); // Based on JSC's GetStackTraceFunctor (Interpreter.cpp) - if (visitor->isWasmFrame()) { - m_wasmFunctionIndexOrName = visitor->wasmFunctionIndexOrName(); - m_isWasmFrame = true; + if (visitor->isNativeCalleeFrame()) { + auto* nativeCallee = visitor->callee().asNativeCallee(); + switch (nativeCallee->category()) { + case NativeCallee::Category::Wasm: { + m_wasmFunctionIndexOrName = visitor->wasmFunctionIndexOrName(); + m_isWasmFrame = true; + break; + } + case NativeCallee::Category::InlineCache: { + break; + } + } } else if (!!visitor->codeBlock() && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) { m_codeBlock = visitor->codeBlock(); m_bytecodeIndex = visitor->bytecodeIndex(); @@ -153,8 +163,8 @@ JSCStackFrame::JSCStackFrame(JSC::VM& vm, const JSC::StackFrame& frame) , m_callFrame(nullptr) , m_codeBlock(nullptr) , m_bytecodeIndex(JSC::BytecodeIndex()) - , m_sourceURL(nullptr) - , m_functionName(nullptr) + , m_sourceURL() + , m_functionName() , m_isWasmFrame(false) , m_sourcePositionsState(SourcePositionsState::NotCalculated) { @@ -183,7 +193,7 @@ JSC::JSString* JSCStackFrame::sourceURL() m_sourceURL = retrieveSourceURL(); } - return m_sourceURL; + return jsString(this->m_vm, m_sourceURL); } JSC::JSString* JSCStackFrame::functionName() @@ -192,7 +202,7 @@ JSC::JSString* JSCStackFrame::functionName() m_functionName = retrieveFunctionName(); } - return m_functionName; + return jsString(this->m_vm, m_functionName); } JSC::JSString* JSCStackFrame::typeName() @@ -201,7 +211,7 @@ JSC::JSString* JSCStackFrame::typeName() m_typeName = retrieveTypeName(); } - return m_typeName; + return jsString(this->m_vm, m_typeName); } JSCStackFrame::SourcePositions* JSCStackFrame::getSourcePositions() @@ -213,91 +223,61 @@ JSCStackFrame::SourcePositions* JSCStackFrame::getSourcePositions() return (SourcePositionsState::Calculated == m_sourcePositionsState) ? &m_sourcePositions : nullptr; } -ALWAYS_INLINE JSC::JSString* JSCStackFrame::retrieveSourceURL() +ALWAYS_INLINE String JSCStackFrame::retrieveSourceURL() { static auto sourceURLWasmString = MAKE_STATIC_STRING_IMPL("[wasm code]"); static auto sourceURLNativeString = MAKE_STATIC_STRING_IMPL("[native code]"); if (m_isWasmFrame) { - return jsOwnedString(m_vm, sourceURLWasmString); + return String(sourceURLWasmString); } if (!m_codeBlock) { - return jsOwnedString(m_vm, sourceURLNativeString); + return String(sourceURLNativeString); } - String sourceURL = m_codeBlock->ownerExecutable()->sourceURL(); - return sourceURL.isNull() ? m_vm.smallStrings.emptyString() : JSC::jsString(m_vm, sourceURL); + return m_codeBlock->ownerExecutable()->sourceURL(); } -ALWAYS_INLINE JSC::JSString* JSCStackFrame::retrieveFunctionName() +ALWAYS_INLINE String JSCStackFrame::retrieveFunctionName() { static auto functionNameEvalCodeString = MAKE_STATIC_STRING_IMPL("eval code"); static auto functionNameModuleCodeString = MAKE_STATIC_STRING_IMPL("module code"); static auto functionNameGlobalCodeString = MAKE_STATIC_STRING_IMPL("global code"); if (m_isWasmFrame) { - return jsString(m_vm, JSC::Wasm::makeString(m_wasmFunctionIndexOrName)); + return JSC::Wasm::makeString(m_wasmFunctionIndexOrName); } if (m_codeBlock) { switch (m_codeBlock->codeType()) { case JSC::EvalCode: - return JSC::jsOwnedString(m_vm, functionNameEvalCodeString); + return String(functionNameEvalCodeString); case JSC::ModuleCode: - return JSC::jsOwnedString(m_vm, functionNameModuleCodeString); + return String(functionNameModuleCodeString); case JSC::FunctionCode: break; case JSC::GlobalCode: - return JSC::jsOwnedString(m_vm, functionNameGlobalCodeString); + return String(functionNameGlobalCodeString); default: ASSERT_NOT_REACHED(); } } - if (!m_callee || !m_callee->isObject()) { - return m_vm.smallStrings.emptyString(); - } - - JSC::JSObject* calleeAsObject = JSC::jsCast<JSC::JSObject*>(m_callee); - - // First, try the "displayName" property - JSC::JSValue displayName = calleeAsObject->getDirect(m_vm, m_vm.propertyNames->displayName); - if (displayName && isJSString(displayName)) { - return JSC::asString(displayName); - } - - // Our addition - if there's no "dispalyName" property, try the "name" property - JSC::JSValue name = calleeAsObject->getDirect(m_vm, m_vm.propertyNames->name); - if (name && isJSString(name)) { - return JSC::asString(name); - } - - /* For functions (either JSFunction or InternalFunction), fallback to their "native" name property. - * Based on JSC::getCalculatedDisplayName, "inlining" the - * JSFunction::calculatedDisplayName\InternalFunction::calculatedDisplayName calls */ - if (JSC::JSFunction* function = JSC::jsDynamicCast<JSC::JSFunction*>(calleeAsObject)) { - // Based on JSC::JSFunction::calculatedDisplayName, skipping the "displayName" property check - WTF::String actualName = function->name(m_vm); - if (!actualName.isEmpty() || function->isHostOrBuiltinFunction()) { - return JSC::jsString(m_vm, actualName); - } - - return JSC::jsString(m_vm, function->jsExecutable()->name().string()); - } - if (JSC::InternalFunction* function = JSC::jsDynamicCast<JSC::InternalFunction*>(calleeAsObject)) { - // Based on JSC::InternalFunction::calculatedDisplayName, skipping the "displayName" property check - return JSC::jsString(m_vm, function->name()); + String name; + if (m_callee) { + if (m_callee->isObject()) + name = getCalculatedDisplayName(m_vm, jsCast<JSObject*>(m_callee)).impl(); } - return m_vm.smallStrings.emptyString(); + return name.isNull() ? emptyString() : name; } -ALWAYS_INLINE JSC::JSString* JSCStackFrame::retrieveTypeName() +ALWAYS_INLINE String JSCStackFrame::retrieveTypeName() { JSC::JSObject* calleeObject = JSC::jsCast<JSC::JSObject*>(m_callee); // return JSC::jsTypeStringForValue(m_globalObjectcalleeObject->toThis() - return jsString(m_vm, makeString(calleeObject->className())); + return calleeObject->className(); } // General flow here is based on JSC's appendSourceToError (ErrorInstance.cpp) diff --git a/src/bun.js/bindings/ErrorStackTrace.h b/src/bun.js/bindings/ErrorStackTrace.h index 1284376a4..ac40eaf4b 100644 --- a/src/bun.js/bindings/ErrorStackTrace.h +++ b/src/bun.js/bindings/ErrorStackTrace.h @@ -61,9 +61,9 @@ private: JSC::BytecodeIndex m_bytecodeIndex; // Lazy-initialized - JSC::JSString* m_sourceURL; - JSC::JSString* m_functionName; - JSC::JSString* m_typeName; + WTF::String m_sourceURL; + WTF::String m_functionName; + WTF::String m_typeName; // m_wasmFunctionIndexOrName has meaning only when m_isWasmFrame is set JSC::Wasm::IndexOrName m_wasmFunctionIndexOrName; @@ -105,7 +105,7 @@ public: bool isConstructor() const { return m_codeBlock && (JSC::CodeForConstruct == m_codeBlock->specializationKind()); } private: - ALWAYS_INLINE JSC::JSString* retrieveSourceURL(); + ALWAYS_INLINE String retrieveSourceURL(); /* Regarding real functions (not eval\module\global code), both v8 and JSC seem to follow * the same logic, which is to first try the function's "display name", and if it's not defined, @@ -119,9 +119,9 @@ private: * and just try to use the "name" property when needed, so our lookup will be: * "display name" property -> "name" property -> JSFunction\InternalFunction "name" methods. */ - ALWAYS_INLINE JSC::JSString* retrieveFunctionName(); + ALWAYS_INLINE String retrieveFunctionName(); - ALWAYS_INLINE JSC::JSString* retrieveTypeName(); + ALWAYS_INLINE String retrieveTypeName(); bool calculateSourcePositions(); }; diff --git a/src/bun.js/bindings/FFI.zig b/src/bun.js/bindings/FFI.zig index 9d16bd78e..da98438ba 100644 --- a/src/bun.js/bindings/FFI.zig +++ b/src/bun.js/bindings/FFI.zig @@ -20,8 +20,9 @@ pub const EncodedJSValue = union_EncodedJSValue; pub export var ValueUndefined: EncodedJSValue = EncodedJSValue{ .asInt64 = @as(i64, @bitCast(@as(c_longlong, @as(c_int, 2) | @as(c_int, 8)))), }; +pub const TrueI64 = @as(i64, @bitCast(@as(c_longlong, (@as(c_int, 2) | @as(c_int, 4)) | @as(c_int, 1)))); pub export var ValueTrue: EncodedJSValue = EncodedJSValue{ - .asInt64 = @as(i64, @bitCast(@as(c_longlong, (@as(c_int, 2) | @as(c_int, 4)) | @as(c_int, 1)))), + .asInt64 = TrueI64, }; pub const JSContext = ?*anyopaque; pub inline fn JSVALUE_IS_CELL(arg_val: EncodedJSValue) bool { diff --git a/src/bun.js/bindings/ImportMetaObject.cpp b/src/bun.js/bindings/ImportMetaObject.cpp index 4160102a5..199a13392 100644 --- a/src/bun.js/bindings/ImportMetaObject.cpp +++ b/src/bun.js/bindings/ImportMetaObject.cpp @@ -64,6 +64,12 @@ static EncodedJSValue functionRequireResolve(JSC::JSGlobalObject* globalObject, JSC::JSValue moduleName = callFrame->argument(0); auto doIt = [&](const WTF::String& fromStr) -> JSC::EncodedJSValue { + if (auto* virtualModules = jsCast<Zig::GlobalObject*>(globalObject)->onLoadPlugins.virtualModules) { + if (virtualModules->contains(fromStr)) { + return JSC::JSValue::encode(jsString(vm, fromStr)); + } + } + BunString from = Bun::toString(fromStr); auto result = Bun__resolveSyncWithSource(globalObject, JSC::JSValue::encode(moduleName), &from, false); @@ -160,6 +166,14 @@ extern "C" EncodedJSValue functionImportMeta__resolveSync(JSC::JSGlobalObject* g JSC__JSValue from; bool isESM = true; + if (auto* virtualModules = jsCast<Zig::GlobalObject*>(globalObject)->onLoadPlugins.virtualModules) { + if (moduleName.isString()) { + if (virtualModules->contains(moduleName.toWTFString(globalObject))) { + return JSC::JSValue::encode(moduleName); + } + } + } + if (callFrame->argumentCount() > 1) { if (callFrame->argumentCount() > 2) { @@ -226,6 +240,7 @@ extern "C" EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlobalOb { JSC::VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + auto* global = jsDynamicCast<Zig::GlobalObject*>(globalObject); JSC::JSValue moduleName = callFrame->argument(0); JSValue from = callFrame->argument(1); @@ -239,12 +254,19 @@ extern "C" EncodedJSValue functionImportMeta__resolveSyncPrivate(JSC::JSGlobalOb RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSC::JSValue {})); + if (auto* virtualModules = global->onLoadPlugins.virtualModules) { + if (moduleName.isString()) { + if (virtualModules->contains(moduleName.toWTFString(globalObject))) { + return JSC::JSValue::encode(moduleName); + } + } + } + if (!isESM) { - auto* global = jsDynamicCast<Zig::GlobalObject*>(globalObject); if (LIKELY(global)) { auto overrideHandler = global->m_nodeModuleOverriddenResolveFilename.get(); if (UNLIKELY(overrideHandler)) { - ASSERT(overrideHandler.isCallable(globalObject)); + ASSERT(overrideHandler->isCallable()); MarkedArgumentBuffer args; args.append(moduleName); args.append(from); @@ -289,6 +311,14 @@ JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve, JSC__JSValue from; + if (auto* virtualModules = jsCast<Zig::GlobalObject*>(globalObject)->onLoadPlugins.virtualModules) { + if (moduleName.isString()) { + if (virtualModules->contains(moduleName.toWTFString(globalObject))) { + return JSC::JSValue::encode(moduleName); + } + } + } + if (callFrame->argumentCount() > 1 && callFrame->argument(1).isString()) { from = JSC::JSValue::encode(callFrame->argument(1)); } else { @@ -404,6 +434,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ImportMetaObjectPrototype, Base); return &vm.plainObjectSpace(); } @@ -417,11 +448,13 @@ public: reifyStaticProperties(vm, ImportMetaObject::info(), ImportMetaObjectPrototypeValues, *this); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); - this->putDirect( - vm, + auto mainGetter = JSFunction::create(vm, importMetaObjectMainCodeGenerator(vm), globalObject); + + this->putDirectAccessor( + this->globalObject(), builtinNames.mainPublicName(), - GetterSetter::create(vm, globalObject, JSFunction::create(vm, importMetaObjectMainCodeGenerator(vm), globalObject), nullptr), - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin | 0); + GetterSetter::create(vm, globalObject, mainGetter, mainGetter), + JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | 0); } ImportMetaObjectPrototype(JSC::VM& vm, JSC::Structure* structure) @@ -433,7 +466,7 @@ public: const ClassInfo ImportMetaObjectPrototype::s_info = { "ImportMeta"_s, - Base::info(), nullptr, nullptr, CREATE_METHOD_TABLE(ImportMetaObjectPrototype) + &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ImportMetaObjectPrototype) }; JSC::Structure* ImportMetaObject::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject) diff --git a/src/bun.js/bindings/InternalModuleRegistry.cpp b/src/bun.js/bindings/InternalModuleRegistry.cpp index 8dbf42a02..03f946192 100644 --- a/src/bun.js/bindings/InternalModuleRegistry.cpp +++ b/src/bun.js/bindings/InternalModuleRegistry.cpp @@ -33,7 +33,9 @@ static void maybeAddCodeCoverage(JSC::VM& vm, const JSC::SourceCode& code) #define INTERNAL_MODULE_REGISTRY_GENERATE_(globalObject, vm, SOURCE, moduleName, urlString) \ auto throwScope = DECLARE_THROW_SCOPE(vm); \ auto&& origin = SourceOrigin(WTF::URL(urlString)); \ - SourceCode source = JSC::makeSource(SOURCE, origin, moduleName); \ + SourceCode source = JSC::makeSource(SOURCE, origin, \ + JSC::SourceTaintedOrigin::Untainted, \ + moduleName); \ maybeAddCodeCoverage(vm, source); \ JSFunction* func \ = JSFunction::create( \ @@ -118,16 +120,23 @@ DEFINE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE, InternalModuleRegistry); InternalModuleRegistry* InternalModuleRegistry::create(VM& vm, Structure* structure) { InternalModuleRegistry* registry = new (NotNull, allocateCell<InternalModuleRegistry>(vm)) InternalModuleRegistry(vm, structure); + registry->finishCreation(vm); + return registry; +} + +void InternalModuleRegistry::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); + for (uint8_t i = 0; i < BUN_INTERNAL_MODULE_COUNT; i++) { - registry->internalField(static_cast<Field>(i)) - .set(vm, registry, jsUndefined()); + this->internalField(static_cast<Field>(i)).set(vm, this, jsUndefined()); } - return registry; } Structure* InternalModuleRegistry::createStructure(VM& vm, JSGlobalObject* globalObject) { - return Structure::create(vm, globalObject, jsNull(), TypeInfo(InternalFieldTupleType, StructureFlags), info(), 0, 48); + return Structure::create(vm, globalObject, jsNull(), TypeInfo(InternalFieldTupleType, StructureFlags), info(), 0, 0); } JSValue InternalModuleRegistry::requireId(JSGlobalObject* globalObject, VM& vm, Field id) @@ -150,7 +159,7 @@ JSC_DEFINE_HOST_FUNCTION(InternalModuleRegistry::jsCreateInternalModuleById, (JS auto throwScope = DECLARE_THROW_SCOPE(vm); auto id = callframe->argument(0).toUInt32(lexicalGlobalObject); - auto registry = static_cast<Zig::GlobalObject*>(lexicalGlobalObject)->internalModuleRegistry(); + auto registry = jsCast<Zig::GlobalObject*>(lexicalGlobalObject)->internalModuleRegistry(); auto mod = registry->createInternalModuleById(lexicalGlobalObject, vm, static_cast<Field>(id)); RETURN_IF_EXCEPTION(throwScope, {}); registry->internalField(static_cast<Field>(id)).set(vm, registry, mod); diff --git a/src/bun.js/bindings/InternalModuleRegistry.h b/src/bun.js/bindings/InternalModuleRegistry.h index d14625e00..0944a382a 100644 --- a/src/bun.js/bindings/InternalModuleRegistry.h +++ b/src/bun.js/bindings/InternalModuleRegistry.h @@ -16,19 +16,21 @@ using namespace JSC; // - some are written in JS (src/js, there is a readme file that explain those files more. // - others are native code (src/bun.js/modules), see _NativeModule.h in there. class InternalModuleRegistry : public JSInternalFieldObjectImpl<BUN_INTERNAL_MODULE_COUNT> { -protected: - JS_EXPORT_PRIVATE InternalModuleRegistry(VM&, Structure*); - DECLARE_DEFAULT_FINISH_CREATION; - DECLARE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE); - public: using Base = JSInternalFieldObjectImpl<BUN_INTERNAL_MODULE_COUNT>; DECLARE_EXPORT_INFO; + static size_t allocationSize(Checked<size_t> inlineCapacity) + { + ASSERT_UNUSED(inlineCapacity, inlineCapacity == 0U); + return sizeof(InternalModuleRegistry); + } + enum Field : uint8_t { #include "../../../src/js/out/InternalModuleRegistry+enum.h" }; + const WriteBarrier<Unknown>& internalField(Field field) const { return Base::internalField(static_cast<uint32_t>(field)); } WriteBarrier<Unknown>& internalField(Field field) { return Base::internalField(static_cast<uint32_t>(field)); } @@ -52,8 +54,11 @@ public: static JSC_DECLARE_HOST_FUNCTION(jsCreateInternalModuleById); -protected: +private: + JS_EXPORT_PRIVATE InternalModuleRegistry(VM&, Structure*); + DECLARE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE); JSValue createInternalModuleById(JSGlobalObject* globalObject, VM& vm, Field id); + void finishCreation(VM&); }; } // namespace Bun diff --git a/src/bun.js/bindings/JSBuffer.cpp b/src/bun.js/bindings/JSBuffer.cpp index 9227e47b3..524007f86 100644 --- a/src/bun.js/bindings/JSBuffer.cpp +++ b/src/bun.js/bindings/JSBuffer.cpp @@ -819,6 +819,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBufferPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -865,28 +866,49 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_compareBody(JSC::JSG size_t sourceEndInit = castedThis->byteLength(); size_t sourceEnd = sourceEndInit; + JSValue targetStartValue = jsUndefined(); + JSValue targetEndValue = jsUndefined(); + JSValue sourceStartValue = jsUndefined(); + JSValue sourceEndValue = jsUndefined(); + switch (callFrame->argumentCount()) { default: - sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(4)); - RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + sourceEndValue = callFrame->uncheckedArgument(4); FALLTHROUGH; case 4: - sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3)); - RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + sourceStartValue = callFrame->uncheckedArgument(3); FALLTHROUGH; case 3: - targetEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2)); - RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + targetEndValue = callFrame->uncheckedArgument(2); FALLTHROUGH; case 2: - targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(1)); - RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + targetStartValue = callFrame->uncheckedArgument(1); break; case 1: case 0: break; } + if (!targetStartValue.isUndefined()) { + targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(1)); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + } + + if (!targetEndValue.isUndefined()) { + targetEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2)); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + } + + if (!sourceStartValue.isUndefined()) { + sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3)); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + } + + if (!sourceEndValue.isUndefined()) { + sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(4)); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + } + targetStart = std::min(targetStart, std::min(targetEnd, targetEndInit)); sourceStart = std::min(sourceStart, std::min(sourceEnd, sourceEndInit)); @@ -931,24 +953,40 @@ static inline JSC::EncodedJSValue jsBufferPrototypeFunction_copyBody(JSC::JSGlob size_t sourceEndInit = castedThis->byteLength(); size_t sourceEnd = sourceEndInit; + JSValue targetStartValue = jsUndefined(); + JSValue sourceStartValue = jsUndefined(); + JSValue sourceEndValue = jsUndefined(); + switch (callFrame->argumentCount()) { default: - sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3)); - RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + sourceEndValue = callFrame->uncheckedArgument(3); FALLTHROUGH; case 3: - sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2)); - RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + sourceStartValue = callFrame->uncheckedArgument(2); FALLTHROUGH; case 2: - targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(1)); - RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + targetStartValue = callFrame->uncheckedArgument(1); break; case 1: case 0: break; } + if (!targetStartValue.isUndefined()) { + targetStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(1)); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + } + + if (!sourceStartValue.isUndefined()) { + sourceStart = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(2)); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + } + + if (!sourceEndValue.isUndefined()) { + sourceEnd = parseIndex(lexicalGlobalObject, throwScope, callFrame->uncheckedArgument(3)); + RETURN_IF_EXCEPTION(throwScope, JSValue::encode(jsUndefined())); + } + targetStart = std::min(targetStart, targetEnd); sourceEnd = std::min(sourceEnd, sourceEndInit); sourceStart = std::min(sourceStart, sourceEnd); @@ -1614,7 +1652,7 @@ JSC_DEFINE_HOST_FUNCTION(jsBufferConstructorFunction_toBuffer, (JSGlobalObject * class JSBufferConstructor final : public JSC::InternalFunction { public: using Base = JSC::InternalFunction; - static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable; ~JSBufferConstructor() = default; @@ -1700,8 +1738,6 @@ JSC_DEFINE_JIT_OPERATION(jsBufferConstructorAllocUnsafeSlowWithoutTypeChecks, JS JSC_ANNOTATE_HOST_FUNCTION(JSBufferConstructorConstruct, JSBufferConstructor::construct); -const ClassInfo JSBufferConstructor::s_info = { "Buffer"_s, nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferConstructor) }; - class JSBuffer : public JSC::JSNonFinalObject { DECLARE_INFO; @@ -1790,8 +1826,8 @@ static const HashTableValue JSBufferPrototypeTableValues[] { "lastIndexOf"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferPrototypeFunction_lastIndexOf, 3 } }, { "latin1Slice"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeLatin1SliceCodeGenerator, 2 } }, { "latin1Write"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeLatin1WriteCodeGenerator, 1 } }, - { "offset"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeOffsetCodeGenerator, 0 } }, - { "parent"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeParentCodeGenerator, 0 } }, + { "offset"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinAccessorType, jsBufferPrototypeOffsetCodeGenerator, 0 } }, + { "parent"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinAccessorType, jsBufferPrototypeParentCodeGenerator, 0 } }, { "readBigInt64"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadBigInt64LECodeGenerator, 1 } }, { "readBigInt64BE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadBigInt64BECodeGenerator, 1 } }, { "readBigInt64LE"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferPrototypeReadBigInt64LECodeGenerator, 1 } }, @@ -1899,8 +1935,7 @@ const ClassInfo JSBufferPrototype::s_info = { // We must use the same naming convention to match Node // Some packages (like MongoDB's official Node.js client) rely on this behavior. "Uint8Array"_s, - - nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferPrototype) + &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferPrototype) }; static const JSC::DOMJIT::Signature DOMJITSignaturejsBufferConstructorAlloc(jsBufferConstructorAllocWithoutTypeChecks, @@ -1917,27 +1952,27 @@ static const JSC::DOMJIT::Signature DOMJITSignaturejsBufferConstructorAllocUnsaf JSC::DOMJIT::Effect::forWriteKinds(JSC::DFG::AbstractHeapKind::Heap), JSC::SpecUint8Array, JSC::SpecInt32Only); -/* Hash table for constructor */ -static const HashTableValue JSBufferConstructorTableValues[] = { - // { "alloc"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, jsBufferConstructorFunction_alloc, &DOMJITSignaturejsBufferConstructorAlloc } }, - { "alloc"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_alloc, 1 } }, - // { "allocUnsafe"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, jsBufferConstructorFunction_allocUnsafe, &DOMJITSignaturejsBufferConstructorAllocUnsafe } }, - { "allocUnsafe"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_allocUnsafe, 1 } }, - // { "allocUnsafeSlow"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, jsBufferConstructorFunction_allocUnsafeSlow, &DOMJITSignaturejsBufferConstructorAllocUnsafeSlow } }, - { "allocUnsafeSlow"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_allocUnsafeSlow, 1 } }, - { "byteLength"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_byteLength, 2 } }, - { "compare"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_compare, 2 } }, - { "concat"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_concat, 2 } }, - { "from"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferConstructorFromCodeGenerator, 1 } }, - { "isBuffer"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferConstructorIsBufferCodeGenerator, 1 } }, - { "toBuffer"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_toBuffer, 1 } }, - { "isEncoding"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_isEncoding, 1 } }, -}; +/* Source for JSBuffer.lut.h +@begin jsBufferConstructorTable + alloc jsBufferConstructorFunction_alloc Constructable|Function 1 + allocUnsafe jsBufferConstructorFunction_allocUnsafe Constructable|Function 1 + allocUnsafeSlow jsBufferConstructorFunction_allocUnsafeSlow Constructable|Function 1 + byteLength jsBufferConstructorFunction_byteLength Function 2 + compare jsBufferConstructorFunction_compare Function 2 + concat jsBufferConstructorFunction_concat Function 2 + from JSBuiltin Builtin|Function 1 + isBuffer JSBuiltin Builtin|Function 1 + toBuffer jsBufferConstructorFunction_toBuffer Function 1 + isEncoding jsBufferConstructorFunction_isEncoding Function 1 +@end +*/ +#include "JSBuffer.lut.h" + +const ClassInfo JSBufferConstructor::s_info = { "Buffer"_s, &Base::s_info, &jsBufferConstructorTable, nullptr, CREATE_METHOD_TABLE(JSBufferConstructor) }; void JSBufferConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject, JSC::JSObject* prototype) { Base::finishCreation(vm, 3, "Buffer"_s, PropertyAdditionMode::WithoutStructureTransition); - reifyStaticProperties(vm, JSBufferConstructor::info(), JSBufferConstructorTableValues, *this); putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); prototype->putDirect(vm, vm.propertyNames->speciesSymbol, this, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); } diff --git a/src/bun.js/bindings/JSBuffer.lut.h b/src/bun.js/bindings/JSBuffer.lut.h new file mode 100644 index 000000000..35a3acea9 --- /dev/null +++ b/src/bun.js/bindings/JSBuffer.lut.h @@ -0,0 +1,52 @@ +// File generated via `make static-hash-table` / `make cpp` +static const struct CompactHashIndex jsBufferConstructorTableIndex[33] = { + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 1, 32 }, + { 0, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 8, -1 }, + { 3, -1 }, + { -1, -1 }, + { 5, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 9, -1 }, + { -1, -1 }, + { 4, -1 }, + { -1, -1 }, + { 6, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 2, -1 }, + { -1, -1 }, + { 7, -1 }, +}; + +static const struct HashTableValue jsBufferConstructorTableValues[10] = { + { "alloc"_s, static_cast<unsigned>(PropertyAttribute::Constructable|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_alloc, 1 } }, + { "allocUnsafe"_s, static_cast<unsigned>(PropertyAttribute::Constructable|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_allocUnsafe, 1 } }, + { "allocUnsafeSlow"_s, static_cast<unsigned>(PropertyAttribute::Constructable|PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_allocUnsafeSlow, 1 } }, + { "byteLength"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_byteLength, 2 } }, + { "compare"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_compare, 2 } }, + { "concat"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_concat, 2 } }, + { "from"_s, ((static_cast<unsigned>(PropertyAttribute::Builtin|PropertyAttribute::Function)) & ~PropertyAttribute::Function) | PropertyAttribute::Builtin, NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferConstructorFromCodeGenerator, 1 } }, + { "isBuffer"_s, ((static_cast<unsigned>(PropertyAttribute::Builtin|PropertyAttribute::Function)) & ~PropertyAttribute::Function) | PropertyAttribute::Builtin, NoIntrinsic, { HashTableValue::BuiltinGeneratorType, jsBufferConstructorIsBufferCodeGenerator, 1 } }, + { "toBuffer"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_toBuffer, 1 } }, + { "isEncoding"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsBufferConstructorFunction_isEncoding, 1 } }, +}; + +static const struct HashTable jsBufferConstructorTable = + { 10, 31, false, nullptr, jsBufferConstructorTableValues, jsBufferConstructorTableIndex }; diff --git a/src/bun.js/bindings/JSBufferList.cpp b/src/bun.js/bindings/JSBufferList.cpp index a8cefa710..0db5527d7 100644 --- a/src/bun.js/bindings/JSBufferList.cpp +++ b/src/bun.js/bindings/JSBufferList.cpp @@ -118,8 +118,7 @@ JSC::JSValue JSBufferList::_getString(JSC::VM& vm, JSC::JSGlobalObject* lexicalG RELEASE_AND_RETURN(throwScope, JSC::jsEmptyString(vm)); } - auto iter = m_deque.begin(); - JSC::JSString* str = JSC::jsDynamicCast<JSC::JSString*>(iter->get()); + JSC::JSString* str = JSC::jsDynamicCast<JSC::JSString*>(m_deque.first().get()); if (UNLIKELY(!str)) { return throwTypeError(lexicalGlobalObject, throwScope, "_getString can only be called when all buffers are string"_s); } @@ -132,13 +131,14 @@ JSC::JSValue JSBufferList::_getString(JSC::VM& vm, JSC::JSGlobalObject* lexicalG } if (n < len) { JSString* firstHalf = JSC::jsSubstring(lexicalGlobalObject, str, 0, n); - iter->set(vm, this, JSC::jsSubstring(lexicalGlobalObject, str, n, len - n)); + m_deque.first().set(vm, this, JSC::jsSubstring(lexicalGlobalObject, str, n, len - n)); RELEASE_AND_RETURN(throwScope, firstHalf); } JSRopeString::RopeBuilder<RecordOverflow> ropeBuilder(vm); - for (const auto end = m_deque.end(); iter != end; ++iter) { - JSC::JSString* str = JSC::jsDynamicCast<JSC::JSString*>(iter->get()); + while (m_deque.size() > 0) { + auto& element = m_deque.first(); + JSC::JSString* str = JSC::jsDynamicCast<JSC::JSString*>(element.get()); if (UNLIKELY(!str)) { return throwTypeError(lexicalGlobalObject, throwScope, "_getString can only be called when all buffers are string"_s); } @@ -147,7 +147,7 @@ JSC::JSValue JSBufferList::_getString(JSC::VM& vm, JSC::JSGlobalObject* lexicalG JSString* firstHalf = JSC::jsSubstring(lexicalGlobalObject, str, 0, n); if (!ropeBuilder.append(firstHalf)) return throwOutOfMemoryError(lexicalGlobalObject, throwScope); - iter->set(vm, this, JSC::jsSubstring(lexicalGlobalObject, str, n, len - n)); + element.set(vm, this, JSC::jsSubstring(lexicalGlobalObject, str, n, len - n)); break; } if (!ropeBuilder.append(str)) @@ -169,8 +169,7 @@ JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalG RELEASE_AND_RETURN(throwScope, JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, 0)); } - auto iter = m_deque.begin(); - JSC::JSUint8Array* array = JSC::jsDynamicCast<JSC::JSUint8Array*>(iter->get()); + JSC::JSUint8Array* array = JSC::jsDynamicCast<JSC::JSUint8Array*>(m_deque.first().get()); if (UNLIKELY(!array)) { return throwTypeError(lexicalGlobalObject, throwScope, "_getBuffer can only be called when all buffers are Uint8Array"_s); } @@ -185,7 +184,7 @@ JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalG auto buffer = array->possiblySharedBuffer(); JSC::JSUint8Array* retArray = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, buffer, 0, n); JSC::JSUint8Array* newArray = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, buffer, n, len - n); - iter->set(vm, this, newArray); + m_deque.first().set(vm, this, newArray); RELEASE_AND_RETURN(throwScope, retArray); } @@ -196,8 +195,9 @@ JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalG } JSC::JSUint8Array* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, WTFMove(arrayBuffer), 0, n); size_t offset = 0; - for (const auto end = m_deque.end(); iter != end; ++iter) { - JSC::JSUint8Array* array = JSC::jsDynamicCast<JSC::JSUint8Array*>(iter->get()); + while (m_deque.size() > 0) { + auto& element = m_deque.first(); + JSC::JSUint8Array* array = JSC::jsDynamicCast<JSC::JSUint8Array*>(element.get()); if (UNLIKELY(!array)) { return throwTypeError(lexicalGlobalObject, throwScope, "_getBuffer can only be called when all buffers are Uint8Array"_s); } @@ -208,7 +208,7 @@ JSC::JSValue JSBufferList::_getBuffer(JSC::VM& vm, JSC::JSGlobalObject* lexicalG } auto buffer = array->possiblySharedBuffer(); JSC::JSUint8Array* newArray = JSC::JSUint8Array::create(lexicalGlobalObject, subclassStructure, buffer, n, len - n); - iter->set(vm, this, newArray); + element.set(vm, this, newArray); offset += n; break; } @@ -411,11 +411,11 @@ static const HashTableValue JSBufferListPrototypeTableValues[] void JSBufferListPrototype::finishCreation(VM& vm, JSC::JSGlobalObject* globalThis) { Base::finishCreation(vm); - this->setPrototypeDirect(vm, globalThis->objectPrototype()); reifyStaticProperties(vm, JSBufferList::info(), JSBufferListPrototypeTableValues, *this); + ASSERT(inherits(info())); } -const ClassInfo JSBufferListPrototype::s_info = { "BufferList"_s, nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferListPrototype) }; +const ClassInfo JSBufferListPrototype::s_info = { "BufferList"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSBufferListPrototype) }; void JSBufferListConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSBufferListPrototype* prototype) { diff --git a/src/bun.js/bindings/JSBufferList.h b/src/bun.js/bindings/JSBufferList.h index 94a69c8d1..ebbc1781e 100644 --- a/src/bun.js/bindings/JSBufferList.h +++ b/src/bun.js/bindings/JSBufferList.h @@ -46,7 +46,7 @@ public: void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject); static void destroy(JSCell*) {} - size_t length() { return m_deque.size(); } + inline size_t length() { return m_deque.size(); } void push(JSC::VM& vm, JSC::JSValue v) { m_deque.append(WriteBarrier<Unknown>()); @@ -100,6 +100,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBufferListPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) diff --git a/src/bun.js/bindings/JSBundlerPlugin.cpp b/src/bun.js/bindings/JSBundlerPlugin.cpp index 6ae266df7..d896d5b3d 100644 --- a/src/bun.js/bindings/JSBundlerPlugin.cpp +++ b/src/bun.js/bindings/JSBundlerPlugin.cpp @@ -31,6 +31,7 @@ namespace Bun { extern "C" void JSBundlerPlugin__addError(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue); extern "C" void JSBundlerPlugin__onLoadAsync(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue); extern "C" void JSBundlerPlugin__onResolveAsync(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::EncodedJSValue); +extern "C" void JSBundlerPlugin__onVirtualModulePlugin(void*, void*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::EncodedJSValue); JSC_DECLARE_HOST_FUNCTION(jsBundlerPluginFunction_addFilter); JSC_DECLARE_HOST_FUNCTION(jsBundlerPluginFunction_addError); @@ -154,6 +155,7 @@ public: Bun::BundlerPlugin plugin; JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> onLoadFunction; JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> onResolveFunction; + JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> moduleFunction; JSC::LazyProperty<JSBundlerPlugin, JSC::JSFunction> setupFunction; private: diff --git a/src/bun.js/bindings/JSCUSocketsLoopIntegration.cpp b/src/bun.js/bindings/JSCUSocketsLoopIntegration.cpp new file mode 100644 index 000000000..0e3fcf47d --- /dev/null +++ b/src/bun.js/bindings/JSCUSocketsLoopIntegration.cpp @@ -0,0 +1,30 @@ +#include "root.h" +#include "JavaScriptCore/VM.h" + +// On Linux, signals are used to suspend/resume threads in JavaScriptCore +// When `.acquireAccess` is called, the signal might be raised. +// This causes issues with LLDB which might catch the signal. +// So we want to avoid that, we really only want this code to be executed when the debugger is attached +// But it's pretty hard to tell if LLDB is attached or not, so we just disable this code on Linux when in debug mode +#ifndef ACQUIRE_RELEASE_HEAP_ACCESS +#if OS(DARWIN) +#define ACQUIRE_RELEASE_HEAP_ACCESS 1 +#else +#ifndef BUN_DEBUG +#define ACQUIRE_RELEASE_HEAP_ACCESS 1 +#endif +#endif +#endif + +extern "C" void bun_on_tick_before(JSC::VM* vm) +{ +#if ACQUIRE_RELEASE_HEAP_ACCESS + // vm->heap.releaseAccess(); +#endif +} +extern "C" void bun_on_tick_after(JSC::VM* vm) +{ +#if ACQUIRE_RELEASE_HEAP_ACCESS + // vm->heap.acquireAccess(); +#endif +}
\ No newline at end of file diff --git a/src/bun.js/bindings/JSDOMFile.cpp b/src/bun.js/bindings/JSDOMFile.cpp index 1d7770ac1..1e1f9f2bc 100644 --- a/src/bun.js/bindings/JSDOMFile.cpp +++ b/src/bun.js/bindings/JSDOMFile.cpp @@ -17,7 +17,7 @@ class JSDOMFile : public JSC::InternalFunction { public: JSDOMFile(JSC::VM& vm, JSC::Structure* structure) - : Base(vm, structure, nullptr, construct) + : Base(vm, structure, call, construct) { } @@ -43,7 +43,8 @@ public: static JSDOMFile* create(JSC::VM& vm, JSGlobalObject* globalObject) { auto* zigGlobal = reinterpret_cast<Zig::GlobalObject*>(globalObject); - auto* object = new (NotNull, JSC::allocateCell<JSDOMFile>(vm)) JSDOMFile(vm, createStructure(vm, globalObject, zigGlobal->functionPrototype())); + auto structure = createStructure(vm, globalObject, zigGlobal->functionPrototype()); + auto* object = new (NotNull, JSC::allocateCell<JSDOMFile>(vm)) JSDOMFile(vm, structure); object->finishCreation(vm); // This is not quite right. But we'll fix it if someone files an issue about it. @@ -91,6 +92,12 @@ public: return JSValue::encode( WebCore::JSBlob::create(vm, globalObject, structure, ptr)); } + + static EncodedJSValue call(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) + { + auto scope = DECLARE_THROW_SCOPE(lexicalGlobalObject->vm()); + throwTypeError(lexicalGlobalObject, scope, "Class constructor File cannot be invoked without 'new"_s); + } }; const JSC::ClassInfo JSDOMFile::s_info = { "File"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDOMFile) }; diff --git a/src/bun.js/bindings/JSDOMWrapperCache.h b/src/bun.js/bindings/JSDOMWrapperCache.h index 7656c7c17..e06f2607d 100644 --- a/src/bun.js/bindings/JSDOMWrapperCache.h +++ b/src/bun.js/bindings/JSDOMWrapperCache.h @@ -215,6 +215,10 @@ template<typename DOMClass> inline void setSubclassStructureIfNeeded(JSC::JSGlob JSC::VM& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); + // If the new target isn't actually callable + if (UNLIKELY(!newTarget->isCallable())) + newTarget = constructor; + auto* functionGlobalObject = JSC::getFunctionRealm(lexicalGlobalObject, newTarget); RETURN_IF_EXCEPTION(scope, void()); auto* newTargetGlobalObject = JSC::jsCast<JSDOMGlobalObject*>(functionGlobalObject); diff --git a/src/bun.js/bindings/JSMockFunction.cpp b/src/bun.js/bindings/JSMockFunction.cpp index a8bac7c56..498864dfc 100644 --- a/src/bun.js/bindings/JSMockFunction.cpp +++ b/src/bun.js/bindings/JSMockFunction.cpp @@ -486,6 +486,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSMockFunctionPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -623,7 +624,6 @@ extern "C" EncodedJSValue JSMock__jsSpyOn(JSC::JSGlobalObject* lexicalGlobalObje mock->copyNameAndLength(vm, globalObject, value); - attributes |= PropertyAttribute::Function; object->putDirect(vm, propertyKey, mock, attributes); RETURN_IF_EXCEPTION(scope, {}); @@ -1320,7 +1320,7 @@ MockWithImplementationCleanupData* MockWithImplementationCleanupData::create(VM& } Structure* MockWithImplementationCleanupData::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info()); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); } MockWithImplementationCleanupData::MockWithImplementationCleanupData(VM& vm, Structure* structure) diff --git a/src/bun.js/bindings/JSNextTickQueue.cpp b/src/bun.js/bindings/JSNextTickQueue.cpp index 8916ef6c8..18963645c 100644 --- a/src/bun.js/bindings/JSNextTickQueue.cpp +++ b/src/bun.js/bindings/JSNextTickQueue.cpp @@ -18,7 +18,7 @@ namespace Bun { using namespace JSC; -const JSC::ClassInfo JSNextTickQueue::s_info = { "JSNextTickQueue"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSNextTickQueue) }; +const JSC::ClassInfo JSNextTickQueue::s_info = { "NextTickQueue"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSNextTickQueue) }; template<typename, JSC::SubspaceAccess mode> JSC::GCClient::IsoSubspace* JSNextTickQueue::subspaceFor(JSC::VM& vm) @@ -34,11 +34,12 @@ JSC::GCClient::IsoSubspace* JSNextTickQueue::subspaceFor(JSC::VM& vm) JSNextTickQueue* JSNextTickQueue::create(VM& vm, Structure* structure) { JSNextTickQueue* mod = new (NotNull, allocateCell<JSNextTickQueue>(vm)) JSNextTickQueue(vm, structure); + mod->finishCreation(vm); return mod; } Structure* JSNextTickQueue::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info()); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); } JSNextTickQueue::JSNextTickQueue(VM& vm, Structure* structure) @@ -65,7 +66,6 @@ JSNextTickQueue* JSNextTickQueue::create(JSC::JSGlobalObject* globalObject) { auto& vm = globalObject->vm(); auto* obj = create(vm, createStructure(vm, globalObject, jsNull())); - obj->finishCreation(vm); return obj; } diff --git a/src/bun.js/bindings/JSNextTickQueue.h b/src/bun.js/bindings/JSNextTickQueue.h index c3bd228cc..3a499345d 100644 --- a/src/bun.js/bindings/JSNextTickQueue.h +++ b/src/bun.js/bindings/JSNextTickQueue.h @@ -10,7 +10,6 @@ using namespace JSC; class JSNextTickQueue : public JSC::JSInternalFieldObjectImpl<3> { public: - static constexpr unsigned numberOfInternalFields = 3; using Base = JSC::JSInternalFieldObjectImpl<3>; template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm); diff --git a/src/bun.js/bindings/JSReadableState.cpp b/src/bun.js/bindings/JSReadableState.cpp index 1f3a36def..22b1ec357 100644 --- a/src/bun.js/bindings/JSReadableState.cpp +++ b/src/bun.js/bindings/JSReadableState.cpp @@ -314,12 +314,12 @@ JSReadableState_NULLABLE_BOOLEAN_GETTER_SETTER(paused) #undef JSReadableState_JSVALUE_GETTER_SETTER -#define JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(NAME) \ - { \ -#NAME ""_s, static_cast < unsigned>(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, \ - { \ - HashTableValue::GetterSetterType, jsReadableState_##NAME, setJSReadableState_##NAME \ - } \ +#define JSReadableState_GETTER_SETTER_HASH_TABLE_VALUE(NAME) \ + { \ + #NAME ""_s, static_cast<unsigned>(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, \ + { \ + HashTableValue::GetterSetterType, jsReadableState_##NAME, setJSReadableState_##NAME \ + } \ } /* Hash table for prototype */ diff --git a/src/bun.js/bindings/JSReadableState.h b/src/bun.js/bindings/JSReadableState.h index c67baebad..78a716910 100644 --- a/src/bun.js/bindings/JSReadableState.h +++ b/src/bun.js/bindings/JSReadableState.h @@ -107,6 +107,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableStatePrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) diff --git a/src/bun.js/bindings/JSSink.cpp b/src/bun.js/bindings/JSSink.cpp index d986ae590..ef6343849 100644 --- a/src/bun.js/bindings/JSSink.cpp +++ b/src/bun.js/bindings/JSSink.cpp @@ -711,6 +711,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSArrayBufferSinkPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -743,6 +744,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableArrayBufferSinkControllerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -798,17 +800,19 @@ void JSReadableArrayBufferSinkController::detach() auto readableStream = m_weakReadableStream.get(); auto onClose = m_onClose.get(); - m_onClose.clear(); if (readableStream && onClose) { - JSC::JSGlobalObject* globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); - JSC::MarkedArgumentBuffer arguments; - arguments.append(readableStream); - arguments.append(jsUndefined()); - call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); + if (callData.type != JSC::CallData::Type::None) { + JSC::JSGlobalObject* globalObject = this->globalObject(); + JSC::MarkedArgumentBuffer arguments; + arguments.append(readableStream); + arguments.append(jsUndefined()); + call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); + } } + m_onClose.clear(); m_weakReadableStream.clear(); } @@ -965,6 +969,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSFileSinkPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -997,6 +1002,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableFileSinkControllerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -1052,17 +1058,19 @@ void JSReadableFileSinkController::detach() auto readableStream = m_weakReadableStream.get(); auto onClose = m_onClose.get(); - m_onClose.clear(); if (readableStream && onClose) { - JSC::JSGlobalObject* globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); - JSC::MarkedArgumentBuffer arguments; - arguments.append(readableStream); - arguments.append(jsUndefined()); - call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); + if (callData.type != JSC::CallData::Type::None) { + JSC::JSGlobalObject* globalObject = this->globalObject(); + JSC::MarkedArgumentBuffer arguments; + arguments.append(readableStream); + arguments.append(jsUndefined()); + call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); + } } + m_onClose.clear(); m_weakReadableStream.clear(); } @@ -1219,6 +1227,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPResponseSinkPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -1251,6 +1260,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableHTTPResponseSinkControllerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -1306,17 +1316,19 @@ void JSReadableHTTPResponseSinkController::detach() auto readableStream = m_weakReadableStream.get(); auto onClose = m_onClose.get(); - m_onClose.clear(); if (readableStream && onClose) { - JSC::JSGlobalObject* globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); - JSC::MarkedArgumentBuffer arguments; - arguments.append(readableStream); - arguments.append(jsUndefined()); - call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); + if (callData.type != JSC::CallData::Type::None) { + JSC::JSGlobalObject* globalObject = this->globalObject(); + JSC::MarkedArgumentBuffer arguments; + arguments.append(readableStream); + arguments.append(jsUndefined()); + call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); + } } + m_onClose.clear(); m_weakReadableStream.clear(); } @@ -1473,6 +1485,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPSResponseSinkPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -1505,6 +1518,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSReadableHTTPSResponseSinkControllerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -1560,17 +1574,19 @@ void JSReadableHTTPSResponseSinkController::detach() auto readableStream = m_weakReadableStream.get(); auto onClose = m_onClose.get(); - m_onClose.clear(); if (readableStream && onClose) { - JSC::JSGlobalObject* globalObject = this->globalObject(); auto callData = JSC::getCallData(onClose); - JSC::MarkedArgumentBuffer arguments; - arguments.append(readableStream); - arguments.append(jsUndefined()); - call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); + if (callData.type != JSC::CallData::Type::None) { + JSC::JSGlobalObject* globalObject = this->globalObject(); + JSC::MarkedArgumentBuffer arguments; + arguments.append(readableStream); + arguments.append(jsUndefined()); + call(globalObject, onClose, callData, JSC::jsUndefined(), arguments); + } } + m_onClose.clear(); m_weakReadableStream.clear(); } diff --git a/src/bun.js/bindings/JSSocketAddress.cpp b/src/bun.js/bindings/JSSocketAddress.cpp new file mode 100644 index 000000000..181507339 --- /dev/null +++ b/src/bun.js/bindings/JSSocketAddress.cpp @@ -0,0 +1,63 @@ +#include "JSSocketAddress.h" +#include "ZigGlobalObject.h" +#include "JavaScriptCore/JSObjectInlines.h" +#include "JavaScriptCore/ObjectConstructor.h" +#include "JavaScriptCore/JSCast.h" + +using namespace JSC; + +namespace Bun { +namespace JSSocketAddress { + +// Using a structure with inlined offsets should be more lightweight than a class. +Structure* createStructure(VM& vm, JSGlobalObject* globalObject) +{ + JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype( + globalObject, + globalObject->objectPrototype(), + 3); + + JSC::PropertyOffset offset; + structure = structure->addPropertyTransition( + vm, + structure, + JSC::Identifier::fromString(vm, "address"_s), + 0, + offset); + + structure = structure->addPropertyTransition( + vm, + structure, + JSC::Identifier::fromString(vm, "family"_s), + 0, + offset); + + structure = structure->addPropertyTransition( + vm, + structure, + JSC::Identifier::fromString(vm, "port"_s), + 0, + offset); + + return structure; +} + +} // namespace JSSocketAddress +} // namespace Bun + +extern "C" JSObject* JSSocketAddress__create(JSGlobalObject* globalObject, JSString* value, int32_t port, bool isIPv6) +{ + static const NeverDestroyed<String> IPv4 = MAKE_STATIC_STRING_IMPL("IPv4"); + static const NeverDestroyed<String> IPv6 = MAKE_STATIC_STRING_IMPL("IPv6"); + + VM& vm = globalObject->vm(); + + auto* global = jsCast<Zig::GlobalObject*>(globalObject); + + JSObject* thisObject = constructEmptyObject(vm, global->JSSocketAddressStructure()); + thisObject->putDirectOffset(vm, 0, value); + thisObject->putDirectOffset(vm, 1, isIPv6 ? jsString(vm, IPv6) : jsString(vm, IPv4)); + thisObject->putDirectOffset(vm, 2, jsNumber(port)); + + return thisObject; +} diff --git a/src/bun.js/bindings/JSSocketAddress.h b/src/bun.js/bindings/JSSocketAddress.h new file mode 100644 index 000000000..77bdca5d4 --- /dev/null +++ b/src/bun.js/bindings/JSSocketAddress.h @@ -0,0 +1,16 @@ +// The object returned by Bun.serve's .requestIP() +#pragma once +#include "root.h" +#include "JavaScriptCore/JSObjectInlines.h" + +using namespace JSC; + +namespace Bun { +namespace JSSocketAddress { + +Structure* createStructure(VM& vm, JSGlobalObject* globalObject); + +} // namespace JSSocketAddress +} // namespace Bun + +extern "C" JSObject* JSSocketAddress__create(JSGlobalObject* globalObject, JSString* value, int port, bool isIPv6); diff --git a/src/bun.js/bindings/JSStringDecoder.h b/src/bun.js/bindings/JSStringDecoder.h index bce1ae05d..cd2e017d6 100644 --- a/src/bun.js/bindings/JSStringDecoder.h +++ b/src/bun.js/bindings/JSStringDecoder.h @@ -77,6 +77,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStringDecoderPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) diff --git a/src/bun.js/bindings/KeyObject.cpp b/src/bun.js/bindings/KeyObject.cpp new file mode 100644 index 000000000..d5782779d --- /dev/null +++ b/src/bun.js/bindings/KeyObject.cpp @@ -0,0 +1,2389 @@ +// Attribution: Some parts of of this module are derived from code originating from the Node.js +// crypto module which is licensed under an MIT license: +// +// Copyright Node.js contributors. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "KeyObject.h" +#include "webcrypto/JSCryptoKey.h" +#include "webcrypto/JSSubtleCrypto.h" +#include "webcrypto/CryptoKeyOKP.h" +#include "webcrypto/CryptoKeyEC.h" +#include "webcrypto/CryptoKeyRSA.h" +#include "webcrypto/CryptoKeyAES.h" +#include "webcrypto/CryptoKeyHMAC.h" +#include "webcrypto/CryptoKeyRaw.h" +#include "webcrypto/CryptoKeyUsage.h" +#include "webcrypto/JsonWebKey.h" +#include "webcrypto/JSJsonWebKey.h" +#include "JavaScriptCore/JSObject.h" +#include "JavaScriptCore/ObjectConstructor.h" +#include "headers-handwritten.h" +#include <openssl/evp.h> +#include <openssl/mem.h> +#include <openssl/x509.h> +#include <openssl/pem.h> +#include <openssl/curve25519.h> +#include "JSBuffer.h" + +using namespace JSC; +using namespace Bun; +using JSGlobalObject + = JSC::JSGlobalObject; +using Exception = JSC::Exception; +using JSValue = JSC::JSValue; +using JSString = JSC::JSString; +using JSModuleLoader = JSC::JSModuleLoader; +using JSModuleRecord = JSC::JSModuleRecord; +using Identifier = JSC::Identifier; +using SourceOrigin = JSC::SourceOrigin; +using JSObject = JSC::JSObject; +using JSNonFinalObject = JSC::JSNonFinalObject; + +namespace WebCore { + +static bool KeyObject__IsASN1Sequence(const unsigned char* data, size_t size, + size_t* data_offset, size_t* data_size) +{ + if (size < 2 || data[0] != 0x30) + return false; + + if (data[1] & 0x80) { + // Long form. + size_t n_bytes = data[1] & ~0x80; + if (n_bytes + 2 > size || n_bytes > sizeof(size_t)) + return false; + size_t length = 0; + for (size_t i = 0; i < n_bytes; i++) + length = (length << 8) | data[i + 2]; + *data_offset = 2 + n_bytes; + *data_size = std::min(size - 2 - n_bytes, length); + } else { + // Short form. + *data_offset = 2; + *data_size = std::min<size_t>(size - 2, data[1]); + } + + return true; +} +static bool KeyObject__IsRSAPrivateKey(const unsigned char* data, size_t size) +{ + // Both RSAPrivateKey and RSAPublicKey structures start with a SEQUENCE. + size_t offset, len; + if (!KeyObject__IsASN1Sequence(data, size, &offset, &len)) + return false; + + // An RSAPrivateKey sequence always starts with a single-byte integer whose + // value is either 0 or 1, whereas an RSAPublicKey starts with the modulus + // (which is the product of two primes and therefore at least 4), so we can + // decide the type of the structure based on the first three bytes of the + // sequence. + return len >= 3 && data[offset] == 2 && data[offset + 1] == 1 && !(data[offset + 2] & 0xfe); +} + +static bool KeyObject__IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) +{ + // Both PrivateKeyInfo and EncryptedPrivateKeyInfo start with a SEQUENCE. + size_t offset, len; + if (!KeyObject__IsASN1Sequence(data, size, &offset, &len)) + return false; + + // A PrivateKeyInfo sequence always starts with an integer whereas an + // EncryptedPrivateKeyInfo starts with an AlgorithmIdentifier. + return len >= 1 && data[offset] != 2; +} + +struct AsymmetricKeyValue { + EVP_PKEY* key; + bool owned; +}; + +struct AsymmetricKeyValueWithDER { + EVP_PKEY* key; + unsigned char* der_data; + long der_len; +}; + +struct PrivateKeyPassphrase { + char* passphrase; + size_t passphrase_len; +}; + +int PasswordCallback(char* buf, int size, int rwflag, void* u) +{ + auto result = static_cast<PrivateKeyPassphrase*>(u); + if (result != nullptr && size > 0 && result->passphrase != nullptr) { + size_t buflen = static_cast<size_t>(size); + size_t len = result->passphrase_len; + if (buflen < len) + return -1; + memcpy(buf, result->passphrase, buflen); + return len; + } + + return -1; +} + +AsymmetricKeyValueWithDER KeyObject__ParsePublicKeyPEM(const char* key_pem, + size_t key_pem_len) +{ + auto bp = BIOPtr(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len)); + auto result = (AsymmetricKeyValueWithDER) { .key = nullptr, .der_data = nullptr, .der_len = 0 }; + + if (!bp) { + ERR_clear_error(); + return result; + } + + // Try parsing as a SubjectPublicKeyInfo first. + if (PEM_bytes_read_bio(&result.der_data, &result.der_len, nullptr, "PUBLIC KEY", bp.get(), nullptr, nullptr) == 1) { + // OpenSSL might modify the pointer, so we need to make a copy before parsing. + const unsigned char* p = result.der_data; + result.key = d2i_PUBKEY(nullptr, &p, result.der_len); + if (result.key) { + return result; + } + } + + ERR_clear_error(); + BIO_reset(bp.get()); + + // Maybe it is PKCS#1. + if (PEM_bytes_read_bio(&result.der_data, &result.der_len, nullptr, "RSA PUBLIC KEY", bp.get(), nullptr, nullptr) == 1) { + const unsigned char* p = result.der_data; + result.key = d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, result.der_len); + if (result.key) { + return result; + } + } + ERR_clear_error(); + BIO_reset(bp.get()); + + // X.509 fallback. + if (PEM_bytes_read_bio(&result.der_data, &result.der_len, nullptr, "CERTIFICATE", bp.get(), nullptr, nullptr) == 1) { + const unsigned char* p = result.der_data; + X509Ptr x509(d2i_X509(nullptr, &p, result.der_len)); + result.key = x509 ? X509_get_pubkey(x509.get()) : nullptr; + if (result.key) { + return result; + } + OPENSSL_clear_free(result.der_data, result.der_len); + ERR_clear_error(); + result.der_data = nullptr; + result.der_len = 0; + } else { + OPENSSL_clear_free(result.der_data, result.der_len); + ERR_clear_error(); + result.der_data = nullptr; + result.der_len = 0; + } + return result; +} + +JSC::EncodedJSValue KeyObject__createPrivateKey(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + + auto count = callFrame->argumentCount(); + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (count < 1) { + JSC::throwTypeError(globalObject, scope, "createPrivateKey requires 1 arguments"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + auto* options = jsDynamicCast<JSC::JSObject*>(callFrame->argument(0)); + if (!options) { + JSC::throwTypeError(globalObject, scope, "expected options to be a object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + JSValue keyJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "key"_s))); + if (keyJSValue.isUndefinedOrNull() || keyJSValue.isEmpty()) { + JSC::throwTypeError(globalObject, scope, "key is required"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + if (!keyJSValue.isCell()) { + JSC::throwTypeError(globalObject, scope, "key must be a Buffer, Array-like or object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + JSValue formatJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "format"_s))); + if (formatJSValue.isUndefinedOrNull() || formatJSValue.isEmpty()) { + JSC::throwTypeError(globalObject, scope, "format is required"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + if (!formatJSValue.isString()) { + JSC::throwTypeError(globalObject, scope, "format must be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto format = formatJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + + Zig::GlobalObject* zigGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + auto* structure = zigGlobalObject->JSCryptoKeyStructure(); + + void* data; + size_t byteLength; + + auto keyJSValueCell = keyJSValue.asCell(); + auto type = keyJSValueCell->type(); + + switch (type) { + + case DataViewType: + case Uint8ArrayType: + case Uint8ClampedArrayType: + case Uint16ArrayType: + case Uint32ArrayType: + case Int8ArrayType: + case Int16ArrayType: + case Int32ArrayType: + case Float32ArrayType: + case Float64ArrayType: + case BigInt64ArrayType: + case BigUint64ArrayType: { + JSC::JSArrayBufferView* view = jsCast<JSC::JSArrayBufferView*>(keyJSValueCell); + + data = view->vector(); + byteLength = view->length(); + break; + } + case ArrayBufferType: { + auto* jsBuffer = jsDynamicCast<JSC::JSArrayBuffer*>(keyJSValueCell); + if (UNLIKELY(!jsBuffer)) { + throwException(globalObject, scope, createTypeError(globalObject, "ERR_INVALID_ARG_TYPE: expected key to be Buffer or array-like object"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto* buffer = jsBuffer->impl(); + data = buffer->data(); + byteLength = buffer->byteLength(); + break; + } + default: { + if (auto* keyObj = jsDynamicCast<JSC::JSObject*>(keyJSValue)) { + if (format != "jwk"_s) { + JSC::throwTypeError(globalObject, scope, "format should be 'jwk' when key type is 'object'"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto jwk = WebCore::convertDictionary<JsonWebKey>(*globalObject, keyJSValue); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (jwk.kty == "OKP"_s) { + if (jwk.crv == "Ed25519"_s) { + auto result = CryptoKeyOKP::importJwk(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::Ed25519, WTFMove(jwk), true, CryptoKeyUsageSign); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + if (impl->type() != CryptoKeyType::Private) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (jwk.crv == "X25519"_s) { + auto result = CryptoKeyOKP::importJwk(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, WTFMove(jwk), true, CryptoKeyUsageSign); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid X25519 private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + if (impl->type() != CryptoKeyType::Private) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported OKP curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } else if (jwk.kty == "EC"_s) { + auto result = CryptoKeyEC::importJwk(CryptoAlgorithmIdentifier::ECDSA, jwk.crv, WTFMove(jwk), true, jwk.usages); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + if (impl->type() != CryptoKeyType::Private) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (jwk.kty == "RSA"_s) { + auto result = CryptoKeyRSA::importJwk(CryptoAlgorithmIdentifier::RSA_OAEP, std::nullopt, WTFMove(jwk), true, jwk.usages); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid RSA private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + if (impl->type() != CryptoKeyType::Private) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } + JSC::throwTypeError(globalObject, scope, "The \"key\" property must be of type object"_s); + return JSValue::encode(JSC::jsUndefined()); + } + } + + if (format == "jwk"_s) { + JSC::throwTypeError(globalObject, scope, "The \"key\" property must be of type object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + if (UNLIKELY(!data) || UNLIKELY(!byteLength)) { + throwException(globalObject, scope, createTypeError(globalObject, "ERR_INVALID_ARG_TYPE: expected key to be Buffer or array-like object"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + + JSValue passphraseJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "passphrase"_s))); + PrivateKeyPassphrase passphrase = { nullptr, 0 }; + + auto hasPassphrase = !passphraseJSValue.isUndefinedOrNull() && !passphraseJSValue.isEmpty(); + + if (hasPassphrase) { + if (passphraseJSValue.isString()) { + auto passphrase_wtfstr = passphraseJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (!passphrase_wtfstr.isNull()) { + if (auto pass = passphrase_wtfstr.tryGetUTF8()) { + if (pass.has_value()) { + auto value = pass.value(); + passphrase.passphrase = const_cast<char*>(value.data()); + passphrase.passphrase_len = value.length(); + } + } + } + } else if (auto* passphraseBuffer = jsDynamicCast<JSUint8Array*>(passphraseJSValue)) { + passphrase.passphrase = (char*)passphraseBuffer->vector(); + passphrase.passphrase_len = passphraseBuffer->byteLength(); + } else { + JSC::throwTypeError(globalObject, scope, "passphrase must be a Buffer or String"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + + if (format == "pem"_s) { + auto bio = BIOPtr(BIO_new_mem_buf(const_cast<char*>((char*)data), byteLength)); + auto pkey = EvpPKeyPtr(PEM_read_bio_PrivateKey(bio.get(), nullptr, PasswordCallback, &passphrase)); + + if (!pkey) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key pem file"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto pKeyID = EVP_PKEY_id(pkey.get()); + + if (pKeyID == EVP_PKEY_RSA || pKeyID == EVP_PKEY_RSA_PSS) { + auto impl = CryptoKeyRSA::create(pKeyID == EVP_PKEY_RSA_PSS ? CryptoAlgorithmIdentifier::RSA_PSS : CryptoAlgorithmIdentifier::RSA_OAEP, CryptoAlgorithmIdentifier::SHA_1, false, CryptoKeyType::Private, WTFMove(pkey), true, CryptoKeyUsageDecrypt); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_ED25519 || pKeyID == EVP_PKEY_X25519) { + size_t out_len = 0; + if (!EVP_PKEY_get_raw_private_key(pkey.get(), nullptr, &out_len)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + Vector<uint8_t> out(out_len); + if (!EVP_PKEY_get_raw_private_key(pkey.get(), out.data(), &out_len) || out_len != out.size()) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto result = CryptoKeyOKP::create(CryptoAlgorithmIdentifier::Ed25519, pKeyID == EVP_PKEY_ED25519 ? CryptoKeyOKP::NamedCurve::Ed25519 : CryptoKeyOKP::NamedCurve::X25519, CryptoKeyType::Private, WTFMove(out), true, CryptoKeyUsageSign); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_EC) { + EC_KEY* ec_key = EVP_PKEY_get1_EC_KEY(pkey.get()); + if (UNLIKELY(ec_key == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); + // Get the curve name + int curve_name = EC_GROUP_get_curve_name(ec_group); + if (curve_name == NID_undef) { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unable to identify EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + CryptoKeyEC::NamedCurve curve; + if (curve_name == NID_X9_62_prime256v1) + curve = CryptoKeyEC::NamedCurve::P256; + else if (curve_name == NID_secp384r1) + curve = CryptoKeyEC::NamedCurve::P384; + else if (curve_name == NID_secp521r1) + curve = CryptoKeyEC::NamedCurve::P521; + else { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + EC_KEY_free(ec_key); + auto impl = CryptoKeyEC::create(CryptoAlgorithmIdentifier::ECDH, curve, CryptoKeyType::Private, WTFMove(pkey), true, CryptoKeyUsageSign); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } + if (format == "der"_s) { + JSValue typeJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "type"_s))); + WTF::String type = "pkcs8"_s; + if (!typeJSValue.isUndefinedOrNull() && !typeJSValue.isEmpty()) { + if (!typeJSValue.isString()) { + JSC::throwTypeError(globalObject, scope, "type must be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + type = typeJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + } + + if (type == "pkcs1"_s) { + // must be RSA + const unsigned char* p = reinterpret_cast<const unsigned char*>(data); + auto pkey = EvpPKeyPtr(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, byteLength)); + if (!pkey) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid use of PKCS#1 as private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto pKeyID = EVP_PKEY_id(pkey.get()); + auto impl = CryptoKeyRSA::create(pKeyID == EVP_PKEY_RSA_PSS ? CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5 : CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5, CryptoAlgorithmIdentifier::SHA_1, false, CryptoKeyType::Private, WTFMove(pkey), true, CryptoKeyUsageDecrypt); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (type == "pkcs8"_s) { + + auto bio = BIOPtr(BIO_new_mem_buf(const_cast<char*>((char*)data), byteLength)); + WebCore::EvpPKeyPtr pkey; + if (KeyObject__IsEncryptedPrivateKeyInfo(const_cast<unsigned char*>((unsigned char*)data), byteLength)) { + pkey = EvpPKeyPtr(d2i_PKCS8PrivateKey_bio(bio.get(), + nullptr, + PasswordCallback, + &passphrase)); + } else { + auto* p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr); + if (!p8inf) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid PKCS8 data"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + pkey = EvpPKeyPtr(EVP_PKCS82PKEY(p8inf)); + } + if (!pkey) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto pKeyID = EVP_PKEY_id(pkey.get()); + + if (pKeyID == EVP_PKEY_RSA || pKeyID == EVP_PKEY_RSA_PSS) { + auto impl = CryptoKeyRSA::create(pKeyID == EVP_PKEY_RSA_PSS ? CryptoAlgorithmIdentifier::RSA_PSS : CryptoAlgorithmIdentifier::RSA_OAEP, CryptoAlgorithmIdentifier::SHA_1, false, CryptoKeyType::Private, WTFMove(pkey), true, CryptoKeyUsageDecrypt); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_ED25519) { + auto result = CryptoKeyOKP::importPkcs8(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::Ed25519, Vector<uint8_t>((uint8_t*)data, byteLength), true, CryptoKeyUsageSign); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_X25519) { + auto result = CryptoKeyOKP::importPkcs8(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, Vector<uint8_t>((uint8_t*)data, byteLength), true, CryptoKeyUsageSign); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_EC) { + EC_KEY* ec_key = EVP_PKEY_get1_EC_KEY(pkey.get()); + if (UNLIKELY(ec_key == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); + // Get the curve name + int curve_name = EC_GROUP_get_curve_name(ec_group); + if (curve_name == NID_undef) { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unable to identify EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + CryptoKeyEC::NamedCurve curve; + if (curve_name == NID_X9_62_prime256v1) + curve = CryptoKeyEC::NamedCurve::P256; + else if (curve_name == NID_secp384r1) + curve = CryptoKeyEC::NamedCurve::P384; + else if (curve_name == NID_secp521r1) + curve = CryptoKeyEC::NamedCurve::P521; + else { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto result = CryptoKeyEC::platformImportPkcs8(CryptoAlgorithmIdentifier::ECDH, curve, Vector<uint8_t>((uint8_t*)data, byteLength), true, CryptoKeyUsageSign); + if (UNLIKELY(result == nullptr)) { + result = CryptoKeyEC::platformImportPkcs8(CryptoAlgorithmIdentifier::ECDSA, curve, Vector<uint8_t>((uint8_t*)data, byteLength), true, CryptoKeyUsageSign); + } + EC_KEY_free(ec_key); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } else if (type == "sec1"_s) { + const unsigned char* p = reinterpret_cast<const unsigned char*>(data); + auto pkey = EvpPKeyPtr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, byteLength)); + auto pKeyID = EVP_PKEY_id(pkey.get()); + + if (pKeyID == EVP_PKEY_EC) { + EC_KEY* ec_key = EVP_PKEY_get1_EC_KEY(pkey.get()); + if (UNLIKELY(ec_key == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); + // Get the curve name + int curve_name = EC_GROUP_get_curve_name(ec_group); + if (curve_name == NID_undef) { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unable to identify EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + CryptoKeyEC::NamedCurve curve; + if (curve_name == NID_X9_62_prime256v1) + curve = CryptoKeyEC::NamedCurve::P256; + else if (curve_name == NID_secp384r1) + curve = CryptoKeyEC::NamedCurve::P384; + else if (curve_name == NID_secp521r1) + curve = CryptoKeyEC::NamedCurve::P521; + else { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + EC_KEY_free(ec_key); + auto impl = CryptoKeyEC::create(CryptoAlgorithmIdentifier::ECDH, curve, CryptoKeyType::Private, WTFMove(pkey), true, CryptoKeyUsageSign); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } + + JSC::throwTypeError(globalObject, scope, "type should be 'pkcs1', 'pkcs8' or 'sec1'"_s); + return JSValue::encode(JSC::jsUndefined()); + } + + JSC::throwTypeError(globalObject, scope, "format should be 'pem' or 'der'"_s); + return JSValue::encode(JSC::jsUndefined()); +} + +static JSC::EncodedJSValue KeyObject__createRSAFromPrivate(JSC::JSGlobalObject* globalObject, EVP_PKEY* pkey, WebCore::CryptoAlgorithmIdentifier alg) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + const RSA* rsa_key = EVP_PKEY_get0_RSA(pkey); + + auto publicRSA = RSAPtr(RSAPublicKey_dup(rsa_key)); + if (!publicRSA) { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Failed to create a public key from private"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto publicPKey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_RSA(publicPKey.get(), publicRSA.get()) <= 0) { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Failed to create a public key from private"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto impl = CryptoKeyRSA::create(alg, CryptoAlgorithmIdentifier::SHA_1, false, CryptoKeyType::Public, WTFMove(publicPKey), true, CryptoKeyUsageVerify); + Zig::GlobalObject* zigGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + auto* structure = zigGlobalObject->JSCryptoKeyStructure(); + + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); +} + +static JSC::EncodedJSValue KeyObject__createECFromPrivate(JSC::JSGlobalObject* globalObject, EVP_PKEY* pkey, CryptoKeyEC::NamedCurve namedCurve, WebCore::CryptoAlgorithmIdentifier alg) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey); + auto point = ECPointPtr(EC_POINT_dup(EC_KEY_get0_public_key(ec_key), EC_KEY_get0_group(ec_key))); + if (!point) { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Failed to create a public key from private 1"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto curve = NID_undef; + + switch (namedCurve) { + case CryptoKeyEC::NamedCurve::P256: + curve = NID_X9_62_prime256v1; + break; + case CryptoKeyEC::NamedCurve::P384: + curve = NID_secp384r1; + break; + case CryptoKeyEC::NamedCurve::P521: + curve = NID_secp521r1; + break; + } + auto publicECKey = ECKeyPtr(EC_KEY_new_by_curve_name(curve)); + if (!publicECKey) { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Failed to create a public key from private 2"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + // OPENSSL_EC_NAMED_CURVE needs to be set to export the key with the curve name, not with the curve parameters. + EC_KEY_set_asn1_flag(publicECKey.get(), OPENSSL_EC_NAMED_CURVE); + if (EC_KEY_set_public_key(publicECKey.get(), point.get()) <= 0) { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Failed to create a public key from private 3"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto publicPKey = EvpPKeyPtr(EVP_PKEY_new()); + if (EVP_PKEY_set1_EC_KEY(publicPKey.get(), publicECKey.get()) <= 0) { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Failed to create a public key from private 4"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto impl = CryptoKeyEC::create(alg, namedCurve, CryptoKeyType::Public, WTFMove(publicPKey), true, CryptoKeyUsageVerify); + + Zig::GlobalObject* zigGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + auto* structure = zigGlobalObject->JSCryptoKeyStructure(); + + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); +} + +static JSC::EncodedJSValue KeyObject__createOKPFromPrivate(JSC::JSGlobalObject* globalObject, const WebCore::CryptoKeyOKP::KeyMaterial keyData, CryptoKeyOKP::NamedCurve namedCurve, WebCore::CryptoAlgorithmIdentifier alg) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + uint8_t public_key[ED25519_PUBLIC_KEY_LEN]; + + if (namedCurve == CryptoKeyOKP::NamedCurve::Ed25519) { + memcpy(public_key, keyData.data() + ED25519_PRIVATE_KEY_LEN, ED25519_PUBLIC_KEY_LEN); + } else { + X25519_public_from_private(public_key, keyData.data()); + } + auto result = CryptoKeyOKP::create(alg, namedCurve, CryptoKeyType::Public, Vector<uint8_t>(public_key), true, CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Failed to create a public key from private"_s); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + + Zig::GlobalObject* zigGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + auto* structure = zigGlobalObject->JSCryptoKeyStructure(); + + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); +} + +static JSC::EncodedJSValue KeyObject__createPublicFromPrivate(JSC::JSGlobalObject* globalObject, EVP_PKEY* pkey) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto pKeyID = EVP_PKEY_id(pkey); + if (pKeyID == EVP_PKEY_RSA || pKeyID == EVP_PKEY_RSA_PSS) { + return KeyObject__createRSAFromPrivate(globalObject, pkey, pKeyID == EVP_PKEY_RSA_PSS ? CryptoAlgorithmIdentifier::RSA_PSS : CryptoAlgorithmIdentifier::RSA_OAEP); + } else if (pKeyID == EVP_PKEY_EC) { + + EC_KEY* ec_key = EVP_PKEY_get1_EC_KEY(pkey); + if (UNLIKELY(ec_key == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); + // Get the curve name + int curve_name = EC_GROUP_get_curve_name(ec_group); + if (curve_name == NID_undef) { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unable to identify EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + CryptoKeyEC::NamedCurve curve; + if (curve_name == NID_X9_62_prime256v1) + curve = CryptoKeyEC::NamedCurve::P256; + else if (curve_name == NID_secp384r1) + curve = CryptoKeyEC::NamedCurve::P384; + else if (curve_name == NID_secp521r1) + curve = CryptoKeyEC::NamedCurve::P521; + else { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + EC_KEY_free(ec_key); + return KeyObject__createECFromPrivate(globalObject, pkey, curve, CryptoAlgorithmIdentifier::ECDSA); + } else if (pKeyID == EVP_PKEY_ED25519 || pKeyID == EVP_PKEY_X25519) { + size_t out_len = 0; + auto& vm = globalObject->vm(); + if (!EVP_PKEY_get_raw_private_key(pkey, nullptr, &out_len)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + Vector<uint8_t> out(out_len); + if (!EVP_PKEY_get_raw_private_key(pkey, out.data(), &out_len) || out_len != out.size()) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return KeyObject__createOKPFromPrivate(globalObject, out, pKeyID == EVP_PKEY_ED25519 ? CryptoKeyOKP::NamedCurve::Ed25519 : CryptoKeyOKP::NamedCurve::X25519, CryptoAlgorithmIdentifier::Ed25519); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid private key type"_s)); + return JSValue::encode(JSC::jsUndefined()); + } +} + +JSC::EncodedJSValue KeyObject__createPublicKey(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + + auto count = callFrame->argumentCount(); + auto& vm = globalObject->vm(); + + auto scope = DECLARE_THROW_SCOPE(vm); + + if (count < 1) { + auto scope = DECLARE_THROW_SCOPE(vm); + JSC::throwTypeError(globalObject, scope, "createPublicKey requires 1 arguments"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto* options = jsDynamicCast<JSC::JSObject*>(callFrame->argument(0)); + if (!options) { + JSC::throwTypeError(globalObject, scope, "expected options to be a object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + JSValue keyJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "key"_s))); + if (keyJSValue.isUndefinedOrNull() || keyJSValue.isEmpty()) { + JSC::throwTypeError(globalObject, scope, "key is required"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + Zig::GlobalObject* zigGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + auto* structure = zigGlobalObject->JSCryptoKeyStructure(); + + void* data; + size_t byteLength; + if (auto* key = jsDynamicCast<JSCryptoKey*>(keyJSValue)) { + auto& wrapped = key->wrapped(); + auto key_type = wrapped.type(); + if (key_type != CryptoKeyType::Private) { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Invalid key object type, expected private"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto id = wrapped.keyClass(); + + switch (id) { + case CryptoKeyClass::RSA: { + return KeyObject__createRSAFromPrivate(globalObject, downcast<WebCore::CryptoKeyRSA>(wrapped).platformKey(), wrapped.algorithmIdentifier()); + } + case CryptoKeyClass::EC: { + auto& impl = downcast<WebCore::CryptoKeyEC>(wrapped); + return KeyObject__createECFromPrivate(globalObject, impl.platformKey(), impl.namedCurve(), wrapped.algorithmIdentifier()); + } + case CryptoKeyClass::OKP: { + auto& impl = downcast<WebCore::CryptoKeyOKP>(wrapped); + return KeyObject__createOKPFromPrivate(globalObject, impl.exportKey(), impl.namedCurve(), wrapped.algorithmIdentifier()); + } + default: { + JSC::throwTypeError(globalObject, scope, "ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE: Invalid key object type, expected private"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + } + if (!keyJSValue.isCell()) { + JSC::throwTypeError(globalObject, scope, "expected options to be a object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + JSValue formatJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "format"_s))); + if (formatJSValue.isUndefinedOrNull() || formatJSValue.isEmpty()) { + JSC::throwTypeError(globalObject, scope, "format is required"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + if (!formatJSValue.isString()) { + JSC::throwTypeError(globalObject, scope, "format must be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto format = formatJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + + auto keyJSValueCell = keyJSValue.asCell(); + auto type = keyJSValueCell->type(); + + switch (type) { + + case DataViewType: + case Uint8ArrayType: + case Uint8ClampedArrayType: + case Uint16ArrayType: + case Uint32ArrayType: + case Int8ArrayType: + case Int16ArrayType: + case Int32ArrayType: + case Float32ArrayType: + case Float64ArrayType: + case BigInt64ArrayType: + case BigUint64ArrayType: { + JSC::JSArrayBufferView* view = jsCast<JSC::JSArrayBufferView*>(keyJSValueCell); + + data = view->vector(); + byteLength = view->length(); + break; + } + case ArrayBufferType: { + auto* jsBuffer = jsDynamicCast<JSC::JSArrayBuffer*>(keyJSValueCell); + if (UNLIKELY(!jsBuffer)) { + auto scope = DECLARE_THROW_SCOPE(vm); + throwException(globalObject, scope, createTypeError(globalObject, "ERR_INVALID_ARG_TYPE: expected key to be Buffer or array-like object"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto* buffer = jsBuffer->impl(); + data = buffer->data(); + byteLength = buffer->byteLength(); + break; + } + default: { + if (auto* keyObj = jsDynamicCast<JSC::JSObject*>(keyJSValue)) { + if (format != "jwk"_s) { + JSC::throwTypeError(globalObject, scope, "format should be 'jwk' when key type is 'object'"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto jwk = WebCore::convertDictionary<JsonWebKey>(*globalObject, keyJSValue); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (jwk.kty == "OKP"_s) { + if (jwk.crv == "Ed25519"_s) { + auto result = CryptoKeyOKP::importPublicJwk(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::Ed25519, WTFMove(jwk), true, CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + if (impl->type() == CryptoKeyType::Private) { + return KeyObject__createOKPFromPrivate(globalObject, impl.get().exportKey(), CryptoKeyOKP::NamedCurve::Ed25519, CryptoAlgorithmIdentifier::Ed25519); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (jwk.crv == "X25519"_s) { + auto result = CryptoKeyOKP::importPublicJwk(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, WTFMove(jwk), true, CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid X25519 public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + if (impl->type() == CryptoKeyType::Private) { + return KeyObject__createOKPFromPrivate(globalObject, impl.get().exportKey(), CryptoKeyOKP::NamedCurve::X25519, CryptoAlgorithmIdentifier::Ed25519); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported OKP curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } else if (jwk.kty == "EC"_s) { + auto result = CryptoKeyEC::importJwk(CryptoAlgorithmIdentifier::ECDSA, jwk.crv, WTFMove(jwk), true, jwk.usages); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + if (impl->type() == CryptoKeyType::Private) { + return KeyObject__createECFromPrivate(globalObject, impl.get().platformKey(), impl.get().namedCurve(), CryptoAlgorithmIdentifier::ECDSA); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (jwk.kty == "RSA"_s) { + auto result = CryptoKeyRSA::importJwk(CryptoAlgorithmIdentifier::RSA_OAEP, std::nullopt, WTFMove(jwk), true, jwk.usages); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid RSA public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + if (impl->type() == CryptoKeyType::Private) { + return KeyObject__createRSAFromPrivate(globalObject, impl.get().platformKey(), CryptoAlgorithmIdentifier::RSA_OAEP); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } + } + } + + if (format == "jwk"_s) { + JSC::throwTypeError(globalObject, scope, "The \"key\" property must be of type object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + if (UNLIKELY(!data) || UNLIKELY(!byteLength)) { + throwException(globalObject, scope, createTypeError(globalObject, "ERR_INVALID_ARG_TYPE: expected key to be Buffer or array-like object"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + + if (format == "pem"_s) { + auto pem = KeyObject__ParsePublicKeyPEM((const char*)data, byteLength); + if (!pem.key) { + // maybe is a private pem + auto bio = BIOPtr(BIO_new_mem_buf(const_cast<char*>((char*)data), byteLength)); + JSValue passphraseJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "passphrase"_s))); + PrivateKeyPassphrase passphrase = { nullptr, 0 }; + + auto hasPassphrase = !passphraseJSValue.isUndefinedOrNull() && !passphraseJSValue.isEmpty(); + + if (hasPassphrase) { + if (passphraseJSValue.isString()) { + auto passphrase_wtfstr = passphraseJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (!passphrase_wtfstr.isNull()) { + if (auto pass = passphrase_wtfstr.tryGetUTF8()) { + if (pass.has_value()) { + auto value = pass.value(); + passphrase.passphrase = const_cast<char*>(value.data()); + passphrase.passphrase_len = value.length(); + } + } + } + } else if (auto* passphraseBuffer = jsDynamicCast<JSUint8Array*>(passphraseJSValue)) { + passphrase.passphrase = (char*)passphraseBuffer->vector(); + passphrase.passphrase_len = passphraseBuffer->byteLength(); + } else { + JSC::throwTypeError(globalObject, scope, "passphrase must be a Buffer or String"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + + auto pkey = EvpPKeyPtr(PEM_read_bio_PrivateKey(bio.get(), nullptr, PasswordCallback, &passphrase)); + if (!pkey) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid PEM data"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return KeyObject__createPublicFromPrivate(globalObject, pkey.get()); + } + auto pkey = EvpPKeyPtr(pem.key); + auto pKeyID = EVP_PKEY_id(pem.key); + if (pKeyID == EVP_PKEY_RSA || pKeyID == EVP_PKEY_RSA_PSS) { + if (pem.der_data) { + OPENSSL_clear_free(pem.der_data, pem.der_len); + } + auto impl = CryptoKeyRSA::create(pKeyID == EVP_PKEY_RSA_PSS ? CryptoAlgorithmIdentifier::RSA_PSS : CryptoAlgorithmIdentifier::RSA_OAEP, CryptoAlgorithmIdentifier::SHA_1, false, CryptoKeyType::Public, WTFMove(pkey), true, CryptoKeyUsageEncrypt); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_ED25519) { + auto result = CryptoKeyOKP::importSpki(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::Ed25519, Vector<uint8_t>((uint8_t*)pem.der_data, (size_t)pem.der_len), true, CryptoKeyUsageVerify); + if (pem.der_data) { + OPENSSL_clear_free(pem.der_data, pem.der_len); + } + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_X25519) { + auto result = CryptoKeyOKP::importSpki(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, Vector<uint8_t>((uint8_t*)pem.der_data, (size_t)pem.der_len), true, CryptoKeyUsageVerify); + if (pem.der_data) { + OPENSSL_clear_free(pem.der_data, pem.der_len); + } + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_EC) { + EC_KEY* ec_key = EVP_PKEY_get1_EC_KEY(pkey.get()); + if (UNLIKELY(ec_key == nullptr)) { + if (pem.der_data) { + OPENSSL_clear_free(pem.der_data, pem.der_len); + } + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); + // Get the curve name + int curve_name = EC_GROUP_get_curve_name(ec_group); + if (curve_name == NID_undef) { + if (pem.der_data) { + OPENSSL_clear_free(pem.der_data, pem.der_len); + } + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unable to identify EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + CryptoKeyEC::NamedCurve curve; + if (curve_name == NID_X9_62_prime256v1) + curve = CryptoKeyEC::NamedCurve::P256; + else if (curve_name == NID_secp384r1) + curve = CryptoKeyEC::NamedCurve::P384; + else if (curve_name == NID_secp521r1) + curve = CryptoKeyEC::NamedCurve::P521; + else { + if (pem.der_data) { + OPENSSL_clear_free(pem.der_data, pem.der_len); + } + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto result = CryptoKeyEC::platformImportSpki(CryptoAlgorithmIdentifier::ECDH, curve, Vector<uint8_t>((uint8_t*)pem.der_data, (size_t)pem.der_len), true, CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + result = CryptoKeyEC::platformImportSpki(CryptoAlgorithmIdentifier::ECDSA, curve, Vector<uint8_t>((uint8_t*)pem.der_data, (size_t)pem.der_len), true, CryptoKeyUsageVerify); + } + if (pem.der_data) { + OPENSSL_clear_free(pem.der_data, pem.der_len); + } + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + if (pem.der_data) { + OPENSSL_clear_free(pem.der_data, pem.der_len); + } + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } + if (format == "der"_s) { + JSValue typeJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "type"_s))); + WTF::String type = "spki"_s; + if (!typeJSValue.isUndefinedOrNull() && !typeJSValue.isEmpty()) { + if (!typeJSValue.isString()) { + JSC::throwTypeError(globalObject, scope, "type must be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + type = typeJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + } + + if (type == "pkcs1"_s) { + // must be RSA + const unsigned char* p = reinterpret_cast<const unsigned char*>(data); + auto pkey = EvpPKeyPtr(d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, byteLength)); + if (!pkey) { + // maybe is a private RSA key + const unsigned char* p = reinterpret_cast<const unsigned char*>(data); + pkey = EvpPKeyPtr(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, byteLength)); + if (!pkey) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid PKCS#1"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + + auto pKeyID = EVP_PKEY_id(pkey.get()); + return KeyObject__createRSAFromPrivate(globalObject, pkey.get(), pKeyID == EVP_PKEY_RSA_PSS ? CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5 : CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5); + } + + auto pKeyID = EVP_PKEY_id(pkey.get()); + auto impl = CryptoKeyRSA::create(pKeyID == EVP_PKEY_RSA_PSS ? CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5 : CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5, CryptoAlgorithmIdentifier::SHA_1, false, CryptoKeyType::Public, WTFMove(pkey), true, CryptoKeyUsageEncrypt); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (type == "spki"_s) { + // We use d2i_PUBKEY() to import a public key. + const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data); + auto pkey = EvpPKeyPtr(d2i_PUBKEY(nullptr, &ptr, byteLength)); + if (!pkey) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto pKeyID = EVP_PKEY_id(pkey.get()); + + if (pKeyID == EVP_PKEY_RSA || pKeyID == EVP_PKEY_RSA_PSS) { + auto impl = CryptoKeyRSA::create(pKeyID == EVP_PKEY_RSA_PSS ? CryptoAlgorithmIdentifier::RSA_PSS : CryptoAlgorithmIdentifier::RSA_OAEP, CryptoAlgorithmIdentifier::SHA_1, false, CryptoKeyType::Public, WTFMove(pkey), true, CryptoKeyUsageEncrypt); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_ED25519) { + auto result = CryptoKeyOKP::importSpki(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::Ed25519, Vector<uint8_t>((uint8_t*)data, byteLength), true, CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_X25519) { + auto result = CryptoKeyOKP::importSpki(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, Vector<uint8_t>((uint8_t*)data, byteLength), true, CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid Ed25519 public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else if (pKeyID == EVP_PKEY_EC) { + EC_KEY* ec_key = EVP_PKEY_get1_EC_KEY(pkey.get()); + if (UNLIKELY(ec_key == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); + // Get the curve name + int curve_name = EC_GROUP_get_curve_name(ec_group); + if (curve_name == NID_undef) { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unable to identify EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + CryptoKeyEC::NamedCurve curve; + if (curve_name == NID_X9_62_prime256v1) + curve = CryptoKeyEC::NamedCurve::P256; + else if (curve_name == NID_secp384r1) + curve = CryptoKeyEC::NamedCurve::P384; + else if (curve_name == NID_secp521r1) + curve = CryptoKeyEC::NamedCurve::P521; + else { + EC_KEY_free(ec_key); + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported EC curve"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto alg = CryptoAlgorithmIdentifier::ECDH; + auto result = CryptoKeyEC::platformImportSpki(alg, curve, Vector<uint8_t>((uint8_t*)data, byteLength), true, CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + alg = CryptoAlgorithmIdentifier::ECDSA; + result = CryptoKeyEC::platformImportSpki(CryptoAlgorithmIdentifier::ECDSA, curve, Vector<uint8_t>((uint8_t*)data, byteLength), true, CryptoKeyUsageVerify); + } + if (UNLIKELY(result == nullptr)) { + throwException(globalObject, scope, createTypeError(globalObject, "Invalid EC public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto impl = result.releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(impl))); + } else { + throwException(globalObject, scope, createTypeError(globalObject, "Unsupported public key"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } + + JSC::throwTypeError(globalObject, scope, "type should be 'pkcs1' or 'spki'"_s); + return JSValue::encode(JSC::jsUndefined()); + } + JSC::throwTypeError(globalObject, scope, "format should be 'pem' or 'der'"_s); + return JSValue::encode(JSC::jsUndefined()); +} + +JSC::EncodedJSValue KeyObject__createSecretKey(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + + JSValue bufferArg = callFrame->uncheckedArgument(0); + auto& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto* structure = globalObject->JSCryptoKeyStructure(); + + if (!bufferArg.isCell()) { + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "ERR_INVALID_ARG_TYPE: expected Buffer or array-like object"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + + auto bufferArgCell = bufferArg.asCell(); + auto type = bufferArgCell->type(); + + switch (type) { + + case DataViewType: + case Uint8ArrayType: + case Uint8ClampedArrayType: + case Uint16ArrayType: + case Uint32ArrayType: + case Int8ArrayType: + case Int16ArrayType: + case Int32ArrayType: + case Float32ArrayType: + case Float64ArrayType: + case BigInt64ArrayType: + case BigUint64ArrayType: { + JSC::JSArrayBufferView* view = jsCast<JSC::JSArrayBufferView*>(bufferArgCell); + + void* data = view->vector(); + size_t byteLength = view->length(); + if (UNLIKELY(!data)) { + break; + } + auto impl = CryptoKeyHMAC::generateFromBytes(data, byteLength, CryptoAlgorithmIdentifier::HMAC, true, CryptoKeyUsageSign | CryptoKeyUsageVerify).releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, globalObject, WTFMove(impl))); + } + case ArrayBufferType: { + auto* jsBuffer = jsDynamicCast<JSC::JSArrayBuffer*>(bufferArgCell); + if (UNLIKELY(!jsBuffer)) { + break; + } + auto* buffer = jsBuffer->impl(); + void* data = buffer->data(); + size_t byteLength = buffer->byteLength(); + if (UNLIKELY(!data)) { + break; + } + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto impl = CryptoKeyHMAC::generateFromBytes(data, byteLength, CryptoAlgorithmIdentifier::HMAC, true, CryptoKeyUsageSign | CryptoKeyUsageVerify).releaseNonNull(); + return JSC::JSValue::encode(JSCryptoKey::create(structure, globalObject, WTFMove(impl))); + } + default: + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "ERR_INVALID_ARG_TYPE: expected Buffer or array-like object"_s)); + return JSValue::encode(JSC::jsUndefined()); + } +} + +JSC::EncodedJSValue KeyObject__Exports(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + + auto count = callFrame->argumentCount(); + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (count < 2) { + JSC::throwTypeError(globalObject, scope, "exports requires 2 arguments"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + auto* key = jsDynamicCast<JSCryptoKey*>(callFrame->argument(0)); + if (!key) { + // No JSCryptoKey instance + JSC::throwTypeError(globalObject, scope, "expected CryptoKey as first argument"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + auto& wrapped = key->wrapped(); + auto key_type = wrapped.type(); + auto id = wrapped.keyClass(); + if (auto* options = jsDynamicCast<JSC::JSObject*>(callFrame->argument(1))) { + JSValue formatJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "format"_s))); + JSValue typeJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "type"_s))); + JSValue passphraseJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "passphrase"_s))); + auto hasPassphrase = !passphraseJSValue.isUndefinedOrNull() && !passphraseJSValue.isEmpty(); + if (formatJSValue.isUndefinedOrNull() || formatJSValue.isEmpty()) { + JSC::throwTypeError(globalObject, scope, "format is expected to be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + auto string = formatJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (string == "jwk"_s && hasPassphrase) { + JSC::throwTypeError(globalObject, scope, "encryption is not supported for jwk format"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + switch (id) { + case CryptoKeyClass::HMAC: { + const auto& hmac = downcast<WebCore::CryptoKeyHMAC>(wrapped); + if (string == "buffer"_s) { + auto keyData = hmac.key(); + auto size = keyData.size(); + auto* buffer = jsCast<JSUint8Array*>(JSValue::decode(JSBuffer__bufferFromLength(globalObject, size))); + if (size > 0) + memcpy(buffer->vector(), keyData.data(), size); + + return JSC::JSValue::encode(buffer); + } else if (string == "jwk"_s) { + const JsonWebKey& jwkValue = hmac.exportJwk(); + Zig::GlobalObject* domGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + return JSC::JSValue::encode(WebCore::convertDictionaryToJS(*globalObject, *domGlobalObject, jwkValue, true)); + } + break; + } + case CryptoKeyClass::AES: { + const auto& aes = downcast<WebCore::CryptoKeyAES>(wrapped); + if (string == "buffer"_s) { + auto keyData = aes.key(); + auto size = keyData.size(); + auto* buffer = jsCast<JSUint8Array*>(JSValue::decode(JSBuffer__bufferFromLength(globalObject, size))); + if (size > 0) + memcpy(buffer->vector(), keyData.data(), size); + + return JSC::JSValue::encode(buffer); + } else if (string == "jwk"_s) { + const JsonWebKey& jwkValue = aes.exportJwk(); + Zig::GlobalObject* domGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + return JSC::JSValue::encode(WebCore::convertDictionaryToJS(*globalObject, *domGlobalObject, jwkValue, true)); + } + break; + } + case CryptoKeyClass::RSA: { + const auto& rsa = downcast<WebCore::CryptoKeyRSA>(wrapped); + if (string == "jwk"_s) { + const JsonWebKey& jwkValue = rsa.exportJwk(); + Zig::GlobalObject* domGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + return JSC::JSValue::encode(WebCore::convertDictionaryToJS(*globalObject, *domGlobalObject, jwkValue, true)); + } else { + WTF::String type = "pkcs1"_s; + if (!typeJSValue.isUndefinedOrNull() && !typeJSValue.isEmpty()) { + if (!typeJSValue.isString()) { + JSC::throwTypeError(globalObject, scope, "type must be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + type = typeJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + } + + auto* bio = BIO_new(BIO_s_mem()); + auto* rsaKey = rsa.platformKey(); + auto* rsa_ptr = EVP_PKEY_get0_RSA(rsaKey); + + if (key_type == CryptoKeyType::Public) { + if (string == "pem"_s) { + if (type == "pkcs1"_s) { + if (PEM_write_bio_RSAPublicKey(bio, rsa_ptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write public key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (type == "spki"_s) { + if (PEM_write_bio_PUBKEY(bio, rsaKey) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write public key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'pkcs1' or 'spki'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + } else if (string == "der"_s) { + if (type == "pkcs1"_s) { + if (i2d_RSAPublicKey_bio(bio, rsa_ptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write public key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (type == "spki"_s) { + if (i2d_PUBKEY_bio(bio, rsaKey) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write public key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'pkcs1' or 'spki'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "format expected to be 'der', 'pem' or 'jwk'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSValue cipherJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "cipher"_s))); + + const EVP_CIPHER* cipher = nullptr; + if (!cipherJSValue.isUndefinedOrNull() && !cipherJSValue.isEmpty() && cipherJSValue.isString()) { + auto cipher_wtfstr = cipherJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (!cipher_wtfstr.isNull()) { + auto cipherOrError = cipher_wtfstr.tryGetUTF8(); + if (!cipherOrError.has_value()) { + JSC::throwTypeError(globalObject, scope, "invalid cipher name"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } else { + auto value = cipherOrError.value(); + auto cipher_str = value.data(); + if (cipher_str != nullptr) { + cipher = EVP_get_cipherbyname(cipher_str); + } + } + } + } + void* passphrase = nullptr; + size_t passphrase_len = 0; + if (hasPassphrase) { + if (!cipher) { + JSC::throwTypeError(globalObject, scope, "cipher is required when passphrase is specified"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + if (passphraseJSValue.isString()) { + auto passphrase_wtfstr = passphraseJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (!passphrase_wtfstr.isNull()) { + if (auto pass = passphrase_wtfstr.tryGetUTF8()) { + if (pass.has_value()) { + auto value = pass.value(); + passphrase = const_cast<char*>(value.data()); + passphrase_len = value.length(); + } + } + } + } else if (auto* passphraseBuffer = jsDynamicCast<JSUint8Array*>(passphraseJSValue)) { + passphrase = passphraseBuffer->vector(); + passphrase_len = passphraseBuffer->byteLength(); + } else { + JSC::throwTypeError(globalObject, scope, "passphrase must be a Buffer or String"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + + if (string == "pem"_s) { + if (type == "pkcs1"_s) { + if (PEM_write_bio_RSAPrivateKey(bio, rsa_ptr, cipher, (unsigned char*)passphrase, passphrase_len, nullptr, nullptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (type == "pkcs8"_s) { + if (PEM_write_bio_PKCS8PrivateKey(bio, rsaKey, cipher, (char*)passphrase, passphrase_len, nullptr, nullptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'pkcs1' or 'pkcs8'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (string == "der"_s) { + if (type == "pkcs1"_s) { + if (i2d_RSAPrivateKey_bio(bio, rsa_ptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (type == "pkcs8"_s) { + if (i2d_PKCS8PrivateKey_bio(bio, rsaKey, cipher, (char*)passphrase, passphrase_len, nullptr, nullptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'pkcs1' or 'pkcs8'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "format expected to be 'der', 'pem' or 'jwk'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + + BUF_MEM* bptr; + BIO_get_mem_ptr(bio, &bptr); + auto length = bptr->length; + if (string == "pem"_s) { + auto str = WTF::String::fromUTF8(bptr->data, length); + return JSValue::encode(JSC::jsString(vm, str)); + } + + auto* buffer = jsCast<JSUint8Array*>(JSValue::decode(JSBuffer__bufferFromLength(globalObject, length))); + if (length > 0) + memcpy(buffer->vector(), bptr->data, length); + + BIO_free(bio); + return JSC::JSValue::encode(buffer); + } + } + case CryptoKeyClass::EC: { + const auto& ec = downcast<WebCore::CryptoKeyEC>(wrapped); + if (string == "jwk"_s) { + auto result = ec.exportJwk(); + if (result.hasException()) { + WebCore::propagateException(*globalObject, scope, result.releaseException()); + return JSC::JSValue::encode(JSC::JSValue {}); + } + const JsonWebKey& jwkValue = result.releaseReturnValue(); + Zig::GlobalObject* domGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + return JSC::JSValue::encode(WebCore::convertDictionaryToJS(*globalObject, *domGlobalObject, jwkValue, true)); + } else { + WTF::String type = "spki"_s; + if (!typeJSValue.isUndefinedOrNull() && !typeJSValue.isEmpty()) { + if (!typeJSValue.isString()) { + JSC::throwTypeError(globalObject, scope, "type must be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + type = typeJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + } + + auto* bio = BIO_new(BIO_s_mem()); + auto* ecKey = ec.platformKey(); + auto* ec_ptr = EVP_PKEY_get1_EC_KEY(ecKey); + + if (key_type == CryptoKeyType::Public) { + if (string == "pem"_s) { + if (type == "spki"_s) { + if (PEM_write_bio_PUBKEY(bio, ecKey) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write public key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'spki'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + } else if (string == "der"_s) { + if (type == "spki"_s) { + if (i2d_PUBKEY_bio(bio, ecKey) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write public key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'spki'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "format expected to be 'der', 'pem' or 'jwk'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSValue passphraseJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "passphrase"_s))); + JSValue cipherJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "cipher"_s))); + + const EVP_CIPHER* cipher = nullptr; + if (!cipherJSValue.isUndefinedOrNull() && !cipherJSValue.isEmpty()) { + auto cipher_wtfstr = cipherJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (!cipher_wtfstr.isNull()) { + auto cipherOrError = cipher_wtfstr.tryGetUTF8(); + if (!cipherOrError.has_value()) { + JSC::throwTypeError(globalObject, scope, "invalid cipher name"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } else { + auto value = cipherOrError.value(); + auto cipher_str = value.data(); + if (cipher_str != nullptr) { + cipher = EVP_get_cipherbyname(cipher_str); + } + } + } + } + void* passphrase = nullptr; + size_t passphrase_len = 0; + auto hasPassphrase = !passphraseJSValue.isUndefinedOrNull() && !passphraseJSValue.isEmpty(); + + if (hasPassphrase) { + if (!cipher) { + JSC::throwTypeError(globalObject, scope, "cipher is required when passphrase is specified"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + if (passphraseJSValue.isString()) { + auto passphrase_wtfstr = passphraseJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (!passphrase_wtfstr.isNull()) { + if (auto pass = passphrase_wtfstr.tryGetUTF8()) { + if (pass.has_value()) { + auto value = pass.value(); + passphrase = const_cast<char*>(value.data()); + passphrase_len = value.length(); + } + } + } + } else if (auto* passphraseBuffer = jsDynamicCast<JSUint8Array*>(passphraseJSValue)) { + passphrase = passphraseBuffer->vector(); + passphrase_len = passphraseBuffer->byteLength(); + } else { + JSC::throwTypeError(globalObject, scope, "passphrase must be a Buffer or String"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + + if (string == "pem"_s) { + if (type == "sec1"_s) { + if (PEM_write_bio_ECPrivateKey(bio, ec_ptr, cipher, (unsigned char*)passphrase, passphrase_len, nullptr, nullptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (type == "pkcs8"_s) { + if (PEM_write_bio_PKCS8PrivateKey(bio, ecKey, cipher, (char*)passphrase, passphrase_len, nullptr, nullptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'sec1' or 'pkcs8'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (string == "der"_s) { + if (type == "sec1"_s) { + if (i2d_ECPrivateKey_bio(bio, ec_ptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (type == "pkcs8"_s) { + if (i2d_PKCS8PrivateKey_bio(bio, ecKey, cipher, (char*)passphrase, passphrase_len, nullptr, nullptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'sec1' or 'pkcs8'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "format expected to be 'der', 'pem' or 'jwk'"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + + BUF_MEM* bptr; + BIO_get_mem_ptr(bio, &bptr); + auto length = bptr->length; + if (string == "pem"_s) { + auto str = WTF::String::fromUTF8(bptr->data, length); + return JSValue::encode(JSC::jsString(vm, str)); + } + + auto* buffer = jsCast<JSUint8Array*>(JSValue::decode(JSBuffer__bufferFromLength(globalObject, length))); + if (length > 0) + memcpy(buffer->vector(), bptr->data, length); + + BIO_free(bio); + return JSC::JSValue::encode(buffer); + } + } + case CryptoKeyClass::OKP: { + const auto& okpKey = downcast<WebCore::CryptoKeyOKP>(wrapped); + if (string == "jwk"_s) { + auto result = okpKey.exportJwk(); + if (result.hasException()) { + WebCore::propagateException(*globalObject, scope, result.releaseException()); + return JSC::JSValue::encode(JSC::JSValue {}); + } + const JsonWebKey& jwkValue = result.releaseReturnValue(); + Zig::GlobalObject* domGlobalObject = reinterpret_cast<Zig::GlobalObject*>(globalObject); + return JSC::JSValue::encode(WebCore::convertDictionaryToJS(*globalObject, *domGlobalObject, jwkValue, true)); + } else { + WTF::String type = "pkcs8"_s; + if (!typeJSValue.isUndefinedOrNull() && !typeJSValue.isEmpty()) { + if (!typeJSValue.isString()) { + JSC::throwTypeError(globalObject, scope, "type must be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + type = typeJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + } + + auto keyData = okpKey.exportKey(); + auto* bio = BIO_new(BIO_s_mem()); + + EVP_PKEY* evpKey; + // TODO: CHECK THIS WHEN X488 AND ED448 ARE ADDED + if (okpKey.type() == CryptoKeyType::Private) { + evpKey = EVP_PKEY_new_raw_private_key(okpKey.namedCurve() == CryptoKeyOKP::NamedCurve::X25519 ? EVP_PKEY_X25519 : EVP_PKEY_ED25519, nullptr, keyData.data(), keyData.size()); + JSValue passphraseJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "passphrase"_s))); + JSValue cipherJSValue = options->getIfPropertyExists(globalObject, PropertyName(Identifier::fromString(vm, "cipher"_s))); + + const EVP_CIPHER* cipher = nullptr; + if (!cipherJSValue.isUndefinedOrNull() && !cipherJSValue.isEmpty() && cipherJSValue.isString()) { + auto cipher_wtfstr = cipherJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (!cipher_wtfstr.isNull()) { + auto cipherOrError = cipher_wtfstr.tryGetUTF8(); + if (!cipherOrError.has_value()) { + JSC::throwTypeError(globalObject, scope, "invalid cipher name"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } else { + auto value = cipherOrError.value(); + auto cipher_str = value.data(); + if (cipher_str != nullptr) { + cipher = EVP_get_cipherbyname(cipher_str); + } + } + } + } + void* passphrase = nullptr; + size_t passphrase_len = 0; + auto hasPassphrase = !passphraseJSValue.isUndefinedOrNull() && !passphraseJSValue.isEmpty(); + + if (hasPassphrase) { + if (!cipher) { + JSC::throwTypeError(globalObject, scope, "cipher is required when passphrase is specified"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + if (passphraseJSValue.isString()) { + auto passphrase_wtfstr = passphraseJSValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (!passphrase_wtfstr.isNull()) { + if (auto pass = passphrase_wtfstr.tryGetUTF8()) { + if (pass.has_value()) { + auto value = pass.value(); + passphrase = const_cast<char*>(value.data()); + passphrase_len = value.length(); + } + } + } + } else if (auto* passphraseBuffer = jsDynamicCast<JSUint8Array*>(passphraseJSValue)) { + passphrase = passphraseBuffer->vector(); + passphrase_len = passphraseBuffer->byteLength(); + } else { + JSC::throwTypeError(globalObject, scope, "passphrase must be a Buffer or String"_s); + BIO_free(bio); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + + if (string == "pem"_s) { + if (type == "pkcs8"_s) { + if (PEM_write_bio_PKCS8PrivateKey(bio, evpKey, cipher, (char*)passphrase, passphrase_len, nullptr, nullptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'pkcs8'"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else if (string == "der"_s) { + if (type == "pkcs8"_s) { + if (i2d_PKCS8PrivateKey_bio(bio, evpKey, cipher, (char*)passphrase, passphrase_len, nullptr, nullptr) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write private key"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'pkcs8'"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "format expected to be 'der', 'pem' or 'jwk'"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + evpKey = EVP_PKEY_new_raw_public_key(okpKey.namedCurve() == CryptoKeyOKP::NamedCurve::X25519 ? EVP_PKEY_X25519 : EVP_PKEY_ED25519, nullptr, keyData.data(), keyData.size()); + if (string == "pem"_s) { + if (type == "spki"_s) { + if (PEM_write_bio_PUBKEY(bio, evpKey) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write public key"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'spki'"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + } else if (string == "der"_s) { + if (type == "spki"_s) { + if (i2d_PUBKEY_bio(bio, evpKey) != 1) { + JSC::throwTypeError(globalObject, scope, "Failed to write public key"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "type should be 'spki'"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } else { + JSC::throwTypeError(globalObject, scope, "format expected to be 'der', 'pem' or 'jwk'"_s); + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + + BUF_MEM* bptr; + BIO_get_mem_ptr(bio, &bptr); + auto length = bptr->length; + if (string == "pem"_s) { + auto str = WTF::String::fromUTF8(bptr->data, length); + EVP_PKEY_free(evpKey); + return JSValue::encode(JSC::jsString(vm, str)); + } + + auto* buffer = jsCast<JSUint8Array*>(JSValue::decode(JSBuffer__bufferFromLength(globalObject, length))); + if (length > 0) + memcpy(buffer->vector(), bptr->data, length); + + BIO_free(bio); + EVP_PKEY_free(evpKey); + return JSC::JSValue::encode(buffer); + } + } + case CryptoKeyClass::Raw: { + const auto& raw = downcast<WebCore::CryptoKeyRaw>(wrapped); + if (string == "buffer"_s) { + auto keyData = raw.key(); + auto size = keyData.size(); + auto* buffer = jsCast<JSUint8Array*>(JSValue::decode(JSBuffer__bufferFromLength(globalObject, size))); + if (size > 0) + memcpy(buffer->vector(), keyData.data(), size); + + return JSC::JSValue::encode(buffer); + } + + JSC::throwTypeError(globalObject, scope, "format is expected to be 'buffer'"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + default: { + JSC::throwTypeError(globalObject, scope, "Invalid Operation"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + } + JSC::throwTypeError(globalObject, scope, "format is expected to be 'buffer' or 'jwk'"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } else { + JSC::throwTypeError(globalObject, scope, "expected options to be a object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } +} + +static char* bignum_to_string(const BIGNUM* bn) +{ + char *tmp, *ret; + size_t len; + + // Display large numbers in hex and small numbers in decimal. Converting to + // decimal takes quadratic time and is no more useful than hex for large + // numbers. + if (BN_num_bits(bn) < 32) { + return BN_bn2dec(bn); + } + + tmp = BN_bn2hex(bn); + if (tmp == NULL) { + return NULL; + } + + len = strlen(tmp) + 3; + ret = (char*)OPENSSL_malloc(len); + if (ret == NULL) { + OPENSSL_free(tmp); + return NULL; + } + + // Prepend "0x", but place it after the "-" if negative. + if (tmp[0] == '-') { + OPENSSL_strlcpy(ret, "-0x", len); + OPENSSL_strlcat(ret, tmp + 1, len); + } else { + OPENSSL_strlcpy(ret, "0x", len); + OPENSSL_strlcat(ret, tmp, len); + } + OPENSSL_free(tmp); + return ret; +} + +JSC::EncodedJSValue KeyObject_AsymmetricKeyDetails(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + + if (auto* key = jsDynamicCast<JSCryptoKey*>(callFrame->argument(0))) { + auto id = key->wrapped().algorithmIdentifier(); + auto& vm = lexicalGlobalObject->vm(); + switch (id) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::RSA_PSS: { + auto* obj = JSC::constructEmptyObject(lexicalGlobalObject); + + auto& wrapped = key->wrapped(); + const auto& rsa = downcast<WebCore::CryptoKeyRSA>(wrapped); + auto* platformKey = rsa.platformKey(); + const BIGNUM* e; // Public Exponent + const BIGNUM* n; // Modulus + const RSA* rsa_key = EVP_PKEY_get0_RSA(platformKey); + if (rsa_key == nullptr) { + return JSValue::encode(JSC::jsUndefined()); + } + + RSA_get0_key(rsa_key, &n, &e, nullptr); + + auto modulus_length = BN_num_bits(n); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "modulusLength"_s)), jsNumber(modulus_length), 0); + + auto str = bignum_to_string(e); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "publicExponent"_s)), JSC::JSBigInt::stringToBigInt(lexicalGlobalObject, StringView::fromLatin1(str)), 0); + OPENSSL_free(str); + + if (id == CryptoAlgorithmIdentifier::RSA_PSS) { + // Due to the way ASN.1 encoding works, default values are omitted when + // encoding the data structure. However, there are also RSA-PSS keys for + // which no parameters are set. In that case, the ASN.1 RSASSA-PSS-params + // sequence will be missing entirely and RSA_get0_pss_params will return + // nullptr. If parameters are present but all parameters are set to their + // default values, an empty sequence will be stored in the ASN.1 structure. + // In that case, RSA_get0_pss_params does not return nullptr but all fields + // of the returned RSA_PSS_PARAMS will be set to nullptr. + + auto* params = RSA_get0_pss_params(rsa_key); + if (params != nullptr) { + int hash_nid = NID_sha1; + int mgf_nid = NID_mgf1; + int mgf1_hash_nid = NID_sha1; + int64_t salt_length = 20; + + if (params->hashAlgorithm != nullptr) { + hash_nid = OBJ_obj2nid(params->hashAlgorithm->algorithm); + } + auto* hash_srt = OBJ_nid2ln(hash_nid); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "hashAlgorithm"_s)), Bun::toJS(lexicalGlobalObject, Bun::toString(hash_srt, strlen(hash_srt))), 0); + if (params->maskGenAlgorithm != nullptr) { + mgf_nid = OBJ_obj2nid(params->maskGenAlgorithm->algorithm); + if (mgf_nid == NID_mgf1) { + mgf1_hash_nid = OBJ_obj2nid(params->maskHash->algorithm); + } + } + + // If, for some reason, the MGF is not MGF1, then the MGF1 hash function + // is intentionally not added to the object. + if (mgf_nid == NID_mgf1) { + auto* mgf1_hash_srt = OBJ_nid2ln(mgf1_hash_nid); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "mgf1HashAlgorithm"_s)), Bun::toJS(lexicalGlobalObject, Bun::toString(mgf1_hash_srt, strlen(mgf1_hash_srt))), 0); + } + + if (params->saltLength != nullptr) { + if (ASN1_INTEGER_get_int64(&salt_length, params->saltLength) != 1) { + auto scope = DECLARE_THROW_SCOPE(vm); + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "Failed to get saltLenght"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + } + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "saltLength"_s)), jsNumber(salt_length), 0); + } + } + return JSC::JSValue::encode(obj); + } + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: { + auto* obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), 1); + + auto& wrapped = key->wrapped(); + const auto& ec = downcast<WebCore::CryptoKeyEC>(wrapped); + static const NeverDestroyed<String> values[] = { + MAKE_STATIC_STRING_IMPL("prime256v1"), + MAKE_STATIC_STRING_IMPL("secp384r1"), + MAKE_STATIC_STRING_IMPL("secp521r1"), + }; + + WTF::String named_curve; + switch (ec.namedCurve()) { + case CryptoKeyEC::NamedCurve::P256: + named_curve = values[0]; + break; + case CryptoKeyEC::NamedCurve::P384: + named_curve = values[1]; + break; + case CryptoKeyEC::NamedCurve::P521: + named_curve = values[2]; + break; + default: + ASSERT_NOT_REACHED(); + named_curve = WTF::emptyString(); + } + + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "namedCurve"_s)), JSC::jsString(vm, named_curve), 0); + return JSC::JSValue::encode(obj); + } + case CryptoAlgorithmIdentifier::Ed25519: { + auto* obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), 1); + auto& wrapped = key->wrapped(); + const auto& okp = downcast<WebCore::CryptoKeyOKP>(wrapped); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "namedCurve"_s)), JSC::jsString(vm, okp.namedCurveString()), 0); + return JSC::JSValue::encode(obj); + } + default: + return JSC::JSValue::encode(JSC::jsUndefined()); + } + } + return JSC::JSValue::encode(JSC::jsUndefined()); +} + +JSC::EncodedJSValue KeyObject__generateKeyPairSync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + auto count = callFrame->argumentCount(); + auto& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (count < 1) { + JSC::throwTypeError(lexicalGlobalObject, scope, "generateKeyPairSync requires 1 arguments"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + auto type = callFrame->argument(0); + if (type.isUndefinedOrNull() || type.isEmpty() || !type.isString()) { + JSC::throwTypeError(lexicalGlobalObject, scope, "type is expected to be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto type_str = type.toWTFString(lexicalGlobalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + + Zig::GlobalObject* zigGlobalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto* structure = zigGlobalObject->JSCryptoKeyStructure(); + // TODO: rsa-pss + if (type_str == "rsa"_s) { + if (count == 1) { + JSC::throwTypeError(lexicalGlobalObject, scope, "options.modulusLength are required for rsa"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto* options = jsDynamicCast<JSC::JSObject*>(callFrame->argument(1)); + if (options == nullptr) { + JSC::throwTypeError(lexicalGlobalObject, scope, "options is expected to be a object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto modulusLengthJS = options->getIfPropertyExists(lexicalGlobalObject, PropertyName(Identifier::fromString(vm, "modulusLength"_s))); + if (!modulusLengthJS.isNumber()) { + JSC::throwTypeError(lexicalGlobalObject, scope, "options.modulusLength is expected to be a number"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto publicExponentJS = options->getIfPropertyExists(lexicalGlobalObject, PropertyName(Identifier::fromString(vm, "publicExponent"_s))); + uint32_t publicExponent = 0x10001; + if (publicExponentJS.isNumber()) { + publicExponent = publicExponentJS.toUInt32(lexicalGlobalObject); + } else if (!publicExponentJS.isUndefinedOrNull() && !publicExponentJS.isEmpty()) { + JSC::throwTypeError(lexicalGlobalObject, scope, "options.publicExponent is expected to be a number"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + uint8_t publicExponentArray[4]; + publicExponentArray[0] = (uint8_t)(publicExponent >> 24); + publicExponentArray[1] = (uint8_t)(publicExponent >> 16); + publicExponentArray[2] = (uint8_t)(publicExponent >> 8); + publicExponentArray[3] = (uint8_t)publicExponent; + + int modulusLength = modulusLengthJS.toUInt32(lexicalGlobalObject); + auto returnValue = JSC::JSValue {}; + auto keyPairCallback = [&](CryptoKeyPair&& pair) { + pair.publicKey->setUsagesBitmap(pair.publicKey->usagesBitmap() & CryptoKeyUsageVerify); + pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & CryptoKeyUsageSign); + + auto obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), 2); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "publicKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.publicKey.releaseNonNull()), 0); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "privateKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.privateKey.releaseNonNull()), 0); + returnValue = obj; + }; + auto failureCallback = [&]() { + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "Failed to generate key pair"_s)); + }; + // this is actually sync + CryptoKeyRSA::generatePair(CryptoAlgorithmIdentifier::RSA_OAEP, CryptoAlgorithmIdentifier::SHA_1, false, modulusLength, Vector<uint8_t>((uint8_t*)&publicExponentArray, 4), true, CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt, WTFMove(keyPairCallback), WTFMove(failureCallback), zigGlobalObject->scriptExecutionContext()); + return JSValue::encode(returnValue); + } else if (type_str == "ec"_s) { + if (count == 1) { + JSC::throwTypeError(lexicalGlobalObject, scope, "options.namedCurve is required for ec"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto* options = jsDynamicCast<JSC::JSObject*>(callFrame->argument(1)); + if (options == nullptr) { + JSC::throwTypeError(lexicalGlobalObject, scope, "options is expected to be a object"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto namedCurveJS = options->getIfPropertyExists(lexicalGlobalObject, PropertyName(Identifier::fromString(vm, "namedCurve"_s))); + if (namedCurveJS.isUndefinedOrNull() || namedCurveJS.isEmpty() || !namedCurveJS.isString()) { + JSC::throwTypeError(lexicalGlobalObject, scope, "namedCurve is expected to be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto namedCurve = namedCurveJS.toWTFString(lexicalGlobalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if(namedCurve == "P-384"_s || namedCurve == "p384"_s || namedCurve == "secp384r1"_s) { + namedCurve = "P-384"_s; + } else if(namedCurve == "P-256"_s || namedCurve == "p256"_s || namedCurve == "prime256v1"_s) { + namedCurve = "P-256"_s; + } else if(namedCurve == "P-521"_s || namedCurve == "p521"_s || namedCurve == "secp521r1"_s) { + namedCurve = "P-521"_s; + }else { + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "curve not supported"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + + auto result = CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier::ECDSA, namedCurve, true, CryptoKeyUsageSign | CryptoKeyUsageVerify); + if (result.hasException()) { + WebCore::propagateException(*lexicalGlobalObject, scope, result.releaseException()); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto pair = result.releaseReturnValue(); + auto obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), 2); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "publicKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.publicKey.releaseNonNull()), 0); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "privateKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.privateKey.releaseNonNull()), 0); + return JSValue::encode(obj); + } else if (type_str == "ed25519"_s) { + auto result = CryptoKeyOKP::generatePair(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::Ed25519, true, CryptoKeyUsageSign | CryptoKeyUsageVerify); + if (result.hasException()) { + WebCore::propagateException(*lexicalGlobalObject, scope, result.releaseException()); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto pair = result.releaseReturnValue(); + auto obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), 2); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "publicKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.publicKey.releaseNonNull()), 0); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "privateKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.privateKey.releaseNonNull()), 0); + return JSValue::encode(obj); + } else if (type_str == "x25519"_s) { + auto result = CryptoKeyOKP::generatePair(CryptoAlgorithmIdentifier::Ed25519, CryptoKeyOKP::NamedCurve::X25519, true, CryptoKeyUsageSign | CryptoKeyUsageVerify); + if (result.hasException()) { + WebCore::propagateException(*lexicalGlobalObject, scope, result.releaseException()); + return JSC::JSValue::encode(JSC::JSValue {}); + } + auto pair = result.releaseReturnValue(); + auto obj = JSC::constructEmptyObject(lexicalGlobalObject, lexicalGlobalObject->objectPrototype(), 2); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "publicKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.publicKey.releaseNonNull()), 0); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "privateKey"_s)), JSCryptoKey::create(structure, zigGlobalObject, pair.privateKey.releaseNonNull()), 0); + return JSValue::encode(obj); + } else { + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "algorithm should be 'rsa', 'ec', 'x25519' or 'ed25519'"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return JSValue::encode(JSC::jsUndefined()); +} +JSC::EncodedJSValue KeyObject__generateKeySync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + auto count = callFrame->argumentCount(); + auto& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + if (count < 2) { + JSC::throwTypeError(lexicalGlobalObject, scope, "generateKeySync requires 2 arguments"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + auto type = callFrame->argument(0); + if (type.isUndefinedOrNull() || type.isEmpty() || !type.isString()) { + JSC::throwTypeError(lexicalGlobalObject, scope, "type is expected to be a string"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + + auto type_str = type.toWTFString(lexicalGlobalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + + if (type_str == "hmac"_s) { + Zig::GlobalObject* zigGlobalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto* structure = zigGlobalObject->JSCryptoKeyStructure(); + size_t lengthBits = 0; + auto length = callFrame->argument(1); + if (!length.isNumber()) { + JSC::throwTypeError(lexicalGlobalObject, scope, "length is expected to be a number"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + lengthBits = length.toUInt32(lexicalGlobalObject); + auto result = CryptoKeyHMAC::generate(lengthBits, WebCore::CryptoAlgorithmIdentifier::HMAC, true, CryptoKeyUsageSign | CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "Invalid length"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(result.releaseNonNull()))); + } else if (type_str == "aes"_s) { + Zig::GlobalObject* zigGlobalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto* structure = zigGlobalObject->JSCryptoKeyStructure(); + size_t lengthBits = 0; + if (count > 1) { + auto length = callFrame->argument(1); + if (!length.isNumber()) { + JSC::throwTypeError(lexicalGlobalObject, scope, "length is expected to be a number"_s); + return JSC::JSValue::encode(JSC::JSValue {}); + } + lengthBits = length.toUInt32(lexicalGlobalObject); + } + + auto result = CryptoKeyAES::generate(WebCore::CryptoAlgorithmIdentifier::AES_CBC, lengthBits, true, CryptoKeyUsageSign | CryptoKeyUsageVerify); + if (UNLIKELY(result == nullptr)) { + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "Invalid length"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return JSC::JSValue::encode(JSCryptoKey::create(structure, zigGlobalObject, WTFMove(result.releaseNonNull()))); + } else { + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "algorithm should be 'aes' or 'hmac'"_s)); + return JSValue::encode(JSC::jsUndefined()); + } +} + +JSC::EncodedJSValue KeyObject__AsymmetricKeyType(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + static const NeverDestroyed<String> values[] = { + MAKE_STATIC_STRING_IMPL("rsa"), + MAKE_STATIC_STRING_IMPL("rsa-pss"), + MAKE_STATIC_STRING_IMPL("ec"), + MAKE_STATIC_STRING_IMPL("x25519"), + MAKE_STATIC_STRING_IMPL("ed25519"), + }; + + // TODO: Look into DSA and DH + if (auto* key = jsDynamicCast<JSCryptoKey*>(callFrame->argument(0))) { + auto id = key->wrapped().algorithmIdentifier(); + switch (id) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_OAEP: + return JSC::JSValue::encode(JSC::jsStringWithCache(lexicalGlobalObject->vm(), values[0])); + case CryptoAlgorithmIdentifier::RSA_PSS: + return JSC::JSValue::encode(JSC::jsStringWithCache(lexicalGlobalObject->vm(), values[1])); + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + return JSC::JSValue::encode(JSC::jsStringWithCache(lexicalGlobalObject->vm(), values[2])); + case CryptoAlgorithmIdentifier::Ed25519: { + const auto& okpKey = downcast<WebCore::CryptoKeyOKP>(key->wrapped()); + // TODO: CHECK THIS WHEN X488 AND ED448 ARE ADDED + return JSC::JSValue::encode(JSC::jsStringWithCache(lexicalGlobalObject->vm(), String(okpKey.namedCurve() == CryptoKeyOKP::NamedCurve::X25519 ? values[3] : values[4]))); + } + default: + return JSC::JSValue::encode(JSC::jsUndefined()); + } + } + return JSC::JSValue::encode(JSC::jsUndefined()); +} + +static Vector<uint8_t> GetRawKeyFromSecret(WebCore::CryptoKey& key) +{ + auto id = key.keyClass(); + switch (id) { + case CryptoKeyClass::HMAC: { + const auto& hmac = downcast<WebCore::CryptoKeyHMAC>(key); + return hmac.key(); + } + case CryptoKeyClass::AES: { + const auto& aes = downcast<WebCore::CryptoKeyAES>(key); + return aes.key(); + } + case CryptoKeyClass::Raw: { + const auto& raw = downcast<WebCore::CryptoKeyRaw>(key); + return raw.key(); + } + default: { + Vector<uint8_t> empty; + return empty; + } + } +} +static AsymmetricKeyValue GetInternalAsymmetricKey(WebCore::CryptoKey& key) +{ + auto id = key.algorithmIdentifier(); + switch (id) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::RSA_PSS: + return (AsymmetricKeyValue) { .key = downcast<WebCore::CryptoKeyRSA>(key).platformKey(), .owned = false }; + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + return (AsymmetricKeyValue) { .key = downcast<WebCore::CryptoKeyEC>(key).platformKey(), .owned = false }; + case CryptoAlgorithmIdentifier::Ed25519: { + const auto& okpKey = downcast<WebCore::CryptoKeyOKP>(key); + auto keyData = okpKey.exportKey(); + if (okpKey.type() == CryptoKeyType::Private) { + auto* evp_key = EVP_PKEY_new_raw_private_key(okpKey.namedCurve() == CryptoKeyOKP::NamedCurve::X25519 ? EVP_PKEY_X25519 : EVP_PKEY_ED25519, nullptr, keyData.data(), keyData.size()); + return (AsymmetricKeyValue) { .key = evp_key, .owned = true }; + } else { + auto* evp_key = EVP_PKEY_new_raw_public_key(okpKey.namedCurve() == CryptoKeyOKP::NamedCurve::X25519 ? EVP_PKEY_X25519 : EVP_PKEY_ED25519, nullptr, keyData.data(), keyData.size()); + return (AsymmetricKeyValue) { .key = evp_key, .owned = true }; + } + } + default: + return (AsymmetricKeyValue) { .key = NULL, .owned = false }; + } +} + +JSC::EncodedJSValue KeyObject__Equals(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + if (auto* key = jsDynamicCast<JSCryptoKey*>(callFrame->argument(0))) { + if (auto* key2 = jsDynamicCast<JSCryptoKey*>(callFrame->argument(1))) { + auto& wrapped = key->wrapped(); + auto& wrapped2 = key2->wrapped(); + auto key_type = wrapped.type(); + auto key_class = wrapped.keyClass(); + if (key_type != wrapped2.type()) { + return JSC::JSValue::encode(jsBoolean(false)); + } + + if (key_type == CryptoKeyType::Secret) { + auto keyData = GetRawKeyFromSecret(wrapped); + auto keyData2 = GetRawKeyFromSecret(wrapped2); + auto size = keyData.size(); + + if (size != keyData2.size()) { + return JSC::JSValue::encode(jsBoolean(false)); + } + return JSC::JSValue::encode(jsBoolean(CRYPTO_memcmp(keyData.data(), keyData2.data(), size) == 0)); + } + auto evp_key = GetInternalAsymmetricKey(wrapped); + auto evp_key2 = GetInternalAsymmetricKey(wrapped2); + + int ok = !evp_key.key || !evp_key2.key ? -2 : EVP_PKEY_cmp(evp_key.key, evp_key2.key); + + if (evp_key.key && evp_key.owned) { + EVP_PKEY_free(evp_key.key); + } + if (evp_key2.key && evp_key2.owned) { + EVP_PKEY_free(evp_key2.key); + } + if (ok == -2) { + auto& vm = lexicalGlobalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + throwException(lexicalGlobalObject, scope, createTypeError(lexicalGlobalObject, "ERR_CRYPTO_UNSUPPORTED_OPERATION"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + return JSC::JSValue::encode(jsBoolean(ok == 1)); + } + } + return JSC::JSValue::encode(jsBoolean(false)); +} + +JSC::EncodedJSValue KeyObject__SymmetricKeySize(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) +{ + if (auto* key = jsDynamicCast<JSCryptoKey*>(callFrame->argument(0))) { + auto& wrapped = key->wrapped(); + auto id = wrapped.keyClass(); + size_t size = 0; + switch (id) { + case CryptoKeyClass::HMAC: { + const auto& hmac = downcast<WebCore::CryptoKeyHMAC>(wrapped); + auto keyData = hmac.key(); + size = keyData.size(); + break; + } + case CryptoKeyClass::AES: { + const auto& aes = downcast<WebCore::CryptoKeyAES>(wrapped); + auto keyData = aes.key(); + size = keyData.size(); + break; + } + case CryptoKeyClass::Raw: { + const auto& raw = downcast<WebCore::CryptoKeyRaw>(wrapped); + auto keyData = raw.key(); + size = keyData.size(); + break; + } + default: { + return JSC::JSValue::encode(JSC::jsUndefined()); + } + } + + if (!size) { + return JSC::JSValue::encode(JSC::jsUndefined()); + } + + return JSC::JSValue::encode(JSC::jsNumber(size)); + } + + return JSC::JSValue::encode(JSC::jsUndefined()); +} + +}
\ No newline at end of file diff --git a/src/bun.js/bindings/KeyObject.h b/src/bun.js/bindings/KeyObject.h new file mode 100644 index 000000000..c9b172e3b --- /dev/null +++ b/src/bun.js/bindings/KeyObject.h @@ -0,0 +1,18 @@ + +#pragma once + +#include "root.h" +#include "helpers.h" +namespace WebCore { + +JSC::EncodedJSValue KeyObject__AsymmetricKeyType(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject_AsymmetricKeyDetails(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject__SymmetricKeySize(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject__Equals(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject__Exports(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject__createSecretKey(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject__createPublicKey(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject__createPrivateKey(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject__generateKeySync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC::EncodedJSValue KeyObject__generateKeyPairSync(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +}
\ No newline at end of file diff --git a/src/bun.js/bindings/ModuleLoader.cpp b/src/bun.js/bindings/ModuleLoader.cpp index 252c446b1..ac980d062 100644 --- a/src/bun.js/bindings/ModuleLoader.cpp +++ b/src/bun.js/bindings/ModuleLoader.cpp @@ -27,7 +27,6 @@ #include "EventEmitter.h" #include "JSEventEmitter.h" -#include "CommonJSModuleRecord.h" #include <JavaScriptCore/JSModuleLoader.h> #include <JavaScriptCore/Completion.h> #include <JavaScriptCore/JSModuleNamespaceObject.h> @@ -93,13 +92,20 @@ generateInternalModuleSourceCode(JSC::JSGlobalObject* globalObject, InternalModu exportNames.reserveCapacity(len); exportValues.ensureCapacity(len); - exportNames.append(vm.propertyNames->defaultKeyword); - exportValues.append(object); + bool hasDefault = false; for (auto& entry : properties) { + if (UNLIKELY(entry == vm.propertyNames->defaultKeyword)) { + hasDefault = true; + } exportNames.append(entry); exportValues.append(object->get(globalObject, entry)); } + + if (!hasDefault) { + exportNames.append(vm.propertyNames->defaultKeyword); + exportValues.append(object); + } }; } @@ -139,7 +145,7 @@ PendingVirtualModuleResult* PendingVirtualModuleResult::create(VM& vm, Structure } Structure* PendingVirtualModuleResult::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info()); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); } PendingVirtualModuleResult::PendingVirtualModuleResult(VM& vm, Structure* structure) @@ -459,7 +465,7 @@ JSValue fetchCommonJSModule( } } - if (JSC::JSValue virtualModuleResult = JSValue::decode(Bun__runVirtualModule(globalObject, specifier))) { + if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier)) { JSPromise* promise = jsCast<JSPromise*>(handleVirtualModuleResult<true>(globalObject, virtualModuleResult, res, specifier, referrer)); switch (promise->status(vm)) { case JSPromise::Status::Rejected: { @@ -534,7 +540,7 @@ JSValue fetchCommonJSModule( RELEASE_AND_RETURN(scope, {}); } - target->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), value, value.isCell() && value.isCallable() ? JSC::PropertyAttribute::Function | 0 : 0); + target->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), value, 0); target->hasEvaluated = true; RELEASE_AND_RETURN(scope, target); } @@ -634,7 +640,7 @@ static JSValue fetchESMSourceCode( } } - if (JSC::JSValue virtualModuleResult = JSValue::decode(Bun__runVirtualModule(globalObject, specifier))) { + if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier)) { return handleVirtualModuleResult<allowPromise>(globalObject, virtualModuleResult, res, specifier, referrer); } diff --git a/src/bun.js/bindings/ModuleLoader.h b/src/bun.js/bindings/ModuleLoader.h index ee726ebcf..72dd8b49a 100644 --- a/src/bun.js/bindings/ModuleLoader.h +++ b/src/bun.js/bindings/ModuleLoader.h @@ -4,6 +4,9 @@ #include "JavaScriptCore/JSCInlines.h" #include "BunClientData.h" +extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); + namespace Zig { class GlobalObject; } diff --git a/src/bun.js/bindings/NodeVMScript.cpp b/src/bun.js/bindings/NodeVMScript.cpp index 05921dd8d..e0e0dc93a 100644 --- a/src/bun.js/bindings/NodeVMScript.cpp +++ b/src/bun.js/bindings/NodeVMScript.cpp @@ -19,6 +19,7 @@ #include "JavaScriptCore/JSWeakMap.h" #include "JavaScriptCore/JSWeakMapInlines.h" #include "JavaScriptCore/JSWithScope.h" +#include "JavaScriptCore/JSGlobalProxyInlines.h" #include "Buffer.h" #include "GCDefferalContext.h" #include "Buffer.h" @@ -120,7 +121,7 @@ constructScript(JSGlobalObject* globalObject, CallFrame* callFrame, JSValue newT auto scope = DECLARE_THROW_SCOPE(vm); SourceCode source( - JSC::StringSourceProvider::create(sourceString, JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(options.filename)), options.filename, TextPosition(options.lineOffset, options.columnOffset)), + JSC::StringSourceProvider::create(sourceString, JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(options.filename)), options.filename, JSC::SourceTaintedOrigin::Untainted, TextPosition(options.lineOffset, options.columnOffset)), options.lineOffset.zeroBasedInt(), options.columnOffset.zeroBasedInt()); RETURN_IF_EXCEPTION(scope, {}); NodeVMScript* script = NodeVMScript::create(vm, globalObject, structure, source); @@ -263,7 +264,7 @@ JSC_DEFINE_HOST_FUNCTION(vmModuleRunInNewContext, (JSGlobalObject * globalObject } } SourceCode source( - JSC::StringSourceProvider::create(sourceString, JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(options.filename)), options.filename, TextPosition(options.lineOffset, options.columnOffset)), + JSC::StringSourceProvider::create(sourceString, JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(options.filename)), options.filename, JSC::SourceTaintedOrigin::Untainted, TextPosition(options.lineOffset, options.columnOffset)), options.lineOffset.zeroBasedInt(), options.columnOffset.zeroBasedInt()); auto* zigGlobal = reinterpret_cast<Zig::GlobalObject*>(globalObject); @@ -332,7 +333,7 @@ JSC_DEFINE_HOST_FUNCTION(vmModuleRunInThisContext, (JSGlobalObject * globalObjec } } SourceCode source( - JSC::StringSourceProvider::create(sourceString, JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(options.filename)), options.filename, TextPosition(options.lineOffset, options.columnOffset)), + JSC::StringSourceProvider::create(sourceString, JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(options.filename)), options.filename, JSC::SourceTaintedOrigin::Untainted, TextPosition(options.lineOffset, options.columnOffset)), options.lineOffset.zeroBasedInt(), options.columnOffset.zeroBasedInt()); auto* zigGlobal = reinterpret_cast<Zig::GlobalObject*>(globalObject); JSObject* context = asObject(contextObjectValue); @@ -501,6 +502,7 @@ public: template<typename CellType, SubspaceAccess> static GCClient::IsoSubspace* subspaceFor(VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(NodeVMScriptPrototype, Base); return &vm.plainObjectSpace(); } static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) diff --git a/src/bun.js/bindings/Path.cpp b/src/bun.js/bindings/Path.cpp index 808613b0c..6507b7122 100644 --- a/src/bun.js/bindings/Path.cpp +++ b/src/bun.js/bindings/Path.cpp @@ -173,7 +173,7 @@ static JSC::JSObject* createPath(JSGlobalObject* globalThis, bool isWindows) JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject*>(globalThis), 0, "relative"_s, Path_functionRelative, ImplementationVisibility::Public), 0); - path->putDirect(vm, clientData->builtinNames().resolvePublicName(), + path->putDirect(vm, vm.propertyNames->resolve, JSC::JSFunction::create(vm, JSC::jsCast<JSC::JSGlobalObject*>(globalThis), 0, "resolve"_s, Path_functionResolve, ImplementationVisibility::Public), 0); diff --git a/src/bun.js/bindings/Process.cpp b/src/bun.js/bindings/Process.cpp index 282cf6460..6fbc797cd 100644 --- a/src/bun.js/bindings/Process.cpp +++ b/src/bun.js/bindings/Process.cpp @@ -20,6 +20,8 @@ #include <errno.h> #include <sys/ioctl.h> #include "JSNextTickQueue.h" +#include "ProcessBindingUV.h" +#include "ProcessBindingNatives.h" #pragma mark - Node.js Process @@ -39,11 +41,11 @@ #include <unistd.h> // setuid, getuid #endif -namespace Zig { +namespace Bun { using namespace JSC; -#define REPORTED_NODE_VERSION "18.15.0" +#define REPORTED_NODE_VERSION "20.8.0" #define processObjectBindingCodeGenerator processObjectInternalsBindingCodeGenerator #define processObjectMainModuleCodeGenerator moduleMainCodeGenerator @@ -226,7 +228,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionDlopen, } } - JSC::EncodedJSValue (*napi_register_module_v1)(JSC::JSGlobalObject * globalObject, + JSC::EncodedJSValue (*napi_register_module_v1)(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue exports); napi_register_module_v1 = reinterpret_cast<JSC::EncodedJSValue (*)(JSC::JSGlobalObject*, @@ -618,7 +620,7 @@ static void onDidChangeListeners(EventEmitter& eventEmitter, const Identifier& e continue; JSGlobalObject* lexicalGlobalObject = context->jsGlobalObject(); - Zig::GlobalObject* globalObject = static_cast<Zig::GlobalObject*>(lexicalGlobalObject); + Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(lexicalGlobalObject); Process* process = jsCast<Process*>(globalObject->processObject()); @@ -677,7 +679,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionAbort, (JSGlobalObject * globalObject, JSC_DEFINE_HOST_FUNCTION(Process_emitWarning, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { - Zig::GlobalObject* globalObject = static_cast<Zig::GlobalObject*>(lexicalGlobalObject); + Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(lexicalGlobalObject); VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); @@ -747,8 +749,8 @@ JSC_DEFINE_CUSTOM_SETTER(setProcessExitCode, (JSC::JSGlobalObject * lexicalGloba int exitCodeInt = exitCode.toInt32(lexicalGlobalObject); RETURN_IF_EXCEPTION(throwScope, false); - if (exitCodeInt < 0 || exitCodeInt > 127) { - throwRangeError(lexicalGlobalObject, throwScope, "exitCode must be between 0 and 127"_s); + if (exitCodeInt < 0 || exitCodeInt > 255) { + throwRangeError(lexicalGlobalObject, throwScope, "exitCode must be between 0 and 255"_s); return false; } @@ -808,12 +810,12 @@ static JSValue constructVersions(VM& vm, JSObject* processObject) object->putDirect(vm, JSC::Identifier::fromString(vm, "usockets"_s), JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_usockets))), 0); - object->putDirect(vm, JSC::Identifier::fromString(vm, "v8"_s), JSValue(JSC::jsString(vm, makeString("10.8.168.20-node.8"_s))), 0); - object->putDirect(vm, JSC::Identifier::fromString(vm, "uv"_s), JSValue(JSC::jsString(vm, makeString("1.44.2"_s))), 0); - object->putDirect(vm, JSC::Identifier::fromString(vm, "napi"_s), JSValue(JSC::jsString(vm, makeString("8"_s))), 0); + object->putDirect(vm, JSC::Identifier::fromString(vm, "v8"_s), JSValue(JSC::jsString(vm, makeString("11.3.244.8-node.15"_s))), 0); + object->putDirect(vm, JSC::Identifier::fromString(vm, "uv"_s), JSValue(JSC::jsString(vm, makeString("1.46.0"_s))), 0); + object->putDirect(vm, JSC::Identifier::fromString(vm, "napi"_s), JSValue(JSC::jsString(vm, makeString("9"_s))), 0); object->putDirect(vm, JSC::Identifier::fromString(vm, "modules"_s), - JSC::JSValue(JSC::jsString(vm, makeAtomString("108")))); + JSC::JSValue(JSC::jsString(vm, makeAtomString("115")))); return object; } @@ -950,7 +952,7 @@ static JSValue constructProcessSend(VM& vm, JSObject* processObject) if (Bun__GlobalObject__hasIPC(globalObject)) { return JSC::JSFunction::create(vm, globalObject, 1, String("send"_s), Bun__Process__send, ImplementationVisibility::Public); } else { - return jsNumber(4); + return jsUndefined(); } } @@ -1121,6 +1123,91 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionAssert, (JSGlobalObject * globalObject, return JSValue::encode(jsUndefined()); } +#define PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE(str, issue) \ + { \ + throwScope.throwException(globalObject, createError(globalObject, String("process.binding(\"" str "\") is not implemented in Bun. Track the status & thumbs up the issue: https://github.com/oven-sh/bun/issues/" issue ""_s))); \ + return JSValue::encode(JSValue {}); \ + } + +#define PROCESS_BINDING_NOT_IMPLEMENTED(str) \ + { \ + throwScope.throwException(globalObject, createError(globalObject, String("process.binding(\"" str "\") is not implemented in Bun. If that breaks something, please file an issue and include a reproducible code sample."_s))); \ + return JSValue::encode(JSValue {}); \ + } + +inline JSValue processBindingUtil(Zig::GlobalObject* globalObject, JSC::VM& vm) +{ + auto& builtinNames = WebCore::builtinNames(vm); + auto fn = globalObject->getDirect(vm, builtinNames.requireNativeModulePrivateName()); + auto callData = JSC::getCallData(fn); + JSC::MarkedArgumentBuffer args; + args.append(jsString(vm, String("util/types"_s))); + return JSC::call(globalObject, fn, callData, globalObject, args); +} + +inline JSValue processBindingConfig(Zig::GlobalObject* globalObject, JSC::VM& vm) +{ + auto config = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 9); +#ifdef BUN_DEBUG + config->putDirect(vm, Identifier::fromString(vm, "isDebugBuild"_s), jsBoolean(true), 0); +#else + config->putDirect(vm, Identifier::fromString(vm, "isDebugBuild"_s), jsBoolean(false), 0); +#endif + config->putDirect(vm, Identifier::fromString(vm, "hasOpenSSL"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "fipsMode"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasIntl"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasTracing"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasNodeOptions"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasInspector"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "noBrowserGlobals"_s), jsBoolean(false), 0); + config->putDirect(vm, Identifier::fromString(vm, "bits"_s), jsNumber(64), 0); + return config; +} + +JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * jsGlobalObject, CallFrame* callFrame)) +{ + auto& vm = jsGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto globalObject = jsCast<Zig::GlobalObject*>(jsGlobalObject); + auto process = jsCast<Process*>(globalObject->processObject()); + auto moduleName = callFrame->argument(0).toWTFString(globalObject); + + // clang-format off + if (moduleName == "async_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("async_wrap"); + if (moduleName == "buffer"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("buffer", "2020"); + if (moduleName == "cares_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("cares_wrap"); + if (moduleName == "config"_s) return JSValue::encode(processBindingConfig(globalObject, vm)); + if (moduleName == "constants"_s) return JSValue::encode(globalObject->processBindingConstants()); + if (moduleName == "contextify"_s) PROCESS_BINDING_NOT_IMPLEMENTED("contextify"); + if (moduleName == "crypto"_s) PROCESS_BINDING_NOT_IMPLEMENTED("crypto"); + if (moduleName == "fs"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("fs", "3546"); + if (moduleName == "fs_event_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("fs_event_wrap"); + if (moduleName == "http_parser"_s) PROCESS_BINDING_NOT_IMPLEMENTED("http_parser"); + if (moduleName == "icu"_s) PROCESS_BINDING_NOT_IMPLEMENTED("icu"); + if (moduleName == "inspector"_s) PROCESS_BINDING_NOT_IMPLEMENTED("inspector"); + if (moduleName == "js_stream"_s) PROCESS_BINDING_NOT_IMPLEMENTED("js_stream"); + if (moduleName == "natives"_s) return JSValue::encode(process->bindingNatives()); + if (moduleName == "os"_s) PROCESS_BINDING_NOT_IMPLEMENTED("os"); + if (moduleName == "pipe_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("pipe_wrap"); + if (moduleName == "process_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("process_wrap"); + if (moduleName == "signal_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("signal_wrap"); + if (moduleName == "spawn_sync"_s) PROCESS_BINDING_NOT_IMPLEMENTED("spawn_sync"); + if (moduleName == "stream_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("stream_wrap", "4957"); + if (moduleName == "tcp_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("tcp_wrap"); + if (moduleName == "tls_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("tls_wrap"); + if (moduleName == "tty_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("tty_wrap", "4694"); + if (moduleName == "udp_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("udp_wrap"); + if (moduleName == "url"_s) PROCESS_BINDING_NOT_IMPLEMENTED("url"); + if (moduleName == "util"_s) return JSValue::encode(processBindingUtil(globalObject, vm)); + if (moduleName == "uv"_s) return JSValue::encode(process->bindingUV()); + if (moduleName == "v8"_s) PROCESS_BINDING_NOT_IMPLEMENTED("v8"); + if (moduleName == "zlib"_s) PROCESS_BINDING_NOT_IMPLEMENTED("zlib"); + // clang-format on + + throwScope.throwException(globalObject, createError(globalObject, makeString("No such module: "_s, moduleName))); + return JSValue::encode(jsUndefined()); +} + JSC_DEFINE_HOST_FUNCTION(Process_functionReallyExit, (JSGlobalObject * globalObject, CallFrame* callFrame)) { auto& vm = globalObject->vm(); @@ -1158,8 +1245,10 @@ void Process::visitChildrenImpl(JSCell* cell, Visitor& visitor) Process* thisObject = jsCast<Process*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, info()); Base::visitChildren(thisObject, visitor); - thisObject->cpuUsageStructure.visit(visitor); - thisObject->memoryUsageStructure.visit(visitor); + thisObject->m_cpuUsageStructure.visit(visitor); + thisObject->m_memoryUsageStructure.visit(visitor); + thisObject->m_bindingUV.visit(visitor); + thisObject->m_bindingNatives.visit(visitor); } DEFINE_VISIT_CHILDREN(Process); @@ -1239,6 +1328,16 @@ static Process* getProcessObject(JSC::JSGlobalObject* lexicalGlobalObject, JSVal return process; } +JSC_DEFINE_HOST_FUNCTION(Process_functionConstrainedMemory, + (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ +#if OS(LINUX) || OS(FREEBSD) + return JSValue::encode(jsDoubleNumber(static_cast<double>(WTF::ramSize()))); +#else + return JSValue::encode(jsUndefined()); +#endif +} + JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { @@ -1252,7 +1351,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionCpuUsage, auto* process = getProcessObject(globalObject, callFrame->thisValue()); - Structure* cpuUsageStructure = process->cpuUsageStructure.getInitializedOnMainThread(process); + Structure* cpuUsageStructure = process->cpuUsageStructure(); constexpr double MICROS_PER_SEC = 1000000.0; @@ -1405,7 +1504,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionMemoryUsage, return JSC::JSValue::encode(JSC::JSValue {}); } - JSC::JSObject* result = JSC::constructEmptyObject(vm, process->memoryUsageStructure.getInitializedOnMainThread(process)); + JSC::JSObject* result = JSC::constructEmptyObject(vm, process->memoryUsageStructure()); if (UNLIKELY(throwScope.exception())) { return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1525,7 +1624,7 @@ static JSValue constructMemoryUsage(VM& vm, JSObject* processObject) JSC::JSFunction* rss = JSC::JSFunction::create(vm, globalObject, 0, String("rss"_s), Process_functionMemoryUsageRSS, ImplementationVisibility::Public); - memoryUsage->putDirect(vm, JSC::Identifier::fromString(vm, "rss"_s), rss, JSC::PropertyAttribute::Function | 0); + memoryUsage->putDirect(vm, JSC::Identifier::fromString(vm, "rss"_s), rss, 0); return memoryUsage; } @@ -1548,14 +1647,14 @@ static JSValue constructProcessNextTickFn(VM& vm, JSObject* processObject) Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(lexicalGlobalObject); JSValue nextTickQueueObject; if (!globalObject->m_nextTickQueue) { - Bun::JSNextTickQueue* queue = Bun::JSNextTickQueue::create(globalObject); - globalObject->m_nextTickQueue.set(vm, globalObject, queue); - nextTickQueueObject = queue; + nextTickQueueObject = Bun::JSNextTickQueue::create(globalObject); + globalObject->m_nextTickQueue.set(vm, globalObject, nextTickQueueObject); } else { nextTickQueueObject = jsCast<Bun::JSNextTickQueue*>(globalObject->m_nextTickQueue.get()); } JSC::JSFunction* initializer = JSC::JSFunction::create(vm, processObjectInternalsInitializeNextTickQueueCodeGenerator(vm), lexicalGlobalObject); + JSC::MarkedArgumentBuffer args; args.append(processObject); args.append(nextTickQueueObject); @@ -1736,7 +1835,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionKill, return JSValue::encode(jsUndefined()); } - return JSValue::encode(jsUndefined()); + return JSValue::encode(jsBoolean(true)); } extern "C" void Process__emitMessageEvent(Zig::GlobalObject* global, EncodedJSValue value) @@ -1770,11 +1869,12 @@ extern "C" void Process__emitDisconnectEvent(Zig::GlobalObject* global) argv constructArgv PropertyCallback argv0 constructArgv0 PropertyCallback assert Process_functionAssert Function 1 - binding JSBuiltin Function 1 + binding Process_functionBinding Function 1 browser constructBrowser PropertyCallback chdir Process_functionChdir Function 1 config constructProcessConfigObject PropertyCallback connected processConnected CustomAccessor + constrainedMemory Process_functionConstrainedMemory Function 0 cpuUsage Process_functionCpuUsage Function 1 cwd Process_functionCwd Function 1 debugPort processDebugPort CustomAccessor @@ -1831,7 +1931,6 @@ extern "C" void Process__emitDisconnectEvent(Zig::GlobalObject* global) _kill Process_functionReallyKill Function 2 @end */ - #include "Process.lut.h" const JSC::ClassInfo Process::s_info = { "Process"_s, &Base::s_info, &processObjectTable, nullptr, CREATE_METHOD_TABLE(Process) }; @@ -1840,17 +1939,24 @@ void Process::finishCreation(JSC::VM& vm) { Base::finishCreation(vm); - this->wrapped().onDidChangeListener = &onDidChangeListeners; + wrapped().onDidChangeListener = &onDidChangeListeners; - this->cpuUsageStructure.initLater([](const JSC::LazyProperty<JSC::JSObject, JSC::Structure>::Initializer& init) { + m_cpuUsageStructure.initLater([](const JSC::LazyProperty<Process, JSC::Structure>::Initializer& init) { init.set(constructCPUUsageStructure(init.vm, init.owner->globalObject())); }); - this->memoryUsageStructure.initLater([](const JSC::LazyProperty<JSC::JSObject, JSC::Structure>::Initializer& init) { + m_memoryUsageStructure.initLater([](const JSC::LazyProperty<Process, JSC::Structure>::Initializer& init) { init.set(constructMemoryUsageStructure(init.vm, init.owner->globalObject())); }); - this->putDirect(vm, vm.propertyNames->toStringTagSymbol, jsString(vm, String("process"_s)), 0); + m_bindingUV.initLater([](const JSC::LazyProperty<Process, JSC::JSObject>::Initializer& init) { + init.set(Bun::ProcessBindingUV::create(init.vm, init.owner->globalObject())); + }); + m_bindingNatives.initLater([](const JSC::LazyProperty<Process, JSC::JSObject>::Initializer& init) { + init.set(Bun::ProcessBindingNatives::create(init.vm, ProcessBindingNatives::createStructure(init.vm, init.owner->globalObject()))); + }); + + putDirect(vm, vm.propertyNames->toStringTagSymbol, jsString(vm, String("process"_s)), 0); } -} // namespace Zig +} // namespace Bun diff --git a/src/bun.js/bindings/Process.h b/src/bun.js/bindings/Process.h index ab344c7fe..1615aabdd 100644 --- a/src/bun.js/bindings/Process.h +++ b/src/bun.js/bindings/Process.h @@ -6,7 +6,7 @@ #include "BunClientData.h" #include "JSEventEmitter.h" -namespace Zig { +namespace Bun { // TODO: find a better place for this int getRSS(size_t* rss); @@ -16,6 +16,11 @@ using namespace JSC; class Process : public WebCore::JSEventEmitter { using Base = WebCore::JSEventEmitter; + LazyProperty<Process, Structure> m_cpuUsageStructure; + LazyProperty<Process, Structure> m_memoryUsageStructure; + LazyProperty<Process, JSObject> m_bindingUV; + LazyProperty<Process, JSObject> m_bindingNatives; + public: Process(JSC::Structure* structure, WebCore::JSDOMGlobalObject& globalObject, Ref<WebCore::EventEmitter>&& impl) : Base(structure, globalObject, WTFMove(impl)) @@ -50,9 +55,6 @@ public: return accessor; } - LazyProperty<JSObject, Structure> cpuUsageStructure; - LazyProperty<JSObject, Structure> memoryUsageStructure; - DECLARE_VISIT_CHILDREN; template<typename, SubspaceAccess mode> @@ -69,6 +71,11 @@ public: } void finishCreation(JSC::VM& vm); + + inline Structure* cpuUsageStructure() { return m_cpuUsageStructure.getInitializedOnMainThread(this); } + inline Structure* memoryUsageStructure() { return m_memoryUsageStructure.getInitializedOnMainThread(this); } + inline JSObject* bindingUV() { return m_bindingUV.getInitializedOnMainThread(this); } + inline JSObject* bindingNatives() { return m_bindingNatives.getInitializedOnMainThread(this); } }; -} // namespace Zig
\ No newline at end of file +} // namespace Bun
\ No newline at end of file diff --git a/src/bun.js/bindings/Process.lut.h b/src/bun.js/bindings/Process.lut.h index dda54ff01..6016466c2 100644 --- a/src/bun.js/bindings/Process.lut.h +++ b/src/bun.js/bindings/Process.lut.h @@ -1,6 +1,6 @@ -// File generated via `make generate-builtins` -static const struct CompactHashIndex processObjectTableIndex[267] = { - { 47, -1 }, +// File generated via `make static-hash-table` / `make cpp` +static const struct CompactHashIndex processObjectTableIndex[268] = { + { 48, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -14,9 +14,9 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 20, -1 }, + { 21, -1 }, { -1, -1 }, - { 49, -1 }, + { 50, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -41,14 +41,14 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 34, -1 }, + { 35, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 29, -1 }, - { 13, -1 }, + { 30, -1 }, + { 14, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -57,11 +57,11 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 59, -1 }, + { 60, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 55, -1 }, + { 56, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -75,36 +75,36 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 43, -1 }, + { 44, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { 0, -1 }, - { 28, -1 }, - { 37, -1 }, - { 42, -1 }, + { 29, -1 }, + { 38, -1 }, + { 43, -1 }, { -1, -1 }, - { 25, -1 }, - { 12, -1 }, + { 26, -1 }, + { 13, -1 }, { -1, -1 }, { -1, -1 }, - { 62, -1 }, + { 63, -1 }, { -1, -1 }, { -1, -1 }, - { 33, -1 }, - { 44, -1 }, + { 34, -1 }, + { 45, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 26, -1 }, + { 27, -1 }, { -1, -1 }, { -1, -1 }, - { 22, -1 }, + { 23, -1 }, { -1, -1 }, { 5, -1 }, { -1, -1 }, - { 64, -1 }, + { 65, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -115,19 +115,19 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 27, 261 }, + { 28, 262 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 23, 262 }, + { 24, 263 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 50, 265 }, + { 51, 266 }, { -1, -1 }, - { 19, -1 }, + { 20, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -139,10 +139,10 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 17, 257 }, + { 18, 257 }, { -1, -1 }, - { 14, -1 }, - { 57, -1 }, + { 15, -1 }, + { 58, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -161,12 +161,12 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 3, 266 }, + { 3, 267 }, { 1, -1 }, { -1, -1 }, - { 63, -1 }, + { 64, -1 }, { -1, -1 }, - { 11, -1 }, + { 12, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -174,24 +174,24 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 56, -1 }, + { 57, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { 10, 256 }, { -1, -1 }, - { 16, 263 }, + { 17, 264 }, { -1, -1 }, - { 39, -1 }, + { 40, -1 }, { -1, -1 }, - { 41, -1 }, + { 42, -1 }, { -1, -1 }, - { 38, -1 }, - { 6, 264 }, + { 11, 260 }, + { 6, 265 }, { -1, -1 }, { -1, -1 }, { 4, -1 }, - { 51, -1 }, + { 52, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -205,11 +205,11 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 31, 260 }, + { 32, 261 }, { -1, -1 }, { -1, -1 }, - { 48, -1 }, - { 18, 258 }, + { 49, -1 }, + { 19, 258 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -219,10 +219,10 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 53, -1 }, + { 54, -1 }, { -1, -1 }, - { 32, -1 }, - { 24, -1 }, + { 33, -1 }, + { 25, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -233,12 +233,12 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 52, -1 }, + { 53, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 15, 259 }, + { 16, 259 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, @@ -256,31 +256,33 @@ static const struct CompactHashIndex processObjectTableIndex[267] = { { -1, -1 }, { -1, -1 }, { -1, -1 }, - { 21, -1 }, - { 30, -1 }, - { 35, -1 }, + { 22, -1 }, + { 31, -1 }, { 36, -1 }, - { 40, -1 }, - { 45, -1 }, + { 37, -1 }, + { 39, -1 }, + { 41, -1 }, { 46, -1 }, - { 54, -1 }, - { 58, -1 }, - { 60, -1 }, + { 47, -1 }, + { 55, -1 }, + { 59, -1 }, { 61, -1 }, + { 62, -1 }, }; -static const struct HashTableValue processObjectTableValues[65] = { +static const struct HashTableValue processObjectTableValues[66] = { { "abort"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionAbort, 1 } }, { "allowedNodeEnvironmentFlags"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, Process_stubEmptySet } }, { "arch"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructArch } }, { "argv"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructArgv } }, { "argv0"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructArgv0 } }, { "assert"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionAssert, 1 } }, - { "binding"_s, ((static_cast<unsigned>(PropertyAttribute::Function)) & ~PropertyAttribute::Function) | PropertyAttribute::Builtin, NoIntrinsic, { HashTableValue::BuiltinGeneratorType, processObjectBindingCodeGenerator, 1 } }, + { "binding"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionBinding, 1 } }, { "browser"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructBrowser } }, { "chdir"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionChdir, 1 } }, { "config"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, constructProcessConfigObject } }, { "connected"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, processConnected, setProcessConnected } }, + { "constrainedMemory"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionConstrainedMemory, 0 } }, { "cpuUsage"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionCpuUsage, 1 } }, { "cwd"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Process_functionCwd, 1 } }, { "debugPort"_s, static_cast<unsigned>(PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, processDebugPort, setProcessDebugPort } }, @@ -338,4 +340,4 @@ static const struct HashTableValue processObjectTableValues[65] = { }; static const struct HashTable processObjectTable = - { 65, 255, true, nullptr, processObjectTableValues, processObjectTableIndex }; + { 66, 255, true, nullptr, processObjectTableValues, processObjectTableIndex }; diff --git a/src/bun.js/bindings/ProcessBindingConstants.cpp b/src/bun.js/bindings/ProcessBindingConstants.cpp index 36a4a7f96..8544b2f20 100644 --- a/src/bun.js/bindings/ProcessBindingConstants.cpp +++ b/src/bun.js/bindings/ProcessBindingConstants.cpp @@ -685,9 +685,6 @@ static JSValue processBindingConstantsGetFs(VM& vm, JSObject* bindingObject) #ifdef O_DIRECTORY object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_DIRECTORY"_s)), jsNumber(O_DIRECTORY)); #endif -#ifdef O_EXCL - object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_EXCL"_s)), jsNumber(O_EXCL)); -#endif #ifdef O_NOATIME object->putDirect(vm, PropertyName(Identifier::fromString(vm, "O_NOATIME"_s)), jsNumber(O_NOATIME)); #endif @@ -1082,15 +1079,18 @@ static JSValue processBindingConstantsGetZlib(VM& vm, JSObject* bindingObject) return object; } -static const HashTableValue ProcessBindingConstantsValues[] = { - { "os"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetOs } }, - { "fs"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetFs } }, - { "crypto"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetCrypto } }, - { "zlib"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetZlib } }, - { "trace"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetTrace } }, -}; +/* Source for ProcessBindingConstants.lut.h +@begin processBindingConstantsTable + os processBindingConstantsGetOs PropertyCallback + fs processBindingConstantsGetFs PropertyCallback + crypto processBindingConstantsGetCrypto PropertyCallback + zlib processBindingConstantsGetZlib PropertyCallback + trace processBindingConstantsGetTrace PropertyCallback +@end +*/ +#include "ProcessBindingConstants.lut.h" -const ClassInfo ProcessBindingConstants::s_info = { "ProcessBindingConstants"_s, Base::info(), nullptr, nullptr, CREATE_METHOD_TABLE(ProcessBindingConstants) }; +const ClassInfo ProcessBindingConstants::s_info = { "ProcessBindingConstants"_s, &Base::s_info, &processBindingConstantsTable, nullptr, CREATE_METHOD_TABLE(ProcessBindingConstants) }; ProcessBindingConstants* ProcessBindingConstants::create(VM& vm, Structure* structure) { @@ -1107,8 +1107,7 @@ Structure* ProcessBindingConstants::createStructure(VM& vm, JSGlobalObject* glob void ProcessBindingConstants::finishCreation(JSC::VM& vm) { Base::finishCreation(vm); - reifyStaticProperties(vm, ProcessBindingConstants::info(), ProcessBindingConstantsValues, *this); - ASSERT(inherits(vm, info())); + ASSERT(inherits(info())); } template<typename Visitor> diff --git a/src/bun.js/bindings/ProcessBindingConstants.h b/src/bun.js/bindings/ProcessBindingConstants.h index 5a9be7ce7..6115534a0 100644 --- a/src/bun.js/bindings/ProcessBindingConstants.h +++ b/src/bun.js/bindings/ProcessBindingConstants.h @@ -1,3 +1,4 @@ +#pragma once #include "root.h" namespace Bun { @@ -11,12 +12,15 @@ public: using Base = JSC::JSNonFinalObject; + static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable; + static ProcessBindingConstants* create(JSC::VM& vm, JSC::Structure* structure); static Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject); template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ProcessBindingConstants, Base); return &vm.plainObjectSpace(); } diff --git a/src/bun.js/bindings/ProcessBindingConstants.lut.h b/src/bun.js/bindings/ProcessBindingConstants.lut.h new file mode 100644 index 000000000..4ad86860d --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingConstants.lut.h @@ -0,0 +1,31 @@ +// File generated via `make static-hash-table` / `make cpp` +static const struct CompactHashIndex processBindingConstantsTableIndex[17] = { + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 2, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 0, 16 }, + { -1, -1 }, + { -1, -1 }, + { 4, -1 }, + { 3, -1 }, +}; + +static const struct HashTableValue processBindingConstantsTableValues[5] = { + { "os"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetOs } }, + { "fs"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetFs } }, + { "crypto"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetCrypto } }, + { "zlib"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetZlib } }, + { "trace"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingConstantsGetTrace } }, +}; + +static const struct HashTable processBindingConstantsTable = + { 5, 15, false, nullptr, processBindingConstantsTableValues, processBindingConstantsTableIndex }; diff --git a/src/bun.js/bindings/ProcessBindingNatives.cpp b/src/bun.js/bindings/ProcessBindingNatives.cpp new file mode 100644 index 000000000..2a2685524 --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingNatives.cpp @@ -0,0 +1,131 @@ +// Modelled off of https://github.com/nodejs/node/blob/main/src/node_constants.cc +// Note that if you change any of this code, you probably also have to change NodeConstantsModule.h +#include "ProcessBindingNatives.h" +#include "JavaScriptCore/ObjectConstructor.h" + +namespace Bun { +using namespace JSC; + +static JSValue processBindingNativesGetter(VM& vm, JSObject* bindingObject) +{ + // Instead of actually returning our source code, we just return a dummy string. + // Most people just use `process.binding('natives')` to get a list of builtin modules + // We also don't report internal modules. + // If any of this breaks your package, please open an issue. + return jsString(vm, String("/* [native code] */"_s)); +} + +static JSValue processBindingNativesReturnUndefined(VM& vm, JSObject* bindingObject) +{ + // process.binding('natives').config === undefined + return jsUndefined(); +} + +/* Source for ProcessBindingNatives.lut.h +@begin processBindingNativesTable + _http_agent processBindingNativesGetter PropertyCallback + _http_client processBindingNativesGetter PropertyCallback + _http_common processBindingNativesGetter PropertyCallback + _http_incoming processBindingNativesGetter PropertyCallback + _http_outgoing processBindingNativesGetter PropertyCallback + _http_server processBindingNativesGetter PropertyCallback + _stream_duplex processBindingNativesGetter PropertyCallback + _stream_passthrough processBindingNativesGetter PropertyCallback + _stream_readable processBindingNativesGetter PropertyCallback + _stream_transform processBindingNativesGetter PropertyCallback + _stream_wrap processBindingNativesGetter PropertyCallback + _stream_writable processBindingNativesGetter PropertyCallback + _tls_common processBindingNativesGetter PropertyCallback + _tls_wrap processBindingNativesGetter PropertyCallback + assert processBindingNativesGetter PropertyCallback + assert/strict processBindingNativesGetter PropertyCallback + async_hooks processBindingNativesGetter PropertyCallback + buffer processBindingNativesGetter PropertyCallback + child_process processBindingNativesGetter PropertyCallback + cluster processBindingNativesGetter PropertyCallback + console processBindingNativesGetter PropertyCallback + constants processBindingNativesGetter PropertyCallback + crypto processBindingNativesGetter PropertyCallback + dgram processBindingNativesGetter PropertyCallback + diagnostics_channel processBindingNativesGetter PropertyCallback + dns processBindingNativesGetter PropertyCallback + dns/promises processBindingNativesGetter PropertyCallback + domain processBindingNativesGetter PropertyCallback + events processBindingNativesGetter PropertyCallback + fs processBindingNativesGetter PropertyCallback + fs/promises processBindingNativesGetter PropertyCallback + http processBindingNativesGetter PropertyCallback + http2 processBindingNativesGetter PropertyCallback + https processBindingNativesGetter PropertyCallback + inspector processBindingNativesGetter PropertyCallback + inspector/promises processBindingNativesGetter PropertyCallback + module processBindingNativesGetter PropertyCallback + net processBindingNativesGetter PropertyCallback + os processBindingNativesGetter PropertyCallback + path processBindingNativesGetter PropertyCallback + path/posix processBindingNativesGetter PropertyCallback + path/win32 processBindingNativesGetter PropertyCallback + perf_hooks processBindingNativesGetter PropertyCallback + process processBindingNativesGetter PropertyCallback + punycode processBindingNativesGetter PropertyCallback + querystring processBindingNativesGetter PropertyCallback + readline processBindingNativesGetter PropertyCallback + readline/promises processBindingNativesGetter PropertyCallback + repl processBindingNativesGetter PropertyCallback + stream processBindingNativesGetter PropertyCallback + stream/consumers processBindingNativesGetter PropertyCallback + stream/promises processBindingNativesGetter PropertyCallback + stream/web processBindingNativesGetter PropertyCallback + string_decoder processBindingNativesGetter PropertyCallback + sys processBindingNativesGetter PropertyCallback + test processBindingNativesGetter PropertyCallback + test/reporters processBindingNativesGetter PropertyCallback + timers processBindingNativesGetter PropertyCallback + timers/promises processBindingNativesGetter PropertyCallback + tls processBindingNativesGetter PropertyCallback + trace_events processBindingNativesGetter PropertyCallback + tty processBindingNativesGetter PropertyCallback + url processBindingNativesGetter PropertyCallback + util processBindingNativesGetter PropertyCallback + util/types processBindingNativesGetter PropertyCallback + v8 processBindingNativesGetter PropertyCallback + vm processBindingNativesGetter PropertyCallback + wasi processBindingNativesGetter PropertyCallback + worker_threads processBindingNativesGetter PropertyCallback + zlib processBindingNativesGetter PropertyCallback + configs processBindingNativesReturnUndefined PropertyCallback +@end +*/ +#include "ProcessBindingNatives.lut.h" + +const ClassInfo ProcessBindingNatives::s_info = { "ProcessBindingNatives"_s, &Base::s_info, &processBindingNativesTable, nullptr, CREATE_METHOD_TABLE(ProcessBindingNatives) }; + +ProcessBindingNatives* ProcessBindingNatives::create(VM& vm, Structure* structure) +{ + ProcessBindingNatives* obj = new (NotNull, allocateCell<ProcessBindingNatives>(vm)) ProcessBindingNatives(vm, structure); + obj->finishCreation(vm); + return obj; +} + +Structure* ProcessBindingNatives::createStructure(VM& vm, JSGlobalObject* globalObject) +{ + return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), ProcessBindingNatives::info()); +} + +void ProcessBindingNatives::finishCreation(JSC::VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); +} + +template<typename Visitor> +void ProcessBindingNatives::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + ProcessBindingNatives* thisObject = jsCast<ProcessBindingNatives*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); +} + +DEFINE_VISIT_CHILDREN(ProcessBindingNatives); + +} // namespace Bun diff --git a/src/bun.js/bindings/ProcessBindingNatives.h b/src/bun.js/bindings/ProcessBindingNatives.h new file mode 100644 index 000000000..bbeaaa524 --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingNatives.h @@ -0,0 +1,36 @@ +#pragma once +#include "root.h" + +namespace Bun { +using namespace JSC; + +// The object returned from process.binding('natives') +class ProcessBindingNatives final : public JSC::JSNonFinalObject { +public: + DECLARE_INFO; + DECLARE_VISIT_CHILDREN; + + using Base = JSC::JSNonFinalObject; + + static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable; + + static ProcessBindingNatives* create(JSC::VM& vm, JSC::Structure* structure); + static Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject); + + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ProcessBindingNatives, Base); + return &vm.plainObjectSpace(); + } + +private: + void finishCreation(JSC::VM& vm); + + ProcessBindingNatives(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } +}; + +} // namespace Bun diff --git a/src/bun.js/bindings/ProcessBindingNatives.lut.h b/src/bun.js/bindings/ProcessBindingNatives.lut.h new file mode 100644 index 000000000..2bc7e34f5 --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingNatives.lut.h @@ -0,0 +1,339 @@ +// File generated via `make static-hash-table` / `make cpp` +static const struct CompactHashIndex processBindingNativesTableIndex[259] = { + { 11, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 16, -1 }, + { 40, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 17, -1 }, + { -1, -1 }, + { -1, -1 }, + { 18, -1 }, + { -1, -1 }, + { 59, -1 }, + { -1, -1 }, + { 58, -1 }, + { 29, -1 }, + { -1, -1 }, + { 12, -1 }, + { 56, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 64, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 63, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 61, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 50, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 35, -1 }, + { 42, -1 }, + { 55, -1 }, + { -1, -1 }, + { -1, -1 }, + { 66, -1 }, + { -1, -1 }, + { 52, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 60, -1 }, + { -1, -1 }, + { 41, -1 }, + { 21, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 47, -1 }, + { 30, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 15, -1 }, + { 70, -1 }, + { 26, -1 }, + { -1, -1 }, + { -1, -1 }, + { 54, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 51, -1 }, + { -1, -1 }, + { 2, -1 }, + { 28, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 14, -1 }, + { -1, -1 }, + { -1, -1 }, + { 27, -1 }, + { -1, -1 }, + { 37, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 36, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 1, -1 }, + { -1, -1 }, + { 3, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 19, -1 }, + { -1, -1 }, + { 10, -1 }, + { -1, -1 }, + { -1, -1 }, + { 8, 257 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 43, -1 }, + { -1, -1 }, + { -1, -1 }, + { 5, -1 }, + { -1, -1 }, + { 62, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 57, -1 }, + { 38, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 6, 256 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 22, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 0, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 48, -1 }, + { -1, -1 }, + { -1, -1 }, + { 4, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 32, -1 }, + { -1, -1 }, + { 31, -1 }, + { 49, -1 }, + { 34, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 68, -1 }, + { -1, -1 }, + { -1, -1 }, + { 69, -1 }, + { 33, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 9, -1 }, + { 44, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 23, -1 }, + { -1, -1 }, + { 7, -1 }, + { 67, -1 }, + { -1, -1 }, + { 24, -1 }, + { 25, -1 }, + { -1, -1 }, + { -1, -1 }, + { 20, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 65, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 46, -1 }, + { -1, -1 }, + { 45, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 13, -1 }, + { 39, 258 }, + { 53, -1 }, +}; + +static const struct HashTableValue processBindingNativesTableValues[71] = { + { "_http_agent"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_http_client"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_http_common"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_http_incoming"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_http_outgoing"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_http_server"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_stream_duplex"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_stream_passthrough"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_stream_readable"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_stream_transform"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_stream_wrap"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_stream_writable"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_tls_common"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "_tls_wrap"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "assert"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "assert/strict"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "async_hooks"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "buffer"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "child_process"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "cluster"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "console"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "constants"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "crypto"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "dgram"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "diagnostics_channel"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "dns"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "dns/promises"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "domain"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "events"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "fs"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "fs/promises"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "http"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "http2"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "https"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "inspector"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "inspector/promises"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "module"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "net"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "os"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "path"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "path/posix"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "path/win32"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "perf_hooks"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "process"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "punycode"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "querystring"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "readline"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "readline/promises"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "repl"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "stream"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "stream/consumers"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "stream/promises"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "stream/web"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "string_decoder"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "sys"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "test"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "test/reporters"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "timers"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "timers/promises"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "tls"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "trace_events"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "tty"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "url"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "util"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "util/types"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "v8"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "vm"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "wasi"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "worker_threads"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "zlib"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesGetter } }, + { "configs"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, processBindingNativesReturnUndefined } }, +}; + +static const struct HashTable processBindingNativesTable = + { 71, 255, false, nullptr, processBindingNativesTableValues, processBindingNativesTableIndex }; diff --git a/src/bun.js/bindings/ProcessBindingUV.cpp b/src/bun.js/bindings/ProcessBindingUV.cpp new file mode 100644 index 000000000..8173072a9 --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingUV.cpp @@ -0,0 +1,158 @@ +#include "ProcessBindingUV.h" +#include "ZigGlobalObject.h" +#include "JavaScriptCore/ObjectConstructor.h" +#include "JavaScriptCore/JSMap.h" +#include "JavaScriptCore/JSMapInlines.h" + +// clang-format off + +#define UV_ERRNO_MAP(macro) \ + macro(E2BIG, -7, "argument list too long") \ + macro(EACCES, -13, "permission denied") \ + macro(EADDRINUSE, -48, "address already in use") \ + macro(EADDRNOTAVAIL, -49, "address not available") \ + macro(EAFNOSUPPORT, -47, "address family not supported") \ + macro(EAGAIN, -35, "resource temporarily unavailable") \ + macro(EAI_ADDRFAMILY, -3000, "address family not supported") \ + macro(EAI_AGAIN, -3001, "temporary failure") \ + macro(EAI_BADFLAGS, -3002, "bad ai_flags value") \ + macro(EAI_BADHINTS, -3013, "invalid value for hints") \ + macro(EAI_CANCELED, -3003, "request canceled") \ + macro(EAI_FAIL, -3004, "permanent failure") \ + macro(EAI_FAMILY, -3005, "ai_family not supported") \ + macro(EAI_MEMORY, -3006, "out of memory") \ + macro(EAI_NODATA, -3007, "no address") \ + macro(EAI_NONAME, -3008, "unknown node or service") \ + macro(EAI_OVERFLOW, -3009, "argument buffer overflow") \ + macro(EAI_PROTOCOL, -3014, "resolved protocol is unknown") \ + macro(EAI_SERVICE, -3010, "service not available for socket type") \ + macro(EAI_SOCKTYPE, -3011, "socket type not supported") \ + macro(EALREADY, -37, "connection already in progress") \ + macro(EBADF, -9, "bad file descriptor") \ + macro(EBUSY, -16, "resource busy or locked") \ + macro(ECANCELED, -89, "operation canceled") \ + macro(ECHARSET, -4080, "invalid Unicode character") \ + macro(ECONNABORTED, -53, "software caused connection abort") \ + macro(ECONNREFUSED, -61, "connection refused") \ + macro(ECONNRESET, -54, "connection reset by peer") \ + macro(EDESTADDRREQ, -39, "destination address required") \ + macro(EEXIST, -17, "file already exists") \ + macro(EFAULT, -14, "bad address in system call argument") \ + macro(EFBIG, -27, "file too large") \ + macro(EHOSTUNREACH, -65, "host is unreachable") \ + macro(EINTR, -4, "interrupted system call") \ + macro(EINVAL, -22, "invalid argument") \ + macro(EIO, -5, "i/o error") \ + macro(EISCONN, -56, "socket is already connected") \ + macro(EISDIR, -21, "illegal operation on a directory") \ + macro(ELOOP, -62, "too many symbolic links encountered") \ + macro(EMFILE, -24, "too many open files") \ + macro(EMSGSIZE, -40, "message too long") \ + macro(ENAMETOOLONG, -63, "name too long") \ + macro(ENETDOWN, -50, "network is down") \ + macro(ENETUNREACH, -51, "network is unreachable") \ + macro(ENFILE, -23, "file table overflow") \ + macro(ENOBUFS, -55, "no buffer space available") \ + macro(ENODEV, -19, "no such device") \ + macro(ENOENT, -2, "no such file or directory") \ + macro(ENOMEM, -12, "not enough memory") \ + macro(ENONET, -4056, "machine is not on the network") \ + macro(ENOPROTOOPT, -42, "protocol not available") \ + macro(ENOSPC, -28, "no space left on device") \ + macro(ENOSYS, -78, "function not implemented") \ + macro(ENOTCONN, -57, "socket is not connected") \ + macro(ENOTDIR, -20, "not a directory") \ + macro(ENOTEMPTY, -66, "directory not empty") \ + macro(ENOTSOCK, -38, "socket operation on non-socket") \ + macro(ENOTSUP, -45, "operation not supported on socket") \ + macro(EOVERFLOW, -84, "value too large for defined data type") \ + macro(EPERM, -1, "operation not permitted") \ + macro(EPIPE, -32, "broken pipe") \ + macro(EPROTO, -100, "protocol error") \ + macro(EPROTONOSUPPORT, -43, "protocol not supported") \ + macro(EPROTOTYPE, -41, "protocol wrong type for socket") \ + macro(ERANGE, -34, "result too large") \ + macro(EROFS, -30, "read-only file system") \ + macro(ESHUTDOWN, -58, "cannot send after transport endpoint shutdown") \ + macro(ESPIPE, -29, "invalid seek") \ + macro(ESRCH, -3, "no such process") \ + macro(ETIMEDOUT, -60, "connection timed out") \ + macro(ETXTBSY, -26, "text file is busy") \ + macro(EXDEV, -18, "cross-device link not permitted") \ + macro(UNKNOWN, -4094, "unknown error") \ + macro(EOF, -4095, "end of file") \ + macro(ENXIO, -6, "no such device or address") \ + macro(EMLINK, -31, "too many links") \ + macro(EHOSTDOWN, -64, "host is down") \ + macro(EREMOTEIO, -4030, "remote I/O error") \ + macro(ENOTTY, -25, "inappropriate ioctl for device") \ + macro(EFTYPE, -79, "inappropriate file type or format") \ + macro(EILSEQ, -92, "illegal byte sequence") \ + macro(ESOCKTNOSUPPORT, -44, "socket type not supported") \ + macro(ENODATA, -96, "no data available") \ + macro(EUNATCH, -4023, "protocol driver not attache") + +// clang-format on +namespace Bun { +namespace ProcessBindingUV { + +JSC_DEFINE_HOST_FUNCTION(jsErrname, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + auto arg0 = callFrame->argument(0); + auto& vm = globalObject->vm(); + + // Node.js will actualy crash here, lol. + if (!arg0.isInt32()) + return JSValue::encode(jsString(vm, makeString("Unknown system error "_s, arg0.toWTFString(globalObject)))); + + auto err = arg0.asInt32(); + switch (err) { +#define CASE(name, value, desc) \ + case value: \ + return JSValue::encode(JSC::jsString(vm, String(#name##_s))); + + UV_ERRNO_MAP(CASE) +#undef CASE + } + + return JSValue::encode(jsString(vm, makeString("Unknown system error "_s, String::number(err)))); +} + +JSC_DEFINE_HOST_FUNCTION(jsGetErrorMap, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + auto& vm = globalObject->vm(); + auto map = JSC::JSMap::create(vm, globalObject->mapStructure()); + +#define PUT_PROPERTY(name, value, desc) \ + { \ + auto arr = JSC::constructEmptyArray(globalObject, nullptr, 2); \ + arr->putDirectIndex(globalObject, 0, JSC::jsString(vm, String(#name##_s))); \ + arr->putDirectIndex(globalObject, 1, JSC::jsString(vm, String(desc##_s))); \ + map->set(globalObject, JSC::jsNumber(value), arr); \ + } + + UV_ERRNO_MAP(PUT_PROPERTY) +#undef PUT_PROPERTY + + return JSValue::encode(map); +} + +JSObject* create(VM& vm, JSGlobalObject* globalObject) +{ + auto bindingObject = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 0); + + bindingObject->putDirect(vm, JSC::Identifier::fromString(vm, "errname"_s), JSC::JSFunction::create(vm, globalObject, 1, "errname"_s, jsErrname, ImplementationVisibility::Public)); + +#define PUT_PROPERTY(name, value, desc) \ + bindingObject->putDirect(vm, JSC::Identifier::fromString(vm, "UV_" #name##_s), JSC::jsNumber(value)); + + UV_ERRNO_MAP(PUT_PROPERTY) +#undef PUT_PROPERTY + + bindingObject->putDirect(vm, JSC::Identifier::fromString(vm, "getErrorMap"_s), JSC::JSFunction::create(vm, globalObject, 0, "getErrorMap"_s, jsGetErrorMap, ImplementationVisibility::Public)); + + return bindingObject; +} + +} // namespace ProcessBindingUV +} // namespace Bun
\ No newline at end of file diff --git a/src/bun.js/bindings/ProcessBindingUV.h b/src/bun.js/bindings/ProcessBindingUV.h new file mode 100644 index 000000000..4306e21f8 --- /dev/null +++ b/src/bun.js/bindings/ProcessBindingUV.h @@ -0,0 +1,13 @@ +#include "root.h" + +namespace Bun { +namespace ProcessBindingUV { + +JSC_DECLARE_HOST_FUNCTION(jsErrname); + +JSC_DECLARE_HOST_FUNCTION(jsGetErrorMap); + +JSC::JSObject* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject); + +} // namespace ProcessBindingUV +} // namespace Bun
\ No newline at end of file diff --git a/src/bun.js/bindings/RegularExpression.cpp b/src/bun.js/bindings/RegularExpression.cpp index 1c8df1bc0..c59e6fa4c 100644 --- a/src/bun.js/bindings/RegularExpression.cpp +++ b/src/bun.js/bindings/RegularExpression.cpp @@ -1,12 +1,16 @@ #include "root.h" #include "headers-handwritten.h" #include "JavaScriptCore/RegularExpression.h" +#include "JavaScriptCore/Options.h" using namespace JSC; using namespace JSC::Yarr; extern "C" RegularExpression* Yarr__RegularExpression__init(BunString pattern, uint16_t flags) { + // TODO: Remove this, we technically are accessing options before we finalize them. + // This means you cannot use BUN_JSC_dumpCompiledRegExpPatterns on the flag passed to `bun test -t` + Options::AllowUnfinalizedAccessScope scope; return new RegularExpression(Bun::toWTFString(pattern), OptionSet<Flags>(static_cast<Flags>(flags))); } extern "C" void Yarr__RegularExpression__deinit(RegularExpression* re) diff --git a/src/bun.js/bindings/ScriptExecutionContext.cpp b/src/bun.js/bindings/ScriptExecutionContext.cpp index 2113c9f64..9f824dde5 100644 --- a/src/bun.js/bindings/ScriptExecutionContext.cpp +++ b/src/bun.js/bindings/ScriptExecutionContext.cpp @@ -105,7 +105,7 @@ bool ScriptExecutionContext::postTaskTo(ScriptExecutionContextIdentifier identif void ScriptExecutionContext::didCreateDestructionObserver(ContextDestructionObserver& observer) { - ASSERT(!m_inScriptExecutionContextDestructor); + // ASSERT(!m_inScriptExecutionContextDestructor); m_destructionObservers.add(&observer); } @@ -181,7 +181,7 @@ void ScriptExecutionContext::dispatchMessagePortEvents() ASSERT(isContextThread()); checkConsistency(); - ASSERT(m_willprocessMessageWithMessagePortsSoon); + ASSERT(m_willProcessMessageWithMessagePortsSoon); m_willProcessMessageWithMessagePortsSoon = false; auto completionHandlers = std::exchange(m_processMessageWithMessagePortsSoonHandlers, Vector<CompletionHandler<void()>> {}); diff --git a/src/bun.js/bindings/Serialization.cpp b/src/bun.js/bindings/Serialization.cpp index 89937ebbb..fdaf2ab75 100644 --- a/src/bun.js/bindings/Serialization.cpp +++ b/src/bun.js/bindings/Serialization.cpp @@ -8,9 +8,15 @@ using namespace JSC; using namespace WebCore; -/// This is used for Bun.spawn() IPC because otherwise we would have to copy the data once to get it to zig, then write it. -/// Returns `true` on success, `false` on failure + throws a JS error. -extern "C" bool Bun__serializeJSValueForSubprocess(JSGlobalObject* globalObject, EncodedJSValue encodedValue, int fd) +// Must be synced with bindings.zig's JSValue.SerializedScriptValue.External +struct SerializedValueSlice { + uint8_t* bytes; + size_t size; + WebCore::SerializedScriptValue* value; +}; + +/// Returns a "slice" that also contains a pointer to the SerializedScriptValue. Must be freed by the caller +extern "C" SerializedValueSlice Bun__serializeJSValue(JSGlobalObject* globalObject, EncodedJSValue encodedValue) { JSValue value = JSValue::decode(encodedValue); @@ -25,19 +31,23 @@ extern "C" bool Bun__serializeJSValueForSubprocess(JSGlobalObject* globalObject, if (serialized.hasException()) { WebCore::propagateException(*globalObject, scope, serialized.releaseException()); - RELEASE_AND_RETURN(scope, false); + RELEASE_AND_RETURN(scope, { 0 }); } auto serializedValue = serialized.releaseReturnValue(); - auto bytes = serializedValue.ptr()->wireBytes(); - uint8_t id = 2; // IPCMessageType.SerializedMessage - write(fd, &id, sizeof(uint8_t)); - uint32_t size = bytes.size(); - write(fd, &size, sizeof(uint32_t)); - write(fd, bytes.data(), size); + auto bytes = serializedValue->wireBytes(); - RELEASE_AND_RETURN(scope, true); + return { + bytes.data(), + bytes.size(), + &serializedValue.leakRef(), + }; +} + +extern "C" void Bun__SerializedScriptSlice__free(SerializedScriptValue* value) +{ + delete value; } extern "C" EncodedJSValue Bun__JSValue__deserialize(JSGlobalObject* globalObject, const uint8_t* bytes, size_t size) diff --git a/src/bun.js/bindings/URLDecomposition.cpp b/src/bun.js/bindings/URLDecomposition.cpp index d3f11b27f..21168f70f 100644 --- a/src/bun.js/bindings/URLDecomposition.cpp +++ b/src/bun.js/bindings/URLDecomposition.cpp @@ -35,7 +35,14 @@ String URLDecomposition::origin() const if (fullURL.protocolIsInHTTPFamily() or fullURL.protocolIsInFTPFamily() or fullURL.protocolIs("ws"_s) or fullURL.protocolIs("wss"_s)) return fullURL.protocolHostAndPort(); - + if (fullURL.protocolIsBlob()) { + const String& path = fullURL.path().toString(); + const URL subUrl { URL {}, path }; + if (subUrl.isValid()) { + if (subUrl.protocolIsInHTTPFamily() or subUrl.protocolIsInFTPFamily() or subUrl.protocolIs("ws"_s) or subUrl.protocolIs("wss"_s) or subUrl.protocolIsFile()) + return subUrl.protocolHostAndPort(); + } + } return "null"_s; } diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h index a364c0a48..cef5c512a 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h @@ -16,6 +16,7 @@ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForEndTag; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpect; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpectConstructor;std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpectAny; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpectAnything; +std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpectArrayContaining; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpectStringContaining; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForExpectStringMatching; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForFFI; diff --git a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h index e98ea16c3..d06451eda 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h @@ -16,6 +16,7 @@ std::unique_ptr<IsoSubspace> m_subspaceForEndTag; std::unique_ptr<IsoSubspace> m_subspaceForExpect; std::unique_ptr<IsoSubspace> m_subspaceForExpectConstructor;std::unique_ptr<IsoSubspace> m_subspaceForExpectAny; std::unique_ptr<IsoSubspace> m_subspaceForExpectAnything; +std::unique_ptr<IsoSubspace> m_subspaceForExpectArrayContaining; std::unique_ptr<IsoSubspace> m_subspaceForExpectStringContaining; std::unique_ptr<IsoSubspace> m_subspaceForExpectStringMatching; std::unique_ptr<IsoSubspace> m_subspaceForFFI; diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h index 2c075a508..381378262 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h @@ -1,300 +1,204 @@ JSC::Structure* JSAttributeIteratorStructure() { return m_JSAttributeIterator.getInitializedOnMainThread(this); } - JSC::JSObject* JSAttributeIteratorConstructor() { return m_JSAttributeIterator.constructorInitializedOnMainThread(this); } - JSC::JSValue JSAttributeIteratorPrototype() { return m_JSAttributeIterator.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSAttributeIteratorConstructor() { return m_JSAttributeIterator.constructorInitializedOnMainThread(this); } + JSC::JSValue JSAttributeIteratorPrototype() { return m_JSAttributeIterator.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSAttributeIterator; - bool hasJSAttributeIteratorSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSAttributeIteratorSetterValue; JSC::Structure* JSBigIntStatsStructure() { return m_JSBigIntStats.getInitializedOnMainThread(this); } - JSC::JSObject* JSBigIntStatsConstructor() { return m_JSBigIntStats.constructorInitializedOnMainThread(this); } - JSC::JSValue JSBigIntStatsPrototype() { return m_JSBigIntStats.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSBigIntStatsConstructor() { return m_JSBigIntStats.constructorInitializedOnMainThread(this); } + JSC::JSValue JSBigIntStatsPrototype() { return m_JSBigIntStats.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSBigIntStats; - bool hasJSBigIntStatsSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSBigIntStatsSetterValue; JSC::Structure* JSBlobStructure() { return m_JSBlob.getInitializedOnMainThread(this); } - JSC::JSObject* JSBlobConstructor() { return m_JSBlob.constructorInitializedOnMainThread(this); } - JSC::JSValue JSBlobPrototype() { return m_JSBlob.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSBlobConstructor() { return m_JSBlob.constructorInitializedOnMainThread(this); } + JSC::JSValue JSBlobPrototype() { return m_JSBlob.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSBlob; - bool hasJSBlobSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSBlobSetterValue; JSC::Structure* JSBuildArtifactStructure() { return m_JSBuildArtifact.getInitializedOnMainThread(this); } - JSC::JSObject* JSBuildArtifactConstructor() { return m_JSBuildArtifact.constructorInitializedOnMainThread(this); } - JSC::JSValue JSBuildArtifactPrototype() { return m_JSBuildArtifact.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSBuildArtifactConstructor() { return m_JSBuildArtifact.constructorInitializedOnMainThread(this); } + JSC::JSValue JSBuildArtifactPrototype() { return m_JSBuildArtifact.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSBuildArtifact; - bool hasJSBuildArtifactSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSBuildArtifactSetterValue; JSC::Structure* JSBuildMessageStructure() { return m_JSBuildMessage.getInitializedOnMainThread(this); } - JSC::JSObject* JSBuildMessageConstructor() { return m_JSBuildMessage.constructorInitializedOnMainThread(this); } - JSC::JSValue JSBuildMessagePrototype() { return m_JSBuildMessage.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSBuildMessageConstructor() { return m_JSBuildMessage.constructorInitializedOnMainThread(this); } + JSC::JSValue JSBuildMessagePrototype() { return m_JSBuildMessage.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSBuildMessage; - bool hasJSBuildMessageSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSBuildMessageSetterValue; JSC::Structure* JSCommentStructure() { return m_JSComment.getInitializedOnMainThread(this); } - JSC::JSObject* JSCommentConstructor() { return m_JSComment.constructorInitializedOnMainThread(this); } - JSC::JSValue JSCommentPrototype() { return m_JSComment.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSCommentConstructor() { return m_JSComment.constructorInitializedOnMainThread(this); } + JSC::JSValue JSCommentPrototype() { return m_JSComment.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSComment; - bool hasJSCommentSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSCommentSetterValue; JSC::Structure* JSCryptoStructure() { return m_JSCrypto.getInitializedOnMainThread(this); } - JSC::JSObject* JSCryptoConstructor() { return m_JSCrypto.constructorInitializedOnMainThread(this); } - JSC::JSValue JSCryptoPrototype() { return m_JSCrypto.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSCryptoConstructor() { return m_JSCrypto.constructorInitializedOnMainThread(this); } + JSC::JSValue JSCryptoPrototype() { return m_JSCrypto.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSCrypto; - bool hasJSCryptoSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSCryptoSetterValue; JSC::Structure* JSCryptoHasherStructure() { return m_JSCryptoHasher.getInitializedOnMainThread(this); } - JSC::JSObject* JSCryptoHasherConstructor() { return m_JSCryptoHasher.constructorInitializedOnMainThread(this); } - JSC::JSValue JSCryptoHasherPrototype() { return m_JSCryptoHasher.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSCryptoHasherConstructor() { return m_JSCryptoHasher.constructorInitializedOnMainThread(this); } + JSC::JSValue JSCryptoHasherPrototype() { return m_JSCryptoHasher.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSCryptoHasher; - bool hasJSCryptoHasherSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSCryptoHasherSetterValue; JSC::Structure* JSDebugHTTPSServerStructure() { return m_JSDebugHTTPSServer.getInitializedOnMainThread(this); } - JSC::JSObject* JSDebugHTTPSServerConstructor() { return m_JSDebugHTTPSServer.constructorInitializedOnMainThread(this); } - JSC::JSValue JSDebugHTTPSServerPrototype() { return m_JSDebugHTTPSServer.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSDebugHTTPSServerConstructor() { return m_JSDebugHTTPSServer.constructorInitializedOnMainThread(this); } + JSC::JSValue JSDebugHTTPSServerPrototype() { return m_JSDebugHTTPSServer.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSDebugHTTPSServer; - bool hasJSDebugHTTPSServerSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSDebugHTTPSServerSetterValue; JSC::Structure* JSDebugHTTPServerStructure() { return m_JSDebugHTTPServer.getInitializedOnMainThread(this); } - JSC::JSObject* JSDebugHTTPServerConstructor() { return m_JSDebugHTTPServer.constructorInitializedOnMainThread(this); } - JSC::JSValue JSDebugHTTPServerPrototype() { return m_JSDebugHTTPServer.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSDebugHTTPServerConstructor() { return m_JSDebugHTTPServer.constructorInitializedOnMainThread(this); } + JSC::JSValue JSDebugHTTPServerPrototype() { return m_JSDebugHTTPServer.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSDebugHTTPServer; - bool hasJSDebugHTTPServerSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSDebugHTTPServerSetterValue; JSC::Structure* JSDirentStructure() { return m_JSDirent.getInitializedOnMainThread(this); } - JSC::JSObject* JSDirentConstructor() { return m_JSDirent.constructorInitializedOnMainThread(this); } - JSC::JSValue JSDirentPrototype() { return m_JSDirent.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSDirentConstructor() { return m_JSDirent.constructorInitializedOnMainThread(this); } + JSC::JSValue JSDirentPrototype() { return m_JSDirent.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSDirent; - bool hasJSDirentSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSDirentSetterValue; JSC::Structure* JSDocEndStructure() { return m_JSDocEnd.getInitializedOnMainThread(this); } - JSC::JSObject* JSDocEndConstructor() { return m_JSDocEnd.constructorInitializedOnMainThread(this); } - JSC::JSValue JSDocEndPrototype() { return m_JSDocEnd.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSDocEndConstructor() { return m_JSDocEnd.constructorInitializedOnMainThread(this); } + JSC::JSValue JSDocEndPrototype() { return m_JSDocEnd.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSDocEnd; - bool hasJSDocEndSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSDocEndSetterValue; JSC::Structure* JSDocTypeStructure() { return m_JSDocType.getInitializedOnMainThread(this); } - JSC::JSObject* JSDocTypeConstructor() { return m_JSDocType.constructorInitializedOnMainThread(this); } - JSC::JSValue JSDocTypePrototype() { return m_JSDocType.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSDocTypeConstructor() { return m_JSDocType.constructorInitializedOnMainThread(this); } + JSC::JSValue JSDocTypePrototype() { return m_JSDocType.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSDocType; - bool hasJSDocTypeSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSDocTypeSetterValue; JSC::Structure* JSElementStructure() { return m_JSElement.getInitializedOnMainThread(this); } - JSC::JSObject* JSElementConstructor() { return m_JSElement.constructorInitializedOnMainThread(this); } - JSC::JSValue JSElementPrototype() { return m_JSElement.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSElementConstructor() { return m_JSElement.constructorInitializedOnMainThread(this); } + JSC::JSValue JSElementPrototype() { return m_JSElement.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSElement; - bool hasJSElementSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSElementSetterValue; JSC::Structure* JSEndTagStructure() { return m_JSEndTag.getInitializedOnMainThread(this); } - JSC::JSObject* JSEndTagConstructor() { return m_JSEndTag.constructorInitializedOnMainThread(this); } - JSC::JSValue JSEndTagPrototype() { return m_JSEndTag.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSEndTagConstructor() { return m_JSEndTag.constructorInitializedOnMainThread(this); } + JSC::JSValue JSEndTagPrototype() { return m_JSEndTag.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSEndTag; - bool hasJSEndTagSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSEndTagSetterValue; JSC::Structure* JSExpectStructure() { return m_JSExpect.getInitializedOnMainThread(this); } - JSC::JSObject* JSExpectConstructor() { return m_JSExpect.constructorInitializedOnMainThread(this); } - JSC::JSValue JSExpectPrototype() { return m_JSExpect.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSExpectConstructor() { return m_JSExpect.constructorInitializedOnMainThread(this); } + JSC::JSValue JSExpectPrototype() { return m_JSExpect.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSExpect; - bool hasJSExpectSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSExpectSetterValue; JSC::Structure* JSExpectAnyStructure() { return m_JSExpectAny.getInitializedOnMainThread(this); } - JSC::JSObject* JSExpectAnyConstructor() { return m_JSExpectAny.constructorInitializedOnMainThread(this); } - JSC::JSValue JSExpectAnyPrototype() { return m_JSExpectAny.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSExpectAnyConstructor() { return m_JSExpectAny.constructorInitializedOnMainThread(this); } + JSC::JSValue JSExpectAnyPrototype() { return m_JSExpectAny.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSExpectAny; - bool hasJSExpectAnySetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSExpectAnySetterValue; JSC::Structure* JSExpectAnythingStructure() { return m_JSExpectAnything.getInitializedOnMainThread(this); } - JSC::JSObject* JSExpectAnythingConstructor() { return m_JSExpectAnything.constructorInitializedOnMainThread(this); } - JSC::JSValue JSExpectAnythingPrototype() { return m_JSExpectAnything.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSExpectAnythingConstructor() { return m_JSExpectAnything.constructorInitializedOnMainThread(this); } + JSC::JSValue JSExpectAnythingPrototype() { return m_JSExpectAnything.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSExpectAnything; - bool hasJSExpectAnythingSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSExpectAnythingSetterValue; +JSC::Structure* JSExpectArrayContainingStructure() { return m_JSExpectArrayContaining.getInitializedOnMainThread(this); } + JSC::JSObject* JSExpectArrayContainingConstructor() { return m_JSExpectArrayContaining.constructorInitializedOnMainThread(this); } + JSC::JSValue JSExpectArrayContainingPrototype() { return m_JSExpectArrayContaining.prototypeInitializedOnMainThread(this); } + JSC::LazyClassStructure m_JSExpectArrayContaining; JSC::Structure* JSExpectStringContainingStructure() { return m_JSExpectStringContaining.getInitializedOnMainThread(this); } - JSC::JSObject* JSExpectStringContainingConstructor() { return m_JSExpectStringContaining.constructorInitializedOnMainThread(this); } - JSC::JSValue JSExpectStringContainingPrototype() { return m_JSExpectStringContaining.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSExpectStringContainingConstructor() { return m_JSExpectStringContaining.constructorInitializedOnMainThread(this); } + JSC::JSValue JSExpectStringContainingPrototype() { return m_JSExpectStringContaining.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSExpectStringContaining; - bool hasJSExpectStringContainingSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSExpectStringContainingSetterValue; JSC::Structure* JSExpectStringMatchingStructure() { return m_JSExpectStringMatching.getInitializedOnMainThread(this); } - JSC::JSObject* JSExpectStringMatchingConstructor() { return m_JSExpectStringMatching.constructorInitializedOnMainThread(this); } - JSC::JSValue JSExpectStringMatchingPrototype() { return m_JSExpectStringMatching.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSExpectStringMatchingConstructor() { return m_JSExpectStringMatching.constructorInitializedOnMainThread(this); } + JSC::JSValue JSExpectStringMatchingPrototype() { return m_JSExpectStringMatching.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSExpectStringMatching; - bool hasJSExpectStringMatchingSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSExpectStringMatchingSetterValue; JSC::Structure* JSFFIStructure() { return m_JSFFI.getInitializedOnMainThread(this); } - JSC::JSObject* JSFFIConstructor() { return m_JSFFI.constructorInitializedOnMainThread(this); } - JSC::JSValue JSFFIPrototype() { return m_JSFFI.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSFFIConstructor() { return m_JSFFI.constructorInitializedOnMainThread(this); } + JSC::JSValue JSFFIPrototype() { return m_JSFFI.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSFFI; - bool hasJSFFISetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSFFISetterValue; JSC::Structure* JSFSWatcherStructure() { return m_JSFSWatcher.getInitializedOnMainThread(this); } - JSC::JSObject* JSFSWatcherConstructor() { return m_JSFSWatcher.constructorInitializedOnMainThread(this); } - JSC::JSValue JSFSWatcherPrototype() { return m_JSFSWatcher.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSFSWatcherConstructor() { return m_JSFSWatcher.constructorInitializedOnMainThread(this); } + JSC::JSValue JSFSWatcherPrototype() { return m_JSFSWatcher.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSFSWatcher; - bool hasJSFSWatcherSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSFSWatcherSetterValue; JSC::Structure* JSFileSystemRouterStructure() { return m_JSFileSystemRouter.getInitializedOnMainThread(this); } - JSC::JSObject* JSFileSystemRouterConstructor() { return m_JSFileSystemRouter.constructorInitializedOnMainThread(this); } - JSC::JSValue JSFileSystemRouterPrototype() { return m_JSFileSystemRouter.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSFileSystemRouterConstructor() { return m_JSFileSystemRouter.constructorInitializedOnMainThread(this); } + JSC::JSValue JSFileSystemRouterPrototype() { return m_JSFileSystemRouter.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSFileSystemRouter; - bool hasJSFileSystemRouterSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSFileSystemRouterSetterValue; JSC::Structure* JSHTMLRewriterStructure() { return m_JSHTMLRewriter.getInitializedOnMainThread(this); } - JSC::JSObject* JSHTMLRewriterConstructor() { return m_JSHTMLRewriter.constructorInitializedOnMainThread(this); } - JSC::JSValue JSHTMLRewriterPrototype() { return m_JSHTMLRewriter.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSHTMLRewriterConstructor() { return m_JSHTMLRewriter.constructorInitializedOnMainThread(this); } + JSC::JSValue JSHTMLRewriterPrototype() { return m_JSHTMLRewriter.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSHTMLRewriter; - bool hasJSHTMLRewriterSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSHTMLRewriterSetterValue; JSC::Structure* JSHTTPSServerStructure() { return m_JSHTTPSServer.getInitializedOnMainThread(this); } - JSC::JSObject* JSHTTPSServerConstructor() { return m_JSHTTPSServer.constructorInitializedOnMainThread(this); } - JSC::JSValue JSHTTPSServerPrototype() { return m_JSHTTPSServer.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSHTTPSServerConstructor() { return m_JSHTTPSServer.constructorInitializedOnMainThread(this); } + JSC::JSValue JSHTTPSServerPrototype() { return m_JSHTTPSServer.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSHTTPSServer; - bool hasJSHTTPSServerSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSHTTPSServerSetterValue; JSC::Structure* JSHTTPServerStructure() { return m_JSHTTPServer.getInitializedOnMainThread(this); } - JSC::JSObject* JSHTTPServerConstructor() { return m_JSHTTPServer.constructorInitializedOnMainThread(this); } - JSC::JSValue JSHTTPServerPrototype() { return m_JSHTTPServer.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSHTTPServerConstructor() { return m_JSHTTPServer.constructorInitializedOnMainThread(this); } + JSC::JSValue JSHTTPServerPrototype() { return m_JSHTTPServer.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSHTTPServer; - bool hasJSHTTPServerSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSHTTPServerSetterValue; JSC::Structure* JSListenerStructure() { return m_JSListener.getInitializedOnMainThread(this); } - JSC::JSObject* JSListenerConstructor() { return m_JSListener.constructorInitializedOnMainThread(this); } - JSC::JSValue JSListenerPrototype() { return m_JSListener.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSListenerConstructor() { return m_JSListener.constructorInitializedOnMainThread(this); } + JSC::JSValue JSListenerPrototype() { return m_JSListener.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSListener; - bool hasJSListenerSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSListenerSetterValue; JSC::Structure* JSMD4Structure() { return m_JSMD4.getInitializedOnMainThread(this); } - JSC::JSObject* JSMD4Constructor() { return m_JSMD4.constructorInitializedOnMainThread(this); } - JSC::JSValue JSMD4Prototype() { return m_JSMD4.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSMD4Constructor() { return m_JSMD4.constructorInitializedOnMainThread(this); } + JSC::JSValue JSMD4Prototype() { return m_JSMD4.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSMD4; - bool hasJSMD4SetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSMD4SetterValue; JSC::Structure* JSMD5Structure() { return m_JSMD5.getInitializedOnMainThread(this); } - JSC::JSObject* JSMD5Constructor() { return m_JSMD5.constructorInitializedOnMainThread(this); } - JSC::JSValue JSMD5Prototype() { return m_JSMD5.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSMD5Constructor() { return m_JSMD5.constructorInitializedOnMainThread(this); } + JSC::JSValue JSMD5Prototype() { return m_JSMD5.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSMD5; - bool hasJSMD5SetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSMD5SetterValue; JSC::Structure* JSMatchedRouteStructure() { return m_JSMatchedRoute.getInitializedOnMainThread(this); } - JSC::JSObject* JSMatchedRouteConstructor() { return m_JSMatchedRoute.constructorInitializedOnMainThread(this); } - JSC::JSValue JSMatchedRoutePrototype() { return m_JSMatchedRoute.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSMatchedRouteConstructor() { return m_JSMatchedRoute.constructorInitializedOnMainThread(this); } + JSC::JSValue JSMatchedRoutePrototype() { return m_JSMatchedRoute.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSMatchedRoute; - bool hasJSMatchedRouteSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSMatchedRouteSetterValue; JSC::Structure* JSNodeJSFSStructure() { return m_JSNodeJSFS.getInitializedOnMainThread(this); } - JSC::JSObject* JSNodeJSFSConstructor() { return m_JSNodeJSFS.constructorInitializedOnMainThread(this); } - JSC::JSValue JSNodeJSFSPrototype() { return m_JSNodeJSFS.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSNodeJSFSConstructor() { return m_JSNodeJSFS.constructorInitializedOnMainThread(this); } + JSC::JSValue JSNodeJSFSPrototype() { return m_JSNodeJSFS.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSNodeJSFS; - bool hasJSNodeJSFSSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSNodeJSFSSetterValue; JSC::Structure* JSRequestStructure() { return m_JSRequest.getInitializedOnMainThread(this); } - JSC::JSObject* JSRequestConstructor() { return m_JSRequest.constructorInitializedOnMainThread(this); } - JSC::JSValue JSRequestPrototype() { return m_JSRequest.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSRequestConstructor() { return m_JSRequest.constructorInitializedOnMainThread(this); } + JSC::JSValue JSRequestPrototype() { return m_JSRequest.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSRequest; - bool hasJSRequestSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSRequestSetterValue; JSC::Structure* JSResolveMessageStructure() { return m_JSResolveMessage.getInitializedOnMainThread(this); } - JSC::JSObject* JSResolveMessageConstructor() { return m_JSResolveMessage.constructorInitializedOnMainThread(this); } - JSC::JSValue JSResolveMessagePrototype() { return m_JSResolveMessage.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSResolveMessageConstructor() { return m_JSResolveMessage.constructorInitializedOnMainThread(this); } + JSC::JSValue JSResolveMessagePrototype() { return m_JSResolveMessage.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSResolveMessage; - bool hasJSResolveMessageSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSResolveMessageSetterValue; JSC::Structure* JSResponseStructure() { return m_JSResponse.getInitializedOnMainThread(this); } - JSC::JSObject* JSResponseConstructor() { return m_JSResponse.constructorInitializedOnMainThread(this); } - JSC::JSValue JSResponsePrototype() { return m_JSResponse.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSResponseConstructor() { return m_JSResponse.constructorInitializedOnMainThread(this); } + JSC::JSValue JSResponsePrototype() { return m_JSResponse.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSResponse; - bool hasJSResponseSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSResponseSetterValue; JSC::Structure* JSSHA1Structure() { return m_JSSHA1.getInitializedOnMainThread(this); } - JSC::JSObject* JSSHA1Constructor() { return m_JSSHA1.constructorInitializedOnMainThread(this); } - JSC::JSValue JSSHA1Prototype() { return m_JSSHA1.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSSHA1Constructor() { return m_JSSHA1.constructorInitializedOnMainThread(this); } + JSC::JSValue JSSHA1Prototype() { return m_JSSHA1.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSSHA1; - bool hasJSSHA1SetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSSHA1SetterValue; JSC::Structure* JSSHA224Structure() { return m_JSSHA224.getInitializedOnMainThread(this); } - JSC::JSObject* JSSHA224Constructor() { return m_JSSHA224.constructorInitializedOnMainThread(this); } - JSC::JSValue JSSHA224Prototype() { return m_JSSHA224.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSSHA224Constructor() { return m_JSSHA224.constructorInitializedOnMainThread(this); } + JSC::JSValue JSSHA224Prototype() { return m_JSSHA224.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSSHA224; - bool hasJSSHA224SetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSSHA224SetterValue; JSC::Structure* JSSHA256Structure() { return m_JSSHA256.getInitializedOnMainThread(this); } - JSC::JSObject* JSSHA256Constructor() { return m_JSSHA256.constructorInitializedOnMainThread(this); } - JSC::JSValue JSSHA256Prototype() { return m_JSSHA256.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSSHA256Constructor() { return m_JSSHA256.constructorInitializedOnMainThread(this); } + JSC::JSValue JSSHA256Prototype() { return m_JSSHA256.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSSHA256; - bool hasJSSHA256SetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSSHA256SetterValue; JSC::Structure* JSSHA384Structure() { return m_JSSHA384.getInitializedOnMainThread(this); } - JSC::JSObject* JSSHA384Constructor() { return m_JSSHA384.constructorInitializedOnMainThread(this); } - JSC::JSValue JSSHA384Prototype() { return m_JSSHA384.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSSHA384Constructor() { return m_JSSHA384.constructorInitializedOnMainThread(this); } + JSC::JSValue JSSHA384Prototype() { return m_JSSHA384.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSSHA384; - bool hasJSSHA384SetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSSHA384SetterValue; JSC::Structure* JSSHA512Structure() { return m_JSSHA512.getInitializedOnMainThread(this); } - JSC::JSObject* JSSHA512Constructor() { return m_JSSHA512.constructorInitializedOnMainThread(this); } - JSC::JSValue JSSHA512Prototype() { return m_JSSHA512.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSSHA512Constructor() { return m_JSSHA512.constructorInitializedOnMainThread(this); } + JSC::JSValue JSSHA512Prototype() { return m_JSSHA512.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSSHA512; - bool hasJSSHA512SetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSSHA512SetterValue; JSC::Structure* JSSHA512_256Structure() { return m_JSSHA512_256.getInitializedOnMainThread(this); } - JSC::JSObject* JSSHA512_256Constructor() { return m_JSSHA512_256.constructorInitializedOnMainThread(this); } - JSC::JSValue JSSHA512_256Prototype() { return m_JSSHA512_256.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSSHA512_256Constructor() { return m_JSSHA512_256.constructorInitializedOnMainThread(this); } + JSC::JSValue JSSHA512_256Prototype() { return m_JSSHA512_256.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSSHA512_256; - bool hasJSSHA512_256SetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSSHA512_256SetterValue; JSC::Structure* JSServerWebSocketStructure() { return m_JSServerWebSocket.getInitializedOnMainThread(this); } - JSC::JSObject* JSServerWebSocketConstructor() { return m_JSServerWebSocket.constructorInitializedOnMainThread(this); } - JSC::JSValue JSServerWebSocketPrototype() { return m_JSServerWebSocket.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSServerWebSocketConstructor() { return m_JSServerWebSocket.constructorInitializedOnMainThread(this); } + JSC::JSValue JSServerWebSocketPrototype() { return m_JSServerWebSocket.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSServerWebSocket; - bool hasJSServerWebSocketSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSServerWebSocketSetterValue; JSC::Structure* JSStatWatcherStructure() { return m_JSStatWatcher.getInitializedOnMainThread(this); } - JSC::JSObject* JSStatWatcherConstructor() { return m_JSStatWatcher.constructorInitializedOnMainThread(this); } - JSC::JSValue JSStatWatcherPrototype() { return m_JSStatWatcher.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSStatWatcherConstructor() { return m_JSStatWatcher.constructorInitializedOnMainThread(this); } + JSC::JSValue JSStatWatcherPrototype() { return m_JSStatWatcher.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSStatWatcher; - bool hasJSStatWatcherSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSStatWatcherSetterValue; JSC::Structure* JSStatsStructure() { return m_JSStats.getInitializedOnMainThread(this); } - JSC::JSObject* JSStatsConstructor() { return m_JSStats.constructorInitializedOnMainThread(this); } - JSC::JSValue JSStatsPrototype() { return m_JSStats.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSStatsConstructor() { return m_JSStats.constructorInitializedOnMainThread(this); } + JSC::JSValue JSStatsPrototype() { return m_JSStats.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSStats; - bool hasJSStatsSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSStatsSetterValue; JSC::Structure* JSSubprocessStructure() { return m_JSSubprocess.getInitializedOnMainThread(this); } - JSC::JSObject* JSSubprocessConstructor() { return m_JSSubprocess.constructorInitializedOnMainThread(this); } - JSC::JSValue JSSubprocessPrototype() { return m_JSSubprocess.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSSubprocessConstructor() { return m_JSSubprocess.constructorInitializedOnMainThread(this); } + JSC::JSValue JSSubprocessPrototype() { return m_JSSubprocess.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSSubprocess; - bool hasJSSubprocessSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSSubprocessSetterValue; JSC::Structure* JSTCPSocketStructure() { return m_JSTCPSocket.getInitializedOnMainThread(this); } - JSC::JSObject* JSTCPSocketConstructor() { return m_JSTCPSocket.constructorInitializedOnMainThread(this); } - JSC::JSValue JSTCPSocketPrototype() { return m_JSTCPSocket.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSTCPSocketConstructor() { return m_JSTCPSocket.constructorInitializedOnMainThread(this); } + JSC::JSValue JSTCPSocketPrototype() { return m_JSTCPSocket.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSTCPSocket; - bool hasJSTCPSocketSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSTCPSocketSetterValue; JSC::Structure* JSTLSSocketStructure() { return m_JSTLSSocket.getInitializedOnMainThread(this); } - JSC::JSObject* JSTLSSocketConstructor() { return m_JSTLSSocket.constructorInitializedOnMainThread(this); } - JSC::JSValue JSTLSSocketPrototype() { return m_JSTLSSocket.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSTLSSocketConstructor() { return m_JSTLSSocket.constructorInitializedOnMainThread(this); } + JSC::JSValue JSTLSSocketPrototype() { return m_JSTLSSocket.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSTLSSocket; - bool hasJSTLSSocketSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSTLSSocketSetterValue; JSC::Structure* JSTextChunkStructure() { return m_JSTextChunk.getInitializedOnMainThread(this); } - JSC::JSObject* JSTextChunkConstructor() { return m_JSTextChunk.constructorInitializedOnMainThread(this); } - JSC::JSValue JSTextChunkPrototype() { return m_JSTextChunk.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSTextChunkConstructor() { return m_JSTextChunk.constructorInitializedOnMainThread(this); } + JSC::JSValue JSTextChunkPrototype() { return m_JSTextChunk.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSTextChunk; - bool hasJSTextChunkSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSTextChunkSetterValue; JSC::Structure* JSTextDecoderStructure() { return m_JSTextDecoder.getInitializedOnMainThread(this); } - JSC::JSObject* JSTextDecoderConstructor() { return m_JSTextDecoder.constructorInitializedOnMainThread(this); } - JSC::JSValue JSTextDecoderPrototype() { return m_JSTextDecoder.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSTextDecoderConstructor() { return m_JSTextDecoder.constructorInitializedOnMainThread(this); } + JSC::JSValue JSTextDecoderPrototype() { return m_JSTextDecoder.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSTextDecoder; - bool hasJSTextDecoderSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSTextDecoderSetterValue; JSC::Structure* JSTimeoutStructure() { return m_JSTimeout.getInitializedOnMainThread(this); } - JSC::JSObject* JSTimeoutConstructor() { return m_JSTimeout.constructorInitializedOnMainThread(this); } - JSC::JSValue JSTimeoutPrototype() { return m_JSTimeout.prototypeInitializedOnMainThread(this); } + JSC::JSObject* JSTimeoutConstructor() { return m_JSTimeout.constructorInitializedOnMainThread(this); } + JSC::JSValue JSTimeoutPrototype() { return m_JSTimeout.prototypeInitializedOnMainThread(this); } JSC::LazyClassStructure m_JSTimeout; - bool hasJSTimeoutSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSTimeoutSetterValue; JSC::Structure* JSTranspilerStructure() { return m_JSTranspiler.getInitializedOnMainThread(this); } - JSC::JSObject* JSTranspilerConstructor() { return m_JSTranspiler.constructorInitializedOnMainThread(this); } - JSC::JSValue JSTranspilerPrototype() { return m_JSTranspiler.prototypeInitializedOnMainThread(this); } - JSC::LazyClassStructure m_JSTranspiler; - bool hasJSTranspilerSetterValue { false }; - mutable JSC::WriteBarrier<JSC::Unknown> m_JSTranspilerSetterValue;
\ No newline at end of file + JSC::JSObject* JSTranspilerConstructor() { return m_JSTranspiler.constructorInitializedOnMainThread(this); } + JSC::JSValue JSTranspilerPrototype() { return m_JSTranspiler.prototypeInitializedOnMainThread(this); } + JSC::LazyClassStructure m_JSTranspiler;
\ No newline at end of file diff --git a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h index cb4c47ccb..84d3df7a0 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h +++ b/src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h @@ -1,4 +1,4 @@ -void GlobalObject::initGeneratedLazyClasses() { +ALWAYS_INLINE void GlobalObject::initGeneratedLazyClasses() { m_JSAttributeIterator.initLater( [](LazyClassStructure::Initializer& init) { init.setPrototype(WebCore::JSAttributeIterator::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); @@ -107,6 +107,12 @@ void GlobalObject::initGeneratedLazyClasses() { init.setStructure(WebCore::JSExpectAnything::createStructure(init.vm, init.global, init.prototype)); }); + m_JSExpectArrayContaining.initLater( + [](LazyClassStructure::Initializer& init) { + init.setPrototype(WebCore::JSExpectArrayContaining::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); + init.setStructure(WebCore::JSExpectArrayContaining::createStructure(init.vm, init.global, init.prototype)); + + }); m_JSExpectStringContaining.initLater( [](LazyClassStructure::Initializer& init) { init.setPrototype(WebCore::JSExpectStringContaining::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); @@ -303,54 +309,55 @@ void GlobalObject::initGeneratedLazyClasses() { template<typename Visitor> void GlobalObject::visitGeneratedLazyClasses(GlobalObject *thisObject, Visitor& visitor) { - thisObject->m_JSAttributeIterator.visit(visitor); visitor.append(thisObject->m_JSAttributeIteratorSetterValue); - thisObject->m_JSBigIntStats.visit(visitor); visitor.append(thisObject->m_JSBigIntStatsSetterValue); - thisObject->m_JSBlob.visit(visitor); visitor.append(thisObject->m_JSBlobSetterValue); - thisObject->m_JSBuildArtifact.visit(visitor); visitor.append(thisObject->m_JSBuildArtifactSetterValue); - thisObject->m_JSBuildMessage.visit(visitor); visitor.append(thisObject->m_JSBuildMessageSetterValue); - thisObject->m_JSComment.visit(visitor); visitor.append(thisObject->m_JSCommentSetterValue); - thisObject->m_JSCrypto.visit(visitor); visitor.append(thisObject->m_JSCryptoSetterValue); - thisObject->m_JSCryptoHasher.visit(visitor); visitor.append(thisObject->m_JSCryptoHasherSetterValue); - thisObject->m_JSDebugHTTPSServer.visit(visitor); visitor.append(thisObject->m_JSDebugHTTPSServerSetterValue); - thisObject->m_JSDebugHTTPServer.visit(visitor); visitor.append(thisObject->m_JSDebugHTTPServerSetterValue); - thisObject->m_JSDirent.visit(visitor); visitor.append(thisObject->m_JSDirentSetterValue); - thisObject->m_JSDocEnd.visit(visitor); visitor.append(thisObject->m_JSDocEndSetterValue); - thisObject->m_JSDocType.visit(visitor); visitor.append(thisObject->m_JSDocTypeSetterValue); - thisObject->m_JSElement.visit(visitor); visitor.append(thisObject->m_JSElementSetterValue); - thisObject->m_JSEndTag.visit(visitor); visitor.append(thisObject->m_JSEndTagSetterValue); - thisObject->m_JSExpect.visit(visitor); visitor.append(thisObject->m_JSExpectSetterValue); - thisObject->m_JSExpectAny.visit(visitor); visitor.append(thisObject->m_JSExpectAnySetterValue); - thisObject->m_JSExpectAnything.visit(visitor); visitor.append(thisObject->m_JSExpectAnythingSetterValue); - thisObject->m_JSExpectStringContaining.visit(visitor); visitor.append(thisObject->m_JSExpectStringContainingSetterValue); - thisObject->m_JSExpectStringMatching.visit(visitor); visitor.append(thisObject->m_JSExpectStringMatchingSetterValue); - thisObject->m_JSFFI.visit(visitor); visitor.append(thisObject->m_JSFFISetterValue); - thisObject->m_JSFSWatcher.visit(visitor); visitor.append(thisObject->m_JSFSWatcherSetterValue); - thisObject->m_JSFileSystemRouter.visit(visitor); visitor.append(thisObject->m_JSFileSystemRouterSetterValue); - thisObject->m_JSHTMLRewriter.visit(visitor); visitor.append(thisObject->m_JSHTMLRewriterSetterValue); - thisObject->m_JSHTTPSServer.visit(visitor); visitor.append(thisObject->m_JSHTTPSServerSetterValue); - thisObject->m_JSHTTPServer.visit(visitor); visitor.append(thisObject->m_JSHTTPServerSetterValue); - thisObject->m_JSListener.visit(visitor); visitor.append(thisObject->m_JSListenerSetterValue); - thisObject->m_JSMD4.visit(visitor); visitor.append(thisObject->m_JSMD4SetterValue); - thisObject->m_JSMD5.visit(visitor); visitor.append(thisObject->m_JSMD5SetterValue); - thisObject->m_JSMatchedRoute.visit(visitor); visitor.append(thisObject->m_JSMatchedRouteSetterValue); - thisObject->m_JSNodeJSFS.visit(visitor); visitor.append(thisObject->m_JSNodeJSFSSetterValue); - thisObject->m_JSRequest.visit(visitor); visitor.append(thisObject->m_JSRequestSetterValue); - thisObject->m_JSResolveMessage.visit(visitor); visitor.append(thisObject->m_JSResolveMessageSetterValue); - thisObject->m_JSResponse.visit(visitor); visitor.append(thisObject->m_JSResponseSetterValue); - thisObject->m_JSSHA1.visit(visitor); visitor.append(thisObject->m_JSSHA1SetterValue); - thisObject->m_JSSHA224.visit(visitor); visitor.append(thisObject->m_JSSHA224SetterValue); - thisObject->m_JSSHA256.visit(visitor); visitor.append(thisObject->m_JSSHA256SetterValue); - thisObject->m_JSSHA384.visit(visitor); visitor.append(thisObject->m_JSSHA384SetterValue); - thisObject->m_JSSHA512.visit(visitor); visitor.append(thisObject->m_JSSHA512SetterValue); - thisObject->m_JSSHA512_256.visit(visitor); visitor.append(thisObject->m_JSSHA512_256SetterValue); - thisObject->m_JSServerWebSocket.visit(visitor); visitor.append(thisObject->m_JSServerWebSocketSetterValue); - thisObject->m_JSStatWatcher.visit(visitor); visitor.append(thisObject->m_JSStatWatcherSetterValue); - thisObject->m_JSStats.visit(visitor); visitor.append(thisObject->m_JSStatsSetterValue); - thisObject->m_JSSubprocess.visit(visitor); visitor.append(thisObject->m_JSSubprocessSetterValue); - thisObject->m_JSTCPSocket.visit(visitor); visitor.append(thisObject->m_JSTCPSocketSetterValue); - thisObject->m_JSTLSSocket.visit(visitor); visitor.append(thisObject->m_JSTLSSocketSetterValue); - thisObject->m_JSTextChunk.visit(visitor); visitor.append(thisObject->m_JSTextChunkSetterValue); - thisObject->m_JSTextDecoder.visit(visitor); visitor.append(thisObject->m_JSTextDecoderSetterValue); - thisObject->m_JSTimeout.visit(visitor); visitor.append(thisObject->m_JSTimeoutSetterValue); - thisObject->m_JSTranspiler.visit(visitor); visitor.append(thisObject->m_JSTranspilerSetterValue); + thisObject->m_JSAttributeIterator.visit(visitor); + thisObject->m_JSBigIntStats.visit(visitor); + thisObject->m_JSBlob.visit(visitor); + thisObject->m_JSBuildArtifact.visit(visitor); + thisObject->m_JSBuildMessage.visit(visitor); + thisObject->m_JSComment.visit(visitor); + thisObject->m_JSCrypto.visit(visitor); + thisObject->m_JSCryptoHasher.visit(visitor); + thisObject->m_JSDebugHTTPSServer.visit(visitor); + thisObject->m_JSDebugHTTPServer.visit(visitor); + thisObject->m_JSDirent.visit(visitor); + thisObject->m_JSDocEnd.visit(visitor); + thisObject->m_JSDocType.visit(visitor); + thisObject->m_JSElement.visit(visitor); + thisObject->m_JSEndTag.visit(visitor); + thisObject->m_JSExpect.visit(visitor); + thisObject->m_JSExpectAny.visit(visitor); + thisObject->m_JSExpectAnything.visit(visitor); + thisObject->m_JSExpectArrayContaining.visit(visitor); + thisObject->m_JSExpectStringContaining.visit(visitor); + thisObject->m_JSExpectStringMatching.visit(visitor); + thisObject->m_JSFFI.visit(visitor); + thisObject->m_JSFSWatcher.visit(visitor); + thisObject->m_JSFileSystemRouter.visit(visitor); + thisObject->m_JSHTMLRewriter.visit(visitor); + thisObject->m_JSHTTPSServer.visit(visitor); + thisObject->m_JSHTTPServer.visit(visitor); + thisObject->m_JSListener.visit(visitor); + thisObject->m_JSMD4.visit(visitor); + thisObject->m_JSMD5.visit(visitor); + thisObject->m_JSMatchedRoute.visit(visitor); + thisObject->m_JSNodeJSFS.visit(visitor); + thisObject->m_JSRequest.visit(visitor); + thisObject->m_JSResolveMessage.visit(visitor); + thisObject->m_JSResponse.visit(visitor); + thisObject->m_JSSHA1.visit(visitor); + thisObject->m_JSSHA224.visit(visitor); + thisObject->m_JSSHA256.visit(visitor); + thisObject->m_JSSHA384.visit(visitor); + thisObject->m_JSSHA512.visit(visitor); + thisObject->m_JSSHA512_256.visit(visitor); + thisObject->m_JSServerWebSocket.visit(visitor); + thisObject->m_JSStatWatcher.visit(visitor); + thisObject->m_JSStats.visit(visitor); + thisObject->m_JSSubprocess.visit(visitor); + thisObject->m_JSTCPSocket.visit(visitor); + thisObject->m_JSTLSSocket.visit(visitor); + thisObject->m_JSTextChunk.visit(visitor); + thisObject->m_JSTextDecoder.visit(visitor); + thisObject->m_JSTimeout.visit(visitor); + thisObject->m_JSTranspiler.visit(visitor); }
\ No newline at end of file diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index ec2add296..8d8c98154 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -43,6 +43,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSAttributeIteratorPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -150,7 +151,7 @@ void JSAttributeIteratorPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObje { Base::finishCreation(vm); reifyStaticProperties(vm, JSAttributeIterator::info(), JSAttributeIteratorPrototypeTableValues, *this); - this->putDirect(vm, vm.propertyNames->iteratorSymbol, JSFunction::create(vm, globalObject, 1, String("iterator"_s), AttributeIteratorPrototype__iteratorCallback, ImplementationVisibility::Public), PropertyAttribute::Function | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); + this->putDirect(vm, vm.propertyNames->iteratorSymbol, JSFunction::create(vm, globalObject, 1, String("iterator"_s), AttributeIteratorPrototype__iteratorCallback, ImplementationVisibility::Public), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } @@ -245,6 +246,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBigIntStatsPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -1301,6 +1303,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBlobPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -1777,7 +1780,7 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSBlobConstructor::construct(JSC::J } JSBlob* instance = JSBlob::create(vm, globalObject, structure, ptr); - vm.heap.reportExtraMemoryAllocated(Blob__estimatedSize(instance->wrapped())); + vm.heap.reportExtraMemoryAllocated(instance, Blob__estimatedSize(instance->wrapped())); return JSValue::encode(instance); } @@ -1871,7 +1874,7 @@ extern "C" EncodedJSValue Blob__create(Zig::GlobalObject* globalObject, void* pt auto& vm = globalObject->vm(); JSC::Structure* structure = globalObject->JSBlobStructure(); JSBlob* instance = JSBlob::create(vm, globalObject, structure, ptr); - vm.heap.reportExtraMemoryAllocated(Blob__estimatedSize(ptr)); + vm.heap.reportExtraMemoryAllocated(instance, Blob__estimatedSize(ptr)); return JSValue::encode(instance); } @@ -1924,6 +1927,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBuildArtifactPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -2471,6 +2475,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBuildMessagePrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -2752,7 +2757,7 @@ void JSBuildMessagePrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* g { Base::finishCreation(vm); reifyStaticProperties(vm, JSBuildMessage::info(), JSBuildMessagePrototypeTableValues, *this); - this->putDirect(vm, vm.propertyNames->toPrimitiveSymbol, JSFunction::create(vm, globalObject, 1, String("toPrimitive"_s), BuildMessagePrototype__toPrimitiveCallback, ImplementationVisibility::Public), PropertyAttribute::Function | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); + this->putDirect(vm, vm.propertyNames->toPrimitiveSymbol, JSFunction::create(vm, globalObject, 1, String("toPrimitive"_s), BuildMessagePrototype__toPrimitiveCallback, ImplementationVisibility::Public), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); this->putDirect(vm, vm.propertyNames->name, jsString(vm, String("BuildMessage"_s)), PropertyAttribute::ReadOnly | 0); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } @@ -2950,6 +2955,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCommentPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -3262,6 +3268,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCryptoPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -3715,6 +3722,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSCryptoHasherPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -4146,6 +4154,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDebugHTTPSServerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -4167,6 +4176,9 @@ JSC_DECLARE_CUSTOM_GETTER(jsDebugHTTPSServerConstructor); extern "C" void DebugHTTPSServerClass__finalize(void*); +extern "C" JSC::EncodedJSValue DebugHTTPSServerPrototype__getAddress(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(DebugHTTPSServerPrototype__addressGetterWrap); + extern "C" JSC::EncodedJSValue DebugHTTPSServerPrototype__getDevelopment(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(DebugHTTPSServerPrototype__developmentGetterWrap); @@ -4197,6 +4209,9 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__publishCallback); extern "C" EncodedJSValue DebugHTTPSServerPrototype__doReload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__reloadCallback); +extern "C" EncodedJSValue DebugHTTPSServerPrototype__doRequestIP(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__requestIPCallback); + extern "C" EncodedJSValue DebugHTTPSServerPrototype__doStop(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__stopCallback); @@ -4206,6 +4221,7 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__upgradeCallback); STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDebugHTTPSServerPrototype, JSDebugHTTPSServerPrototype::Base); static const HashTableValue JSDebugHTTPSServerPrototypeTableValues[] = { + { "address"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__addressGetterWrap, 0 } }, { "development"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__developmentGetterWrap, 0 } }, { "fetch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__fetchCallback, 1 } }, { "hostname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__hostnameGetterWrap, 0 } }, @@ -4216,6 +4232,7 @@ static const HashTableValue JSDebugHTTPSServerPrototypeTableValues[] = { { "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__protocolGetterWrap, 0 } }, { "publish"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__publishCallback, 3 } }, { "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__reloadCallback, 2 } }, + { "requestIP"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__requestIPCallback, 1 } }, { "stop"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__stopCallback, 1 } }, { "upgrade"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__upgradeCallback, 1 } } }; @@ -4234,6 +4251,37 @@ JSC_DEFINE_CUSTOM_GETTER(jsDebugHTTPSServerConstructor, (JSGlobalObject * lexica return JSValue::encode(globalObject->JSDebugHTTPSServerConstructor()); } +JSC_DEFINE_CUSTOM_GETTER(DebugHTTPSServerPrototype__addressGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSDebugHTTPSServer* thisObject = jsCast<JSDebugHTTPSServer*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_address.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + DebugHTTPSServerPrototype__getAddress(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_address.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void DebugHTTPSServerPrototype__addressSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSDebugHTTPSServer*>(JSValue::decode(thisValue)); + thisObject->m_address.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue DebugHTTPSServerPrototype__addressGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSDebugHTTPSServer*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_address.get()); +} + JSC_DEFINE_CUSTOM_GETTER(DebugHTTPSServerPrototype__developmentGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); @@ -4440,6 +4488,34 @@ JSC_DEFINE_HOST_FUNCTION(DebugHTTPSServerPrototype__reloadCallback, (JSGlobalObj return DebugHTTPSServerPrototype__doReload(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(DebugHTTPSServerPrototype__requestIPCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSDebugHTTPSServer* thisObject = jsDynamicCast<JSDebugHTTPSServer*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof DebugHTTPSServer"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return DebugHTTPSServerPrototype__doRequestIP(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_HOST_FUNCTION(DebugHTTPSServerPrototype__stopCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -4598,6 +4674,7 @@ void JSDebugHTTPSServer::visitAdditionalChildren(Visitor& visitor) JSDebugHTTPSServer* thisObject = this; ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + visitor.append(thisObject->m_address); visitor.append(thisObject->m_hostname); visitor.append(thisObject->m_id); } @@ -4628,6 +4705,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDebugHTTPServerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -4649,6 +4727,9 @@ JSC_DECLARE_CUSTOM_GETTER(jsDebugHTTPServerConstructor); extern "C" void DebugHTTPServerClass__finalize(void*); +extern "C" JSC::EncodedJSValue DebugHTTPServerPrototype__getAddress(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(DebugHTTPServerPrototype__addressGetterWrap); + extern "C" JSC::EncodedJSValue DebugHTTPServerPrototype__getDevelopment(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(DebugHTTPServerPrototype__developmentGetterWrap); @@ -4679,6 +4760,9 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__publishCallback); extern "C" EncodedJSValue DebugHTTPServerPrototype__doReload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__reloadCallback); +extern "C" EncodedJSValue DebugHTTPServerPrototype__doRequestIP(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__requestIPCallback); + extern "C" EncodedJSValue DebugHTTPServerPrototype__doStop(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__stopCallback); @@ -4688,6 +4772,7 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__upgradeCallback); STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDebugHTTPServerPrototype, JSDebugHTTPServerPrototype::Base); static const HashTableValue JSDebugHTTPServerPrototypeTableValues[] = { + { "address"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__addressGetterWrap, 0 } }, { "development"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__developmentGetterWrap, 0 } }, { "fetch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__fetchCallback, 1 } }, { "hostname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__hostnameGetterWrap, 0 } }, @@ -4698,6 +4783,7 @@ static const HashTableValue JSDebugHTTPServerPrototypeTableValues[] = { { "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__protocolGetterWrap, 0 } }, { "publish"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__publishCallback, 3 } }, { "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__reloadCallback, 2 } }, + { "requestIP"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__requestIPCallback, 1 } }, { "stop"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__stopCallback, 1 } }, { "upgrade"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__upgradeCallback, 1 } } }; @@ -4716,6 +4802,37 @@ JSC_DEFINE_CUSTOM_GETTER(jsDebugHTTPServerConstructor, (JSGlobalObject * lexical return JSValue::encode(globalObject->JSDebugHTTPServerConstructor()); } +JSC_DEFINE_CUSTOM_GETTER(DebugHTTPServerPrototype__addressGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSDebugHTTPServer* thisObject = jsCast<JSDebugHTTPServer*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_address.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + DebugHTTPServerPrototype__getAddress(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_address.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void DebugHTTPServerPrototype__addressSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSDebugHTTPServer*>(JSValue::decode(thisValue)); + thisObject->m_address.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue DebugHTTPServerPrototype__addressGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSDebugHTTPServer*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_address.get()); +} + JSC_DEFINE_CUSTOM_GETTER(DebugHTTPServerPrototype__developmentGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); @@ -4922,6 +5039,34 @@ JSC_DEFINE_HOST_FUNCTION(DebugHTTPServerPrototype__reloadCallback, (JSGlobalObje return DebugHTTPServerPrototype__doReload(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(DebugHTTPServerPrototype__requestIPCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSDebugHTTPServer* thisObject = jsDynamicCast<JSDebugHTTPServer*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof DebugHTTPServer"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return DebugHTTPServerPrototype__doRequestIP(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_HOST_FUNCTION(DebugHTTPServerPrototype__stopCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -5080,6 +5225,7 @@ void JSDebugHTTPServer::visitAdditionalChildren(Visitor& visitor) JSDebugHTTPServer* thisObject = this; ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + visitor.append(thisObject->m_address); visitor.append(thisObject->m_hostname); visitor.append(thisObject->m_id); } @@ -5110,6 +5256,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDirentPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -5644,6 +5791,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDocEndPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -5814,6 +5962,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDocTypePrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -6092,6 +6241,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSElementPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -6808,6 +6958,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSEndTagPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -7072,6 +7223,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSExpectPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -7257,6 +7409,9 @@ JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toEndWithCallback); extern "C" EncodedJSValue ExpectPrototype__toEqual(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toEqualCallback); +extern "C" EncodedJSValue ExpectPrototype__toEqualIgnoringWhitespace(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toEqualIgnoringWhitespaceCallback); + extern "C" EncodedJSValue ExpectPrototype__toHaveBeenCalled(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(ExpectPrototype__toHaveBeenCalledCallback); @@ -7371,6 +7526,7 @@ static const HashTableValue JSExpectPrototypeTableValues[] = { { "toContainEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toContainEqualCallback, 1 } }, { "toEndWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toEndWithCallback, 1 } }, { "toEqual"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toEqualCallback, 1 } }, + { "toEqualIgnoringWhitespace"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toEqualIgnoringWhitespaceCallback, 1 } }, { "toHaveBeenCalled"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenCalledCallback, 0 } }, { "toHaveBeenCalledTimes"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenCalledTimesCallback, 1 } }, { "toHaveBeenCalledWith"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ExpectPrototype__toHaveBeenCalledWithCallback, 1 } }, @@ -8538,6 +8694,34 @@ JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toEqualCallback, (JSGlobalObject * lex return ExpectPrototype__toEqual(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toEqualIgnoringWhitespaceCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSExpect* thisObject = jsDynamicCast<JSExpect*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof Expect"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return ExpectPrototype__toEqualIgnoringWhitespace(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_HOST_FUNCTION(ExpectPrototype__toHaveBeenCalledCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -9436,6 +9620,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSExpectAnyPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -9604,6 +9789,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSExpectAnythingPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -9712,6 +9898,175 @@ extern "C" EncodedJSValue ExpectAnything__create(Zig::GlobalObject* globalObject return JSValue::encode(instance); } +class JSExpectArrayContainingPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + + static JSExpectArrayContainingPrototype* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSExpectArrayContainingPrototype* ptr = new (NotNull, JSC::allocateCell<JSExpectArrayContainingPrototype>(vm)) JSExpectArrayContainingPrototype(vm, globalObject, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSExpectArrayContainingPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSExpectArrayContainingPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; + +extern "C" void ExpectArrayContainingClass__finalize(void*); +extern "C" JSC_DECLARE_HOST_FUNCTION(ExpectArrayContainingClass__call); + +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSExpectArrayContainingPrototype, JSExpectArrayContainingPrototype::Base); + +static const HashTableValue JSExpectArrayContainingPrototypeTableValues[] = {}; + +const ClassInfo JSExpectArrayContainingPrototype::s_info = { "ExpectArrayContaining"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSExpectArrayContainingPrototype) }; + +extern "C" void ExpectArrayContainingPrototype__arrayValueSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSExpectArrayContaining*>(JSValue::decode(thisValue)); + thisObject->m_arrayValue.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue ExpectArrayContainingPrototype__arrayValueGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSExpectArrayContaining*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_arrayValue.get()); +} + +void JSExpectArrayContainingPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + Base::finishCreation(vm); + + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +JSExpectArrayContaining::~JSExpectArrayContaining() +{ + if (m_ctx) { + ExpectArrayContainingClass__finalize(m_ctx); + } +} +void JSExpectArrayContaining::destroy(JSCell* cell) +{ + static_cast<JSExpectArrayContaining*>(cell)->JSExpectArrayContaining::~JSExpectArrayContaining(); +} + +const ClassInfo JSExpectArrayContaining::s_info = { "ExpectArrayContaining"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSExpectArrayContaining) }; + +void JSExpectArrayContaining::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); +} + +JSExpectArrayContaining* JSExpectArrayContaining::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx) +{ + JSExpectArrayContaining* ptr = new (NotNull, JSC::allocateCell<JSExpectArrayContaining>(vm)) JSExpectArrayContaining(vm, structure, ctx); + ptr->finishCreation(vm); + return ptr; +} + +extern "C" void* ExpectArrayContaining__fromJS(JSC::EncodedJSValue value) +{ + JSC::JSValue decodedValue = JSC::JSValue::decode(value); + if (decodedValue.isEmpty() || !decodedValue.isCell()) + return nullptr; + + JSC::JSCell* cell = decodedValue.asCell(); + JSExpectArrayContaining* object = JSC::jsDynamicCast<JSExpectArrayContaining*>(cell); + + if (!object) + return nullptr; + + return object->wrapped(); +} + +extern "C" bool ExpectArrayContaining__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr) +{ + JSExpectArrayContaining* object = JSC::jsDynamicCast<JSExpectArrayContaining*>(JSValue::decode(value)); + if (!object) + return false; + + object->m_ctx = ptr; + return true; +} + +extern "C" const size_t ExpectArrayContaining__ptrOffset = JSExpectArrayContaining::offsetOfWrapped(); + +void JSExpectArrayContaining::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSExpectArrayContaining*>(cell); + if (void* wrapped = thisObject->wrapped()) { + // if (thisObject->scriptExecutionContext()) + // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + } + Base::analyzeHeap(cell, analyzer); +} + +JSObject* JSExpectArrayContaining::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) +{ + return JSExpectArrayContainingPrototype::create(vm, globalObject, JSExpectArrayContainingPrototype::createStructure(vm, globalObject, globalObject->objectPrototype())); +} + +extern "C" EncodedJSValue ExpectArrayContaining__create(Zig::GlobalObject* globalObject, void* ptr) +{ + auto& vm = globalObject->vm(); + JSC::Structure* structure = globalObject->JSExpectArrayContainingStructure(); + JSExpectArrayContaining* instance = JSExpectArrayContaining::create(vm, globalObject, structure, ptr); + + return JSValue::encode(instance); +} + +template<typename Visitor> +void JSExpectArrayContaining::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSExpectArrayContaining* thisObject = jsCast<JSExpectArrayContaining*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_CHILDREN(JSExpectArrayContaining); + +template<typename Visitor> +void JSExpectArrayContaining::visitAdditionalChildren(Visitor& visitor) +{ + JSExpectArrayContaining* thisObject = this; + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + visitor.append(thisObject->m_arrayValue); +} + +DEFINE_VISIT_ADDITIONAL_CHILDREN(JSExpectArrayContaining); + +template<typename Visitor> +void JSExpectArrayContaining::visitOutputConstraintsImpl(JSCell* cell, Visitor& visitor) +{ + JSExpectArrayContaining* thisObject = jsCast<JSExpectArrayContaining*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + thisObject->visitAdditionalChildren<Visitor>(visitor); +} + +DEFINE_VISIT_OUTPUT_CONSTRAINTS(JSExpectArrayContaining); class JSExpectStringContainingPrototype final : public JSC::JSNonFinalObject { public: using Base = JSC::JSNonFinalObject; @@ -9727,6 +10082,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSExpectStringContainingPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -9895,6 +10251,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSExpectStringMatchingPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -10063,6 +10420,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSFFIPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -10313,6 +10671,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSFSWatcherPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -10617,6 +10976,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSFileSystemRouterPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -11063,6 +11423,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTMLRewriterPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -11401,6 +11762,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPSServerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -11422,6 +11784,9 @@ JSC_DECLARE_CUSTOM_GETTER(jsHTTPSServerConstructor); extern "C" void HTTPSServerClass__finalize(void*); +extern "C" JSC::EncodedJSValue HTTPSServerPrototype__getAddress(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(HTTPSServerPrototype__addressGetterWrap); + extern "C" JSC::EncodedJSValue HTTPSServerPrototype__getDevelopment(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(HTTPSServerPrototype__developmentGetterWrap); @@ -11452,6 +11817,9 @@ JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__publishCallback); extern "C" EncodedJSValue HTTPSServerPrototype__doReload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__reloadCallback); +extern "C" EncodedJSValue HTTPSServerPrototype__doRequestIP(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__requestIPCallback); + extern "C" EncodedJSValue HTTPSServerPrototype__doStop(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__stopCallback); @@ -11461,6 +11829,7 @@ JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__upgradeCallback); STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPSServerPrototype, JSHTTPSServerPrototype::Base); static const HashTableValue JSHTTPSServerPrototypeTableValues[] = { + { "address"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__addressGetterWrap, 0 } }, { "development"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__developmentGetterWrap, 0 } }, { "fetch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__fetchCallback, 1 } }, { "hostname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__hostnameGetterWrap, 0 } }, @@ -11471,6 +11840,7 @@ static const HashTableValue JSHTTPSServerPrototypeTableValues[] = { { "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__protocolGetterWrap, 0 } }, { "publish"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__publishCallback, 3 } }, { "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__reloadCallback, 2 } }, + { "requestIP"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__requestIPCallback, 1 } }, { "stop"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__stopCallback, 1 } }, { "upgrade"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__upgradeCallback, 1 } } }; @@ -11489,6 +11859,37 @@ JSC_DEFINE_CUSTOM_GETTER(jsHTTPSServerConstructor, (JSGlobalObject * lexicalGlob return JSValue::encode(globalObject->JSHTTPSServerConstructor()); } +JSC_DEFINE_CUSTOM_GETTER(HTTPSServerPrototype__addressGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSHTTPSServer* thisObject = jsCast<JSHTTPSServer*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_address.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + HTTPSServerPrototype__getAddress(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_address.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void HTTPSServerPrototype__addressSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSHTTPSServer*>(JSValue::decode(thisValue)); + thisObject->m_address.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue HTTPSServerPrototype__addressGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSHTTPSServer*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_address.get()); +} + JSC_DEFINE_CUSTOM_GETTER(HTTPSServerPrototype__developmentGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); @@ -11695,6 +12096,34 @@ JSC_DEFINE_HOST_FUNCTION(HTTPSServerPrototype__reloadCallback, (JSGlobalObject * return HTTPSServerPrototype__doReload(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(HTTPSServerPrototype__requestIPCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSHTTPSServer* thisObject = jsDynamicCast<JSHTTPSServer*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof HTTPSServer"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return HTTPSServerPrototype__doRequestIP(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_HOST_FUNCTION(HTTPSServerPrototype__stopCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -11853,6 +12282,7 @@ void JSHTTPSServer::visitAdditionalChildren(Visitor& visitor) JSHTTPSServer* thisObject = this; ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + visitor.append(thisObject->m_address); visitor.append(thisObject->m_hostname); visitor.append(thisObject->m_id); } @@ -11883,6 +12313,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPServerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -11904,6 +12335,9 @@ JSC_DECLARE_CUSTOM_GETTER(jsHTTPServerConstructor); extern "C" void HTTPServerClass__finalize(void*); +extern "C" JSC::EncodedJSValue HTTPServerPrototype__getAddress(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(HTTPServerPrototype__addressGetterWrap); + extern "C" JSC::EncodedJSValue HTTPServerPrototype__getDevelopment(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(HTTPServerPrototype__developmentGetterWrap); @@ -11934,6 +12368,9 @@ JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__publishCallback); extern "C" EncodedJSValue HTTPServerPrototype__doReload(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__reloadCallback); +extern "C" EncodedJSValue HTTPServerPrototype__doRequestIP(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__requestIPCallback); + extern "C" EncodedJSValue HTTPServerPrototype__doStop(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__stopCallback); @@ -11943,6 +12380,7 @@ JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__upgradeCallback); STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSHTTPServerPrototype, JSHTTPServerPrototype::Base); static const HashTableValue JSHTTPServerPrototypeTableValues[] = { + { "address"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__addressGetterWrap, 0 } }, { "development"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__developmentGetterWrap, 0 } }, { "fetch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__fetchCallback, 1 } }, { "hostname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__hostnameGetterWrap, 0 } }, @@ -11953,6 +12391,7 @@ static const HashTableValue JSHTTPServerPrototypeTableValues[] = { { "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__protocolGetterWrap, 0 } }, { "publish"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__publishCallback, 3 } }, { "reload"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__reloadCallback, 2 } }, + { "requestIP"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__requestIPCallback, 1 } }, { "stop"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__stopCallback, 1 } }, { "upgrade"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__upgradeCallback, 1 } } }; @@ -11971,6 +12410,37 @@ JSC_DEFINE_CUSTOM_GETTER(jsHTTPServerConstructor, (JSGlobalObject * lexicalGloba return JSValue::encode(globalObject->JSHTTPServerConstructor()); } +JSC_DEFINE_CUSTOM_GETTER(HTTPServerPrototype__addressGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSHTTPServer* thisObject = jsCast<JSHTTPServer*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + if (JSValue cachedValue = thisObject->m_address.get()) + return JSValue::encode(cachedValue); + + JSC::JSValue result = JSC::JSValue::decode( + HTTPServerPrototype__getAddress(thisObject->wrapped(), globalObject)); + RETURN_IF_EXCEPTION(throwScope, {}); + thisObject->m_address.set(vm, thisObject, result); + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +extern "C" void HTTPServerPrototype__addressSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value) +{ + auto& vm = globalObject->vm(); + auto* thisObject = jsCast<JSHTTPServer*>(JSValue::decode(thisValue)); + thisObject->m_address.set(vm, thisObject, JSValue::decode(value)); +} + +extern "C" EncodedJSValue HTTPServerPrototype__addressGetCachedValue(JSC::EncodedJSValue thisValue) +{ + auto* thisObject = jsCast<JSHTTPServer*>(JSValue::decode(thisValue)); + return JSValue::encode(thisObject->m_address.get()); +} + JSC_DEFINE_CUSTOM_GETTER(HTTPServerPrototype__developmentGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); @@ -12177,6 +12647,34 @@ JSC_DEFINE_HOST_FUNCTION(HTTPServerPrototype__reloadCallback, (JSGlobalObject * return HTTPServerPrototype__doReload(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(HTTPServerPrototype__requestIPCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSHTTPServer* thisObject = jsDynamicCast<JSHTTPServer*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + throwVMTypeError(lexicalGlobalObject, throwScope, "Expected 'this' to be instanceof HTTPServer"_s); + return JSValue::encode({}); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + +#ifdef BUN_DEBUG + /** View the file name of the JS file that called this function + * from a debugger */ + SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm); + const char* fileName = sourceOrigin.string().utf8().data(); + static const char* lastFileName = nullptr; + if (lastFileName != fileName) { + lastFileName = fileName; + } +#endif + + return HTTPServerPrototype__doRequestIP(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_HOST_FUNCTION(HTTPServerPrototype__stopCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -12335,6 +12833,7 @@ void JSHTTPServer::visitAdditionalChildren(Visitor& visitor) JSHTTPServer* thisObject = this; ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + visitor.append(thisObject->m_address); visitor.append(thisObject->m_hostname); visitor.append(thisObject->m_id); } @@ -12365,6 +12864,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSListenerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -12781,6 +13281,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSMD4Prototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -13111,6 +13612,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSMD5Prototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -13441,6 +13943,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSMatchedRoutePrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -13898,6 +14401,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSNodeJSFSPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -16889,6 +17393,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSRequestPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -17514,7 +18019,7 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSRequestConstructor::construct(JSC } JSRequest* instance = JSRequest::create(vm, globalObject, structure, ptr); - vm.heap.reportExtraMemoryAllocated(Request__estimatedSize(instance->wrapped())); + vm.heap.reportExtraMemoryAllocated(instance, Request__estimatedSize(instance->wrapped())); return JSValue::encode(instance); } @@ -17608,7 +18113,7 @@ extern "C" EncodedJSValue Request__create(Zig::GlobalObject* globalObject, void* auto& vm = globalObject->vm(); JSC::Structure* structure = globalObject->JSRequestStructure(); JSRequest* instance = JSRequest::create(vm, globalObject, structure, ptr); - vm.heap.reportExtraMemoryAllocated(Request__estimatedSize(ptr)); + vm.heap.reportExtraMemoryAllocated(instance, Request__estimatedSize(ptr)); return JSValue::encode(instance); } @@ -17664,6 +18169,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSResolveMessagePrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -18085,7 +18591,7 @@ void JSResolveMessagePrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* { Base::finishCreation(vm); reifyStaticProperties(vm, JSResolveMessage::info(), JSResolveMessagePrototypeTableValues, *this); - this->putDirect(vm, vm.propertyNames->toPrimitiveSymbol, JSFunction::create(vm, globalObject, 1, String("toPrimitive"_s), ResolveMessagePrototype__toPrimitiveCallback, ImplementationVisibility::Public), PropertyAttribute::Function | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); + this->putDirect(vm, vm.propertyNames->toPrimitiveSymbol, JSFunction::create(vm, globalObject, 1, String("toPrimitive"_s), ResolveMessagePrototype__toPrimitiveCallback, ImplementationVisibility::Public), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); this->putDirect(vm, vm.propertyNames->name, jsString(vm, String("ResolveMessage"_s)), PropertyAttribute::ReadOnly | 0); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } @@ -18287,6 +18793,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSResponsePrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -18841,7 +19348,7 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSResponseConstructor::construct(JS } JSResponse* instance = JSResponse::create(vm, globalObject, structure, ptr); - vm.heap.reportExtraMemoryAllocated(Response__estimatedSize(instance->wrapped())); + vm.heap.reportExtraMemoryAllocated(instance, Response__estimatedSize(instance->wrapped())); return JSValue::encode(instance); } @@ -18935,7 +19442,7 @@ extern "C" EncodedJSValue Response__create(Zig::GlobalObject* globalObject, void auto& vm = globalObject->vm(); JSC::Structure* structure = globalObject->JSResponseStructure(); JSResponse* instance = JSResponse::create(vm, globalObject, structure, ptr); - vm.heap.reportExtraMemoryAllocated(Response__estimatedSize(ptr)); + vm.heap.reportExtraMemoryAllocated(instance, Response__estimatedSize(ptr)); return JSValue::encode(instance); } @@ -18991,6 +19498,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSHA1Prototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -19321,6 +19829,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSHA224Prototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -19651,6 +20160,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSHA256Prototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -19981,6 +20491,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSHA384Prototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -20311,6 +20822,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSHA512Prototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -20641,6 +21153,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSHA512_256Prototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -20971,6 +21484,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSServerWebSocketPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -21929,6 +22443,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStatWatcherPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -22201,6 +22716,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStatsPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -23173,6 +23689,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSSubprocessPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -23736,6 +24253,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSTCPSocketPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -24723,8 +25241,10 @@ bool JSTCPSocket::hasPendingActivity(void* ctx) JSTCPSocket::~JSTCPSocket() { + printf("~JSTCPSocket\n"); if (m_ctx) { TCPSocketClass__finalize(m_ctx); + m_ctx = nullptr; } } void JSTCPSocket::destroy(JSCell* cell) @@ -24847,6 +25367,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSTLSSocketPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -25958,6 +26479,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSTextChunkPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -26324,6 +26846,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSTextDecoderPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -26409,12 +26932,16 @@ JSC_DECLARE_CUSTOM_GETTER(TextDecoderPrototype__encodingGetterWrap); extern "C" JSC::EncodedJSValue TextDecoderPrototype__getFatal(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(TextDecoderPrototype__fatalGetterWrap); +extern "C" JSC::EncodedJSValue TextDecoderPrototype__getIgnoreBOM(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); +JSC_DECLARE_CUSTOM_GETTER(TextDecoderPrototype__ignoreBOMGetterWrap); + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSTextDecoderPrototype, JSTextDecoderPrototype::Base); static const HashTableValue JSTextDecoderPrototypeTableValues[] = { { "decode"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::DOMJITFunctionType, TextDecoderPrototype__decodeCallback, &DOMJITSignatureForTextDecoderPrototype__decode } }, { "encoding"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, TextDecoderPrototype__encodingGetterWrap, 0 } }, - { "fatal"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, TextDecoderPrototype__fatalGetterWrap, 0 } } + { "fatal"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, TextDecoderPrototype__fatalGetterWrap, 0 } }, + { "ignoreBOM"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, TextDecoderPrototype__ignoreBOMGetterWrap, 0 } } }; const ClassInfo JSTextDecoderPrototype::s_info = { "TextDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSTextDecoderPrototype) }; @@ -26502,6 +27029,18 @@ JSC_DEFINE_CUSTOM_GETTER(TextDecoderPrototype__fatalGetterWrap, (JSGlobalObject RELEASE_AND_RETURN(throwScope, result); } +JSC_DEFINE_CUSTOM_GETTER(TextDecoderPrototype__ignoreBOMGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) +{ + auto& vm = lexicalGlobalObject->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSTextDecoder* thisObject = jsCast<JSTextDecoder*>(JSValue::decode(thisValue)); + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + JSC::EncodedJSValue result = TextDecoderPrototype__getIgnoreBOM(thisObject->wrapped(), globalObject); + RETURN_IF_EXCEPTION(throwScope, {}); + RELEASE_AND_RETURN(throwScope, result); +} + void JSTextDecoderPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) { Base::finishCreation(vm); @@ -26700,6 +27239,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSTimeoutPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -26914,7 +27454,7 @@ void JSTimeoutPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* global { Base::finishCreation(vm); reifyStaticProperties(vm, JSTimeout::info(), JSTimeoutPrototypeTableValues, *this); - this->putDirect(vm, vm.propertyNames->toPrimitiveSymbol, JSFunction::create(vm, globalObject, 1, String("toPrimitive"_s), TimeoutPrototype__toPrimitiveCallback, ImplementationVisibility::Public), PropertyAttribute::Function | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); + this->putDirect(vm, vm.propertyNames->toPrimitiveSymbol, JSFunction::create(vm, globalObject, 1, String("toPrimitive"_s), TimeoutPrototype__toPrimitiveCallback, ImplementationVisibility::Public), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | 0); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); } @@ -27042,6 +27582,7 @@ public: template<typename CellType, JSC::SubspaceAccess> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSTranspilerPrototype, Base); return &vm.plainObjectSpace(); } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h index 142a96746..c1d7ca99e 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.h +++ b/src/bun.js/bindings/ZigGeneratedClasses.h @@ -510,6 +510,7 @@ public: template<typename Visitor> void visitAdditionalChildren(Visitor&); DECLARE_VISIT_OUTPUT_CONSTRAINTS; + mutable JSC::WriteBarrier<JSC::Unknown> m_address; mutable JSC::WriteBarrier<JSC::Unknown> m_hostname; mutable JSC::WriteBarrier<JSC::Unknown> m_id; }; @@ -567,6 +568,7 @@ public: template<typename Visitor> void visitAdditionalChildren(Visitor&); DECLARE_VISIT_OUTPUT_CONSTRAINTS; + mutable JSC::WriteBarrier<JSC::Unknown> m_address; mutable JSC::WriteBarrier<JSC::Unknown> m_hostname; mutable JSC::WriteBarrier<JSC::Unknown> m_id; }; @@ -1004,6 +1006,62 @@ public: void finishCreation(JSC::VM&); }; +class JSExpectArrayContaining final : public JSC::JSDestructibleObject { +public: + using Base = JSC::JSDestructibleObject; + static JSExpectArrayContaining* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); + + DECLARE_EXPORT_INFO; + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<JSExpectArrayContaining, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForExpectArrayContaining.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForExpectArrayContaining = std::forward<decltype(space)>(space); }, + [](auto& spaces) { return spaces.m_subspaceForExpectArrayContaining.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForExpectArrayContaining = std::forward<decltype(space)>(space); }); + } + + static void destroy(JSC::JSCell*); + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(0b11101110), StructureFlags), info()); + } + + static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); + ; + + ~JSExpectArrayContaining(); + + void* wrapped() const { return m_ctx; } + + void detach() + { + m_ctx = nullptr; + } + + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSExpectArrayContaining, m_ctx); } + + void* m_ctx { nullptr }; + + JSExpectArrayContaining(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) + : Base(vm, structure) + { + m_ctx = sinkPtr; + } + + void finishCreation(JSC::VM&); + + DECLARE_VISIT_CHILDREN; + template<typename Visitor> void visitAdditionalChildren(Visitor&); + DECLARE_VISIT_OUTPUT_CONSTRAINTS; + + mutable JSC::WriteBarrier<JSC::Unknown> m_arrayValue; +}; + class JSExpectStringContaining final : public JSC::JSDestructibleObject { public: using Base = JSC::JSDestructibleObject; @@ -1416,6 +1474,7 @@ public: template<typename Visitor> void visitAdditionalChildren(Visitor&); DECLARE_VISIT_OUTPUT_CONSTRAINTS; + mutable JSC::WriteBarrier<JSC::Unknown> m_address; mutable JSC::WriteBarrier<JSC::Unknown> m_hostname; mutable JSC::WriteBarrier<JSC::Unknown> m_id; }; @@ -1473,6 +1532,7 @@ public: template<typename Visitor> void visitAdditionalChildren(Visitor&); DECLARE_VISIT_OUTPUT_CONSTRAINTS; + mutable JSC::WriteBarrier<JSC::Unknown> m_address; mutable JSC::WriteBarrier<JSC::Unknown> m_hostname; mutable JSC::WriteBarrier<JSC::Unknown> m_id; }; diff --git a/src/bun.js/bindings/ZigGeneratedCode.cpp b/src/bun.js/bindings/ZigGeneratedCode.cpp index 057eaf28e..777c6455e 100644 --- a/src/bun.js/bindings/ZigGeneratedCode.cpp +++ b/src/bun.js/bindings/ZigGeneratedCode.cpp @@ -51,8 +51,7 @@ extern "C" void FFI__ptr__put(JSC::JSGlobalObject* globalObject, JSC::EncodedJSV thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "ptr"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__u8__slowpathWrapper); @@ -92,8 +91,7 @@ extern "C" void Reader__u8__put(JSC::JSGlobalObject* globalObject, JSC::EncodedJ thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "u8"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__u16__slowpathWrapper); @@ -133,8 +131,7 @@ extern "C" void Reader__u16__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "u16"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__u32__slowpathWrapper); @@ -174,8 +171,7 @@ extern "C" void Reader__u32__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "u32"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__ptr__slowpathWrapper); @@ -215,8 +211,7 @@ extern "C" void Reader__ptr__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "ptr"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__i8__slowpathWrapper); @@ -256,8 +251,7 @@ extern "C" void Reader__i8__put(JSC::JSGlobalObject* globalObject, JSC::EncodedJ thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "i8"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__i16__slowpathWrapper); @@ -297,8 +291,7 @@ extern "C" void Reader__i16__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "i16"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__i32__slowpathWrapper); @@ -338,8 +331,7 @@ extern "C" void Reader__i32__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "i32"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__i64__slowpathWrapper); @@ -379,8 +371,7 @@ extern "C" void Reader__i64__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "i64"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__u64__slowpathWrapper); @@ -420,8 +411,7 @@ extern "C" void Reader__u64__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "u64"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__intptr__slowpathWrapper); @@ -461,8 +451,7 @@ extern "C" void Reader__intptr__put(JSC::JSGlobalObject* globalObject, JSC::Enco thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "intptr"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__f32__slowpathWrapper); @@ -502,8 +491,7 @@ extern "C" void Reader__f32__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "f32"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } extern "C" JSC_DECLARE_HOST_FUNCTION(Reader__f64__slowpathWrapper); @@ -543,8 +531,7 @@ extern "C" void Reader__f64__put(JSC::JSGlobalObject* globalObject, JSC::Encoded thisObject->putDirect( globalObject->vm(), Identifier::fromString(globalObject->vm(), "f64"_s), - function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + function); } /* -- END DOMCall DEFINITIONS-- */ diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index cdc4adb1b..93f9a0fa2 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -23,6 +23,7 @@ #include "JavaScriptCore/InitializeThreading.h" #include "JavaScriptCore/IteratorOperations.h" #include "JavaScriptCore/JSArray.h" +#include "JavaScriptCore/JSGlobalProxyInlines.h" #include "JavaScriptCore/JSCallbackConstructor.h" #include "JavaScriptCore/JSCallbackObject.h" @@ -38,6 +39,7 @@ #include "JavaScriptCore/JSMap.h" #include "JavaScriptCore/JSModuleLoader.h" #include "JavaScriptCore/JSModuleNamespaceObject.h" +#include "JavaScriptCore/JSModuleNamespaceObjectInlines.h" #include "JavaScriptCore/JSModuleRecord.h" #include "JavaScriptCore/JSNativeStdFunction.h" #include "JavaScriptCore/JSObject.h" @@ -103,6 +105,7 @@ #include "JavaScriptCore/LazyClassStructure.h" #include "JavaScriptCore/LazyClassStructureInlines.h" #include "JavaScriptCore/FunctionPrototype.h" +#include "JavaScriptCore/GetterSetter.h" #include "napi.h" #include "JSSQLStatement.h" #include "ModuleLoader.h" @@ -125,6 +128,8 @@ #include "JSDOMFile.h" +#include "ProcessBindingConstants.h" + #if ENABLE(REMOTE_INSPECTOR) #include "JavaScriptCore/RemoteInspectorServer.h" #endif @@ -186,9 +191,6 @@ namespace JSCastingHelpers = JSC::JSCastingHelpers; #include "DOMJITHelpers.h" #include <JavaScriptCore/DFGAbstractHeap.h> -#include "webcrypto/JSCryptoKey.h" -#include "webcrypto/JSSubtleCrypto.h" - #include "JSDOMFormData.h" #include "JSDOMBinding.h" #include "JSDOMConstructor.h" @@ -201,6 +203,7 @@ namespace JSCastingHelpers = JSC::JSCastingHelpers; #include "JSDOMConvertStrings.h" #include "JSDOMConvertUnion.h" #include "AddEventListenerOptions.h" +#include "JSSocketAddress.h" #include "ErrorStackTrace.h" #include "CallSite.h" @@ -211,6 +214,9 @@ namespace JSCastingHelpers = JSC::JSCastingHelpers; #include <wtf/text/Base64.h> #include "simdutf.h" #include "libusockets.h" +#include "KeyObject.h" +#include "webcrypto/JSCryptoKey.h" +#include "webcrypto/JSSubtleCrypto.h" constexpr size_t DEFAULT_ERROR_STACK_TRACE_LIMIT = 10; @@ -226,6 +232,10 @@ static bool has_loaded_jsc = false; Structure* createMemoryFootprintStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject); +namespace Bun { +extern JSC::EncodedJSValue Process_functionInternalGetWindowSize(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); +} + namespace WebCore { class Base64Utilities { public: @@ -270,6 +280,7 @@ extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(c JSC::Options::useShadowRealm() = true; JSC::Options::useResizableArrayBuffer() = true; JSC::Options::usePromiseWithResolversMethod() = true; + JSC::Options::useV8DateParser() = true; #ifdef BUN_DEBUG JSC::Options::showPrivateScriptsInStackTraces() = true; @@ -305,29 +316,16 @@ static bool skipNextComputeErrorInfo = false; // error.stack calls this function static String computeErrorInfoWithoutPrepareStackTrace(JSC::VM& vm, Vector<StackFrame>& stackTrace, unsigned& line, unsigned& column, String& sourceURL, JSObject* errorInstance) { - if (!errorInstance) { - return String(); - } - - if (skipNextComputeErrorInfo) { - return String(); - } - - Zig::GlobalObject* globalObject = jsDynamicCast<Zig::GlobalObject*>(errorInstance->globalObject()); - if (!globalObject) { - // Happens in node:vm - globalObject = jsDynamicCast<Zig::GlobalObject*>(Bun__getDefaultGlobal()); - } + auto* lexicalGlobalObject = errorInstance->globalObject(); + Zig::GlobalObject* globalObject = jsDynamicCast<Zig::GlobalObject*>(lexicalGlobalObject); WTF::String name = "Error"_s; WTF::String message; - if (errorInstance) { - // Note that we are not allowed to allocate memory in here. It's called inside a finalizer. - if (auto* instance = jsDynamicCast<ErrorInstance*>(errorInstance)) { - name = instance->sanitizedNameString(globalObject); - message = instance->sanitizedMessageString(globalObject); - } + // Note that we are not allowed to allocate memory in here. It's called inside a finalizer. + if (auto* instance = jsDynamicCast<ErrorInstance*>(errorInstance)) { + name = instance->sanitizedNameString(lexicalGlobalObject); + message = instance->sanitizedMessageString(lexicalGlobalObject); } WTF::StringBuilder sb; @@ -381,20 +379,23 @@ static String computeErrorInfoWithoutPrepareStackTrace(JSC::VM& vm, Vector<Stack unsigned int thisColumn = 0; frame.computeLineAndColumn(thisLine, thisColumn); memset(remappedFrames + i, 0, sizeof(ZigStackFrame)); - remappedFrames[i].position.line = thisLine; remappedFrames[i].position.column_start = thisColumn; + String sourceURLForFrame = frame.sourceURL(vm); - if (!sourceURLForFrame.isEmpty()) { - remappedFrames[i].source_url = Bun::toString(sourceURLForFrame); - } else { - // https://github.com/oven-sh/bun/issues/3595 - remappedFrames[i].source_url = BunStringEmpty; - } + // If it's not a Zig::GlobalObject, don't bother source-mapping it. + if (globalObject) { + if (!sourceURLForFrame.isEmpty()) { + remappedFrames[i].source_url = Bun::toString(sourceURLForFrame); + } else { + // https://github.com/oven-sh/bun/issues/3595 + remappedFrames[i].source_url = BunStringEmpty; + } - // This ensures the lifetime of the sourceURL is accounted for correctly - Bun__remapStackFramePositions(globalObject, remappedFrames + i, 1); + // This ensures the lifetime of the sourceURL is accounted for correctly + Bun__remapStackFramePositions(globalObject, remappedFrames + i, 1); + } if (!hasSet) { hasSet = true; @@ -402,11 +403,9 @@ static String computeErrorInfoWithoutPrepareStackTrace(JSC::VM& vm, Vector<Stack column = thisColumn; sourceURL = frame.sourceURL(vm); - if (errorInstance) { - if (remappedFrames[i].remapped) { - errorInstance->putDirect(vm, Identifier::fromString(vm, "originalLine"_s), jsNumber(thisLine), 0); - errorInstance->putDirect(vm, Identifier::fromString(vm, "originalColumn"_s), jsNumber(thisColumn), 0); - } + if (remappedFrames[i].remapped) { + errorInstance->putDirect(vm, Identifier::fromString(vm, "originalLine"_s), jsNumber(thisLine), 0); + errorInstance->putDirect(vm, Identifier::fromString(vm, "originalColumn"_s), jsNumber(thisColumn), 0); } } @@ -428,8 +427,95 @@ static String computeErrorInfoWithoutPrepareStackTrace(JSC::VM& vm, Vector<Stack return sb.toString(); } +static String computeErrorInfoWithPrepareStackTrace(JSC::VM& vm, Zig::GlobalObject* globalObject, JSC::JSGlobalObject* lexicalGlobalObject, Vector<StackFrame>& stackFrames, unsigned& line, unsigned& column, String& sourceURL, JSObject* errorObject, JSObject* prepareStackTrace) +{ + auto scope = DECLARE_THROW_SCOPE(vm); + size_t stackTraceLimit = globalObject->stackTraceLimit().value(); + if (stackTraceLimit == 0) { + stackTraceLimit = DEFAULT_ERROR_STACK_TRACE_LIMIT; + } + + JSCStackTrace stackTrace = JSCStackTrace::fromExisting(vm, stackFrames); + + // Note: we cannot use tryCreateUninitializedRestricted here because we cannot allocate memory inside initializeIndex() + JSC::JSArray* callSites = JSC::JSArray::create(vm, + globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous), + stackTrace.size()); + + // Create the call sites (one per frame) + GlobalObject::createCallSitesFromFrames(globalObject, lexicalGlobalObject, stackTrace, callSites); + + // We need to sourcemap it if it's a GlobalObject. + if (globalObject == lexicalGlobalObject) { + size_t framesCount = stackTrace.size(); + ZigStackFrame remappedFrames[framesCount]; + for (int i = 0; i < framesCount; i++) { + memset(remappedFrames + i, 0, sizeof(ZigStackFrame)); + remappedFrames[i].source_url = Bun::toString(lexicalGlobalObject, stackTrace.at(i).sourceURL()); + if (JSCStackFrame::SourcePositions* sourcePositions = stackTrace.at(i).getSourcePositions()) { + remappedFrames[i].position.line = sourcePositions->line.zeroBasedInt(); + remappedFrames[i].position.column_start = sourcePositions->startColumn.zeroBasedInt() + 1; + } else { + remappedFrames[i].position.line = -1; + remappedFrames[i].position.column_start = -1; + } + } + + Bun__remapStackFramePositions(globalObject, remappedFrames, framesCount); + + for (size_t i = 0; i < framesCount; i++) { + JSC::JSValue callSiteValue = callSites->getIndex(lexicalGlobalObject, i); + CallSite* callSite = JSC::jsDynamicCast<CallSite*>(callSiteValue); + if (remappedFrames[i].remapped) { + int32_t remappedColumnStart = remappedFrames[i].position.column_start; + JSC::JSValue columnNumber = JSC::jsNumber(remappedColumnStart); + callSite->setColumnNumber(columnNumber); + + int32_t remappedLine = remappedFrames[i].position.line; + JSC::JSValue lineNumber = JSC::jsNumber(remappedLine); + callSite->setLineNumber(lineNumber); + } + } + } + + globalObject->formatStackTrace(vm, lexicalGlobalObject, errorObject, callSites, prepareStackTrace); + + RETURN_IF_EXCEPTION(scope, String()); + return String(); +} + static String computeErrorInfo(JSC::VM& vm, Vector<StackFrame>& stackTrace, unsigned& line, unsigned& column, String& sourceURL, JSObject* errorInstance) { + if (skipNextComputeErrorInfo) { + return String(); + } + + if (!errorInstance) { + return String(); + } + + auto* lexicalGlobalObject = errorInstance->globalObject(); + Zig::GlobalObject* globalObject = jsDynamicCast<Zig::GlobalObject*>(lexicalGlobalObject); + + // Error.prepareStackTrace - https://v8.dev/docs/stack-trace-api#customizing-stack-traces + if (!globalObject) { + // node:vm will use a different JSGlobalObject + globalObject = Bun__getDefaultGlobal(); + + auto* errorConstructor = lexicalGlobalObject->m_errorStructure.constructor(lexicalGlobalObject); + if (JSValue prepareStackTrace = errorConstructor->getIfPropertyExists(lexicalGlobalObject, Identifier::fromString(vm, "prepareStackTrace"_s))) { + if (prepareStackTrace.isCell() && prepareStackTrace.isObject() && prepareStackTrace.isCallable()) { + return computeErrorInfoWithPrepareStackTrace(vm, globalObject, lexicalGlobalObject, stackTrace, line, column, sourceURL, errorInstance, prepareStackTrace.getObject()); + } + } + } else { + if (JSValue prepareStackTrace = globalObject->m_errorConstructorPrepareStackTraceValue.get()) { + if (prepareStackTrace.isCell() && prepareStackTrace.isObject() && prepareStackTrace.isCallable()) { + return computeErrorInfoWithPrepareStackTrace(vm, globalObject, lexicalGlobalObject, stackTrace, line, column, sourceURL, errorInstance, prepareStackTrace.getObject()); + } + } + } + return computeErrorInfoWithoutPrepareStackTrace(vm, stackTrace, line, column, sourceURL, errorInstance); } @@ -627,69 +713,17 @@ extern "C" bool Zig__GlobalObject__resetModuleRegistryMap(JSC__JSGlobalObject* g return true; } -#define BUN_LAZY_GETTER_FN_NAME(GetterName) BunLazyGetter##GetterName##_getter - -#define DEFINE_BUN_LAZY_GETTER(GetterName, __propertyName) \ - JSC_DEFINE_CUSTOM_GETTER(GetterName, \ - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, \ - JSC::PropertyName)) \ - { \ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); \ - return JSC::JSValue::encode(thisObject->__propertyName()); \ - } - -#define GENERATED_CONSTRUCTOR_GETTER(ConstructorName) \ - JSC_DECLARE_CUSTOM_GETTER(ConstructorName##_getter); \ - JSC_DEFINE_CUSTOM_GETTER(ConstructorName##_getter, \ - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, \ - JSC::PropertyName)) \ - { \ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); \ - if (JSValue override = thisObject->m_##ConstructorName##SetterValue.get()) { \ - return JSC::JSValue::encode(override); \ - } \ - return JSC::JSValue::encode( \ - thisObject->ConstructorName##Constructor()); \ - } - -#define GENERATED_CONSTRUCTOR_SETTER(ConstructorName) \ - JSC_DECLARE_CUSTOM_SETTER(ConstructorName##_setter); \ - JSC_DEFINE_CUSTOM_SETTER(ConstructorName##_setter, \ - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, \ - EncodedJSValue value, JSC::PropertyName)) \ - { \ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); \ - thisObject->m_##ConstructorName##SetterValue.set(thisObject->vm(), thisObject, JSValue::decode(value)); \ - return true; \ - } - -#define WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ConstructorName) \ - JSC_DECLARE_CUSTOM_GETTER(ConstructorName##_getter); \ - JSC_DEFINE_CUSTOM_GETTER(ConstructorName##_getter, \ - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, \ - JSC::PropertyName)) \ - { \ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); \ - if (JSValue override = thisObject->m_##ConstructorName##SetterValue.get()) { \ - return JSC::JSValue::encode(override); \ - } \ - return JSC::JSValue::encode( \ - WebCore::ConstructorName::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); \ - } - -#define WEBCORE_GENERATED_CONSTRUCTOR_SETTER(ConstructorName) \ - JSC_DECLARE_CUSTOM_SETTER(ConstructorName##_setter); \ - JSC_DEFINE_CUSTOM_SETTER(ConstructorName##_setter, \ - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, \ - EncodedJSValue value, JSC::PropertyName)) \ - { \ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); \ - thisObject->m_##ConstructorName##SetterValue.set(thisObject->vm(), thisObject, JSValue::decode(value)); \ - return true; \ - } - -#define PUT_WEBCORE_GENERATED_CONSTRUCTOR(name, ConstructorName) \ - putDirectCustomAccessor(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, name)), JSC::CustomGetterSetter::create(vm, ConstructorName##_getter, ConstructorName##_setter), 0) +#define WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ConstructorName) \ + JSValue ConstructorName##ConstructorCallback(VM& vm, JSObject* lexicalGlobalObject) \ + { \ + return WebCore::JS##ConstructorName::getConstructor(vm, JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject)); \ + } \ + JSC_DEFINE_CUSTOM_GETTER(ConstructorName##_getter, \ + (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, \ + JSC::PropertyName)) \ + { \ + return JSC::JSValue::encode(WebCore::JS##ConstructorName::getConstructor(lexicalGlobalObject->vm(), JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject))); \ + } String GlobalObject::defaultAgentClusterID() { @@ -708,9 +742,6 @@ namespace Zig { using namespace WebCore; -const JSC::ClassInfo GlobalObject::s_info = { "GlobalObject"_s, &Base::s_info, nullptr, nullptr, - CREATE_METHOD_TABLE(GlobalObject) }; - static JSGlobalObject* deriveShadowRealmGlobalObject(JSGlobalObject* globalObject) { auto& vm = globalObject->vm(); @@ -734,9 +765,9 @@ extern "C" JSC__JSValue JSC__JSValue__makeWithNameAndPrototype(JSC__JSGlobalObje JSC::JSObject* wrapped = JSC::JSValue::decode(reinterpret_cast<JSC__JSValue>(wrappedRef)).getObject(); object->setPrototypeDirect(vm, wrapped); JSString* nameString = JSC::jsNontrivialString(vm, Zig::toString(*visibleInterfaceName)); - object->putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + object->putDirect(vm, vm.propertyNames->name, nameString, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum); object->putDirect(vm, vm.propertyNames->toStringTagSymbol, - nameString, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly); + nameString, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly); return JSC::JSValue::encode(JSC::JSValue(object)); } @@ -801,7 +832,7 @@ GlobalObject::~GlobalObject() finalizer(toNapi(this), napiInstanceData, napiInstanceDataFinalizerHint); } - delete crypto; + delete m_subtleCrypto; scriptExecutionContext()->removeFromContextsMap(); } @@ -851,9 +882,31 @@ void GlobalObject::setConsole(void* console) this->setConsoleClient(new Zig::ConsoleClient(console)); } +JSC_DEFINE_CUSTOM_GETTER(errorConstructorPrepareStackTraceGetter, + (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, + JSC::PropertyName)) +{ + Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); + JSValue value = jsUndefined(); + if (thisObject->m_errorConstructorPrepareStackTraceValue) { + value = thisObject->m_errorConstructorPrepareStackTraceValue.get(); + } + return JSValue::encode(value); +} + +JSC_DEFINE_CUSTOM_SETTER(errorConstructorPrepareStackTraceSetter, + (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, + JSC::EncodedJSValue encodedValue, JSC::PropertyName property)) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); + thisObject->m_errorConstructorPrepareStackTraceValue.set(vm, thisObject, JSValue::decode(encodedValue)); + return true; +} + #pragma mark - Globals -JSC_DEFINE_CUSTOM_GETTER(globalGetterOnMessage, +JSC_DEFINE_CUSTOM_GETTER(globalOnMessage, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) { @@ -861,7 +914,7 @@ JSC_DEFINE_CUSTOM_GETTER(globalGetterOnMessage, return JSValue::encode(eventHandlerAttribute(thisObject->eventTarget(), eventNames().messageEvent, thisObject->world())); } -JSC_DEFINE_CUSTOM_GETTER(globalGetterOnError, +JSC_DEFINE_CUSTOM_GETTER(globalOnError, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) { @@ -869,7 +922,7 @@ JSC_DEFINE_CUSTOM_GETTER(globalGetterOnError, return JSValue::encode(eventHandlerAttribute(thisObject->eventTarget(), eventNames().errorEvent, thisObject->world())); } -JSC_DEFINE_CUSTOM_SETTER(globalSetterOnMessage, +JSC_DEFINE_CUSTOM_SETTER(setGlobalOnMessage, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, JSC::PropertyName property)) { @@ -882,7 +935,7 @@ JSC_DEFINE_CUSTOM_SETTER(globalSetterOnMessage, return true; } -JSC_DEFINE_CUSTOM_SETTER(globalSetterOnError, +JSC_DEFINE_CUSTOM_SETTER(setGlobalOnError, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, JSC::PropertyName property)) { @@ -900,8 +953,6 @@ WebCore::EventTarget& GlobalObject::eventTarget() return globalEventScope; } -JSC_DECLARE_CUSTOM_GETTER(functionLazyLoadStreamPrototypeMap_getter); - JSC_DEFINE_CUSTOM_GETTER(functionLazyLoadStreamPrototypeMap_getter, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) @@ -911,165 +962,61 @@ JSC_DEFINE_CUSTOM_GETTER(functionLazyLoadStreamPrototypeMap_getter, thisObject->readableStreamNativeMap()); } -JSC_DECLARE_CUSTOM_GETTER(JSDOMURL_getter); - -JSC_DEFINE_CUSTOM_GETTER(JSDOMURL_getter, - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, - JSC::PropertyName)) -{ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); - return JSC::JSValue::encode( - WebCore::JSDOMURL::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); -} - -JSC_DEFINE_CUSTOM_GETTER(JSBuffer_privateGetter, - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, - JSC::PropertyName)) -{ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); - return JSC::JSValue::encode( - thisObject->JSBufferConstructor()); -} - -GENERATED_CONSTRUCTOR_GETTER(JSBuffer); -GENERATED_CONSTRUCTOR_SETTER(JSBuffer); - -GENERATED_CONSTRUCTOR_GETTER(JSTextDecoder); -GENERATED_CONSTRUCTOR_SETTER(JSTextDecoder); - -GENERATED_CONSTRUCTOR_GETTER(JSResponse); -GENERATED_CONSTRUCTOR_SETTER(JSResponse); - -GENERATED_CONSTRUCTOR_GETTER(JSRequest); -GENERATED_CONSTRUCTOR_SETTER(JSRequest); - -GENERATED_CONSTRUCTOR_GETTER(JSBlob); -GENERATED_CONSTRUCTOR_SETTER(JSBlob); - -GENERATED_CONSTRUCTOR_GETTER(JSHTMLRewriter); -GENERATED_CONSTRUCTOR_SETTER(JSHTMLRewriter); - -GENERATED_CONSTRUCTOR_GETTER(JSCrypto); -GENERATED_CONSTRUCTOR_SETTER(JSCrypto); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSMessageEvent); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSMessageEvent); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSWebSocket); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSWebSocket); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSFetchHeaders); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSFetchHeaders); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSTextEncoder); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSTextEncoder); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSURLSearchParams); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSURLSearchParams); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSDOMFormData); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSDOMFormData); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSWorker); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSWorker); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSMessageChannel); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSMessageChannel); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSMessagePort); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSMessagePort); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSBroadcastChannel); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSBroadcastChannel); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSEvent); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSEvent); - -JSC_DECLARE_CUSTOM_GETTER(JSEvent_getter); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSDOMException); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSDOMException); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSEventTarget); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSEventTarget); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSCustomEvent); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSCustomEvent); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSErrorEvent); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSErrorEvent); - -WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSCloseEvent); -WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSCloseEvent); - -JSC_DECLARE_CUSTOM_GETTER(JSDOMAbortController_getter); - -JSC_DEFINE_CUSTOM_GETTER(JSDOMAbortController_getter, +JSC_DEFINE_CUSTOM_GETTER(JSBuffer_getter, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) { - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); - return JSC::JSValue::encode( - WebCore::JSAbortController::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); -} - -JSC_DECLARE_CUSTOM_GETTER(JSDOMAbortSignal_getter); - -JSC_DEFINE_CUSTOM_GETTER(JSDOMAbortSignal_getter, - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, - JSC::PropertyName)) -{ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); - return JSC::JSValue::encode( - WebCore::JSAbortSignal::getConstructor(JSC::getVM(lexicalGlobalObject), thisObject)); -} - -static JSC_DECLARE_CUSTOM_SETTER(property_lazyProcessSetter); -static JSC_DECLARE_CUSTOM_GETTER(property_lazyProcessGetter); - -JSC_DEFINE_CUSTOM_SETTER(property_lazyProcessSetter, - (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, - JSC::EncodedJSValue value, JSC::PropertyName)) -{ - return false; -} - -JSC_DEFINE_CUSTOM_GETTER(property_lazyProcessGetter, - (JSC::JSGlobalObject * _globalObject, JSC::EncodedJSValue thisValue, - JSC::PropertyName)) -{ - Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(_globalObject); - - JSC::VM& vm = globalObject->vm(); - auto clientData = WebCore::clientData(vm); - return JSC::JSValue::encode( - globalObject->processObject()); -} - -JSC_DEFINE_CUSTOM_GETTER(property_lazyCryptoGetter, - (JSC::JSGlobalObject * lexicalGlobalObject, JSC::EncodedJSValue thisValue, - JSC::PropertyName property)) + return JSC::JSValue::encode(JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject)->JSBufferConstructor()); +} + +// This macro defines the getter needed for ZigGlobalObject.lut.h +// "<ClassName>ConstructorCallback" is a PropertyCallback +// it also defines "<ClassName>_getter" which is the getter for a JSC::CustomGetterSetter +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(AbortController); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(AbortSignal); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(BroadcastChannel); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ByteLengthQueuingStrategy) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(CloseEvent); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(CountQueuingStrategy) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(CryptoKey); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(CustomEvent); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(DOMException); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(DOMFormData); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(DOMURL); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ErrorEvent); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(Event); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(EventTarget); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(FetchHeaders); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(MessageChannel); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(MessageEvent); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(MessagePort); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ReadableByteStreamController) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ReadableStream) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ReadableStreamBYOBReader) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ReadableStreamBYOBRequest) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ReadableStreamDefaultController) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(ReadableStreamDefaultReader) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(SubtleCrypto); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(TextEncoder); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(TransformStream) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(TransformStreamDefaultController) +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(URLSearchParams); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(WebSocket); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(Worker); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(WritableStream); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(WritableStreamDefaultController); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(WritableStreamDefaultWriter); + +JSC_DEFINE_HOST_FUNCTION(functionGetSelf, + (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(JSValue::decode(thisValue)); - JSValue cryptoObject = thisObject->cryptoObject(); - thisObject->putDirect(thisObject->vm(), property, cryptoObject, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - return JSValue::encode(cryptoObject); + return JSC::JSValue::encode(callFrame->thisValue()); } -JSC_DEFINE_CUSTOM_SETTER(lazyProcessEnvSetter, - (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, - JSC::EncodedJSValue value, JSC::PropertyName)) -{ - return false; -} - -JSC_DEFINE_CUSTOM_GETTER(lazyProcessEnvGetter, - (JSC::JSGlobalObject * _globalObject, JSC::EncodedJSValue thisValue, - JSC::PropertyName)) +JSC_DEFINE_HOST_FUNCTION(functionSetSelf, + (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(_globalObject); - return JSC::JSValue::encode( - globalObject->processEnvObject()); + return JSC::JSValue::encode(jsUndefined()); } JSC_DEFINE_HOST_FUNCTION(functionQueueMicrotask, @@ -1385,7 +1332,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBTOA, static_cast<uint8_t>(WebCore::BufferEncodingType::base64))); } -static JSC_DEFINE_HOST_FUNCTION(functionATOB, +JSC_DEFINE_HOST_FUNCTION(functionATOB, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { JSC::VM& vm = globalObject->vm(); @@ -1408,7 +1355,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionATOB, RELEASE_AND_RETURN(throwScope, JSValue::encode(jsString(vm, result.releaseReturnValue()))); } -static JSC_DEFINE_HOST_FUNCTION(functionReportError, +JSC_DEFINE_HOST_FUNCTION(functionReportError, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { switch (callFrame->argumentCount()) { @@ -1538,6 +1485,89 @@ JSC_DEFINE_HOST_FUNCTION(jsTTYSetMode, (JSC::JSGlobalObject * globalObject, Call return JSValue::encode(jsNumber(err)); } +JSC_DEFINE_HOST_FUNCTION(jsHTTPGetHeader, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue headersValue = callFrame->argument(0); + + if (auto* headers = jsDynamicCast<WebCore::JSFetchHeaders*>(headersValue)) { + JSValue nameValue = callFrame->argument(1); + if (nameValue.isString()) { + FetchHeaders* impl = &headers->wrapped(); + String name = nameValue.toWTFString(globalObject); + if (WTF::equalIgnoringASCIICase(name, "set-cookie"_s)) { + return fetchHeadersGetSetCookie(globalObject, vm, impl); + } + + WebCore::ExceptionOr<String> res = impl->get(name); + if (res.hasException()) { + WebCore::propagateException(globalObject, scope, res.releaseException()); + return JSValue::encode(jsUndefined()); + } + + String value = res.returnValue(); + if (value.isEmpty()) { + return JSValue::encode(jsUndefined()); + } + + return JSC::JSValue::encode(jsString(vm, value)); + } + } + + return JSValue::encode(jsUndefined()); +} + +JSC_DEFINE_HOST_FUNCTION(jsHTTPSetHeader, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + auto& vm = globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue headersValue = callFrame->argument(0); + + if (auto* headers = jsDynamicCast<WebCore::JSFetchHeaders*>(headersValue)) { + JSValue nameValue = callFrame->argument(1); + if (nameValue.isString()) { + String name = nameValue.toWTFString(globalObject); + FetchHeaders* impl = &headers->wrapped(); + + JSValue valueValue = callFrame->argument(2); + if (valueValue.isUndefined()) + return JSValue::encode(jsUndefined()); + + if (isArray(globalObject, valueValue)) { + auto* array = jsCast<JSArray*>(valueValue); + unsigned length = array->length(); + if (length > 0) { + JSValue item = array->getIndex(globalObject, 0); + if (UNLIKELY(scope.exception())) + return JSValue::encode(jsUndefined()); + impl->set(name, item.getString(globalObject)); + RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined())); + } + for (unsigned i = 1; i < length; ++i) { + JSValue value = array->getIndex(globalObject, i); + if (UNLIKELY(scope.exception())) + return JSValue::encode(jsUndefined()); + if (!value.isString()) + continue; + impl->append(name, value.getString(globalObject)); + RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined())); + } + RELEASE_AND_RETURN(scope, JSValue::encode(jsUndefined())); + return JSValue::encode(jsUndefined()); + } + + impl->set(name, valueValue.getString(globalObject)); + RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined())); + return JSValue::encode(jsUndefined()); + } + } + + return JSValue::encode(jsUndefined()); +} + JSC_DEFINE_CUSTOM_GETTER(noop_getter, (JSGlobalObject*, EncodedJSValue, PropertyName)) { return JSC::JSValue::encode(JSC::jsUndefined()); @@ -1577,15 +1607,6 @@ enum ReadableStreamTag : int32_t { Bytes = 4, }; -JSC_DEFINE_HOST_FUNCTION(functionCallNotImplemented, - (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) -{ - auto& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - throwTypeError(globalObject, scope, "Not implemented yet in Bun :("_s); - return JSC::JSValue::encode(JSC::JSValue {}); -} - JSC_DEFINE_HOST_FUNCTION(jsReceiveMessageOnPort, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -1614,11 +1635,9 @@ JSC_DEFINE_HOST_FUNCTION(jsReceiveMessageOnPort, (JSGlobalObject * lexicalGlobal return JSC::JSValue::encode(jsUndefined()); } -extern JSC::EncodedJSValue Process_functionInternalGetWindowSize(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); - // we're trying out a new way to do this lazy loading // this is $lazy() in js code -static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, +JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { @@ -1628,7 +1647,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, switch (callFrame->argumentCount()) { case 0: { - JSC::throwTypeError(globalObject, scope, "lazyLoad needs 1 argument (a string)"_s); + JSC::throwTypeError(globalObject, scope, "$lazy needs 1 argument (a string)"_s); scope.release(); return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1637,7 +1656,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, if (moduleName.isNumber()) { switch (moduleName.toInt32(globalObject)) { case 0: { - JSC::throwTypeError(globalObject, scope, "lazyLoad expects a string"_s); + JSC::throwTypeError(globalObject, scope, "$lazy expects a string"_s); scope.release(); return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1654,7 +1673,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, default: { auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); - JSC::throwTypeError(globalObject, scope, "lazyLoad expects a string"_s); + JSC::throwTypeError(globalObject, scope, "$lazy expects a string"_s); scope.release(); return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1663,7 +1682,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, auto string = moduleName.toWTFString(globalObject); if (string.isNull()) { - JSC::throwTypeError(globalObject, scope, "lazyLoad expects a string"_s); + JSC::throwTypeError(globalObject, scope, "$lazy expects a string"_s); scope.release(); return JSC::JSValue::encode(JSC::JSValue {}); } @@ -1672,6 +1691,17 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, return JSC::JSValue::encode(JSSQLStatementConstructor::create(vm, globalObject, JSSQLStatementConstructor::createStructure(vm, globalObject, globalObject->m_functionPrototype.get()))); } + if (string == "http"_s) { + auto* obj = constructEmptyObject(globalObject); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "setHeader"_s)), + JSC::JSFunction::create(vm, globalObject, 3, "setHeader"_s, jsHTTPSetHeader, ImplementationVisibility::Public), NoIntrinsic); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "getHeader"_s)), + JSC::JSFunction::create(vm, globalObject, 2, "getHeader"_s, jsHTTPGetHeader, ImplementationVisibility::Public), NoIntrinsic); + return JSC::JSValue::encode(obj); + } + if (string == "worker_threads"_s) { JSValue workerData = jsUndefined(); @@ -1729,6 +1759,41 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, if (string == "events"_s) { return JSValue::encode(WebCore::JSEventEmitter::getConstructor(vm, globalObject)); } + + if (string == "internal/crypto"_s) { + // auto sourceOrigin = callFrame->callerSourceOrigin(vm).url(); + // bool isBuiltin = sourceOrigin.protocolIs("builtin"_s); + // if (!isBuiltin) { + // return JSC::JSValue::encode(JSC::jsUndefined()); + // } + auto* obj = constructEmptyObject(globalObject); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "symmetricKeySize"_s)), JSC::JSFunction::create(vm, globalObject, 1, "symmetricKeySize"_s, KeyObject__SymmetricKeySize, ImplementationVisibility::Public, NoIntrinsic), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "asymmetricKeyType"_s)), JSC::JSFunction::create(vm, globalObject, 1, "asymmetricKeyType"_s, KeyObject__AsymmetricKeyType, ImplementationVisibility::Public, NoIntrinsic), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "asymmetricKeyDetails"_s)), JSC::JSFunction::create(vm, globalObject, 1, "asymmetricKeyDetails"_s, KeyObject_AsymmetricKeyDetails, ImplementationVisibility::Public, NoIntrinsic), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "equals"_s)), JSC::JSFunction::create(vm, globalObject, 2, "equals"_s, KeyObject__Equals, ImplementationVisibility::Public, NoIntrinsic), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "exports"_s)), JSC::JSFunction::create(vm, globalObject, 2, "exports"_s, KeyObject__Exports, ImplementationVisibility::Public, NoIntrinsic), 0); + + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "createSecretKey"_s)), JSC::JSFunction::create(vm, globalObject, 1, "createSecretKey"_s, KeyObject__createSecretKey, ImplementationVisibility::Public, NoIntrinsic), 0); + + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "createPublicKey"_s)), JSC::JSFunction::create(vm, globalObject, 1, "createPublicKey"_s, KeyObject__createPublicKey, ImplementationVisibility::Public, NoIntrinsic), 0); + + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "createPrivateKey"_s)), JSC::JSFunction::create(vm, globalObject, 1, "createPrivateKey"_s, KeyObject__createPrivateKey, ImplementationVisibility::Public, NoIntrinsic), 0); + + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "generateKeySync"_s)), JSC::JSFunction::create(vm, globalObject, 2, "generateKeySync"_s, KeyObject__generateKeySync, ImplementationVisibility::Public, NoIntrinsic), 0); + + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "generateKeyPairSync"_s)), JSC::JSFunction::create(vm, globalObject, 2, "generateKeyPairSync"_s, KeyObject__generateKeyPairSync, ImplementationVisibility::Public, NoIntrinsic), 0); + + return JSValue::encode(obj); + } + if (string == "internal/tls"_s) { auto* obj = constructEmptyObject(globalObject); @@ -1759,10 +1824,6 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, return JSValue::encode(obj); } - if (string == "masqueradesAsUndefined"_s) { - return JSValue::encode(InternalFunction::createFunctionThatMasqueradesAsUndefined(vm, globalObject, 0, String(), functionCallNotImplemented)); - } - if (string == "vm"_s) { auto* obj = constructEmptyObject(globalObject); obj->putDirect( @@ -1803,7 +1864,7 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, obj->putDirect(vm, PropertyName(Identifier::fromString(vm, "isatty"_s)), JSFunction::create(vm, globalObject, 0, "isatty"_s, jsFunctionTty_isatty, ImplementationVisibility::Public), 1); - obj->putDirect(vm, PropertyName(Identifier::fromString(vm, "getWindowSize"_s)), JSFunction::create(vm, globalObject, 0, "getWindowSize"_s, Process_functionInternalGetWindowSize, ImplementationVisibility::Public), 2); + obj->putDirect(vm, PropertyName(Identifier::fromString(vm, "getWindowSize"_s)), JSFunction::create(vm, globalObject, 0, "getWindowSize"_s, Bun::Process_functionInternalGetWindowSize, ImplementationVisibility::Public), 2); return JSValue::encode(obj); } @@ -1812,9 +1873,9 @@ static JSC_DEFINE_HOST_FUNCTION(functionLazyLoad, auto* obj = constructEmptyObject(globalObject); obj->putDirectCustomAccessor(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "getterSetter"_s)), JSC::CustomGetterSetter::create(vm, noop_getter, noop_setter), 0); Zig::JSFFIFunction* function = Zig::JSFFIFunction::create(vm, reinterpret_cast<Zig::GlobalObject*>(globalObject), 0, String(), functionNoop, JSC::NoIntrinsic); - obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "function"_s)), function, JSC::PropertyAttribute::Function | 0); - obj->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "functionRegular"_s), 1, functionNoop, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function); - obj->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "callback"_s), 1, functionCallback, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function); + obj->putDirect(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "function"_s)), function, 0); + obj->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "functionRegular"_s), 1, functionNoop, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); + obj->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, "callback"_s), 1, functionCallback, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); return JSC::JSValue::encode(obj); } @@ -1903,173 +1964,9 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionDispatchEvent, (JSGlobalObject * lexicalGloba return jsFunctionDispatchEventBody(lexicalGlobalObject, callFrame, jsDynamicCast<Zig::GlobalObject*>(lexicalGlobalObject)); } -static inline JSValue jsServiceWorkerGlobalScope_ByteLengthQueuingStrategyConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSByteLengthQueuingStrategy::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_ByteLengthQueuingStrategyConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_ByteLengthQueuingStrategyConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_CountQueuingStrategyConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSCountQueuingStrategy::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_CountQueuingStrategyConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_CountQueuingStrategyConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_ReadableByteStreamControllerConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSReadableByteStreamController::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_ReadableByteStreamControllerConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_ReadableByteStreamControllerConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_ReadableStreamConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSReadableStream::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_ReadableStreamConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_ReadableStreamConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_ReadableStreamBYOBReaderConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSReadableStreamBYOBReader::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_ReadableStreamBYOBReaderConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_ReadableStreamBYOBReaderConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_ReadableStreamBYOBRequestConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSReadableStreamBYOBRequest::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_ReadableStreamBYOBRequestConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_ReadableStreamBYOBRequestConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_ReadableStreamDefaultControllerConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSReadableStreamDefaultController::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_ReadableStreamDefaultControllerConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_ReadableStreamDefaultControllerConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_ReadableStreamDefaultReaderConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSReadableStreamDefaultReader::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_ReadableStreamDefaultReaderConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_ReadableStreamDefaultReaderConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_TransformStreamConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSTransformStream::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_TransformStreamConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_TransformStreamConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_TransformStreamDefaultControllerConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSTransformStreamDefaultController::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_TransformStreamDefaultControllerConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_TransformStreamDefaultControllerConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_WritableStreamConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSWritableStream::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_WritableStreamConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_WritableStreamConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_WritableStreamDefaultControllerConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSWritableStreamDefaultController::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_WritableStreamDefaultControllerConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_WritableStreamDefaultControllerConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -static inline JSValue jsServiceWorkerGlobalScope_WritableStreamDefaultWriterConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return JSWritableStreamDefaultWriter::getConstructor(JSC::getVM(&lexicalGlobalObject), &thisObject); -} - -JSC_DEFINE_CUSTOM_GETTER(jsServiceWorkerGlobalScope_WritableStreamDefaultWriterConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - return IDLAttribute<Zig::GlobalObject>::get<jsServiceWorkerGlobalScope_WritableStreamDefaultWriterConstructorGetter>(*lexicalGlobalObject, thisValue, attributeName); -} - -JSC_DEFINE_CUSTOM_GETTER(getterSubtleCryptoConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); - return JSValue::encode( - JSSubtleCrypto::getConstructor(thisObject->vm(), thisObject)); -} - -JSC_DEFINE_CUSTOM_GETTER(getterCryptoKeyConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); - return JSValue::encode( - JSCryptoKey::getConstructor(thisObject->vm(), thisObject)); -} - -static inline JSValue getterSubtleCryptoBody(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject) -{ - UNUSED_PARAM(lexicalGlobalObject); - return thisObject.subtleCrypto(); -} - JSC_DEFINE_CUSTOM_GETTER(getterSubtleCrypto, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { - return JSValue::encode( - getterSubtleCryptoBody(*lexicalGlobalObject, *reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject))); + return JSValue::encode(reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject)->subtleCrypto()); } JSC_DECLARE_HOST_FUNCTION(makeThisTypeErrorForBuiltins); @@ -2079,6 +1976,12 @@ JSC_DECLARE_HOST_FUNCTION(createWritableStreamFromInternal); JSC_DECLARE_HOST_FUNCTION(getInternalWritableStream); JSC_DECLARE_HOST_FUNCTION(whenSignalAborted); JSC_DECLARE_HOST_FUNCTION(isAbortSignal); + +JSC_DEFINE_HOST_FUNCTION(jsCreateCJSImportMeta, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + return JSValue::encode(Zig::ImportMetaObject::create(globalObject, callFrame->argument(0).toString(globalObject))); +} + JSC_DEFINE_HOST_FUNCTION(makeThisTypeErrorForBuiltins, (JSGlobalObject * globalObject, CallFrame* callFrame)) { ASSERT(callFrame); @@ -2296,9 +2199,11 @@ static inline EncodedJSValue functionPerformanceNowBody(JSGlobalObject* globalOb { auto* global = reinterpret_cast<GlobalObject*>(globalObject); // nanoseconds to seconds - uint64_t time = Bun__readOriginTimer(global->bunVM()); + double time = static_cast<double>(Bun__readOriginTimer(global->bunVM())); double result = time / 1000000.0; - return JSValue::encode(jsNumber(result)); + + // https://github.com/oven-sh/bun/issues/5604 + return JSValue::encode(jsDoubleNumber(result)); } extern "C" { @@ -2337,11 +2242,12 @@ private: void finishCreation(JSC::VM& vm) { + Base::finishCreation(vm); static const JSC::DOMJIT::Signature DOMJITSignatureForPerformanceNow( functionPerformanceNowWithoutTypeCheck, JSPerformanceObject::info(), JSC::DOMJIT::Effect::forWriteKinds(DFG::AbstractHeapKind::SideState), - SpecBytecodeDouble); + SpecDoubleReal); JSFunction* now = JSFunction::create( vm, @@ -2350,7 +2256,7 @@ private: String("now"_s), functionPerformanceNow, ImplementationVisibility::Public, NoIntrinsic, functionPerformanceNow, &DOMJITSignatureForPerformanceNow); - this->putDirect(vm, JSC::Identifier::fromString(vm, "now"_s), now, JSC::PropertyAttribute::DOMJITFunction | JSC::PropertyAttribute::Function); + this->putDirect(vm, JSC::Identifier::fromString(vm, "now"_s), now, 0); JSFunction* noopNotImplemented = JSFunction::create( vm, @@ -2358,16 +2264,17 @@ private: 0, String("noopNotImplemented"_s), functionNoop, ImplementationVisibility::Public, NoIntrinsic, functionNoop, - &DOMJITSignatureForPerformanceNow); - this->putDirect(vm, JSC::Identifier::fromString(vm, "mark"_s), noopNotImplemented, JSC::PropertyAttribute::DOMJITFunction | JSC::PropertyAttribute::Function); - this->putDirect(vm, JSC::Identifier::fromString(vm, "markResourceTiming"_s), noopNotImplemented, JSC::PropertyAttribute::DOMJITFunction | JSC::PropertyAttribute::Function); - this->putDirect(vm, JSC::Identifier::fromString(vm, "measure"_s), noopNotImplemented, JSC::PropertyAttribute::DOMJITFunction | JSC::PropertyAttribute::Function); + nullptr); + + this->putDirect(vm, JSC::Identifier::fromString(vm, "mark"_s), noopNotImplemented, 0); + this->putDirect(vm, JSC::Identifier::fromString(vm, "markResourceTiming"_s), noopNotImplemented, 0); + this->putDirect(vm, JSC::Identifier::fromString(vm, "measure"_s), noopNotImplemented, 0); this->putDirect( vm, JSC::Identifier::fromString(vm, "timeOrigin"_s), jsNumber(Bun__readOriginTimerStart(reinterpret_cast<Zig::GlobalObject*>(this->globalObject())->bunVM())), - JSC::PropertyAttribute::ReadOnly | 0); + PropertyAttribute::ReadOnly | 0); } }; const ClassInfo JSPerformanceObject::s_info = { "Performance"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSPerformanceObject) }; @@ -2665,7 +2572,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotaskVariadic, (JSGlobalObject * g return JSValue::encode(jsUndefined()); } -void GlobalObject::createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalObject, JSCStackTrace& stackTrace, JSC::JSArray* callSites) +void GlobalObject::createCallSitesFromFrames(Zig::GlobalObject* globalObject, JSC::JSGlobalObject* lexicalGlobalObject, JSCStackTrace& stackTrace, JSC::JSArray* callSites) { /* From v8's "Stack Trace API" (https://github.com/v8/v8/wiki/Stack-Trace-API): * "To maintain restrictions imposed on strict mode functions, frames that have a @@ -2673,10 +2580,11 @@ void GlobalObject::createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalO * their receiver and function objects. For those frames, getFunction() and getThis() * will return undefined."." */ bool encounteredStrictFrame = false; - GlobalObject* globalObject = reinterpret_cast<GlobalObject*>(lexicalGlobalObject); + // TODO: is it safe to use CallSite structure from a different JSGlobalObject? This case would happen within a node:vm JSC::Structure* callSiteStructure = globalObject->callSiteStructure(); size_t framesCount = stackTrace.size(); + for (size_t i = 0; i < framesCount; i++) { CallSite* callSite = CallSite::create(lexicalGlobalObject, callSiteStructure, stackTrace.at(i), encounteredStrictFrame); callSites->putDirectIndex(lexicalGlobalObject, i, callSite); @@ -2687,40 +2595,19 @@ void GlobalObject::createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalO } } -JSC::JSValue GlobalObject::formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* errorObject, JSC::JSArray* callSites) +void GlobalObject::formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* errorObject, JSC::JSArray* callSites, JSValue prepareStackTrace) { auto scope = DECLARE_THROW_SCOPE(vm); - JSValue errorValue = this->get(this, JSC::Identifier::fromString(vm, "Error"_s)); - if (UNLIKELY(scope.exception())) { - return JSValue(); - } - if (!errorValue || errorValue.isUndefined() || !errorValue.isObject()) { - return JSValue(jsEmptyString(vm)); - } + auto* errorConstructor = lexicalGlobalObject->m_errorStructure.constructor(this); - auto* errorConstructor = jsDynamicCast<JSC::JSObject*>(errorValue); - - /* If the user has set a callable Error.prepareStackTrace - use it to format the stack trace. */ - JSC::JSValue prepareStackTrace = errorConstructor->getIfPropertyExists(lexicalGlobalObject, JSC::Identifier::fromString(vm, "prepareStackTrace"_s)); - if (prepareStackTrace && prepareStackTrace.isCallable()) { - JSC::CallData prepareStackTraceCallData = JSC::getCallData(prepareStackTrace); - - if (prepareStackTraceCallData.type != JSC::CallData::Type::None) { - JSC::MarkedArgumentBuffer arguments; - arguments.append(errorObject); - arguments.append(callSites); - ASSERT(!arguments.hasOverflowed()); - - JSC::JSValue result = profiledCall( - lexicalGlobalObject, - JSC::ProfilingReason::Other, - prepareStackTrace, - prepareStackTraceCallData, - errorConstructor, - arguments); - RETURN_IF_EXCEPTION(scope, JSC::jsUndefined()); - return result; + if (!prepareStackTrace) { + if (lexicalGlobalObject->inherits<Zig::GlobalObject>()) { + if (auto prepare = this->m_errorConstructorPrepareStackTraceValue.get()) { + prepareStackTrace = prepare; + } + } else { + prepareStackTrace = errorConstructor->getIfPropertyExists(lexicalGlobalObject, JSC::Identifier::fromString(vm, "prepareStackTrace"_s)); } } @@ -2749,7 +2636,43 @@ JSC::JSValue GlobalObject::formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* le } } - return JSC::JSValue(jsString(vm, sb.toString())); + bool orignialSkipNextComputeErrorInfo = skipNextComputeErrorInfo; + skipNextComputeErrorInfo = true; + if (errorObject->hasProperty(lexicalGlobalObject, vm.propertyNames->stack)) { + skipNextComputeErrorInfo = true; + errorObject->deleteProperty(lexicalGlobalObject, vm.propertyNames->stack); + } + skipNextComputeErrorInfo = orignialSkipNextComputeErrorInfo; + + // In Node, if you console.log(error.stack) inside Error.prepareStackTrace + // it will display the stack as a formatted string, so we have to do the same. + errorObject->putDirect(vm, vm.propertyNames->stack, JSC::JSValue(jsString(vm, sb.toString())), 0); + + if (prepareStackTrace && prepareStackTrace.isCallable()) { + JSC::CallData prepareStackTraceCallData = JSC::getCallData(prepareStackTrace); + + if (prepareStackTraceCallData.type != JSC::CallData::Type::None) { + JSC::MarkedArgumentBuffer arguments; + arguments.append(errorObject); + arguments.append(callSites); + + JSC::JSValue result = profiledCall( + lexicalGlobalObject, + JSC::ProfilingReason::Other, + prepareStackTrace, + prepareStackTraceCallData, + errorConstructor, + arguments); + + RETURN_IF_EXCEPTION(scope, void()); + + if (result.isUndefinedOrNull()) { + result = jsUndefined(); + } + + errorObject->putDirect(vm, vm.propertyNames->stack, result, 0); + } + } } JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncAppendStackTrace, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) @@ -2805,9 +2728,9 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalOb stackTrace.size()); // Create the call sites (one per frame) - GlobalObject::createCallSitesFromFrames(lexicalGlobalObject, stackTrace, callSites); + GlobalObject::createCallSitesFromFrames(globalObject, lexicalGlobalObject, stackTrace, callSites); - /* Foramt the stack trace. + /* Format the stack trace. * Note that v8 won't actually format the stack trace here, but will create a "stack" accessor * on the error object, which will format the stack trace on the first access. For now, since * we're not being used internally by JSC, we can assume callers of Error.captureStackTrace in @@ -2847,23 +2770,9 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalOb } } - JSC::JSValue formattedStackTrace = globalObject->formatStackTrace(vm, lexicalGlobalObject, errorObject, callSites); + globalObject->formatStackTrace(vm, lexicalGlobalObject, errorObject, callSites, JSC::JSValue()); RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode({})); - bool orignialSkipNextComputeErrorInfo = skipNextComputeErrorInfo; - skipNextComputeErrorInfo = true; - if (errorObject->hasProperty(lexicalGlobalObject, vm.propertyNames->stack)) { - skipNextComputeErrorInfo = true; - errorObject->deleteProperty(lexicalGlobalObject, vm.propertyNames->stack); - } - skipNextComputeErrorInfo = orignialSkipNextComputeErrorInfo; - - if (formattedStackTrace.isUndefinedOrNull()) { - formattedStackTrace = JSC::jsUndefined(); - } - - errorObject->putDirect(vm, vm.propertyNames->stack, formattedStackTrace, 0); - if (auto* instance = jsDynamicCast<JSC::ErrorInstance*>(errorObject)) { // we make a separate copy of the StackTrace unfortunately so that we // can later console.log it without losing the info @@ -2900,7 +2809,7 @@ void GlobalObject::finishCreation(VM& vm) init.vm, Identifier::fromString(init.vm, "subtle"_s), JSC::CustomGetterSetter::create(init.vm, getterSubtleCrypto, nullptr), - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); + PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete | 0); init.set(crypto); }); @@ -2950,11 +2859,20 @@ void GlobalObject::finishCreation(VM& vm) m_commonJSFunctionArgumentsStructure.initLater( [](const Initializer<Structure>& init) { auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(init.owner); + + auto prototype = JSC::constructEmptyObject(init.owner, globalObject->objectPrototype(), 1); + prototype->putDirect( + init.vm, + Identifier::fromString(init.vm, "createImportMeta"_s), + JSFunction::create(init.vm, init.owner, 2, ""_s, jsCreateCJSImportMeta, ImplementationVisibility::Public), + PropertyAttribute::DontDelete | PropertyAttribute::DontEnum | 0); + JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype( globalObject, - globalObject->objectPrototype(), - 3); + prototype, + 5); JSC::PropertyOffset offset; + auto& vm = globalObject->vm(); structure = structure->addPropertyTransition( @@ -2967,6 +2885,20 @@ void GlobalObject::finishCreation(VM& vm) structure = structure->addPropertyTransition( vm, structure, + JSC::Identifier::fromString(vm, "require"_s), + 0, + offset); + + structure = structure->addPropertyTransition( + vm, + structure, + JSC::Identifier::fromString(vm, "resolve"_s), + 0, + offset); + + structure = structure->addPropertyTransition( + vm, + structure, JSC::Identifier::fromString(vm, "__dirname"_s), 0, offset); @@ -2981,6 +2913,11 @@ void GlobalObject::finishCreation(VM& vm) init.set(structure); }); + m_JSSocketAddressStructure.initLater( + [](const Initializer<Structure>& init) { + init.set(JSSocketAddress::createStructure(init.vm, init.owner)); + }); + // Change prototype from null to object for synthetic modules. m_moduleNamespaceObjectStructure.initLater( [](const Initializer<Structure>& init) { @@ -3022,7 +2959,7 @@ void GlobalObject::finishCreation(VM& vm) m_utilInspectFunction.initLater( [](const Initializer<JSFunction>& init) { - JSValue nodeUtilValue = static_cast<Zig::GlobalObject*>(init.owner)->internalModuleRegistry()->requireId(init.owner, init.vm, Bun::InternalModuleRegistry::Field::NodeUtil); + JSValue nodeUtilValue = jsCast<Zig::GlobalObject*>(init.owner)->internalModuleRegistry()->requireId(init.owner, init.vm, Bun::InternalModuleRegistry::Field::NodeUtil); RELEASE_ASSERT(nodeUtilValue.isObject()); init.set(jsCast<JSFunction*>(nodeUtilValue.getObject()->getIfPropertyExists(init.owner, Identifier::fromString(init.vm, "inspect"_s)))); }); @@ -3034,7 +2971,7 @@ void GlobalObject::finishCreation(VM& vm) // RETURN_IF_EXCEPTION(scope, {}); JSC::MarkedArgumentBuffer args; - args.append(static_cast<Zig::GlobalObject*>(init.owner)->utilInspectFunction()); + args.append(jsCast<Zig::GlobalObject*>(init.owner)->utilInspectFunction()); auto clientData = WebCore::clientData(init.vm); JSC::CallData callData = JSC::getCallData(getStylize); @@ -3078,7 +3015,7 @@ void GlobalObject::finishCreation(VM& vm) JSC::JSObject* obj = JSC::constructEmptyObject(init.owner, init.owner->objectPrototype(), 4); obj->putDirect(init.vm, userAgentIdentifier, JSC::jsString(init.vm, str)); obj->putDirect(init.vm, init.vm.propertyNames->toStringTagSymbol, - jsNontrivialString(init.vm, "Navigator"_s), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly); + jsNontrivialString(init.vm, "Navigator"_s), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly); // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform // https://github.com/oven-sh/bun/issues/4588 @@ -3091,8 +3028,7 @@ void GlobalObject::finishCreation(VM& vm) #endif obj->putDirect(init.vm, hardwareConcurrencyIdentifier, JSC::jsNumber(cpuCount)); - init.set( - obj); + init.set(obj); }); this->m_pendingVirtualModuleResultStructure.initLater( @@ -3100,6 +3036,11 @@ void GlobalObject::finishCreation(VM& vm) init.set(Bun::PendingVirtualModuleResult::createStructure(init.vm, init.owner, init.owner->objectPrototype())); }); + m_bunObject.initLater( + [](const JSC::LazyProperty<JSC::JSGlobalObject, JSObject>::Initializer& init) { + init.set(Bun::createBunObject(init.vm, init.owner)); + }); + this->initGeneratedLazyClasses(); m_cachedGlobalObjectStructure.initLater( @@ -3119,13 +3060,12 @@ void GlobalObject::finishCreation(VM& vm) m_subtleCryptoObject.initLater( [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) { auto& global = *reinterpret_cast<Zig::GlobalObject*>(init.owner); - if (global.crypto == nullptr) { - global.crypto = WebCore::SubtleCrypto::createPtr(global.scriptExecutionContext()); - global.crypto->ref(); + + if (!global.m_subtleCrypto) { + global.m_subtleCrypto = &WebCore::SubtleCrypto::create(global.scriptExecutionContext()).leakRef(); } - init.set( - toJS<IDLInterface<SubtleCrypto>>(*init.owner, global, global.crypto).getObject()); + init.set(toJS<IDLInterface<SubtleCrypto>>(*init.owner, global, global.m_subtleCrypto).getObject()); }); m_NapiClassStructure.initLater( @@ -3173,8 +3113,8 @@ void GlobalObject::finishCreation(VM& vm) m_processObject.initLater( [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) { Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(init.owner); - auto* process = Zig::Process::create( - *globalObject, Zig::Process::createStructure(init.vm, init.owner, WebCore::JSEventEmitter::prototype(init.vm, *globalObject))); + auto* process = Bun::Process::create( + *globalObject, Bun::Process::createStructure(init.vm, init.owner, WebCore::JSEventEmitter::prototype(init.vm, *globalObject))); init.set(process); }); @@ -3234,7 +3174,7 @@ void GlobalObject::finishCreation(VM& vm) }); m_processBindingConstants.initLater( - [](const JSC::LazyProperty<JSC::JSGlobalObject, Bun::ProcessBindingConstants>::Initializer& init) { + [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) { init.set( ProcessBindingConstants::create( init.vm, @@ -3291,6 +3231,14 @@ void GlobalObject::finishCreation(VM& vm) init.setConstructor(constructor); }); + m_JSCryptoKey.initLater( + [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::Structure>::Initializer& init) { + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(init.owner); + auto* prototype = JSCryptoKey::createPrototype(init.vm, *globalObject); + auto* structure = JSCryptoKey::createStructure(init.vm, init.owner, JSValue(prototype)); + init.set(structure); + }); + m_JSHTTPSResponseSinkClassStructure.initLater( [](LazyClassStructure::Initializer& init) { auto* prototype = createJSSinkPrototype(init.vm, init.global, WebCore::SinkID::HTTPSResponseSink); @@ -3363,22 +3311,13 @@ void GlobalObject::finishCreation(VM& vm) init.setConstructor(constructor); }); - addBuiltinGlobals(vm); - #if ENABLE(REMOTE_INSPECTOR) setInspectable(false); #endif - RELEASE_ASSERT(classInfo()); + addBuiltinGlobals(vm); - JSC::JSObject* errorConstructor = this->errorConstructor(); - errorConstructor->putDirectNativeFunction(vm, this, JSC::Identifier::fromString(vm, "captureStackTrace"_s), 2, errorConstructorFuncCaptureStackTrace, ImplementationVisibility::Public, JSC::NoIntrinsic, PropertyAttribute::DontEnum | 0); - errorConstructor->putDirectNativeFunction(vm, this, JSC::Identifier::fromString(vm, "appendStackTrace"_s), 2, errorConstructorFuncAppendStackTrace, ImplementationVisibility::Private, JSC::NoIntrinsic, PropertyAttribute::DontEnum | 0); - JSC::JSValue console = this->get(this, JSC::Identifier::fromString(vm, "console"_s)); - JSC::JSObject* consoleObject = console.getObject(); - consoleObject->putDirectBuiltinFunction(vm, this, vm.propertyNames->asyncIteratorSymbol, consoleObjectAsyncIteratorCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete); - auto clientData = WebCore::clientData(vm); - consoleObject->putDirectBuiltinFunction(vm, this, clientData->builtinNames().writePublicName(), consoleObjectWriteCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete); + ASSERT(classInfo()); } JSC_DEFINE_HOST_FUNCTION(jsFunctionPostMessage, @@ -3483,7 +3422,7 @@ JSC_DEFINE_CUSTOM_GETTER(BunCommonJSModule_getter, (JSGlobalObject * globalObjec // This implementation works the same as setTimeout(myFunction, 0) // TODO: make it more efficient // https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate -static JSC_DEFINE_HOST_FUNCTION(functionSetImmediate, +JSC_DEFINE_HOST_FUNCTION(functionSetImmediate, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { JSC::VM& vm = globalObject->vm(); @@ -3525,31 +3464,11 @@ static JSC_DEFINE_HOST_FUNCTION(functionSetImmediate, return Bun__Timer__setTimeout(globalObject, JSC::JSValue::encode(job), JSC::JSValue::encode(jsNumber(0)), JSValue::encode(arguments)); } -JSC_DEFINE_CUSTOM_GETTER(JSModuleLoader_getter, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) -{ - return JSValue::encode(globalObject->moduleLoader()); -} - -JSC_DEFINE_CUSTOM_GETTER(functionResolveMessageGetter, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) +JSValue getEventSourceConstructor(VM& vm, JSObject* thisObject) { - return JSValue::encode(reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSResolveMessageConstructor()); -} -JSC_DEFINE_CUSTOM_GETTER(functionBuildMessageGetter, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) -{ - return JSValue::encode(reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSBuildMessageConstructor()); -} - -JSC_DEFINE_CUSTOM_GETTER( - EventSource_getter, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName property)) -{ - auto& vm = globalObject->vm(); + auto globalObject = jsCast<Zig::GlobalObject*>(thisObject); auto scope = DECLARE_THROW_SCOPE(vm); - // If "this" is not the Global object, just return undefined - // you should not be able to reset the global object's EventSource if you muck around with prototypes - if (JSValue::decode(thisValue) != globalObject) - return JSValue::encode(JSC::jsUndefined()); - JSC::JSFunction* getSourceEvent = JSC::JSFunction::create(vm, eventSourceGetEventSourceCodeGenerator(vm), globalObject); RETURN_IF_EXCEPTION(scope, {}); @@ -3564,15 +3483,61 @@ JSC_DEFINE_CUSTOM_GETTER( if (returnedException) { throwException(globalObject, scope, returnedException.get()); + return jsUndefined(); } - RETURN_IF_EXCEPTION(scope, {}); + RELEASE_AND_RETURN(scope, result); +} - if (LIKELY(result)) { - globalObject->putDirect(vm, property, result, 0); +// `console.Console` or `import { Console } from 'console';` +JSC_DEFINE_CUSTOM_GETTER(getConsoleConstructor, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName property)) +{ + auto& vm = globalObject->vm(); + auto console = JSValue::decode(thisValue).getObject(); + JSC::JSFunction* createConsoleConstructor = JSC::JSFunction::create(vm, consoleObjectCreateConsoleConstructorCodeGenerator(vm), globalObject); + JSC::MarkedArgumentBuffer args; + args.append(console); + JSC::CallData callData = JSC::getCallData(createConsoleConstructor); + NakedPtr<JSC::Exception> returnedException = nullptr; + auto result = JSC::call(globalObject, createConsoleConstructor, callData, console, args, returnedException); + if (returnedException) { + auto scope = DECLARE_THROW_SCOPE(vm); + throwException(globalObject, scope, returnedException.get()); } + console->putDirect(vm, property, result, 0); + return JSValue::encode(result); +} + +// `console._stdout` is equal to `process.stdout` +JSC_DEFINE_CUSTOM_GETTER(getConsoleStdout, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName property)) +{ + auto& vm = globalObject->vm(); + auto console = JSValue::decode(thisValue).getObject(); + auto global = jsCast<Zig::GlobalObject*>(globalObject); - RELEASE_AND_RETURN(scope, JSValue::encode(result)); + // instead of calling the constructor builtin, go through the process.stdout getter to ensure it's only created once. + auto stdout = global->processObject()->get(globalObject, Identifier::fromString(vm, "stdout"_s)); + if (!stdout) + return JSValue::encode({}); + + console->putDirect(vm, property, stdout, PropertyAttribute::DontEnum | 0); + return JSValue::encode(stdout); +} + +// `console._stderr` is equal to `process.stderr` +JSC_DEFINE_CUSTOM_GETTER(getConsoleStderr, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName property)) +{ + auto& vm = globalObject->vm(); + auto console = JSValue::decode(thisValue).getObject(); + auto global = jsCast<Zig::GlobalObject*>(globalObject); + + // instead of calling the constructor builtin, go through the process.stdout getter to ensure it's only created once. + auto stdout = global->processObject()->get(globalObject, Identifier::fromString(vm, "stderr"_s)); + if (!stdout) + return JSValue::encode({}); + + console->putDirect(vm, property, stdout, PropertyAttribute::DontEnum | 0); + return JSValue::encode(stdout); } JSC_DEFINE_CUSTOM_SETTER(EventSource_setter, @@ -3680,6 +3645,19 @@ extern "C" EncodedJSValue WebCore__alert(JSC::JSGlobalObject*, JSC::CallFrame*); extern "C" EncodedJSValue WebCore__prompt(JSC::JSGlobalObject*, JSC::CallFrame*); extern "C" EncodedJSValue WebCore__confirm(JSC::JSGlobalObject*, JSC::CallFrame*); +JSValue GlobalObject_getPerformanceObject(VM& vm, JSObject* globalObject) +{ + return jsCast<Zig::GlobalObject*>(globalObject)->performanceObject(); +} + +JSValue GlobalObject_getGlobalThis(VM& vm, JSObject* globalObject) +{ + return jsCast<Zig::GlobalObject*>(globalObject)->globalThis(); +} + +// This is like `putDirectBuiltinFunction` but for the global static list. +#define globalBuiltinFunction(vm, globalObject, identifier, function, attributes) JSC::JSGlobalObject::GlobalPropertyInfo(identifier, JSFunction::create(vm, function, globalObject), attributes) + void GlobalObject::addBuiltinGlobals(JSC::VM& vm) { m_builtinInternalFunctions.initialize(*this); @@ -3687,318 +3665,63 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) auto clientData = WebCore::clientData(vm); auto& builtinNames = WebCore::builtinNames(vm); - WTF::Vector<GlobalPropertyInfo> extraStaticGlobals; - extraStaticGlobals.reserveCapacity(51); - - JSC::Identifier queueMicrotaskIdentifier = JSC::Identifier::fromString(vm, "queueMicrotask"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { JSC::Identifier::fromString(vm, "fetch"_s), - JSC::JSFunction::create(vm, this, 2, - "fetch"_s, Bun__fetch, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { queueMicrotaskIdentifier, - JSC::JSFunction::create(vm, this, 2, - "queueMicrotask"_s, functionQueueMicrotask, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { JSC::Identifier::fromString(vm, "setImmediate"_s), - JSC::JSFunction::create(vm, this, 1, - "setImmediate"_s, functionSetImmediate, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { JSC::Identifier::fromString(vm, "clearImmediate"_s), - JSC::JSFunction::create(vm, this, 1, - "clearImmediate"_s, functionClearTimeout, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { JSC::Identifier::fromString(vm, "structuredClone"_s), - JSC::JSFunction::create(vm, this, 2, - "structuredClone"_s, functionStructuredClone, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - - JSC::Identifier setTimeoutIdentifier = JSC::Identifier::fromString(vm, "setTimeout"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { setTimeoutIdentifier, - JSC::JSFunction::create(vm, this, 1, - "setTimeout"_s, functionSetTimeout, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); + // ----- Private/Static Properties ----- - JSC::Identifier clearTimeoutIdentifier = JSC::Identifier::fromString(vm, "clearTimeout"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { clearTimeoutIdentifier, - JSC::JSFunction::create(vm, this, 1, - "clearTimeout"_s, functionClearTimeout, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); + auto $lazy = JSC::JSFunction::create(vm, this, 0, "$lazy"_s, functionLazyLoad, ImplementationVisibility::Public); - JSC::Identifier setIntervalIdentifier = JSC::Identifier::fromString(vm, "setInterval"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { setIntervalIdentifier, - JSC::JSFunction::create(vm, this, 1, - "setInterval"_s, functionSetInterval, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - - JSC::Identifier clearIntervalIdentifier = JSC::Identifier::fromString(vm, "clearInterval"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { clearIntervalIdentifier, - JSC::JSFunction::create(vm, this, 1, - "clearInterval"_s, functionClearInterval, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - - JSC::Identifier atobIdentifier = JSC::Identifier::fromString(vm, "atob"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { atobIdentifier, - JSC::JSFunction::create(vm, this, 1, - "atob"_s, functionATOB, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - - JSC::Identifier btoaIdentifier = JSC::Identifier::fromString(vm, "btoa"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { btoaIdentifier, - JSC::JSFunction::create(vm, this, 1, - "btoa"_s, functionBTOA, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - JSC::Identifier reportErrorIdentifier = JSC::Identifier::fromString(vm, "reportError"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { reportErrorIdentifier, - JSC::JSFunction::create(vm, this, 1, - "reportError"_s, functionReportError, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - - { - JSC::Identifier postMessageIdentifier = JSC::Identifier::fromString(vm, "postMessage"_s); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { postMessageIdentifier, - JSC::JSFunction::create(vm, this, 1, - "postMessage"_s, jsFunctionPostMessage, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - } - - { - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { JSC::Identifier::fromString(vm, "alert"_s), - JSC::JSFunction::create(vm, this, 1, - "alert"_s, WebCore__alert, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - } - - { - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { JSC::Identifier::fromString(vm, "confirm"_s), - JSC::JSFunction::create(vm, this, 1, - "confirm"_s, WebCore__confirm, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - } - - { - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { JSC::Identifier::fromString(vm, "prompt"_s), - JSC::JSFunction::create(vm, this, 1, - "prompt"_s, WebCore__prompt, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - } - - JSValue bunObject = Bun::createBunObject(this); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { builtinNames.BunPrivateName(), - bunObject, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0 }); - - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { builtinNames.BunPublicName(), - bunObject, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0 }); - - extraStaticGlobals.uncheckedAppend( + GlobalPropertyInfo staticGlobals[] = { GlobalPropertyInfo { builtinNames.startDirectStreamPrivateName(), JSC::JSFunction::create(vm, this, 1, String(), functionStartDirectStream, ImplementationVisibility::Public), - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 }); - - static NeverDestroyed<const String> BunLazyString(MAKE_STATIC_STRING_IMPL("Bun.lazy")); - JSC::Identifier BunLazyIdentifier = JSC::Identifier::fromUid(vm.symbolRegistry().symbolForKey(BunLazyString)); - JSC::JSFunction* lazyLoadFunction = JSC::JSFunction::create(vm, this, 0, - BunLazyString, functionLazyLoad, ImplementationVisibility::Public); - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { BunLazyIdentifier, - lazyLoadFunction, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function | 0 }); - - extraStaticGlobals.uncheckedAppend( - GlobalPropertyInfo { builtinNames.lazyLoadPrivateName(), - lazyLoadFunction, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::Function | 0 }); - - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.makeThisTypeErrorPrivateName(), JSFunction::create(vm, this, 2, String(), makeThisTypeErrorForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.makeGetterTypeErrorPrivateName(), JSFunction::create(vm, this, 2, String(), makeGetterTypeErrorForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.makeDOMExceptionPrivateName(), JSFunction::create(vm, this, 2, String(), makeDOMExceptionForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.whenSignalAbortedPrivateName(), JSFunction::create(vm, this, 2, String(), whenSignalAborted, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.cloneArrayBufferPrivateName(), JSFunction::create(vm, this, 3, String(), cloneArrayBuffer, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.structuredCloneForStreamPrivateName(), JSFunction::create(vm, this, 1, String(), structuredCloneForStream, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.streamClosedPrivateName(), jsNumber(1), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::ConstantInteger)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.streamClosingPrivateName(), jsNumber(2), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::ConstantInteger)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.streamErroredPrivateName(), jsNumber(3), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::ConstantInteger)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.streamReadablePrivateName(), jsNumber(4), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::ConstantInteger)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.streamWaitingPrivateName(), jsNumber(5), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::ConstantInteger)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.streamWritablePrivateName(), jsNumber(6), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::ConstantInteger)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.isAbortSignalPrivateName(), JSFunction::create(vm, this, 1, String(), isAbortSignal, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.getInternalWritableStreamPrivateName(), JSFunction::create(vm, this, 1, String(), getInternalWritableStream, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.createWritableStreamFromInternalPrivateName(), JSFunction::create(vm, this, 1, String(), createWritableStreamFromInternal, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.fulfillModuleSyncPrivateName(), JSFunction::create(vm, this, 1, String(), functionFulfillModuleSync, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(builtinNames.directPrivateName(), JSFunction::create(vm, this, 1, String(), functionGetDirectStreamDetails, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function)); - extraStaticGlobals.uncheckedAppend(GlobalPropertyInfo(vm.propertyNames->builtinNames().ArrayBufferPrivateName(), arrayBufferConstructor(), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly)); - - this->addStaticGlobals(extraStaticGlobals.data(), extraStaticGlobals.size()); - - extraStaticGlobals.releaseBuffer(); + PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | 0 }, + + // TODO: Remove the "Bun.lazy" symbol + // The reason we cant do this easily is our tests rely on this being public to test the internals. + GlobalPropertyInfo { JSC::Identifier::fromUid(vm.symbolRegistry().symbolForKey(MAKE_STATIC_STRING_IMPL("Bun.lazy"))), + $lazy, + PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | 0 }, + + GlobalPropertyInfo { builtinNames.lazyPrivateName(), + $lazy, + PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | 0 }, + + GlobalPropertyInfo(builtinNames.makeThisTypeErrorPrivateName(), JSFunction::create(vm, this, 2, String(), makeThisTypeErrorForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.makeGetterTypeErrorPrivateName(), JSFunction::create(vm, this, 2, String(), makeGetterTypeErrorForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.makeDOMExceptionPrivateName(), JSFunction::create(vm, this, 2, String(), makeDOMExceptionForBuiltins, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.whenSignalAbortedPrivateName(), JSFunction::create(vm, this, 2, String(), whenSignalAborted, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.cloneArrayBufferPrivateName(), JSFunction::create(vm, this, 3, String(), cloneArrayBuffer, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.structuredCloneForStreamPrivateName(), JSFunction::create(vm, this, 1, String(), structuredCloneForStream, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.isAbortSignalPrivateName(), JSFunction::create(vm, this, 1, String(), isAbortSignal, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.getInternalWritableStreamPrivateName(), JSFunction::create(vm, this, 1, String(), getInternalWritableStream, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.createWritableStreamFromInternalPrivateName(), JSFunction::create(vm, this, 1, String(), createWritableStreamFromInternal, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.fulfillModuleSyncPrivateName(), JSFunction::create(vm, this, 1, String(), functionFulfillModuleSync, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.directPrivateName(), JSFunction::create(vm, this, 1, String(), functionGetDirectStreamDetails, ImplementationVisibility::Public), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(vm.propertyNames->builtinNames().ArrayBufferPrivateName(), arrayBufferConstructor(), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.LoaderPrivateName(), this->moduleLoader(), PropertyAttribute::DontDelete | 0), + GlobalPropertyInfo(builtinNames.internalModuleRegistryPrivateName(), this->internalModuleRegistry(), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.processBindingConstantsPrivateName(), this->processBindingConstants(), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), + GlobalPropertyInfo(builtinNames.requireMapPrivateName(), this->requireMap(), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | 0), + }; + addStaticGlobals(staticGlobals, std::size(staticGlobals)); + + // TODO: most/all of these private properties can be made as static globals. + // i've noticed doing it as is will work somewhat but getDirect() wont be able to find them putDirectBuiltinFunction(vm, this, builtinNames.createFIFOPrivateName(), streamInternalsCreateFIFOCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectBuiltinFunction(vm, this, builtinNames.createEmptyReadableStreamPrivateName(), readableStreamCreateEmptyReadableStreamCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); + putDirectBuiltinFunction(vm, this, builtinNames.createUsedReadableStreamPrivateName(), readableStreamCreateUsedReadableStreamCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectBuiltinFunction(vm, this, builtinNames.consumeReadableStreamPrivateName(), readableStreamConsumeReadableStreamCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - - putDirect(vm, builtinNames.LoaderPrivateName(), this->moduleLoader(), 0); putDirectBuiltinFunction(vm, this, builtinNames.createNativeReadableStreamPrivateName(), readableStreamCreateNativeReadableStreamCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - putDirectBuiltinFunction(vm, this, builtinNames.requireESMPrivateName(), importMetaObjectRequireESMCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectBuiltinFunction(vm, this, builtinNames.loadCJS2ESMPrivateName(), importMetaObjectLoadCJS2ESMCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectBuiltinFunction(vm, this, builtinNames.internalRequirePrivateName(), importMetaObjectInternalRequireCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectBuiltinFunction(vm, this, builtinNames.requireNativeModulePrivateName(), moduleRequireNativeModuleCodeGenerator(vm), PropertyAttribute::Builtin | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - putDirectNativeFunction(vm, this, builtinNames.createUninitializedArrayBufferPrivateName(), 1, functionCreateUninitializedArrayBuffer, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function); - putDirectNativeFunction(vm, this, builtinNames.resolveSyncPrivateName(), 1, functionImportMeta__resolveSyncPrivate, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function); - putDirectNativeFunction(vm, this, builtinNames.createInternalModuleByIdPrivateName(), 1, InternalModuleRegistry::jsCreateInternalModuleById, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::Function); - putDirect(vm, builtinNames.internalModuleRegistryPrivateName(), this->internalModuleRegistry(), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - putDirect(vm, builtinNames.processBindingConstantsPrivateName(), this->processBindingConstants(), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "process"_s), JSC::CustomGetterSetter::create(vm, property_lazyProcessGetter, property_lazyProcessSetter), - JSC::PropertyAttribute::CustomAccessor | 0); - putDirect(vm, JSC::Identifier::fromString(vm, "performance"_s), this->performanceObject(), - 0); + putDirectBuiltinFunction(vm, this, builtinNames.overridableRequirePrivateName(), moduleOverridableRequireCodeGenerator(vm), 0); - putDirect(vm, JSC::Identifier::fromString(vm, "self"_s), this->globalThis(), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | 0); - putDirect(vm, JSC::Identifier::fromString(vm, "global"_s), this->globalThis(), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "URL"_s), JSC::CustomGetterSetter::create(vm, JSDOMURL_getter, nullptr), - JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, builtinNames.lazyStreamPrototypeMapPrivateName(), JSC::CustomGetterSetter::create(vm, functionLazyLoadStreamPrototypeMap_getter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "navigator"_s), JSC::CustomGetterSetter::create(vm, functionLazyNavigatorGetter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "ResolveError"_s), JSC::CustomGetterSetter::create(vm, functionResolveMessageGetter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "ResolveMessage"_s), JSC::CustomGetterSetter::create(vm, functionResolveMessageGetter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "BuildError"_s), JSC::CustomGetterSetter::create(vm, functionBuildMessageGetter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "BuildMessage"_s), JSC::CustomGetterSetter::create(vm, functionBuildMessageGetter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); - - putDirect(vm, builtinNames.requireMapPrivateName(), this->requireMap(), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Request"_s), JSC::CustomGetterSetter::create(vm, JSRequest_getter, JSRequest_setter), - JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Response"_s), JSC::CustomGetterSetter::create(vm, JSResponse_getter, JSResponse_setter), - JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "TextDecoder"_s), JSC::CustomGetterSetter::create(vm, JSTextDecoder_getter, JSTextDecoder_setter), - JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Blob"_s), JSC::CustomGetterSetter::create(vm, JSBlob_getter, JSBlob_setter), - JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "HTMLRewriter"_s), JSC::CustomGetterSetter::create(vm, JSHTMLRewriter_getter, JSHTMLRewriter_setter), - JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Crypto"_s), JSC::CustomGetterSetter::create(vm, JSCrypto_getter, JSCrypto_setter), - JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "File"_s), JSC::CustomGetterSetter::create(vm, JSDOMFileConstructor_getter, JSDOMFileConstructor_setter), - JSC::PropertyAttribute::DontDelete | 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "DOMException"_s), JSC::CustomGetterSetter::create(vm, JSDOMException_getter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "Event"_s), JSC::CustomGetterSetter::create(vm, JSEvent_getter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "EventTarget"_s), JSC::CustomGetterSetter::create(vm, JSEventTarget_getter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "AbortController"_s), JSC::CustomGetterSetter::create(vm, JSDOMAbortController_getter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "AbortSignal"_s), JSC::CustomGetterSetter::create(vm, JSDOMAbortSignal_getter, nullptr), - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "$_BunCommonJSModule_$"_s), JSC::CustomGetterSetter::create(vm, BunCommonJSModule_getter, nullptr), - JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "EventSource"_s), JSC::CustomGetterSetter::create(vm, EventSource_getter, EventSource_setter), 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "onmessage"_s), JSC::CustomGetterSetter::create(vm, globalGetterOnMessage, globalSetterOnMessage), 0); - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "onerror"_s), JSC::CustomGetterSetter::create(vm, globalGetterOnError, globalSetterOnError), 0); - - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "crypto"_s), JSC::CustomGetterSetter::create(vm, property_lazyCryptoGetter, nullptr), - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | 0); - - auto bufferAccessor = JSC::CustomGetterSetter::create(vm, JSBuffer_getter, JSBuffer_setter); - auto realBufferAccessor = JSC::CustomGetterSetter::create(vm, JSBuffer_privateGetter, nullptr); - - // - putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().BufferPublicName(), bufferAccessor, - JSC::PropertyAttribute::DontDelete | 0); - putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().BufferPrivateName(), realBufferAccessor, - JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - - PUT_WEBCORE_GENERATED_CONSTRUCTOR("BroadcastChannel"_s, JSBroadcastChannel); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("CloseEvent"_s, JSCloseEvent); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("CustomEvent"_s, JSCustomEvent); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("DOMException"_s, JSDOMException); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("ErrorEvent"_s, JSErrorEvent); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("Event"_s, JSEvent); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("EventTarget"_s, JSEventTarget); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("FormData"_s, JSDOMFormData); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("Headers"_s, JSFetchHeaders); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("MessageChannel"_s, JSMessageChannel); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("MessageEvent"_s, JSMessageEvent); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("MessagePort"_s, JSMessagePort); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("TextEncoder"_s, JSTextEncoder); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("URLSearchParams"_s, JSURLSearchParams); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("WebSocket"_s, JSWebSocket); - PUT_WEBCORE_GENERATED_CONSTRUCTOR("Worker"_s, JSWorker); - - putDirectCustomAccessor(vm, builtinNames.TransformStreamPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_TransformStreamConstructor, nullptr), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::DontEnum))); - putDirectCustomAccessor(vm, builtinNames.TransformStreamPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_TransformStreamConstructor, nullptr), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::DontEnum))); - putDirectCustomAccessor(vm, builtinNames.TransformStreamDefaultControllerPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_TransformStreamDefaultControllerConstructor, nullptr), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::DontEnum))); - putDirectCustomAccessor(vm, builtinNames.TransformStreamDefaultControllerPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_TransformStreamDefaultControllerConstructor, nullptr), attributesForStructure(static_cast<unsigned>(JSC::PropertyAttribute::DontEnum))); - putDirectCustomAccessor(vm, builtinNames.ReadableByteStreamControllerPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableByteStreamControllerConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamBYOBReaderPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamBYOBReaderConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamBYOBRequestPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamBYOBRequestConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamDefaultControllerPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamDefaultControllerConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamDefaultReaderPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamDefaultReaderConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.WritableStreamPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_WritableStreamConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.WritableStreamDefaultControllerPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_WritableStreamDefaultControllerConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.WritableStreamDefaultWriterPrivateName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_WritableStreamDefaultWriterConstructor, nullptr), attributesForStructure(JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly)); - putDirectCustomAccessor(vm, builtinNames.AbortSignalPrivateName(), CustomGetterSetter::create(vm, JSDOMAbortSignal_getter, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.ReadableByteStreamControllerPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableByteStreamControllerConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamBYOBReaderPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamBYOBReaderConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamBYOBRequestPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamBYOBRequestConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamDefaultControllerPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamDefaultControllerConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.ReadableStreamDefaultReaderPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ReadableStreamDefaultReaderConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.WritableStreamPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_WritableStreamConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.WritableStreamDefaultControllerPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_WritableStreamDefaultControllerConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, builtinNames.WritableStreamDefaultWriterPublicName(), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_WritableStreamDefaultWriterConstructor, nullptr), JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + putDirectNativeFunction(vm, this, builtinNames.createUninitializedArrayBufferPrivateName(), 1, functionCreateUninitializedArrayBuffer, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); + putDirectNativeFunction(vm, this, builtinNames.resolveSyncPrivateName(), 1, functionImportMeta__resolveSyncPrivate, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); + putDirectNativeFunction(vm, this, builtinNames.createInternalModuleByIdPrivateName(), 1, InternalModuleRegistry::jsCreateInternalModuleById, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); putDirectNativeFunction(vm, this, builtinNames.createCommonJSModulePrivateName(), @@ -4006,42 +3729,60 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) Bun::jsFunctionCreateCommonJSModule, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete | 0); putDirectNativeFunction(vm, this, builtinNames.evaluateCommonJSModulePrivateName(), 2, Bun::jsFunctionLoadModule, ImplementationVisibility::Public, NoIntrinsic, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "ByteLengthQueuingStrategy"_s), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_ByteLengthQueuingStrategyConstructor, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "CountQueuingStrategy"_s), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_CountQueuingStrategyConstructor, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "SubtleCrypto"_s), JSC::CustomGetterSetter::create(vm, getterSubtleCryptoConstructor, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); - putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "CryptoKey"_s), JSC::CustomGetterSetter::create(vm, getterCryptoKeyConstructor, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); + PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete | 0); + + putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().BufferPrivateName(), JSC::CustomGetterSetter::create(vm, JSBuffer_getter, nullptr), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.lazyStreamPrototypeMapPrivateName(), JSC::CustomGetterSetter::create(vm, functionLazyLoadStreamPrototypeMap_getter, nullptr), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.TransformStreamPrivateName(), CustomGetterSetter::create(vm, TransformStream_getter, nullptr), attributesForStructure(static_cast<unsigned>(PropertyAttribute::DontEnum)) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.TransformStreamDefaultControllerPrivateName(), CustomGetterSetter::create(vm, TransformStreamDefaultController_getter, nullptr), attributesForStructure(static_cast<unsigned>(PropertyAttribute::DontEnum)) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.ReadableByteStreamControllerPrivateName(), CustomGetterSetter::create(vm, ReadableByteStreamController_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.ReadableStreamPrivateName(), CustomGetterSetter::create(vm, ReadableStream_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.ReadableStreamBYOBReaderPrivateName(), CustomGetterSetter::create(vm, ReadableStreamBYOBReader_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.ReadableStreamBYOBRequestPrivateName(), CustomGetterSetter::create(vm, ReadableStreamBYOBRequest_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.ReadableStreamDefaultControllerPrivateName(), CustomGetterSetter::create(vm, ReadableStreamDefaultController_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.ReadableStreamDefaultReaderPrivateName(), CustomGetterSetter::create(vm, ReadableStreamDefaultReader_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.WritableStreamPrivateName(), CustomGetterSetter::create(vm, WritableStream_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.WritableStreamDefaultControllerPrivateName(), CustomGetterSetter::create(vm, WritableStreamDefaultController_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.WritableStreamDefaultWriterPrivateName(), CustomGetterSetter::create(vm, WritableStreamDefaultWriter_getter, nullptr), attributesForStructure(PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly) | PropertyAttribute::CustomAccessorOrValue); + putDirectCustomAccessor(vm, builtinNames.AbortSignalPrivateName(), CustomGetterSetter::create(vm, AbortSignal_getter, nullptr), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::CustomAccessorOrValue); + + // ----- Public Properties ----- + + // a direct accessor (uses js functions for get and set) cannot be on the lookup table. i think. + putDirectAccessor( + this, + builtinNames.selfPublicName(), + JSC::GetterSetter::create( + vm, + this, + JSFunction::create(vm, this, 0, "get"_s, functionGetSelf, ImplementationVisibility::Public), + JSFunction::create(vm, this, 0, "set"_s, functionSetSelf, ImplementationVisibility::Public)), + PropertyAttribute::Accessor | 0); - putDirectNativeFunction(vm, this, - Identifier::fromString(vm, "addEventListener"_s), - 2, - jsFunctionAddEventListener, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + // TODO: this should be usable on the lookup table. it crashed las time i tried it + putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "onmessage"_s), JSC::CustomGetterSetter::create(vm, globalOnMessage, setGlobalOnMessage), 0); + putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "onerror"_s), JSC::CustomGetterSetter::create(vm, globalOnError, setGlobalOnError), 0); - putDirectNativeFunction(vm, this, - Identifier::fromString(vm, "dispatchEvent"_s), - 1, - jsFunctionDispatchEvent, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + // ----- Extensions to Built-in objects ----- - putDirectNativeFunction(vm, this, - Identifier::fromString(vm, "removeEventListener"_s), - 2, - jsFunctionRemoveEventListener, - ImplementationVisibility::Public, - NoIntrinsic, - JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + JSC::JSObject* errorConstructor = this->errorConstructor(); + errorConstructor->putDirectNativeFunction(vm, this, JSC::Identifier::fromString(vm, "captureStackTrace"_s), 2, errorConstructorFuncCaptureStackTrace, ImplementationVisibility::Public, JSC::NoIntrinsic, PropertyAttribute::DontEnum | 0); + errorConstructor->putDirectNativeFunction(vm, this, JSC::Identifier::fromString(vm, "appendStackTrace"_s), 2, errorConstructorFuncAppendStackTrace, ImplementationVisibility::Private, JSC::NoIntrinsic, PropertyAttribute::DontEnum | 0); + errorConstructor->putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "prepareStackTrace"_s), JSC::CustomGetterSetter::create(vm, errorConstructorPrepareStackTraceGetter, errorConstructorPrepareStackTraceSetter), PropertyAttribute::DontEnum | PropertyAttribute::CustomValue); + + JSC::JSObject* consoleObject = this->get(this, JSC::Identifier::fromString(vm, "console"_s)).getObject(); + consoleObject->putDirectBuiltinFunction(vm, this, vm.propertyNames->asyncIteratorSymbol, consoleObjectAsyncIteratorCodeGenerator(vm), PropertyAttribute::Builtin | 0); + consoleObject->putDirectBuiltinFunction(vm, this, clientData->builtinNames().writePublicName(), consoleObjectWriteCodeGenerator(vm), PropertyAttribute::Builtin | 0); + consoleObject->putDirectCustomAccessor(vm, Identifier::fromString(vm, "Console"_s), CustomGetterSetter::create(vm, getConsoleConstructor, nullptr), PropertyAttribute::CustomValue | 0); + consoleObject->putDirectCustomAccessor(vm, Identifier::fromString(vm, "_stdout"_s), CustomGetterSetter::create(vm, getConsoleStdout, nullptr), PropertyAttribute::DontEnum | PropertyAttribute::CustomValue | 0); + consoleObject->putDirectCustomAccessor(vm, Identifier::fromString(vm, "_stderr"_s), CustomGetterSetter::create(vm, getConsoleStderr, nullptr), PropertyAttribute::DontEnum | PropertyAttribute::CustomValue | 0); } extern "C" bool JSC__JSGlobalObject__startRemoteInspector(JSC__JSGlobalObject* globalObject, unsigned char* host, uint16_t arg1) @@ -4104,29 +3845,8 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_readableStreamToFormData); visitor.append(thisObject->m_nodeModuleOverriddenResolveFilename); - visitor.append(thisObject->m_JSBlobSetterValue); - visitor.append(thisObject->m_JSBroadcastChannelSetterValue); - visitor.append(thisObject->m_JSBufferSetterValue); - visitor.append(thisObject->m_JSCloseEventSetterValue); - visitor.append(thisObject->m_JSCustomEventSetterValue); - visitor.append(thisObject->m_JSDOMExceptionSetterValue); - visitor.append(thisObject->m_JSDOMFormDataSetterValue); - visitor.append(thisObject->m_JSErrorEventSetterValue); - visitor.append(thisObject->m_JSEventSetterValue); - visitor.append(thisObject->m_JSEventTargetSetterValue); - visitor.append(thisObject->m_JSFetchHeadersSetterValue); - visitor.append(thisObject->m_JSMessageChannelSetterValue); - visitor.append(thisObject->m_JSMessageEventSetterValue); - visitor.append(thisObject->m_JSMessagePortSetterValue); - visitor.append(thisObject->m_JSRequestSetterValue); - visitor.append(thisObject->m_JSResponseSetterValue); - visitor.append(thisObject->m_JSTextDecoderSetterValue); - visitor.append(thisObject->m_JSTextEncoderSetterValue); - visitor.append(thisObject->m_JSURLSearchParamsSetterValue); - visitor.append(thisObject->m_JSWebSocketSetterValue); - visitor.append(thisObject->m_JSWorkerSetterValue); - visitor.append(thisObject->m_nextTickQueue); + visitor.append(thisObject->m_errorConstructorPrepareStackTraceValue); thisObject->m_JSArrayBufferSinkClassStructure.visit(visitor); thisObject->m_JSBufferListClassStructure.visit(visitor); @@ -4157,17 +3877,19 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_performanceObject.visit(visitor); thisObject->m_processEnvObject.visit(visitor); thisObject->m_processObject.visit(visitor); + thisObject->m_bunObject.visit(visitor); thisObject->m_subtleCryptoObject.visit(visitor); thisObject->m_JSHTTPResponseController.visit(visitor); thisObject->m_callSiteStructure.visit(visitor); thisObject->m_emitReadableNextTickFunction.visit(visitor); thisObject->m_JSBufferSubclassStructure.visit(visitor); + thisObject->m_JSCryptoKey.visit(visitor); + thisObject->m_cryptoObject.visit(visitor); thisObject->m_JSDOMFileConstructor.visit(visitor); thisObject->m_requireFunctionUnbound.visit(visitor); thisObject->m_requireResolveFunctionUnbound.visit(visitor); - thisObject->m_processBindingConstants.visit(visitor); thisObject->m_importMetaObjectStructure.visit(visitor); thisObject->m_asyncBoundFunctionStructure.visit(visitor); thisObject->m_internalModuleRegistry.visit(visitor); @@ -4180,6 +3902,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_commonJSModuleObjectStructure.visit(visitor); thisObject->m_memoryFootprintStructure.visit(visitor); thisObject->m_commonJSFunctionArgumentsStructure.visit(visitor); + thisObject->m_JSSocketAddressStructure.visit(visitor); thisObject->m_cachedGlobalObjectStructure.visit(visitor); thisObject->m_cachedGlobalProxyStructure.visit(visitor); @@ -4291,7 +4014,7 @@ template void GlobalObject::visitOutputConstraints(JSCell*, SlotVisitor&); // void GlobalObject::destroy(JSCell* cell) // { -// static_cast<Zig::GlobalObject*>(cell)->Zig::GlobalObject::~Zig::GlobalObject(); +// jsCast<Zig::GlobalObject*>(cell)->Zig::GlobalObject::~Zig::GlobalObject(); // } // template<typename Visitor> @@ -4351,16 +4074,45 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskCallback(Zig::GlobalObject* g globalObject->queueMicrotask(function, JSValue(bitwise_cast<double>(reinterpret_cast<uintptr_t>(ptr))), JSValue(bitwise_cast<double>(reinterpret_cast<uintptr_t>(callback))), jsUndefined(), jsUndefined()); } -JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, +JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* jsGlobalObject, JSModuleLoader* loader, JSValue key, JSValue referrer, JSValue origin) { + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(jsGlobalObject); + ErrorableString res; res.success = false; - BunString keyZ = Bun::toString(globalObject, key); - BunString referrerZ = referrer && !referrer.isUndefinedOrNull() && referrer.isString() ? Bun::toString(globalObject, referrer) : BunStringEmpty; + + if (key.isString()) { + if (auto* virtualModules = globalObject->onLoadPlugins.virtualModules) { + auto keyString = key.toWTFString(globalObject); + if (virtualModules->contains(keyString)) { + return JSC::Identifier::fromString(globalObject->vm(), keyString); + } + } + } + + BunString keyZ; + if (key.isString()) { + auto moduleName = jsCast<JSString*>(key)->value(globalObject); + if (moduleName.startsWith("file://"_s)) { + auto url = WTF::URL(moduleName); + if (url.isValid() && !url.isEmpty()) { + keyZ = Bun::toStringRef(url.fileSystemPath()); + } else { + keyZ = Bun::toStringRef(moduleName); + } + } else { + keyZ = Bun::toStringRef(moduleName); + } + } else { + keyZ = Bun::toStringRef(globalObject, key); + } + BunString referrerZ = referrer && !referrer.isUndefinedOrNull() && referrer.isString() ? Bun::toStringRef(globalObject, referrer) : BunStringEmpty; ZigString queryString = { 0, 0 }; Zig__GlobalObject__resolve(&res, globalObject, &keyZ, &referrerZ, &queryString); + keyZ.deref(); + referrerZ.deref(); if (res.success) { if (queryString.len > 0) { @@ -4375,25 +4127,60 @@ JSC::Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, } } -JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, +JSC::JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* jsGlobalObject, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin& sourceOrigin) { + auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(jsGlobalObject); JSC::VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); auto* promise = JSC::JSInternalPromise::create(vm, globalObject->internalPromiseStructure()); RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope)); + if (auto* virtualModules = globalObject->onLoadPlugins.virtualModules) { + auto keyString = moduleNameValue->value(globalObject); + if (virtualModules->contains(keyString)) { + auto resolvedIdentifier = JSC::Identifier::fromString(vm, keyString); + + auto result = JSC::importModule(globalObject, resolvedIdentifier, + JSC::jsUndefined(), parameters, JSC::jsUndefined()); + + RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope)); + return result; + } + } + auto sourceURL = sourceOrigin.url(); ErrorableString resolved; - auto moduleNameZ = Bun::toString(globalObject, moduleNameValue); - auto sourceOriginZ = sourceURL.isEmpty() ? BunStringCwd : Bun::toString(sourceURL.fileSystemPath()); + BunString moduleNameZ; + + auto moduleName = moduleNameValue->value(globalObject); +#if BUN_DEBUG + auto startRefCount = moduleName.impl()->refCount(); +#endif + if (moduleName.startsWith("file://"_s)) { + auto url = WTF::URL(moduleName); + if (url.isValid() && !url.isEmpty()) { + moduleNameZ = Bun::toStringRef(url.fileSystemPath()); + } else { + moduleNameZ = Bun::toStringRef(moduleName); + } + } else { + moduleNameZ = Bun::toStringRef(moduleName); + } + auto sourceOriginZ = sourceURL.isEmpty() ? BunStringCwd : Bun::toStringRef(sourceURL.fileSystemPath()); ZigString queryString = { 0, 0 }; resolved.success = false; Zig__GlobalObject__resolve(&resolved, globalObject, &moduleNameZ, &sourceOriginZ, &queryString); + moduleNameZ.deref(); + sourceOriginZ.deref(); +#if BUN_DEBUG + // TODO: ASSERT doesnt work right now + RELEASE_ASSERT(startRefCount == moduleName.impl()->refCount()); +#endif if (!resolved.success) { throwException(scope, resolved.result.err, globalObject); return promise->rejectWithCaughtException(globalObject, scope); @@ -4549,5 +4336,9 @@ GlobalObject::PromiseFunctions GlobalObject::promiseHandlerID(EncodedJSValue (*h } #include "ZigGeneratedClasses+lazyStructureImpl.h" +#include "ZigGlobalObject.lut.h" + +const JSC::ClassInfo GlobalObject::s_info = { "GlobalObject"_s, &Base::s_info, &bunGlobalObjectTable, nullptr, + CREATE_METHOD_TABLE(GlobalObject) }; } // namespace Zig diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 29c1cd09c..19630d4b7 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -13,21 +13,22 @@ namespace JSC { class Structure; class Identifier; class LazyClassStructure; - -} // namespace JSC - -namespace JSC { - enum class JSPromiseRejectionOperation : unsigned; - -} +} // namespace JSC namespace WebCore { class ScriptExecutionContext; class DOMGuardedObject; class EventLoopTask; class DOMWrapperWorld; -} +class GlobalScope; +class SubtleCrypto; +class EventTarget; +} // namespace WebCore + +namespace Bun { +class InternalModuleRegistry; +} // namespace Bun #include "root.h" @@ -43,37 +44,9 @@ class DOMWrapperWorld; #include "BunPlugin.h" #include "JSMockFunction.h" #include "InternalModuleRegistry.h" -#include "ProcessBindingConstants.h" - -namespace WebCore { -class GlobalScope; -class SubtleCrypto; -class EventTarget; -} extern "C" void Bun__reportError(JSC__JSGlobalObject*, JSC__JSValue); extern "C" void Bun__reportUnhandledError(JSC__JSGlobalObject*, JSC::EncodedJSValue); -// defined in ModuleLoader.cpp -extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultResolve(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); -extern "C" JSC::EncodedJSValue jsFunctionOnLoadObjectResultReject(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame); - -// #include "EventTarget.h" - -// namespace WebCore { -// class GlobalEventTarget : public EventTargetWithInlineData, public ContextDestructionObserver { -// WTF_MAKE_ISO_ALLOCATED(GlobalEventTarget); - -// public: -// static Ref<GlobalEventTarget> create(ScriptExecutionContext&); - -// EventTargetInterface eventTargetInterface() const final { return DOMWindowEventTargetInterfaceType; } -// ScriptExecutionContext* scriptExecutionContext() const final { return ContextDestructionObserver::scriptExecutionContext(); } -// void refEventTarget() final {} -// void derefEventTarget() final {} -// void eventListenersDidChange() final; -// }; - -// } namespace Zig { @@ -179,27 +152,17 @@ public: void clearDOMGuardedObjects(); - static void createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalObject, JSCStackTrace& stackTrace, JSC::JSArray* callSites); - JSC::JSValue formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* errorObject, JSC::JSArray* callSites); + static void createCallSitesFromFrames(Zig::GlobalObject* globalObject, JSC::JSGlobalObject* lexicalGlobalObject, JSCStackTrace& stackTrace, JSC::JSArray* callSites); + void formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* errorObject, JSC::JSArray* callSites, JSValue prepareStack = JSC::jsUndefined()); static void reportUncaughtExceptionAtEventLoop(JSGlobalObject*, JSC::Exception*); static JSGlobalObject* deriveShadowRealmGlobalObject(JSGlobalObject* globalObject); - static JSC::JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, JSC::JSModuleLoader*, - JSC::JSString* moduleNameValue, - JSC::JSValue parameters, - const JSC::SourceOrigin&); - static JSC::Identifier moduleLoaderResolve(JSGlobalObject*, JSC::JSModuleLoader*, - JSC::JSValue keyValue, JSC::JSValue referrerValue, - JSC::JSValue); - static JSC::JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, JSC::JSModuleLoader*, - JSC::JSValue, JSC::JSValue, JSC::JSValue); - static JSC::JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, - JSC::JSModuleLoader*, JSC::JSValue, - JSC::JSModuleRecord*, JSC::JSValue); - static JSC::JSValue moduleLoaderEvaluate(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, - JSC::JSValue, JSC::JSValue, JSC::JSValue, JSC::JSValue); - static void promiseRejectionTracker(JSGlobalObject*, JSC::JSPromise*, - JSC::JSPromiseRejectionOperation); + static JSC::JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSString* moduleNameValue, JSC::JSValue parameters, const JSC::SourceOrigin&); + static JSC::Identifier moduleLoaderResolve(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue keyValue, JSC::JSValue referrerValue, JSC::JSValue); + static JSC::JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue); + static JSC::JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSModuleRecord*, JSC::JSValue); + static JSC::JSValue moduleLoaderEvaluate(JSGlobalObject*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue, JSC::JSValue, JSC::JSValue); + static void promiseRejectionTracker(JSGlobalObject*, JSC::JSPromise*, JSC::JSPromiseRejectionOperation); void setConsole(void* console); WebCore::JSBuiltinInternalFunctions& builtinInternalFunctions() { return m_builtinInternalFunctions; } JSC::Structure* FFIFunctionStructure() { return m_JSFFIFunctionStructure.getInitializedOnMainThread(this); } @@ -215,6 +178,8 @@ public: JSC::JSValue JSBufferPrototype() { return m_JSBufferClassStructure.prototypeInitializedOnMainThread(this); } JSC::Structure* JSBufferSubclassStructure() { return m_JSBufferSubclassStructure.getInitializedOnMainThread(this); } + JSC::Structure* JSCryptoKeyStructure() { return m_JSCryptoKey.getInitializedOnMainThread(this); } + JSC::Structure* ArrayBufferSinkStructure() { return m_JSArrayBufferSinkClassStructure.getInitializedOnMainThread(this); } JSC::JSObject* ArrayBufferSink() { return m_JSArrayBufferSinkClassStructure.constructorInitializedOnMainThread(this); } JSC::JSValue ArrayBufferSinkPrototype() { return m_JSArrayBufferSinkClassStructure.prototypeInitializedOnMainThread(this); } @@ -266,7 +231,8 @@ public: JSObject* requireFunctionUnbound() { return m_requireFunctionUnbound.getInitializedOnMainThread(this); } JSObject* requireResolveFunctionUnbound() { return m_requireResolveFunctionUnbound.getInitializedOnMainThread(this); } Bun::InternalModuleRegistry* internalModuleRegistry() { return m_internalModuleRegistry.getInitializedOnMainThread(this); } - Bun::ProcessBindingConstants* processBindingConstants() { return m_processBindingConstants.getInitializedOnMainThread(this); } + + JSObject* processBindingConstants() { return m_processBindingConstants.getInitializedOnMainThread(this); } JSObject* lazyRequireCacheObject() { return m_lazyRequireCacheObject.getInitializedOnMainThread(this); } @@ -281,36 +247,28 @@ public: Structure* AsyncContextFrameStructure() { return m_asyncBoundFunctionStructure.getInitializedOnMainThread(this); } Structure* commonJSFunctionArgumentsStructure() { return m_commonJSFunctionArgumentsStructure.getInitializedOnMainThread(this); } + Structure* JSSocketAddressStructure() { return m_JSSocketAddressStructure.getInitializedOnMainThread(this); } JSWeakMap* vmModuleContextMap() { return m_vmModuleContextMap.getInitializedOnMainThread(this); } bool hasProcessObject() const { return m_processObject.isInitialized(); } - JSC::JSObject* processObject() - { - return m_processObject.getInitializedOnMainThread(this); - } - - JSC::JSObject* processEnvObject() - { - return m_processEnvObject.getInitializedOnMainThread(this); - } + JSC::JSObject* processObject() { return m_processObject.getInitializedOnMainThread(this); } + JSC::JSObject* processEnvObject() { return m_processEnvObject.getInitializedOnMainThread(this); } + JSC::JSObject* bunObject() { return m_bunObject.getInitializedOnMainThread(this); } void drainMicrotasks(); void handleRejectedPromises(); - void initGeneratedLazyClasses(); + ALWAYS_INLINE void initGeneratedLazyClasses(); template<typename Visitor> void visitGeneratedLazyClasses(GlobalObject*, Visitor&); - void* bunVM() { return m_bunVM; } + ALWAYS_INLINE void* bunVM() { return m_bunVM; } bool isThreadLocalDefaultGlobalObject = false; - JSObject* subtleCrypto() - { - return m_subtleCryptoObject.getInitializedOnMainThread(this); - } + JSObject* subtleCrypto() { return m_subtleCryptoObject.getInitializedOnMainThread(this); } EncodedJSValue assignToStream(JSValue stream, JSValue controller); @@ -377,6 +335,7 @@ public: * For example, if you don't add the queueMicrotask functions to visitChildrenImpl(), * those callbacks will eventually never be called anymore. But it'll work the first time! */ + // TODO: these should use LazyProperty mutable WriteBarrier<JSFunction> m_assignToStream; mutable WriteBarrier<JSFunction> m_readableStreamToArrayBuffer; mutable WriteBarrier<JSFunction> m_readableStreamToArrayBufferResolve; @@ -390,28 +349,14 @@ public: mutable WriteBarrier<JSFunction> m_nodeModuleOverriddenResolveFilename; mutable WriteBarrier<Unknown> m_nextTickQueue; + // Value of $_BunCommonJSModule_$ mutable WriteBarrier<Unknown> m_BunCommonJSModuleValue; - mutable WriteBarrier<Unknown> m_JSBroadcastChannelSetterValue; - mutable WriteBarrier<Unknown> m_JSBufferSetterValue; - mutable WriteBarrier<Unknown> m_JSCloseEventSetterValue; - mutable WriteBarrier<Unknown> m_JSCustomEventSetterValue; - mutable WriteBarrier<Unknown> m_JSDOMExceptionSetterValue; - mutable WriteBarrier<Unknown> m_JSDOMFormDataSetterValue; - mutable WriteBarrier<Unknown> m_JSErrorEventSetterValue; - mutable WriteBarrier<Unknown> m_JSEventSetterValue; - mutable WriteBarrier<Unknown> m_JSEventTargetSetterValue; - mutable WriteBarrier<Unknown> m_JSFetchHeadersSetterValue; - mutable WriteBarrier<Unknown> m_JSMessageChannelSetterValue; - mutable WriteBarrier<Unknown> m_JSMessageEventSetterValue; - mutable WriteBarrier<Unknown> m_JSMessagePortSetterValue; - mutable WriteBarrier<Unknown> m_JSTextEncoderSetterValue; - mutable WriteBarrier<Unknown> m_JSURLSearchParamsSetterValue; - mutable WriteBarrier<Unknown> m_JSWebSocketSetterValue; - mutable WriteBarrier<Unknown> m_JSWorkerSetterValue; - - mutable WriteBarrier<Unknown> m_JSBunDebuggerValue; + + // mutable WriteBarrier<Unknown> m_JSBunDebuggerValue; mutable WriteBarrier<JSFunction> m_thenables[promiseFunctionsSize + 1]; + mutable WriteBarrier<JSC::Unknown> m_errorConstructorPrepareStackTraceValue; + Structure* memoryFootprintStructure() { return m_memoryFootprintStructure.getInitializedOnMainThread(this); @@ -439,9 +384,8 @@ public: return false; } - BunPlugin::OnLoad onLoadPlugins[BunPluginTargetMax + 1] {}; - BunPlugin::OnResolve onResolvePlugins[BunPluginTargetMax + 1] {}; - BunPluginTarget defaultBunPluginTarget = BunPluginTargetBun; + BunPlugin::OnLoad onLoadPlugins {}; + BunPlugin::OnResolve onResolvePlugins {}; // This increases the cache hit rate for JSC::VM's SourceProvider cache // It also avoids an extra allocation for the SourceProvider @@ -478,6 +422,7 @@ public: private: void addBuiltinGlobals(JSC::VM&); + void finishCreation(JSC::VM&); friend void WebCore::JSBuiltinInternalFunctions::initialize(Zig::GlobalObject&); WebCore::JSBuiltinInternalFunctions m_builtinInternalFunctions; @@ -490,6 +435,9 @@ private: WebCore::ScriptExecutionContext* m_scriptExecutionContext; Ref<WebCore::DOMWrapperWorld> m_world; + // JSC's hashtable code-generator tries to access these properties, so we make them public. + // However, we'd like it better if they could be protected. +public: /** * WARNING: You must update visitChildrenImpl() if you add a new field. * @@ -523,7 +471,7 @@ private: * For example, if you don't add the queueMicrotask functions to visitChildrenImpl(), * those callbacks will eventually never be called anymore. But it'll work the first time! */ - LazyProperty<JSGlobalObject, JSC::Structure> m_pendingVirtualModuleResultStructure; + LazyProperty<JSGlobalObject, Structure> m_pendingVirtualModuleResultStructure; LazyProperty<JSGlobalObject, JSFunction> m_performMicrotaskFunction; LazyProperty<JSGlobalObject, JSFunction> m_nativeMicrotaskTrampoline; LazyProperty<JSGlobalObject, JSFunction> m_performMicrotaskVariadicFunction; @@ -537,38 +485,40 @@ private: LazyProperty<JSGlobalObject, JSObject> m_JSArrayBufferControllerPrototype; LazyProperty<JSGlobalObject, JSObject> m_JSFileSinkControllerPrototype; LazyProperty<JSGlobalObject, JSObject> m_JSHTTPSResponseControllerPrototype; - LazyProperty<JSGlobalObject, JSObject> m_navigatorObject; - LazyProperty<JSGlobalObject, JSObject> m_performanceObject; - LazyProperty<JSGlobalObject, JSObject> m_processObject; LazyProperty<JSGlobalObject, JSObject> m_subtleCryptoObject; LazyProperty<JSGlobalObject, Structure> m_JSHTTPResponseController; - LazyProperty<JSGlobalObject, JSC::Structure> m_JSBufferSubclassStructure; + LazyProperty<JSGlobalObject, Structure> m_JSBufferSubclassStructure; LazyProperty<JSGlobalObject, JSWeakMap> m_vmModuleContextMap; LazyProperty<JSGlobalObject, JSObject> m_lazyRequireCacheObject; LazyProperty<JSGlobalObject, JSObject> m_lazyTestModuleObject; LazyProperty<JSGlobalObject, JSObject> m_lazyPreloadTestModuleObject; - LazyProperty<JSGlobalObject, JSFunction> m_bunSleepThenCallback; LazyProperty<JSGlobalObject, Structure> m_cachedGlobalObjectStructure; LazyProperty<JSGlobalObject, Structure> m_cachedGlobalProxyStructure; LazyProperty<JSGlobalObject, Structure> m_commonJSModuleObjectStructure; LazyProperty<JSGlobalObject, Structure> m_commonJSFunctionArgumentsStructure; + LazyProperty<JSGlobalObject, Structure> m_JSSocketAddressStructure; LazyProperty<JSGlobalObject, Structure> m_memoryFootprintStructure; - LazyProperty<JSGlobalObject, JSObject> m_cryptoObject; - - LazyProperty<JSGlobalObject, JSC::JSObject> m_requireFunctionUnbound; - LazyProperty<JSGlobalObject, JSC::JSObject> m_requireResolveFunctionUnbound; + LazyProperty<JSGlobalObject, JSObject> m_requireFunctionUnbound; + LazyProperty<JSGlobalObject, JSObject> m_requireResolveFunctionUnbound; LazyProperty<JSGlobalObject, Bun::InternalModuleRegistry> m_internalModuleRegistry; - LazyProperty<JSGlobalObject, Bun::ProcessBindingConstants> m_processBindingConstants; - LazyProperty<JSGlobalObject, JSC::Structure> m_importMetaObjectStructure; - LazyProperty<JSGlobalObject, JSC::Structure> m_asyncBoundFunctionStructure; - + LazyProperty<JSGlobalObject, JSObject> m_processBindingConstants; + LazyProperty<JSGlobalObject, Structure> m_importMetaObjectStructure; + LazyProperty<JSGlobalObject, Structure> m_asyncBoundFunctionStructure; LazyProperty<JSGlobalObject, JSC::JSObject> m_JSDOMFileConstructor; + LazyProperty<JSGlobalObject, Structure> m_JSCryptoKey; + LazyProperty<JSGlobalObject, JSObject> m_bunObject; + LazyProperty<JSGlobalObject, JSObject> m_cryptoObject; + LazyProperty<JSGlobalObject, JSObject> m_navigatorObject; + LazyProperty<JSGlobalObject, JSObject> m_performanceObject; + LazyProperty<JSGlobalObject, JSObject> m_processObject; + +private: DOMGuardedObjectSet m_guardedObjects WTF_GUARDED_BY_LOCK(m_gcLock); void* m_bunVM; - WebCore::SubtleCrypto* crypto = nullptr; + WebCore::SubtleCrypto* m_subtleCrypto = nullptr; WTF::Vector<JSC::Strong<JSC::JSPromise>> m_aboutToBeNotifiedRejectedPromises; WTF::Vector<JSC::Strong<JSC::JSFunction>> m_ffiFunctions; diff --git a/src/bun.js/bindings/ZigGlobalObject.lut.h b/src/bun.js/bindings/ZigGlobalObject.lut.h new file mode 100644 index 000000000..6516648e8 --- /dev/null +++ b/src/bun.js/bindings/ZigGlobalObject.lut.h @@ -0,0 +1,341 @@ +// File generated via `make static-hash-table` / `make cpp` +static const struct CompactHashIndex bunGlobalObjectTableIndex[260] = { + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 42, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 6, -1 }, + { 3, -1 }, + { -1, -1 }, + { 34, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 29, 258 }, + { -1, -1 }, + { -1, -1 }, + { 54, 257 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 51, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 2, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 18, -1 }, + { 56, -1 }, + { -1, -1 }, + { -1, -1 }, + { 14, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 41, -1 }, + { 47, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 69, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 39, -1 }, + { -1, -1 }, + { -1, -1 }, + { 38, -1 }, + { 63, -1 }, + { -1, -1 }, + { 57, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 49, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 58, -1 }, + { 11, -1 }, + { -1, -1 }, + { -1, -1 }, + { 0, -1 }, + { -1, -1 }, + { 37, -1 }, + { 21, -1 }, + { 66, -1 }, + { -1, -1 }, + { -1, -1 }, + { 70, -1 }, + { -1, -1 }, + { 45, -1 }, + { -1, -1 }, + { 48, -1 }, + { -1, -1 }, + { -1, -1 }, + { 24, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 33, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 50, -1 }, + { 46, -1 }, + { -1, -1 }, + { 13, -1 }, + { -1, -1 }, + { -1, -1 }, + { 43, -1 }, + { -1, -1 }, + { 1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 32, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 28, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 26, -1 }, + { -1, -1 }, + { -1, -1 }, + { 17, -1 }, + { -1, -1 }, + { 31, -1 }, + { -1, -1 }, + { -1, -1 }, + { 35, -1 }, + { 71, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 22, -1 }, + { -1, -1 }, + { -1, -1 }, + { 4, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 23, -1 }, + { -1, -1 }, + { -1, -1 }, + { 55, -1 }, + { -1, -1 }, + { 53, -1 }, + { -1, -1 }, + { 12, -1 }, + { 25, -1 }, + { 7, -1 }, + { -1, -1 }, + { 9, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 61, -1 }, + { 60, -1 }, + { -1, -1 }, + { 5, 256 }, + { -1, -1 }, + { 64, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 36, -1 }, + { -1, -1 }, + { 15, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 40, 259 }, + { -1, -1 }, + { -1, -1 }, + { 68, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 52, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 30, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 27, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 44, -1 }, + { -1, -1 }, + { -1, -1 }, + { 65, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 20, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 10, -1 }, + { 16, -1 }, + { -1, -1 }, + { -1, -1 }, + { -1, -1 }, + { 19, -1 }, + { -1, -1 }, + { 8, -1 }, + { 59, -1 }, + { 62, -1 }, + { 67, -1 }, +}; + +static const struct HashTableValue bunGlobalObjectTableValues[72] = { + { "addEventListener"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsFunctionAddEventListener, 2 } }, + { "alert"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, WebCore__alert, 1 } }, + { "atob"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionATOB, 1 } }, + { "btoa"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionBTOA, 1 } }, + { "clearImmediate"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionClearTimeout, 1 } }, + { "clearInterval"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionClearInterval, 1 } }, + { "clearTimeout"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionClearTimeout, 1 } }, + { "confirm"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, WebCore__confirm, 1 } }, + { "dispatchEvent"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsFunctionDispatchEvent, 1 } }, + { "fetch"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, Bun__fetch, 2 } }, + { "postMessage"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsFunctionPostMessage, 1 } }, + { "prompt"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, WebCore__prompt, 1 } }, + { "queueMicrotask"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionQueueMicrotask, 2 } }, + { "removeEventListener"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsFunctionRemoveEventListener, 2 } }, + { "reportError"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionReportError, 1 } }, + { "setImmediate"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionSetImmediate, 1 } }, + { "setInterval"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionSetInterval, 1 } }, + { "setTimeout"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionSetTimeout, 1 } }, + { "structuredClone"_s, static_cast<unsigned>(PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, functionStructuredClone, 2 } }, + { "global"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, GlobalObject_getGlobalThis } }, + { "EventSource"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, getEventSourceConstructor } }, + { "Bun"_s, static_cast<unsigned>(PropertyAttribute::CellProperty|PropertyAttribute::DontDelete|PropertyAttribute::ReadOnly), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_bunObject) } }, + { "File"_s, static_cast<unsigned>(PropertyAttribute::CellProperty), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_JSDOMFileConstructor) } }, + { "crypto"_s, static_cast<unsigned>(PropertyAttribute::CellProperty), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_cryptoObject) } }, + { "navigator"_s, static_cast<unsigned>(PropertyAttribute::CellProperty), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_navigatorObject) } }, + { "performance"_s, static_cast<unsigned>(PropertyAttribute::CellProperty), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_performanceObject) } }, + { "process"_s, static_cast<unsigned>(PropertyAttribute::CellProperty), NoIntrinsic, { HashTableValue::LazyCellPropertyType, OBJECT_OFFSETOF(GlobalObject, m_processObject) } }, + { "Blob"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSBlob) } }, + { "Buffer"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSBufferClassStructure) } }, + { "BuildError"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSBuildMessage) } }, + { "BuildMessage"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSBuildMessage) } }, + { "Crypto"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSCrypto) } }, + { "HTMLRewriter"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSHTMLRewriter) } }, + { "Request"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSRequest) } }, + { "ResolveError"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSResolveMessage) } }, + { "ResolveMessage"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSResolveMessage) } }, + { "Response"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSResponse) } }, + { "TextDecoder"_s, static_cast<unsigned>(PropertyAttribute::ClassStructure), NoIntrinsic, { HashTableValue::LazyClassStructureType, OBJECT_OFFSETOF(GlobalObject, m_JSTextDecoder) } }, + { "AbortController"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, AbortControllerConstructorCallback } }, + { "AbortSignal"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, AbortSignalConstructorCallback } }, + { "BroadcastChannel"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, BroadcastChannelConstructorCallback } }, + { "ByteLengthQueuingStrategy"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, ByteLengthQueuingStrategyConstructorCallback } }, + { "CloseEvent"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, CloseEventConstructorCallback } }, + { "CountQueuingStrategy"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, CountQueuingStrategyConstructorCallback } }, + { "CryptoKey"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, CryptoKeyConstructorCallback } }, + { "CustomEvent"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, CustomEventConstructorCallback } }, + { "DOMException"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, DOMExceptionConstructorCallback } }, + { "ErrorEvent"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, ErrorEventConstructorCallback } }, + { "Event"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, EventConstructorCallback } }, + { "EventTarget"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, EventTargetConstructorCallback } }, + { "FormData"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, DOMFormDataConstructorCallback } }, + { "Headers"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, FetchHeadersConstructorCallback } }, + { "MessageChannel"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, MessageChannelConstructorCallback } }, + { "MessageEvent"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, MessageEventConstructorCallback } }, + { "MessagePort"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, MessagePortConstructorCallback } }, + { "ReadableByteStreamController"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, ReadableByteStreamControllerConstructorCallback } }, + { "ReadableStream"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, ReadableStreamConstructorCallback } }, + { "ReadableStreamBYOBReader"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, ReadableStreamBYOBReaderConstructorCallback } }, + { "ReadableStreamBYOBRequest"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, ReadableStreamBYOBRequestConstructorCallback } }, + { "ReadableStreamDefaultController"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, ReadableStreamDefaultControllerConstructorCallback } }, + { "ReadableStreamDefaultReader"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, ReadableStreamDefaultReaderConstructorCallback } }, + { "SubtleCrypto"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, SubtleCryptoConstructorCallback } }, + { "TextEncoder"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, TextEncoderConstructorCallback } }, + { "TransformStream"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, TransformStreamConstructorCallback } }, + { "URL"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, DOMURLConstructorCallback } }, + { "URLSearchParams"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, URLSearchParamsConstructorCallback } }, + { "WebSocket"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, WebSocketConstructorCallback } }, + { "Worker"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, WorkerConstructorCallback } }, + { "WritableStream"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, WritableStreamConstructorCallback } }, + { "WritableStreamDefaultController"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, WritableStreamDefaultControllerConstructorCallback } }, + { "WritableStreamDefaultWriter"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, WritableStreamDefaultWriterConstructorCallback } }, + { "TransformStreamDefaultController"_s, static_cast<unsigned>(PropertyAttribute::PropertyCallback), NoIntrinsic, { HashTableValue::LazyPropertyType, TransformStreamDefaultControllerConstructorCallback } }, +}; + +static const struct HashTable bunGlobalObjectTable = + { 72, 255, false, nullptr, bunGlobalObjectTableValues, bunGlobalObjectTableIndex }; diff --git a/src/bun.js/bindings/ZigGlobalObject.lut.txt b/src/bun.js/bindings/ZigGlobalObject.lut.txt new file mode 100644 index 000000000..aadaee92a --- /dev/null +++ b/src/bun.js/bindings/ZigGlobalObject.lut.txt @@ -0,0 +1,82 @@ +// In a separate file because processing ZigGlobalObject.cpp takes 15+ seconds + +/* Source for ZigGlobalObject.lut.h +@begin bunGlobalObjectTable + addEventListener jsFunctionAddEventListener Function 2 + alert WebCore__alert Function 1 + atob functionATOB Function 1 + btoa functionBTOA Function 1 + clearImmediate functionClearTimeout Function 1 + clearInterval functionClearInterval Function 1 + clearTimeout functionClearTimeout Function 1 + confirm WebCore__confirm Function 1 + dispatchEvent jsFunctionDispatchEvent Function 1 + fetch Bun__fetch Function 2 + postMessage jsFunctionPostMessage Function 1 + prompt WebCore__prompt Function 1 + queueMicrotask functionQueueMicrotask Function 2 + removeEventListener jsFunctionRemoveEventListener Function 2 + reportError functionReportError Function 1 + setImmediate functionSetImmediate Function 1 + setInterval functionSetInterval Function 1 + setTimeout functionSetTimeout Function 1 + structuredClone functionStructuredClone Function 2 + + global GlobalObject_getGlobalThis PropertyCallback + EventSource getEventSourceConstructor PropertyCallback + + Bun GlobalObject::m_bunObject CellProperty|DontDelete|ReadOnly + File GlobalObject::m_JSDOMFileConstructor CellProperty + crypto GlobalObject::m_cryptoObject CellProperty + navigator GlobalObject::m_navigatorObject CellProperty + performance GlobalObject::m_performanceObject CellProperty + process GlobalObject::m_processObject CellProperty + + Blob GlobalObject::m_JSBlob ClassStructure + Buffer GlobalObject::m_JSBufferClassStructure ClassStructure + BuildError GlobalObject::m_JSBuildMessage ClassStructure + BuildMessage GlobalObject::m_JSBuildMessage ClassStructure + Crypto GlobalObject::m_JSCrypto ClassStructure + HTMLRewriter GlobalObject::m_JSHTMLRewriter ClassStructure + Request GlobalObject::m_JSRequest ClassStructure + ResolveError GlobalObject::m_JSResolveMessage ClassStructure + ResolveMessage GlobalObject::m_JSResolveMessage ClassStructure + Response GlobalObject::m_JSResponse ClassStructure + TextDecoder GlobalObject::m_JSTextDecoder ClassStructure + + AbortController AbortControllerConstructorCallback PropertyCallback + AbortSignal AbortSignalConstructorCallback PropertyCallback + BroadcastChannel BroadcastChannelConstructorCallback PropertyCallback + ByteLengthQueuingStrategy ByteLengthQueuingStrategyConstructorCallback PropertyCallback + CloseEvent CloseEventConstructorCallback PropertyCallback + CountQueuingStrategy CountQueuingStrategyConstructorCallback PropertyCallback + CryptoKey CryptoKeyConstructorCallback PropertyCallback + CustomEvent CustomEventConstructorCallback PropertyCallback + DOMException DOMExceptionConstructorCallback PropertyCallback + ErrorEvent ErrorEventConstructorCallback PropertyCallback + Event EventConstructorCallback PropertyCallback + EventTarget EventTargetConstructorCallback PropertyCallback + FormData DOMFormDataConstructorCallback PropertyCallback + Headers FetchHeadersConstructorCallback PropertyCallback + MessageChannel MessageChannelConstructorCallback PropertyCallback + MessageEvent MessageEventConstructorCallback PropertyCallback + MessagePort MessagePortConstructorCallback PropertyCallback + ReadableByteStreamController ReadableByteStreamControllerConstructorCallback PropertyCallback + ReadableStream ReadableStreamConstructorCallback PropertyCallback + ReadableStreamBYOBReader ReadableStreamBYOBReaderConstructorCallback PropertyCallback + ReadableStreamBYOBRequest ReadableStreamBYOBRequestConstructorCallback PropertyCallback + ReadableStreamDefaultController ReadableStreamDefaultControllerConstructorCallback PropertyCallback + ReadableStreamDefaultReader ReadableStreamDefaultReaderConstructorCallback PropertyCallback + SubtleCrypto SubtleCryptoConstructorCallback PropertyCallback + TextEncoder TextEncoderConstructorCallback PropertyCallback + TransformStream TransformStreamConstructorCallback PropertyCallback + URL DOMURLConstructorCallback PropertyCallback + URLSearchParams URLSearchParamsConstructorCallback PropertyCallback + WebSocket WebSocketConstructorCallback PropertyCallback + Worker WorkerConstructorCallback PropertyCallback + WritableStream WritableStreamConstructorCallback PropertyCallback + WritableStreamDefaultController WritableStreamDefaultControllerConstructorCallback PropertyCallback + WritableStreamDefaultWriter WritableStreamDefaultWriterConstructorCallback PropertyCallback + TransformStreamDefaultController TransformStreamDefaultControllerConstructorCallback PropertyCallback +@end +*/ diff --git a/src/bun.js/bindings/ZigLazyStaticFunctions-inlines.h b/src/bun.js/bindings/ZigLazyStaticFunctions-inlines.h index c97393723..0c13ecd58 100644 --- a/src/bun.js/bindings/ZigLazyStaticFunctions-inlines.h +++ b/src/bun.js/bindings/ZigLazyStaticFunctions-inlines.h @@ -25,7 +25,7 @@ static void DOMCall__FFI__ptr__put(JSC::JSGlobalObject* globalObject, JSC::Encod globalObject->vm(), Identifier::fromString(globalObject->vm(), "ptr"_s), function, - JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction | 0); + 0); } /* -- END DOMCall DEFINITIONS-- */ diff --git a/src/bun.js/bindings/ZigSourceProvider.cpp b/src/bun.js/bindings/ZigSourceProvider.cpp index d11c748da..960e577b9 100644 --- a/src/bun.js/bindings/ZigSourceProvider.cpp +++ b/src/bun.js/bindings/ZigSourceProvider.cpp @@ -104,6 +104,7 @@ Ref<SourceProvider> SourceProvider::create(Zig::GlobalObject* globalObject, Reso auto provider = adoptRef(*new SourceProvider( globalObject->isThreadLocalDefaultGlobalObject ? globalObject : nullptr, resolvedSource, stringImpl.releaseImpl().releaseNonNull(), + JSC::SourceTaintedOrigin::Untainted, toSourceOrigin(sourceURLString, isBuiltin), sourceURLString.impl(), TextPosition(), sourceType)); diff --git a/src/bun.js/bindings/ZigSourceProvider.h b/src/bun.js/bindings/ZigSourceProvider.h index 364e6ee23..b7574c7a4 100644 --- a/src/bun.js/bindings/ZigSourceProvider.h +++ b/src/bun.js/bindings/ZigSourceProvider.h @@ -69,9 +69,10 @@ public: private: SourceProvider(Zig::GlobalObject* globalObject, ResolvedSource resolvedSource, Ref<WTF::StringImpl>&& sourceImpl, + JSC::SourceTaintedOrigin taintedness, const SourceOrigin& sourceOrigin, WTF::String&& sourceURL, const TextPosition& startPosition, JSC::SourceProviderSourceType sourceType) - : Base(sourceOrigin, WTFMove(sourceURL), String(), startPosition, sourceType) + : Base(sourceOrigin, WTFMove(sourceURL), String(), taintedness, startPosition, sourceType) , m_source(sourceImpl) { diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index e46982aad..117b848ef 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -19,6 +19,7 @@ #include "JavaScriptCore/JSArray.h" #include "JavaScriptCore/JSArrayBuffer.h" #include "JavaScriptCore/JSArrayInlines.h" +#include "JavaScriptCore/ErrorInstanceInlines.h" #include "JavaScriptCore/JSCallbackObject.h" #include "JavaScriptCore/JSClassRef.h" @@ -229,6 +230,47 @@ AsymmetricMatcherResult matchAsymmetricMatcher(JSGlobalObject* globalObject, JSC } return AsymmetricMatcherResult::FAIL; + } else if (auto* expectArrayContaining = jsDynamicCast<JSExpectArrayContaining*>(matcherPropCell)) { + JSValue expectedArrayValue = expectArrayContaining->m_arrayValue.get(); + + if (JSC::isArray(globalObject, otherProp)) { + if (JSC::isArray(globalObject, expectedArrayValue)) { + JSArray* expectedArray = jsDynamicCast<JSArray*>(expectedArrayValue); + JSArray* otherArray = jsDynamicCast<JSArray*>(otherProp); + + unsigned expectedLength = expectedArray->length(); + unsigned otherLength = otherArray->length(); + + // A empty array is all array's subset + if (expectedLength == 0) { + return AsymmetricMatcherResult::PASS; + } + + // O(m*n) but works for now + for (unsigned m = 0; m < expectedLength; m++) { + JSValue expectedValue = expectedArray->getIndex(globalObject, m); + bool found = false; + + for (unsigned n = 0; n < otherLength; n++) { + JSValue otherValue = otherArray->getIndex(globalObject, n); + ThrowScope scope = DECLARE_THROW_SCOPE(globalObject->vm()); + Vector<std::pair<JSValue, JSValue>, 16> stack; + if (Bun__deepEquals<false, true>(globalObject, expectedValue, otherValue, stack, &scope, true)) { + found = true; + break; + } + } + + if (!found) { + return AsymmetricMatcherResult::FAIL; + } + } + + return AsymmetricMatcherResult::PASS; + } + } + + return AsymmetricMatcherResult::FAIL; } return AsymmetricMatcherResult::NOT_MATCHER; @@ -306,10 +348,8 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, // need to check this before primitives, asymmetric matchers // can match against any type of value. if constexpr (enableAsymmetricMatchers) { - JSCell* c1 = v1.asCell(); - JSCell* c2 = v2.asCell(); - if (v2.isCell() && !v2.isEmpty() && c2->type() == JSC::JSType(JSDOMWrapperType)) { - switch (matchAsymmetricMatcher(globalObject, c2, v1, scope)) { + if (v2.isCell() && !v2.isEmpty() && v2.asCell()->type() == JSC::JSType(JSDOMWrapperType)) { + switch (matchAsymmetricMatcher(globalObject, v2.asCell(), v1, scope)) { case AsymmetricMatcherResult::FAIL: return false; case AsymmetricMatcherResult::PASS: @@ -318,8 +358,8 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, // continue comparison break; } - } else if (v1.isCell() && !v1.isEmpty() && c1->type() == JSC::JSType(JSDOMWrapperType)) { - switch (matchAsymmetricMatcher(globalObject, c1, v2, scope)) { + } else if (v1.isCell() && !v1.isEmpty() && v1.asCell()->type() == JSC::JSType(JSDOMWrapperType)) { + switch (matchAsymmetricMatcher(globalObject, v1.asCell(), v2, scope)) { case AsymmetricMatcherResult::FAIL: return false; case AsymmetricMatcherResult::PASS: @@ -576,7 +616,7 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, case Float64ArrayType: case BigInt64ArrayType: case BigUint64ArrayType: { - if (!isTypedArrayType(static_cast<JSC::JSType>(c2Type))) { + if (!isTypedArrayType(static_cast<JSC::JSType>(c2Type)) || c1Type != c2Type) { return false; } @@ -627,6 +667,7 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, case JSDOMWrapperType: { if (c2Type == JSDOMWrapperType) { // https://github.com/oven-sh/bun/issues/4089 + // https://github.com/oven-sh/bun/issues/6492 auto* url2 = jsDynamicCast<JSDOMURL*>(v2); auto* url1 = jsDynamicCast<JSDOMURL*>(v1); @@ -635,19 +676,15 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, if ((url2 == nullptr) != (url1 == nullptr)) { return false; } - - if (url2 && url1) { - return url1->wrapped().href() != url2->wrapped().href(); - } - } else { - if (url2 && url1) { - // toEqual should return false when the URLs' href is not equal - // But you could have added additional properties onto the - // url object itself, so we must check those as well - // But it's definitely not equal if the href() is not the same - if (url1->wrapped().href() != url2->wrapped().href()) { - 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 + // url object itself, so we must check those as well + // But it's definitely not equal if the href() is not the same + if (url1->wrapped().href() != url2->wrapped().href()) { + return false; } } } @@ -1045,7 +1082,9 @@ void WebCore__FetchHeaders__toUWSResponse(WebCore__FetchHeaders* arg0, bool is_s WebCore__FetchHeaders* WebCore__FetchHeaders__createEmpty() { - return new WebCore::FetchHeaders({ WebCore::FetchHeaders::Guard::None, {} }); + auto* headers = new WebCore::FetchHeaders({ WebCore::FetchHeaders::Guard::None, {} }); + headers->relaxAdoptionRequirement(); + return headers; } void WebCore__FetchHeaders__append(WebCore__FetchHeaders* headers, const ZigString* arg1, const ZigString* arg2, JSC__JSGlobalObject* lexicalGlobalObject) @@ -1074,6 +1113,7 @@ WebCore__FetchHeaders* WebCore__FetchHeaders__createFromJS(JSC__JSGlobalObject* RETURN_IF_EXCEPTION(throwScope, nullptr); auto* headers = new WebCore::FetchHeaders({ WebCore::FetchHeaders::Guard::None, {} }); + headers->relaxAdoptionRequirement(); if (init) { // `fill` doesn't set an exception on the VM if it fails, it returns an // ExceptionOr<void>. So we need to check for the exception and, if set, @@ -1112,6 +1152,7 @@ WebCore__FetchHeaders* WebCore__FetchHeaders__cloneThis(WebCore__FetchHeaders* h { auto throwScope = DECLARE_THROW_SCOPE(lexicalGlobalObject->vm()); auto* clone = new WebCore::FetchHeaders({ WebCore::FetchHeaders::Guard::None, {} }); + clone->relaxAdoptionRequirement(); WebCore::propagateException(*lexicalGlobalObject, throwScope, clone->fill(*headers)); return clone; @@ -1181,6 +1222,7 @@ WebCore::FetchHeaders* WebCore__FetchHeaders__createFromPicoHeaders_(const void* { PicoHTTPHeaders pico_headers = *reinterpret_cast<const PicoHTTPHeaders*>(arg1); auto* headers = new WebCore::FetchHeaders({ WebCore::FetchHeaders::Guard::None, {} }); + headers->relaxAdoptionRequirement(); // This prevents an assertion later, but may not be the proper approach. if (pico_headers.len > 0) { HTTPHeaderMap map = HTTPHeaderMap(); @@ -1223,6 +1265,8 @@ WebCore::FetchHeaders* WebCore__FetchHeaders__createFromUWS(JSC__JSGlobalObject* size_t i = 0; auto* headers = new WebCore::FetchHeaders({ WebCore::FetchHeaders::Guard::None, {} }); + headers->relaxAdoptionRequirement(); // This prevents an assertion later, but may not be the proper approach. + HTTPHeaderMap map = HTTPHeaderMap(); for (const auto& header : req) { @@ -1246,7 +1290,6 @@ WebCore::FetchHeaders* WebCore__FetchHeaders__createFromUWS(JSC__JSGlobalObject* if (i > 56) __builtin_unreachable(); } - headers->setInternalHeaders(WTFMove(map)); return headers; } @@ -1354,15 +1397,22 @@ BunString WebCore__DOMURL__fileSystemPath(WebCore__DOMURL* arg0) extern "C" JSC__JSValue ZigString__toJSONObject(const ZigString* strPtr, JSC::JSGlobalObject* globalObject) { auto str = Zig::toString(*strPtr); - auto throwScope = DECLARE_THROW_SCOPE(globalObject->vm()); - auto scope = DECLARE_CATCH_SCOPE(globalObject->vm()); - JSValue result = JSONParseWithException(globalObject, str); - if (auto* exception = scope.exception()) { + auto scope = DECLARE_THROW_SCOPE(globalObject->vm()); + + // JSONParseWithException does not propagate exceptions as expected. See #5859 + JSValue result = JSONParse(globalObject, str); + + if (!result && !scope.exception()) { + scope.throwException(globalObject, createSyntaxError(globalObject, "Failed to parse JSON"_s)); + } + + if (scope.exception()) { + auto* exception = scope.exception(); scope.clearException(); - RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(exception->value())); + return JSC::JSValue::encode(exception); } - RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); + return JSValue::encode(result); } JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0, @@ -2063,7 +2113,7 @@ JSC__JSValue JSC__JSModuleLoader__evaluate(JSC__JSGlobalObject* globalObject, co JSC::VM& vm = globalObject->vm(); JSC::SourceCode sourceCode = JSC::makeSource( - src, JSC::SourceOrigin { origin }, origin.fileSystemPath(), + src, JSC::SourceOrigin { origin }, JSC::SourceTaintedOrigin::Untainted, origin.fileSystemPath(), WTF::TextPosition(), JSC::SourceProviderSourceType::Module); globalObject->moduleLoader()->provideFetch(globalObject, jsString(vm, origin.fileSystemPath()), WTFMove(sourceCode)); auto* promise = JSC::importModule(globalObject, JSC::Identifier::fromString(vm, origin.fileSystemPath()), JSValue(jsString(vm, referrer.fileSystemPath())), JSValue(), JSValue()); @@ -2116,6 +2166,14 @@ JSC__JSValue ReadableStream__empty(Zig::GlobalObject* globalObject) return JSValue::encode(JSC::call(globalObject, function, JSC::ArgList(), "ReadableStream.create"_s)); } +JSC__JSValue ReadableStream__used(Zig::GlobalObject* globalObject) +{ + auto& vm = globalObject->vm(); + auto clientData = WebCore::clientData(vm); + auto* function = globalObject->getDirect(vm, clientData->builtinNames().createUsedReadableStreamPrivateName()).getObject(); + return JSValue::encode(JSC::call(globalObject, function, JSC::ArgList(), "ReadableStream.create"_s)); +} + JSC__JSValue JSC__JSValue__createRangeError(const ZigString* message, const ZigString* arg1, JSC__JSGlobalObject* globalObject) { @@ -2303,29 +2361,31 @@ JSC__JSValue JSC__JSValue__createStringArray(JSC__JSGlobalObject* globalObject, JSC::JSArray* array = nullptr; { + JSC::GCDeferralContext deferralContext(vm); JSC::ObjectInitializationScope initializationScope(vm); if ((array = JSC::JSArray::tryCreateUninitializedRestricted( - initializationScope, nullptr, + initializationScope, &deferralContext, globalObject->arrayStructureForIndexingTypeDuringAllocation(JSC::ArrayWithContiguous), arg2))) { if (!clone) { for (size_t i = 0; i < arg2; ++i) { - array->putDirectIndex(globalObject, i, JSC::jsString(vm, Zig::toString(arg1[i]))); + array->putDirectIndex(globalObject, i, JSC::jsString(vm, Zig::toString(arg1[i]), &deferralContext)); } } else { for (size_t i = 0; i < arg2; ++i) { - array->putDirectIndex(globalObject, i, JSC::jsString(vm, Zig::toStringCopy(arg1[i]))); + array->putDirectIndex(globalObject, i, JSC::jsString(vm, Zig::toStringCopy(arg1[i]), &deferralContext)); } } } - } - if (!array) { - JSC::throwOutOfMemoryError(globalObject, scope); - return JSC::JSValue::encode(JSC::JSValue()); - } - RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::JSValue(array))); + if (!array) { + JSC::throwOutOfMemoryError(globalObject, scope); + return JSC::JSValue::encode(JSC::JSValue()); + } + + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::JSValue(array))); + } } JSC__JSValue JSC__JSGlobalObject__createAggregateError(JSC__JSGlobalObject* globalObject, @@ -2803,7 +2863,7 @@ JSC__VM* JSC__JSGlobalObject__vm(JSC__JSGlobalObject* arg0) { return &arg0->vm() void JSC__JSGlobalObject__handleRejectedPromises(JSC__JSGlobalObject* arg0) { - return static_cast<Zig::GlobalObject*>(arg0)->handleRejectedPromises(); + return jsCast<Zig::GlobalObject*>(arg0)->handleRejectedPromises(); } #pragma mark - JSC::JSValue @@ -3012,20 +3072,16 @@ JSC__JSValue JSC__JSValue__jsNumberFromUint64(uint64_t arg0) int64_t JSC__JSValue__toInt64(JSC__JSValue val) { - JSC::JSValue _val = JSC::JSValue::decode(val); - - int64_t result = JSC::tryConvertToInt52(_val.asDouble()); - if (result != JSC::JSValue::notInt52) { - return result; - } - - if (_val.isHeapBigInt()) { - - if (auto* heapBigInt = _val.asHeapBigInt()) { + JSC::JSValue value = JSC::JSValue::decode(val); + ASSERT(value.isHeapBigInt() || value.isNumber()); + if (value.isHeapBigInt()) { + if (auto* heapBigInt = value.asHeapBigInt()) { return heapBigInt->toBigInt64(heapBigInt); } } - return _val.asAnyInt(); + if (value.isInt32()) + return value.asInt32(); + return static_cast<int64_t>(value.asDouble()); } uint8_t JSC__JSValue__asBigIntCompare(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, JSC__JSValue JSValue1) @@ -3086,28 +3142,28 @@ JSC__JSValue JSC__JSValue__fromUInt64NoTruncate(JSC__JSGlobalObject* globalObjec uint64_t JSC__JSValue__toUInt64NoTruncate(JSC__JSValue val) { - JSC::JSValue _val = JSC::JSValue::decode(val); - - int64_t result = JSC::tryConvertToInt52(_val.asDouble()); - if (result != JSC::JSValue::notInt52) { - if (result < 0) - return 0; + JSC::JSValue value = JSC::JSValue::decode(val); + ASSERT(value.isHeapBigInt() || value.isNumber()); - return static_cast<uint64_t>(result); - } - - if (_val.isHeapBigInt()) { - - if (auto* heapBigInt = _val.asHeapBigInt()) { + if (value.isHeapBigInt()) { + if (auto* heapBigInt = value.asHeapBigInt()) { return heapBigInt->toBigUInt64(heapBigInt); } } - if (!_val.isNumber()) { - return 0; + if (value.isInt32()) { + return static_cast<uint64_t>(value.asInt32()); } + ASSERT(value.isDouble()); - return static_cast<uint64_t>(_val.asAnyInt()); + int64_t result = JSC::tryConvertToInt52(value.asDouble()); + if (result != JSC::JSValue::notInt52) { + if (result < 0) + return 0; + + return static_cast<uint64_t>(result); + } + return 0; } JSC__JSValue JSC__JSValue__createObject2(JSC__JSGlobalObject* globalObject, const ZigString* arg1, @@ -4046,6 +4102,7 @@ enum class BuiltinNamesMap : uint8_t { method, headers, status, + statusText, url, body, data, @@ -4065,6 +4122,9 @@ static JSC::Identifier builtinNameMap(JSC::JSGlobalObject* globalObject, unsigne case BuiltinNamesMap::headers: { return clientData->builtinNames().headersPublicName(); } + case BuiltinNamesMap::statusText: { + return clientData->builtinNames().statusTextPublicName(); + } case BuiltinNamesMap::status: { return clientData->builtinNames().statusPublicName(); } @@ -4485,6 +4545,14 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskJob(JSC__JSGlobalObject* arg0 JSC::JSValue::decode(JSValue4)); } +extern "C" WebCore::AbortSignal* WebCore__AbortSignal__new(JSC__JSGlobalObject* globalObject) +{ + Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(globalObject); + auto* context = thisObject->scriptExecutionContext(); + RefPtr<WebCore::AbortSignal> abortSignal = WebCore::AbortSignal::create(context); + return abortSignal.leakRef(); +} + extern "C" JSC__JSValue WebCore__AbortSignal__create(JSC__JSGlobalObject* globalObject) { Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(globalObject); @@ -4701,4 +4769,4 @@ CPP_DECL void JSC__VM__setControlFlowProfiler(JSC__VM* vm, bool isEnabled) } else { vm->disableControlFlowProfiler(); } -}
\ No newline at end of file +} diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 1a82fc5e6..98e91c1ca 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -1969,6 +1969,12 @@ pub const AbortSignal = extern opaque { return cppFn("create", .{global}); } + extern fn WebCore__AbortSignal__new(*JSGlobalObject) *AbortSignal; + pub fn new(global: *JSGlobalObject) *AbortSignal { + JSC.markBinding(@src()); + return WebCore__AbortSignal__new(global); + } + pub fn createAbortError(message: *const ZigString, code: *const ZigString, global: *JSGlobalObject) JSValue { return cppFn("createAbortError", .{ message, code, global }); } @@ -3034,7 +3040,7 @@ pub const JSValue = enum(JSValueReprInt) { zero = 0, undefined = @as(JSValueReprInt, @bitCast(@as(i64, 0xa))), null = @as(JSValueReprInt, @bitCast(@as(i64, 0x2))), - true = @as(JSValueReprInt, @bitCast(@as(i64, 0x4))), + true = FFI.TrueI64, false = @as(JSValueReprInt, @bitCast(@as(i64, 0x6))), _, @@ -3224,7 +3230,7 @@ pub const JSValue = enum(JSValueReprInt) { }; } - pub fn isObject(this: JSType) bool { + pub inline fn isObject(this: JSType) bool { // inline constexpr bool isObjectType(JSType type) { return type >= ObjectType; } return @intFromEnum(this) >= @intFromEnum(JSType.Object); } @@ -3527,7 +3533,7 @@ pub const JSValue = enum(JSValueReprInt) { } pub fn createEmptyObject(global: *JSGlobalObject, len: usize) JSValue { - std.debug.assert(len <= 64); // max inline capacity JSC allows is 64. If you run into this, just set it to 0. + std.debug.assert(len <= 63); // max inline capacity JSC allows is 63. If you run into this, just set it to 0. return cppFn("createEmptyObject", .{ global, len }); } @@ -3903,6 +3909,10 @@ pub const JSValue = enum(JSValueReprInt) { return jsNumberFromInt32(@as(i32, @intCast(i))); } + return jsNumberFromPtrSize(i); + } + + pub fn jsNumberFromPtrSize(i: usize) JSValue { return jsNumberFromDouble(@as(f64, @floatFromInt(@as(i52, @intCast(@as(u51, @truncate(i))))))); } @@ -4255,6 +4265,7 @@ pub const JSValue = enum(JSValueReprInt) { method, headers, status, + statusText, url, body, data, @@ -4924,6 +4935,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; @@ -5492,6 +5531,7 @@ pub const URL = opaque { extern fn URL__getHref(*String) String; extern fn URL__getFileURLString(*String) String; extern fn URL__getHrefJoin(*String, *String) String; + extern fn URL__pathFromFileURL(*String) String; pub fn hrefFromString(str: bun.String) String { JSC.markBinding(@src()); @@ -5512,6 +5552,12 @@ pub const URL = opaque { return URL__getFileURLString(&input); } + pub fn pathFromFileURL(str: bun.String) String { + JSC.markBinding(@src()); + var input = str; + return URL__pathFromFileURL(&input); + } + /// This percent-encodes the URL, punycode-encodes the hostname, and returns the result /// If it fails, the tag is marked Dead pub fn hrefFromJS(value: JSValue, globalObject: *JSC.JSGlobalObject) String { @@ -5816,7 +5862,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. , diff --git a/src/bun.js/bindings/c-bindings.cpp b/src/bun.js/bindings/c-bindings.cpp index ff4c8c4e7..f53ff52cc 100644 --- a/src/bun.js/bindings/c-bindings.cpp +++ b/src/bun.js/bindings/c-bindings.cpp @@ -1,4 +1,5 @@ // when we don't want to use @cInclude, we can just stick wrapper functions here +#include "root.h" #include <sys/resource.h> #include <cstdint> #include <unistd.h> @@ -6,6 +7,32 @@ #include <sys/stat.h> #include <sys/signal.h> +#if CPU(X86_64) +#include <cstring> +#include <cpuid.h> + +extern "C" void bun_warn_avx_missing(const char* url) +{ + __builtin_cpu_init(); + if (__builtin_cpu_supports("avx")) { + return; + } + + static constexpr const char* str = "warn: CPU lacks AVX support, strange crashes may occur. Reinstall Bun or use *-baseline build:\n "; + const size_t len = strlen(str); + + char buf[512]; + strcpy(buf, str); + strcpy(buf + len, url); + strcpy(buf + len + strlen(url), "\n\0"); + write(STDERR_FILENO, buf, strlen(buf)); +} +#else +extern "C" void bun_warn_avx_missing(char* url) +{ +} +#endif + extern "C" int32_t get_process_priority(uint32_t pid) { return getpriority(PRIO_PROCESS, pid); @@ -48,4 +75,4 @@ extern "C" ssize_t bun_sysconf__SC_CLK_TCK() #else return 0; #endif -}
\ No newline at end of file +} diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index 18b7c8bce..617530ec6 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -969,7 +969,7 @@ pub const ZigConsoleClient = struct { Output.prettyFmt("<r><red>Assertion failed<r>\n", true) else "Assertion failed\n"; - console.error_writer.unbuffered_writer.writeAll(text) catch unreachable; + console.error_writer.unbuffered_writer.writeAll(text) catch {}; return; } @@ -983,28 +983,48 @@ pub const ZigConsoleClient = struct { else console.writer; var writer = buffered_writer.writer(); - const Writer = @TypeOf(writer); - if (len > 0) + + var print_length = len; + var print_options: FormatOptions = .{ + .enable_colors = enable_colors, + .add_newline = true, + .flush = true, + }; + + if (message_type == .Dir and len >= 2) { + print_length = 1; + var opts = vals[1]; + if (opts.isObject()) { + if (opts.get(global, "depth")) |depth_prop| { + if (depth_prop.isNumber()) + print_options.max_depth = depth_prop.toU16(); + if (depth_prop.isNull() or depth_prop.toInt64() == std.math.maxInt(i64)) + print_options.max_depth = std.math.maxInt(u16); + } + if (opts.get(global, "colors")) |colors_prop| { + if (colors_prop.isBoolean()) + print_options.enable_colors = colors_prop.toBoolean(); + } + } + } + + if (print_length > 0) format( level, global, vals, - len, + print_length, @TypeOf(buffered_writer.unbuffered_writer.context), Writer, writer, - .{ - .enable_colors = enable_colors, - .add_newline = true, - .flush = true, - }, + print_options, ) else if (message_type == .Log) { _ = console.writer.write("\n") catch 0; console.writer.flush() catch {}; } else if (message_type != .Trace) - writer.writeAll("undefined\n") catch unreachable; + writer.writeAll("undefined\n") catch {}; if (message_type == .Trace) { writeTrace(Writer, writer, global); @@ -1026,14 +1046,14 @@ pub const ZigConsoleClient = struct { writer, exception.stack, true, - ) catch unreachable + ) catch {} else JS.VirtualMachine.printStackTrace( Writer, writer, exception.stack, false, - ) catch unreachable; + ) catch {}; } pub const FormatOptions = struct { @@ -1042,7 +1062,7 @@ pub const ZigConsoleClient = struct { flush: bool, ordered_properties: bool = false, quote_strings: bool = false, - max_depth: u16 = 8, + max_depth: u16 = 2, }; pub fn format( @@ -1082,7 +1102,7 @@ pub const ZigConsoleClient = struct { if (tag.tag == .String) { if (options.enable_colors) { if (level == .Error) { - unbuffered_writer.writeAll(comptime Output.prettyFmt("<r><red>", true)) catch unreachable; + unbuffered_writer.writeAll(comptime Output.prettyFmt("<r><red>", true)) catch {}; } fmt.format( tag, @@ -1093,7 +1113,7 @@ pub const ZigConsoleClient = struct { true, ); if (level == .Error) { - unbuffered_writer.writeAll(comptime Output.prettyFmt("<r>", true)) catch unreachable; + unbuffered_writer.writeAll(comptime Output.prettyFmt("<r>", true)) catch {}; } } else { fmt.format( @@ -1155,7 +1175,7 @@ pub const ZigConsoleClient = struct { var any = false; if (options.enable_colors) { if (level == .Error) { - writer.writeAll(comptime Output.prettyFmt("<r><red>", true)) catch unreachable; + writer.writeAll(comptime Output.prettyFmt("<r><red>", true)) catch {}; } while (true) { if (any) { @@ -1177,7 +1197,7 @@ pub const ZigConsoleClient = struct { fmt.remaining_values = fmt.remaining_values[1..]; } if (level == .Error) { - writer.writeAll(comptime Output.prettyFmt("<r>", true)) catch unreachable; + writer.writeAll(comptime Output.prettyFmt("<r>", true)) catch {}; } } else { while (true) { @@ -2119,7 +2139,7 @@ pub const ZigConsoleClient = struct { this.globalThis, this.custom_formatted_object.function, this.custom_formatted_object.this, - this.max_depth - this.depth, + this.max_depth -| this.depth, this.max_depth, enable_ansi_colors, ); @@ -2158,7 +2178,7 @@ pub const ZigConsoleClient = struct { this.addForNewLine(printable.len); if (printable.len == 0) { - writer.print(comptime Output.prettyFmt("<cyan>[class]<r>", enable_ansi_colors), .{}); + writer.print(comptime Output.prettyFmt("<cyan>[class (anonymous)]<r>", enable_ansi_colors), .{}); } else { writer.print(comptime Output.prettyFmt("<cyan>[class {}]<r>", enable_ansi_colors), .{printable}); } diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index 329506718..c4f63084b 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -1220,6 +1220,28 @@ pub const JSDebugHTTPSServer = struct { return DebugHTTPSServer__fromJS(value); } + extern fn DebugHTTPSServerPrototype__addressSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn DebugHTTPSServerPrototype__addressGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `DebugHTTPSServer.address` setter + /// This value will be visited by the garbage collector. + pub fn addressSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + DebugHTTPSServerPrototype__addressSetCachedValue(thisValue, globalObject, value); + } + + /// `DebugHTTPSServer.address` getter + /// This value will be visited by the garbage collector. + pub fn addressGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = DebugHTTPSServerPrototype__addressGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + extern fn DebugHTTPSServerPrototype__hostnameSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; extern fn DebugHTTPSServerPrototype__hostnameGetCachedValue(JSC.JSValue) JSC.JSValue; @@ -1300,6 +1322,9 @@ pub const JSDebugHTTPSServer = struct { @compileLog("DebugHTTPSServer.finalize is not a finalizer"); } + if (@TypeOf(DebugHTTPSServer.getAddress) != GetterType) + @compileLog("Expected DebugHTTPSServer.getAddress to be a getter"); + if (@TypeOf(DebugHTTPSServer.getDevelopment) != GetterType) @compileLog("Expected DebugHTTPSServer.getDevelopment to be a getter"); @@ -1327,6 +1352,8 @@ pub const JSDebugHTTPSServer = struct { @compileLog("Expected DebugHTTPSServer.doPublish to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doPublish))); if (@TypeOf(DebugHTTPSServer.doReload) != CallbackType) @compileLog("Expected DebugHTTPSServer.doReload to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doReload))); + if (@TypeOf(DebugHTTPSServer.doRequestIP) != CallbackType) + @compileLog("Expected DebugHTTPSServer.doRequestIP to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doRequestIP))); if (@TypeOf(DebugHTTPSServer.doStop) != CallbackType) @compileLog("Expected DebugHTTPSServer.doStop to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPSServer.doStop))); if (@TypeOf(DebugHTTPSServer.doUpgrade) != CallbackType) @@ -1335,9 +1362,11 @@ pub const JSDebugHTTPSServer = struct { @export(DebugHTTPSServer.doFetch, .{ .name = "DebugHTTPSServerPrototype__doFetch" }); @export(DebugHTTPSServer.doPublish, .{ .name = "DebugHTTPSServerPrototype__doPublish" }); @export(DebugHTTPSServer.doReload, .{ .name = "DebugHTTPSServerPrototype__doReload" }); + @export(DebugHTTPSServer.doRequestIP, .{ .name = "DebugHTTPSServerPrototype__doRequestIP" }); @export(DebugHTTPSServer.doStop, .{ .name = "DebugHTTPSServerPrototype__doStop" }); @export(DebugHTTPSServer.doUpgrade, .{ .name = "DebugHTTPSServerPrototype__doUpgrade" }); @export(DebugHTTPSServer.finalize, .{ .name = "DebugHTTPSServerClass__finalize" }); + @export(DebugHTTPSServer.getAddress, .{ .name = "DebugHTTPSServerPrototype__getAddress" }); @export(DebugHTTPSServer.getDevelopment, .{ .name = "DebugHTTPSServerPrototype__getDevelopment" }); @export(DebugHTTPSServer.getHostname, .{ .name = "DebugHTTPSServerPrototype__getHostname" }); @export(DebugHTTPSServer.getId, .{ .name = "DebugHTTPSServerPrototype__getId" }); @@ -1363,6 +1392,28 @@ pub const JSDebugHTTPServer = struct { return DebugHTTPServer__fromJS(value); } + extern fn DebugHTTPServerPrototype__addressSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn DebugHTTPServerPrototype__addressGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `DebugHTTPServer.address` setter + /// This value will be visited by the garbage collector. + pub fn addressSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + DebugHTTPServerPrototype__addressSetCachedValue(thisValue, globalObject, value); + } + + /// `DebugHTTPServer.address` getter + /// This value will be visited by the garbage collector. + pub fn addressGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = DebugHTTPServerPrototype__addressGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + extern fn DebugHTTPServerPrototype__hostnameSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; extern fn DebugHTTPServerPrototype__hostnameGetCachedValue(JSC.JSValue) JSC.JSValue; @@ -1443,6 +1494,9 @@ pub const JSDebugHTTPServer = struct { @compileLog("DebugHTTPServer.finalize is not a finalizer"); } + if (@TypeOf(DebugHTTPServer.getAddress) != GetterType) + @compileLog("Expected DebugHTTPServer.getAddress to be a getter"); + if (@TypeOf(DebugHTTPServer.getDevelopment) != GetterType) @compileLog("Expected DebugHTTPServer.getDevelopment to be a getter"); @@ -1470,6 +1524,8 @@ pub const JSDebugHTTPServer = struct { @compileLog("Expected DebugHTTPServer.doPublish to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doPublish))); if (@TypeOf(DebugHTTPServer.doReload) != CallbackType) @compileLog("Expected DebugHTTPServer.doReload to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doReload))); + if (@TypeOf(DebugHTTPServer.doRequestIP) != CallbackType) + @compileLog("Expected DebugHTTPServer.doRequestIP to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doRequestIP))); if (@TypeOf(DebugHTTPServer.doStop) != CallbackType) @compileLog("Expected DebugHTTPServer.doStop to be a callback but received " ++ @typeName(@TypeOf(DebugHTTPServer.doStop))); if (@TypeOf(DebugHTTPServer.doUpgrade) != CallbackType) @@ -1478,9 +1534,11 @@ pub const JSDebugHTTPServer = struct { @export(DebugHTTPServer.doFetch, .{ .name = "DebugHTTPServerPrototype__doFetch" }); @export(DebugHTTPServer.doPublish, .{ .name = "DebugHTTPServerPrototype__doPublish" }); @export(DebugHTTPServer.doReload, .{ .name = "DebugHTTPServerPrototype__doReload" }); + @export(DebugHTTPServer.doRequestIP, .{ .name = "DebugHTTPServerPrototype__doRequestIP" }); @export(DebugHTTPServer.doStop, .{ .name = "DebugHTTPServerPrototype__doStop" }); @export(DebugHTTPServer.doUpgrade, .{ .name = "DebugHTTPServerPrototype__doUpgrade" }); @export(DebugHTTPServer.finalize, .{ .name = "DebugHTTPServerClass__finalize" }); + @export(DebugHTTPServer.getAddress, .{ .name = "DebugHTTPServerPrototype__getAddress" }); @export(DebugHTTPServer.getDevelopment, .{ .name = "DebugHTTPServerPrototype__getDevelopment" }); @export(DebugHTTPServer.getHostname, .{ .name = "DebugHTTPServerPrototype__getHostname" }); @export(DebugHTTPServer.getId, .{ .name = "DebugHTTPServerPrototype__getId" }); @@ -2205,6 +2263,8 @@ pub const JSExpect = struct { @compileLog("Expected Expect.toEndWith to be a callback but received " ++ @typeName(@TypeOf(Expect.toEndWith))); if (@TypeOf(Expect.toEqual) != CallbackType) @compileLog("Expected Expect.toEqual to be a callback but received " ++ @typeName(@TypeOf(Expect.toEqual))); + if (@TypeOf(Expect.toEqualIgnoringWhitespace) != CallbackType) + @compileLog("Expected Expect.toEqualIgnoringWhitespace to be a callback but received " ++ @typeName(@TypeOf(Expect.toEqualIgnoringWhitespace))); if (@TypeOf(Expect.toHaveBeenCalled) != CallbackType) @compileLog("Expected Expect.toHaveBeenCalled to be a callback but received " ++ @typeName(@TypeOf(Expect.toHaveBeenCalled))); if (@TypeOf(Expect.toHaveBeenCalledTimes) != CallbackType) @@ -2341,6 +2401,7 @@ pub const JSExpect = struct { @export(Expect.toContainEqual, .{ .name = "ExpectPrototype__toContainEqual" }); @export(Expect.toEndWith, .{ .name = "ExpectPrototype__toEndWith" }); @export(Expect.toEqual, .{ .name = "ExpectPrototype__toEqual" }); + @export(Expect.toEqualIgnoringWhitespace, .{ .name = "ExpectPrototype__toEqualIgnoringWhitespace" }); @export(Expect.toHaveBeenCalled, .{ .name = "ExpectPrototype__toHaveBeenCalled" }); @export(Expect.toHaveBeenCalledTimes, .{ .name = "ExpectPrototype__toHaveBeenCalledTimes" }); @export(Expect.toHaveBeenCalledWith, .{ .name = "ExpectPrototype__toHaveBeenCalledWith" }); @@ -2507,6 +2568,87 @@ pub const JSExpectAnything = struct { } } }; +pub const JSExpectArrayContaining = struct { + const ExpectArrayContaining = Classes.ExpectArrayContaining; + const GetterType = fn (*ExpectArrayContaining, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const GetterTypeWithThisValue = fn (*ExpectArrayContaining, JSC.JSValue, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; + const SetterType = fn (*ExpectArrayContaining, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; + const SetterTypeWithThisValue = fn (*ExpectArrayContaining, JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; + const CallbackType = fn (*ExpectArrayContaining, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue; + + /// Return the pointer to the wrapped object. + /// If the object does not match the type, return null. + pub fn fromJS(value: JSC.JSValue) ?*ExpectArrayContaining { + JSC.markBinding(@src()); + return ExpectArrayContaining__fromJS(value); + } + + extern fn ExpectArrayContainingPrototype__arrayValueSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn ExpectArrayContainingPrototype__arrayValueGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `ExpectArrayContaining.arrayValue` setter + /// This value will be visited by the garbage collector. + pub fn arrayValueSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + ExpectArrayContainingPrototype__arrayValueSetCachedValue(thisValue, globalObject, value); + } + + /// `ExpectArrayContaining.arrayValue` getter + /// This value will be visited by the garbage collector. + pub fn arrayValueGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = ExpectArrayContainingPrototype__arrayValueGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + + /// Create a new instance of ExpectArrayContaining + pub fn toJS(this: *ExpectArrayContaining, globalObject: *JSC.JSGlobalObject) JSC.JSValue { + JSC.markBinding(@src()); + if (comptime Environment.allow_assert) { + const value__ = ExpectArrayContaining__create(globalObject, this); + std.debug.assert(value__.as(ExpectArrayContaining).? == this); // If this fails, likely a C ABI issue. + return value__; + } else { + return ExpectArrayContaining__create(globalObject, this); + } + } + + /// Modify the internal ptr to point to a new instance of ExpectArrayContaining. + pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*ExpectArrayContaining) bool { + JSC.markBinding(@src()); + return ExpectArrayContaining__dangerouslySetPtr(value, ptr); + } + + /// Detach the ptr from the thisValue + pub fn detachPtr(_: *ExpectArrayContaining, value: JSC.JSValue) void { + JSC.markBinding(@src()); + std.debug.assert(ExpectArrayContaining__dangerouslySetPtr(value, null)); + } + + extern fn ExpectArrayContaining__fromJS(JSC.JSValue) ?*ExpectArrayContaining; + extern fn ExpectArrayContaining__getConstructor(*JSC.JSGlobalObject) JSC.JSValue; + + extern fn ExpectArrayContaining__create(globalObject: *JSC.JSGlobalObject, ptr: ?*ExpectArrayContaining) JSC.JSValue; + + extern fn ExpectArrayContaining__dangerouslySetPtr(JSC.JSValue, ?*ExpectArrayContaining) bool; + + comptime { + if (@TypeOf(ExpectArrayContaining.finalize) != (fn (*ExpectArrayContaining) callconv(.C) void)) { + @compileLog("ExpectArrayContaining.finalize is not a finalizer"); + } + + if (@TypeOf(ExpectArrayContaining.call) != StaticCallbackType) + @compileLog("Expected ExpectArrayContaining.call to be a static callback"); + if (!JSC.is_bindgen) { + @export(ExpectArrayContaining.call, .{ .name = "ExpectArrayContainingClass__call" }); + @export(ExpectArrayContaining.finalize, .{ .name = "ExpectArrayContainingClass__finalize" }); + } + } +}; pub const JSExpectStringContaining = struct { const ExpectStringContaining = Classes.ExpectStringContaining; const GetterType = fn (*ExpectStringContaining, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; @@ -3089,6 +3231,28 @@ pub const JSHTTPSServer = struct { return HTTPSServer__fromJS(value); } + extern fn HTTPSServerPrototype__addressSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn HTTPSServerPrototype__addressGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `HTTPSServer.address` setter + /// This value will be visited by the garbage collector. + pub fn addressSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + HTTPSServerPrototype__addressSetCachedValue(thisValue, globalObject, value); + } + + /// `HTTPSServer.address` getter + /// This value will be visited by the garbage collector. + pub fn addressGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = HTTPSServerPrototype__addressGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + extern fn HTTPSServerPrototype__hostnameSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; extern fn HTTPSServerPrototype__hostnameGetCachedValue(JSC.JSValue) JSC.JSValue; @@ -3169,6 +3333,9 @@ pub const JSHTTPSServer = struct { @compileLog("HTTPSServer.finalize is not a finalizer"); } + if (@TypeOf(HTTPSServer.getAddress) != GetterType) + @compileLog("Expected HTTPSServer.getAddress to be a getter"); + if (@TypeOf(HTTPSServer.getDevelopment) != GetterType) @compileLog("Expected HTTPSServer.getDevelopment to be a getter"); @@ -3196,6 +3363,8 @@ pub const JSHTTPSServer = struct { @compileLog("Expected HTTPSServer.doPublish to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doPublish))); if (@TypeOf(HTTPSServer.doReload) != CallbackType) @compileLog("Expected HTTPSServer.doReload to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doReload))); + if (@TypeOf(HTTPSServer.doRequestIP) != CallbackType) + @compileLog("Expected HTTPSServer.doRequestIP to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doRequestIP))); if (@TypeOf(HTTPSServer.doStop) != CallbackType) @compileLog("Expected HTTPSServer.doStop to be a callback but received " ++ @typeName(@TypeOf(HTTPSServer.doStop))); if (@TypeOf(HTTPSServer.doUpgrade) != CallbackType) @@ -3204,9 +3373,11 @@ pub const JSHTTPSServer = struct { @export(HTTPSServer.doFetch, .{ .name = "HTTPSServerPrototype__doFetch" }); @export(HTTPSServer.doPublish, .{ .name = "HTTPSServerPrototype__doPublish" }); @export(HTTPSServer.doReload, .{ .name = "HTTPSServerPrototype__doReload" }); + @export(HTTPSServer.doRequestIP, .{ .name = "HTTPSServerPrototype__doRequestIP" }); @export(HTTPSServer.doStop, .{ .name = "HTTPSServerPrototype__doStop" }); @export(HTTPSServer.doUpgrade, .{ .name = "HTTPSServerPrototype__doUpgrade" }); @export(HTTPSServer.finalize, .{ .name = "HTTPSServerClass__finalize" }); + @export(HTTPSServer.getAddress, .{ .name = "HTTPSServerPrototype__getAddress" }); @export(HTTPSServer.getDevelopment, .{ .name = "HTTPSServerPrototype__getDevelopment" }); @export(HTTPSServer.getHostname, .{ .name = "HTTPSServerPrototype__getHostname" }); @export(HTTPSServer.getId, .{ .name = "HTTPSServerPrototype__getId" }); @@ -3232,6 +3403,28 @@ pub const JSHTTPServer = struct { return HTTPServer__fromJS(value); } + extern fn HTTPServerPrototype__addressSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; + + extern fn HTTPServerPrototype__addressGetCachedValue(JSC.JSValue) JSC.JSValue; + + /// `HTTPServer.address` setter + /// This value will be visited by the garbage collector. + pub fn addressSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { + JSC.markBinding(@src()); + HTTPServerPrototype__addressSetCachedValue(thisValue, globalObject, value); + } + + /// `HTTPServer.address` getter + /// This value will be visited by the garbage collector. + pub fn addressGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { + JSC.markBinding(@src()); + const result = HTTPServerPrototype__addressGetCachedValue(thisValue); + if (result == .zero) + return null; + + return result; + } + extern fn HTTPServerPrototype__hostnameSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void; extern fn HTTPServerPrototype__hostnameGetCachedValue(JSC.JSValue) JSC.JSValue; @@ -3312,6 +3505,9 @@ pub const JSHTTPServer = struct { @compileLog("HTTPServer.finalize is not a finalizer"); } + if (@TypeOf(HTTPServer.getAddress) != GetterType) + @compileLog("Expected HTTPServer.getAddress to be a getter"); + if (@TypeOf(HTTPServer.getDevelopment) != GetterType) @compileLog("Expected HTTPServer.getDevelopment to be a getter"); @@ -3339,6 +3535,8 @@ pub const JSHTTPServer = struct { @compileLog("Expected HTTPServer.doPublish to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doPublish))); if (@TypeOf(HTTPServer.doReload) != CallbackType) @compileLog("Expected HTTPServer.doReload to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doReload))); + if (@TypeOf(HTTPServer.doRequestIP) != CallbackType) + @compileLog("Expected HTTPServer.doRequestIP to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doRequestIP))); if (@TypeOf(HTTPServer.doStop) != CallbackType) @compileLog("Expected HTTPServer.doStop to be a callback but received " ++ @typeName(@TypeOf(HTTPServer.doStop))); if (@TypeOf(HTTPServer.doUpgrade) != CallbackType) @@ -3347,9 +3545,11 @@ pub const JSHTTPServer = struct { @export(HTTPServer.doFetch, .{ .name = "HTTPServerPrototype__doFetch" }); @export(HTTPServer.doPublish, .{ .name = "HTTPServerPrototype__doPublish" }); @export(HTTPServer.doReload, .{ .name = "HTTPServerPrototype__doReload" }); + @export(HTTPServer.doRequestIP, .{ .name = "HTTPServerPrototype__doRequestIP" }); @export(HTTPServer.doStop, .{ .name = "HTTPServerPrototype__doStop" }); @export(HTTPServer.doUpgrade, .{ .name = "HTTPServerPrototype__doUpgrade" }); @export(HTTPServer.finalize, .{ .name = "HTTPServerClass__finalize" }); + @export(HTTPServer.getAddress, .{ .name = "HTTPServerPrototype__getAddress" }); @export(HTTPServer.getDevelopment, .{ .name = "HTTPServerPrototype__getDevelopment" }); @export(HTTPServer.getHostname, .{ .name = "HTTPServerPrototype__getHostname" }); @export(HTTPServer.getId, .{ .name = "HTTPServerPrototype__getId" }); @@ -6781,6 +6981,9 @@ pub const JSTextDecoder = struct { if (@TypeOf(TextDecoder.getFatal) != GetterType) @compileLog("Expected TextDecoder.getFatal to be a getter"); + if (@TypeOf(TextDecoder.getIgnoreBOM) != GetterType) + @compileLog("Expected TextDecoder.getIgnoreBOM to be a getter"); + if (!JSC.is_bindgen) { @export(TextDecoder.constructor, .{ .name = "TextDecoderClass__construct" }); @export(TextDecoder.decode, .{ .name = "TextDecoderPrototype__decode" }); @@ -6788,6 +6991,7 @@ pub const JSTextDecoder = struct { @export(TextDecoder.finalize, .{ .name = "TextDecoderClass__finalize" }); @export(TextDecoder.getEncoding, .{ .name = "TextDecoderPrototype__getEncoding" }); @export(TextDecoder.getFatal, .{ .name = "TextDecoderPrototype__getFatal" }); + @export(TextDecoder.getIgnoreBOM, .{ .name = "TextDecoderPrototype__getIgnoreBOM" }); } } }; @@ -7006,6 +7210,7 @@ comptime { _ = JSExpect; _ = JSExpectAny; _ = JSExpectAnything; + _ = JSExpectArrayContaining; _ = JSExpectStringContaining; _ = JSExpectStringMatching; _ = JSFFI; diff --git a/src/bun.js/bindings/generated_classes_list.zig b/src/bun.js/bindings/generated_classes_list.zig index a86f74dd3..3b45f33b8 100644 --- a/src/bun.js/bindings/generated_classes_list.zig +++ b/src/bun.js/bindings/generated_classes_list.zig @@ -17,6 +17,7 @@ pub const Classes = struct { pub const ExpectAnything = JSC.Expect.ExpectAnything; pub const ExpectStringContaining = JSC.Expect.ExpectStringContaining; pub const ExpectStringMatching = JSC.Expect.ExpectStringMatching; + pub const ExpectArrayContaining = JSC.Expect.ExpectArrayContaining; pub const FileSystemRouter = JSC.API.FileSystemRouter; pub const Bundler = JSC.API.JSBundler; pub const JSBundler = Bundler; diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index e19be7abe..d8cfa58ef 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -17,10 +17,6 @@ typedef union BunStringImpl { void* wtf; } BunStringImpl; -typedef struct BunString { - BunStringTag tag; - BunStringImpl impl; -} BunString; #else typedef union BunStringImpl { ZigString zig; @@ -34,13 +30,15 @@ enum class BunStringTag : uint8_t { StaticZigString = 3, Empty = 4, }; +#endif typedef struct BunString { BunStringTag tag; BunStringImpl impl; -} BunString; -#endif + inline void ref(); + inline void deref(); +} BunString; typedef struct ZigErrorType { ZigErrorCode code; @@ -241,6 +239,7 @@ extern "C" void BunString__toWTFString(BunString*); namespace Bun { JSC::JSValue toJS(JSC::JSGlobalObject*, BunString); BunString toString(JSC::JSGlobalObject* globalObject, JSC::JSValue value); +BunString toString(const char* bytes, size_t length); WTF::String toWTFString(const BunString& bunString); BunString toString(WTF::String& wtfString); BunString toString(const WTF::String& wtfString); @@ -348,3 +347,16 @@ class ScriptArguments; using ScriptArguments = Inspector::ScriptArguments; #endif + +ALWAYS_INLINE void BunString::ref() +{ + if (this->tag == BunStringTag::WTFStringImpl) { + this->impl.wtf->ref(); + } +} +ALWAYS_INLINE void BunString::deref() +{ + if (this->tag == BunStringTag::WTFStringImpl) { + this->impl.wtf->deref(); + } +}
\ No newline at end of file diff --git a/src/bun.js/bindings/isBuiltinModule.cpp b/src/bun.js/bindings/isBuiltinModule.cpp new file mode 100644 index 000000000..b8e69f479 --- /dev/null +++ b/src/bun.js/bindings/isBuiltinModule.cpp @@ -0,0 +1,98 @@ +#include "root.h" + +static constexpr ASCIILiteral builtinModuleNamesSortedLength[] = { + "fs"_s, + "os"_s, + "v8"_s, + "vm"_s, + "ws"_s, + "bun"_s, + "dns"_s, + "net"_s, + "sys"_s, + "tls"_s, + "tty"_s, + "url"_s, + "http"_s, + "path"_s, + "repl"_s, + "util"_s, + "wasi"_s, + "zlib"_s, + "dgram"_s, + "http2"_s, + "https"_s, + "assert"_s, + "buffer"_s, + "crypto"_s, + "domain"_s, + "events"_s, + "module"_s, + "stream"_s, + "timers"_s, + "undici"_s, + "bun:ffi"_s, + "bun:jsc"_s, + "cluster"_s, + "console"_s, + "process"_s, + "bun:wrap"_s, + "punycode"_s, + "bun:test"_s, + "bun:main"_s, + "readline"_s, + "_tls_wrap"_s, + "constants"_s, + "inspector"_s, + "bun:sqlite"_s, + "path/posix"_s, + "path/win32"_s, + "perf_hooks"_s, + "stream/web"_s, + "util/types"_s, + "_http_agent"_s, + "_tls_common"_s, + "async_hooks"_s, + "detect-libc"_s, + "fs/promises"_s, + "querystring"_s, + "_http_client"_s, + "_http_common"_s, + "_http_server"_s, + "_stream_wrap"_s, + "dns/promises"_s, + "trace_events"_s, + "assert/strict"_s, + "child_process"_s, + "_http_incoming"_s, + "_http_outgoing"_s, + "_stream_duplex"_s, + "string_decoder"_s, + "worker_threads"_s, + "stream/promises"_s, + "timers/promises"_s, + "_stream_readable"_s, + "_stream_writable"_s, + "stream/consumers"_s, + "_stream_transform"_s, + "readline/promises"_s, + "inspector/promises"_s, + "_stream_passthrough"_s, + "diagnostics_channel"_s, +}; + +namespace Bun { + +bool isBuiltinModule(const String &namePossiblyWithNodePrefix) { + String name = namePossiblyWithNodePrefix; + if (name.startsWith("node:"_s)) + name = name.substringSharingImpl(5); + + for (auto &builtinModule : builtinModuleNamesSortedLength) { + if (name == builtinModule) + return true; + } + return false; +} + +} // namespace Bun
\ No newline at end of file diff --git a/src/bun.js/bindings/isBuiltinModule.h b/src/bun.js/bindings/isBuiltinModule.h new file mode 100644 index 000000000..d66f025d1 --- /dev/null +++ b/src/bun.js/bindings/isBuiltinModule.h @@ -0,0 +1,5 @@ +#pragma once + +namespace Bun { +bool isBuiltinModule(const String &namePossiblyWithNodePrefix); +} // namespace Bun
\ No newline at end of file diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 72ca50dcb..005a753d0 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -83,7 +83,7 @@ JSC::SourceCode generateSourceCode(WTF::String keyString, JSC::VM& vm, JSC::JSOb sourceCodeBuilder.append(";\n"_s); } globalObject->putDirect(vm, ident, object, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum); - return JSC::makeSource(sourceCodeBuilder.toString(), JSC::SourceOrigin(), keyString, WTF::TextPosition(), JSC::SourceProviderSourceType::Module); + return JSC::makeSource(sourceCodeBuilder.toString(), JSC::SourceOrigin(), JSC::SourceTaintedOrigin::Untainted, keyString, WTF::TextPosition(), JSC::SourceProviderSourceType::Module); } } @@ -200,10 +200,6 @@ static uint32_t getPropertyAttributes(napi_property_descriptor prop) // result |= JSC::PropertyAttribute::ReadOnly; // } - if (prop.method) { - result |= JSC::PropertyAttribute::Function; - } - return result; } @@ -257,7 +253,7 @@ static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* t value = JSC::JSValue(function); // } - to->putDirect(vm, propertyName, value, getPropertyAttributes(property) | JSC::PropertyAttribute::Function); + to->putDirect(vm, propertyName, value, getPropertyAttributes(property)); return; } @@ -317,6 +313,10 @@ static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* t extern "C" napi_status napi_set_property(napi_env env, napi_value target, napi_value key, napi_value value) { + if (UNLIKELY(!env || !target || !key)) { + return napi_invalid_arg; + } + auto globalObject = toJS(env); auto& vm = globalObject->vm(); auto* object = toJS(target).getObject(); @@ -327,7 +327,8 @@ extern "C" napi_status napi_set_property(napi_env env, napi_value target, auto keyProp = toJS(key); auto scope = DECLARE_CATCH_SCOPE(vm); - object->putDirect(globalObject->vm(), keyProp.toPropertyKey(globalObject), toJS(value)); + PutPropertySlot slot(object, true); + object->put(object, globalObject, keyProp.toPropertyKey(globalObject), toJS(value), slot); RETURN_IF_EXCEPTION(scope, napi_generic_failure); scope.clearException(); @@ -336,6 +337,10 @@ extern "C" napi_status napi_set_property(napi_env env, napi_value target, extern "C" napi_status napi_has_property(napi_env env, napi_value object, napi_value key, bool* result) { + if (UNLIKELY(!object || !env)) { + return napi_invalid_arg; + } + auto globalObject = toJS(env); auto& vm = globalObject->vm(); auto* target = toJS(object).getObject(); @@ -345,8 +350,7 @@ extern "C" napi_status napi_has_property(napi_env env, napi_value object, auto keyProp = toJS(key); auto scope = DECLARE_CATCH_SCOPE(vm); - // TODO: use the slot directly? - *result = !!target->getIfPropertyExists(globalObject, keyProp.toPropertyKey(globalObject)); + *result = target->hasProperty(globalObject, keyProp.toPropertyKey(globalObject)); RETURN_IF_EXCEPTION(scope, napi_generic_failure); scope.clearException(); @@ -495,6 +499,81 @@ extern "C" napi_status napi_get_named_property(napi_env env, napi_value object, return napi_ok; } +#if !COMPILER(MSVC) +__attribute__((visibility("default"))) +#endif +extern "C" napi_status +node_api_create_external_string_latin1(napi_env env, + char* str, + size_t length, + napi_finalize finalize_callback, + void* finalize_hint, + napi_value* result, + bool* copied) +{ + // https://nodejs.org/api/n-api.html#node_api_create_external_string_latin1 + if (UNLIKELY(!str || !result)) { + return napi_invalid_arg; + } + + length = length == NAPI_AUTO_LENGTH ? strlen(str) : length; + WTF::ExternalStringImpl& impl = WTF::ExternalStringImpl::create(reinterpret_cast<LChar*>(str), static_cast<unsigned int>(length), finalize_hint, [finalize_callback](void* hint, void* str, unsigned length) { + if (finalize_callback) { + finalize_callback(reinterpret_cast<napi_env>(Bun__getDefaultGlobal()), nullptr, hint); + } + }); + JSGlobalObject* globalObject = toJS(env); + // globalObject is allowed to be null here + if (UNLIKELY(!globalObject)) { + globalObject = Bun__getDefaultGlobal(); + } + + JSString* out = JSC::jsString(globalObject->vm(), WTF::String(impl)); + ensureStillAliveHere(out); + *result = toNapi(out); + ensureStillAliveHere(out); + + return napi_ok; +} + +#if !COMPILER(MSVC) +__attribute__((visibility("default"))) +#endif + +extern "C" napi_status +node_api_create_external_string_utf16(napi_env env, + char16_t* str, + size_t length, + napi_finalize finalize_callback, + void* finalize_hint, + napi_value* result, + bool* copied) +{ + // https://nodejs.org/api/n-api.html#node_api_create_external_string_utf16 + if (UNLIKELY(!str || !result)) { + return napi_invalid_arg; + } + + length = length == NAPI_AUTO_LENGTH ? std::char_traits<char16_t>::length(str) : length; + WTF::ExternalStringImpl& impl = WTF::ExternalStringImpl::create(reinterpret_cast<UChar*>(str), static_cast<unsigned int>(length), finalize_hint, [finalize_callback](void* hint, void* str, unsigned length) { + if (finalize_callback) { + finalize_callback(reinterpret_cast<napi_env>(Bun__getDefaultGlobal()), nullptr, hint); + } + }); + JSGlobalObject* globalObject = toJS(env); + // globalObject is allowed to be null here + if (UNLIKELY(!globalObject)) { + globalObject = Bun__getDefaultGlobal(); + } + + JSString* out = JSC::jsString(globalObject->vm(), WTF::String(impl)); + ensureStillAliveHere(out); + *result = toNapi(out); + ensureStillAliveHere(out); + + return napi_ok; +} + extern "C" void napi_module_register(napi_module* mod) { auto* globalObject = Bun__getDefaultGlobal(); @@ -1028,7 +1107,7 @@ extern "C" napi_status napi_fatal_exception(napi_env env, napi_value err) { auto globalObject = toJS(env); - JSC::JSValue value = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(err)); + JSC::JSValue value = toJS(err); JSC::JSObject* obj = value.getObject(); if (UNLIKELY(obj == nullptr || !obj->isErrorInstance())) { return napi_invalid_arg; @@ -1045,7 +1124,7 @@ extern "C" napi_status napi_throw(napi_env env, napi_value error) JSC::VM& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); - JSC::JSValue value = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(error)); + JSC::JSValue value = toJS(error); if (value) { JSC::throwException(globalObject, throwScope, value); } else { @@ -1131,8 +1210,8 @@ extern "C" napi_status napi_create_type_error(napi_env env, napi_value code, Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - JSC::JSValue codeValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(code)); - JSC::JSValue messageValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(msg)); + JSC::JSValue codeValue = toJS(code); + JSC::JSValue messageValue = toJS(msg); auto error = JSC::createTypeError(globalObject, messageValue.toWTFString(globalObject)); if (codeValue) { @@ -1150,10 +1229,11 @@ extern "C" napi_status napi_create_error(napi_env env, napi_value code, Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - JSC::JSValue codeValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(code)); - JSC::JSValue messageValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(msg)); + JSC::JSValue codeValue = toJS(code); + JSC::JSValue messageValue = toJS(msg); - auto error = JSC::createError(globalObject, messageValue.toWTFString(globalObject)); + WTF::String message = messageValue.toWTFString(globalObject); + auto* error = JSC::createError(globalObject, message); if (codeValue) { error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0); } @@ -1557,15 +1637,15 @@ extern "C" napi_status napi_define_class(napi_env env, extern "C" napi_status napi_coerce_to_string(napi_env env, napi_value value, napi_value* result) { - if (UNLIKELY(result == nullptr)) { + if (UNLIKELY(result == nullptr || value == nullptr || env == nullptr)) { return napi_invalid_arg; } Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - auto scope = DECLARE_CATCH_SCOPE(vm); - JSC::JSValue jsValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(value)); + auto scope = DECLARE_THROW_SCOPE(vm); + JSC::JSValue jsValue = toJS(value); JSC::EnsureStillAliveScope ensureStillAlive(jsValue); // .toString() can throw @@ -1588,7 +1668,7 @@ extern "C" napi_status napi_get_property_names(napi_env env, napi_value object, Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - JSC::JSValue jsValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(object)); + JSC::JSValue jsValue = toJS(object); if (!jsValue || !jsValue.isObject()) { return napi_invalid_arg; } @@ -1717,7 +1797,7 @@ extern "C" napi_status napi_get_element(napi_env env, napi_value objectValue, uint32_t index, napi_value* result) { JSValue jsValue = toJS(objectValue); - if (!jsValue || !jsValue.isObject()) { + if (UNLIKELY(!env || !jsValue || !jsValue.isObject())) { return napi_invalid_arg; } @@ -1737,7 +1817,7 @@ extern "C" napi_status napi_get_element(napi_env env, napi_value objectValue, extern "C" napi_status napi_create_object(napi_env env, napi_value* result) { - if (UNLIKELY(result == nullptr)) { + if (UNLIKELY(result == nullptr || env == nullptr)) { return napi_invalid_arg; } diff --git a/src/bun.js/bindings/process.d.ts b/src/bun.js/bindings/process.d.ts deleted file mode 100644 index 194ea2b6a..000000000 --- a/src/bun.js/bindings/process.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * The process object provides information about, and control over, the - * current Bun.js process. While it is available as a global, it is - * recommended to explicitly access it via require or import - */ -export interface Process { - // -} diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index 8519cb2e2..2ce4cc9a6 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -83,6 +83,11 @@ static JSC_DECLARE_CUSTOM_GETTER(jsSqlStatementGetColumnCount); static JSC_DECLARE_HOST_FUNCTION(jsSQLStatementSerialize); static JSC_DECLARE_HOST_FUNCTION(jsSQLStatementDeserialize); +static inline JSC::JSValue jsNumberFromSQLite(sqlite3_stmt* stmt, unsigned int i) +{ + int64_t num = sqlite3_column_int64(stmt, i); + return num > INT_MAX || num < INT_MIN ? JSC::jsDoubleNumber(static_cast<double>(num)) : JSC::jsNumber(static_cast<int>(num)); +} #define CHECK_THIS \ if (UNLIKELY(!castedThis)) { \ @@ -183,7 +188,7 @@ public: JSC::JSValue rebind(JSGlobalObject* globalObject, JSC::JSValue values, bool clone); static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSFunctionType, StructureFlags), info()); } bool need_update() { return version_db->version.load() != version; } @@ -336,10 +341,6 @@ void JSSQLStatement::destroy(JSC::JSCell* cell) thisObject->stmt = nullptr; } -void JSSQLStatementConstructor::destroy(JSC::JSCell* cell) -{ -} - static inline bool rebindValue(JSC::JSGlobalObject* lexicalGlobalObject, sqlite3_stmt* stmt, int i, JSC::JSValue value, JSC::ThrowScope& scope, bool clone) { #define CHECK_BIND(param) \ @@ -690,6 +691,11 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementLoadExtensionFunction, (JSC::JSGlobalObje return JSValue::encode(JSC::jsUndefined()); } + if (sqlite3_compileoption_used("SQLITE_OMIT_LOAD_EXTENSION")) { + throwException(lexicalGlobalObject, scope, createError(lexicalGlobalObject, "This build of sqlite3 does not support dynamic extension loading"_s)); + return JSValue::encode(JSC::jsUndefined()); + } + auto entryPointStr = callFrame->argumentCount() > 2 && callFrame->argument(2).isString() ? callFrame->argument(2).toWTFString(lexicalGlobalObject) : String(); const char* entryPoint = entryPointStr.length() == 0 ? NULL : entryPointStr.utf8().data(); char* error; @@ -1054,7 +1060,7 @@ static const HashTableValue JSSQLStatementConstructorTableValues[] = { { "deserialize"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsSQLStatementDeserialize, 2 } }, }; -const ClassInfo JSSQLStatementConstructor::s_info = { "SQLStatement"_s, nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSSQLStatementConstructor) }; +const ClassInfo JSSQLStatementConstructor::s_info = { "SQLStatement"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSQLStatementConstructor) }; void JSSQLStatementConstructor::finishCreation(VM& vm) { @@ -1090,7 +1096,7 @@ static inline JSC::JSValue constructResultObject(JSC::JSGlobalObject* lexicalGlo switch (sqlite3_column_type(stmt, i)) { case SQLITE_INTEGER: { // https://github.com/oven-sh/bun/issues/1536 - value = jsNumber(sqlite3_column_int64(stmt, i)); + value = jsNumberFromSQLite(stmt, i); break; } case SQLITE_FLOAT: { @@ -1146,11 +1152,11 @@ static inline JSC::JSValue constructResultObject(JSC::JSGlobalObject* lexicalGlo switch (sqlite3_column_type(stmt, i)) { case SQLITE_INTEGER: { // https://github.com/oven-sh/bun/issues/1536 - result->putDirect(vm, name, jsNumber(sqlite3_column_int64(stmt, i)), 0); + result->putDirect(vm, name, jsNumberFromSQLite(stmt, i), 0); break; } case SQLITE_FLOAT: { - result->putDirect(vm, name, jsNumber(sqlite3_column_double(stmt, i)), 0); + result->putDirect(vm, name, jsDoubleNumber(sqlite3_column_double(stmt, i)), 0); break; } // > Note that the SQLITE_TEXT constant was also used in SQLite version @@ -1205,11 +1211,11 @@ static inline JSC::JSArray* constructResultRow(JSC::JSGlobalObject* lexicalGloba switch (sqlite3_column_type(stmt, i)) { case SQLITE_INTEGER: { // https://github.com/oven-sh/bun/issues/1536 - result->putDirectIndex(lexicalGlobalObject, i, jsNumber(sqlite3_column_int64(stmt, i))); + result->putDirectIndex(lexicalGlobalObject, i, jsNumberFromSQLite(stmt, i)); break; } case SQLITE_FLOAT: { - result->putDirectIndex(lexicalGlobalObject, i, jsNumber(sqlite3_column_double(stmt, i))); + result->putDirectIndex(lexicalGlobalObject, i, jsDoubleNumber(sqlite3_column_double(stmt, i))); break; } // > Note that the SQLITE_TEXT constant was also used in SQLite version @@ -1251,7 +1257,6 @@ static inline JSC::JSArray* constructResultRow(JSC::JSGlobalObject* lexicalGloba JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionAll, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - JSC::VM& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); auto castedThis = jsDynamicCast<JSSQLStatement*>(callFrame->thisValue()); @@ -1283,7 +1288,6 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionAll, (JSC::JSGlob size_t columnCount = castedThis->columnNames->size(); JSValue result = jsUndefined(); - if (status == SQLITE_ROW) { // this is a count from UPDATE or another query like that if (columnCount == 0) { @@ -1305,11 +1309,7 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionAll, (JSC::JSGlob result = resultArray; } } else if (status == SQLITE_DONE) { - if (columnCount == 0) { - result = jsNumber(sqlite3_changes(castedThis->version_db->db)); - } else { - result = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); - } + result = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); } if (UNLIKELY(status != SQLITE_DONE && status != SQLITE_OK)) { @@ -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, nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSSQLStatement) }; +const ClassInfo JSSQLStatement::s_info = { "SQLStatement"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSQLStatement) }; /* Hash table for prototype */ static const HashTableValue JSSQLStatementTableValues[] = { diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.h b/src/bun.js/bindings/sqlite/JSSQLStatement.h index 8566fcdd9..b628f2a38 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.h +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.h @@ -50,25 +50,15 @@ namespace WebCore { class JSSQLStatementConstructor final : public JSC::JSFunction { public: using Base = JSC::JSFunction; + static constexpr unsigned StructureFlags = Base::StructureFlags; + static JSSQLStatementConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure); DECLARE_INFO; - template<typename, SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<JSSQLStatementConstructor, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.m_clientSubspaceForJSSQLStatementConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSSQLStatementConstructor = std::forward<decltype(space)>(space); }, - [](auto& spaces) { return spaces.m_subspaceForJSSQLStatementConstructor.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForJSSQLStatementConstructor = std::forward<decltype(space)>(space); }); - } - static void destroy(JSC::JSCell*); static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSFunctionType, StructureFlags), info()); } private: @@ -79,5 +69,6 @@ private: void finishCreation(JSC::VM&); }; +static_assert(sizeof(JSSQLStatementConstructor) == sizeof(JSFunction), "Allocate JSSQLStatementConstructor in JSFunction IsoSubspace"); }
\ No newline at end of file diff --git a/src/bun.js/bindings/sqlite/lazy_sqlite3.h b/src/bun.js/bindings/sqlite/lazy_sqlite3.h index 8b23a7e03..a012f6ab6 100644 --- a/src/bun.js/bindings/sqlite/lazy_sqlite3.h +++ b/src/bun.js/bindings/sqlite/lazy_sqlite3.h @@ -71,6 +71,7 @@ typedef int (*lazy_sqlite3_deserialize_type)( ); typedef int (*lazy_sqlite3_stmt_readonly_type)(sqlite3_stmt* pStmt); +typedef int (*lazy_sqlite3_compileoption_used_type)(const char *zOptName); static lazy_sqlite3_bind_blob_type lazy_sqlite3_bind_blob; static lazy_sqlite3_bind_double_type lazy_sqlite3_bind_double; @@ -112,6 +113,7 @@ static lazy_sqlite3_malloc64_type lazy_sqlite3_malloc64; static lazy_sqlite3_serialize_type lazy_sqlite3_serialize; static lazy_sqlite3_deserialize_type lazy_sqlite3_deserialize; static lazy_sqlite3_stmt_readonly_type lazy_sqlite3_stmt_readonly; +static lazy_sqlite3_compileoption_used_type lazy_sqlite3_compileoption_used; #define sqlite3_bind_blob lazy_sqlite3_bind_blob #define sqlite3_bind_double lazy_sqlite3_bind_double @@ -152,6 +154,7 @@ static lazy_sqlite3_stmt_readonly_type lazy_sqlite3_stmt_readonly; #define sqlite3_deserialize lazy_sqlite3_deserialize #define sqlite3_stmt_readonly lazy_sqlite3_stmt_readonly #define sqlite3_column_int64 lazy_sqlite3_column_int64 +#define sqlite3_compileoption_used lazy_sqlite3_compileoption_used; static void* sqlite3_handle = nullptr; static const char* sqlite3_lib_path = "libsqlite3.dylib"; @@ -204,6 +207,7 @@ static int lazyLoadSQLite() lazy_sqlite3_deserialize = (lazy_sqlite3_deserialize_type)dlsym(sqlite3_handle, "sqlite3_deserialize"); lazy_sqlite3_malloc64 = (lazy_sqlite3_malloc64_type)dlsym(sqlite3_handle, "sqlite3_malloc64"); lazy_sqlite3_stmt_readonly = (lazy_sqlite3_stmt_readonly_type)dlsym(sqlite3_handle, "sqlite3_stmt_readonly"); + lazy_sqlite3_compileoption_used = (lazy_sqlite3_compileoption_used_type)dlsym(sqlite3_handle, "sqlite3_compileoption_used"); return 0; } diff --git a/src/bun.js/bindings/webcore/AbortSignal.h b/src/bun.js/bindings/webcore/AbortSignal.h index 6f4abf5ba..b60d2a6bf 100644 --- a/src/bun.js/bindings/webcore/AbortSignal.h +++ b/src/bun.js/bindings/webcore/AbortSignal.h @@ -45,6 +45,7 @@ class AbortSignal final : public RefCounted<AbortSignal>, public EventTargetWith public: static Ref<AbortSignal> create(ScriptExecutionContext*); WEBCORE_EXPORT ~AbortSignal(); + using NativeCallbackTuple = std::tuple<void*, void (*)(void*, JSC::EncodedJSValue)>; static Ref<AbortSignal> abort(JSDOMGlobalObject&, ScriptExecutionContext&, JSC::JSValue reason); static Ref<AbortSignal> timeout(ScriptExecutionContext&, uint64_t milliseconds); @@ -66,7 +67,7 @@ public: using Algorithm = Function<void(JSValue)>; void addAlgorithm(Algorithm&& algorithm) { m_algorithms.append(WTFMove(algorithm)); } void cleanNativeBindings(void* ref); - void addNativeCallback(std::tuple<void*, void (*)(void*, JSC::EncodedJSValue)> callback) { m_native_callbacks.append(callback); } + void addNativeCallback(NativeCallbackTuple callback) { m_native_callbacks.append(callback); } bool isFollowingSignal() const { return !!m_followingSignal; } @@ -87,8 +88,8 @@ private: void eventListenersDidChange() final; bool m_aborted { false }; - Vector<Algorithm> m_algorithms; - Vector<std::tuple<void*, void (*)(void*, JSC::EncodedJSValue)>> m_native_callbacks; + Vector<Algorithm, 2> m_algorithms; + Vector<NativeCallbackTuple, 2> m_native_callbacks; WeakPtr<AbortSignal> m_followingSignal; JSC::Strong<JSC::Unknown> m_reason; bool m_hasActiveTimeoutTimer { false }; diff --git a/src/bun.js/bindings/webcore/JSDOMURL.cpp b/src/bun.js/bindings/webcore/JSDOMURL.cpp index 747154bed..3f99fc2b7 100644 --- a/src/bun.js/bindings/webcore/JSDOMURL.cpp +++ b/src/bun.js/bindings/webcore/JSDOMURL.cpp @@ -64,6 +64,7 @@ using namespace JSC; static JSC_DECLARE_HOST_FUNCTION(jsDOMURLPrototypeFunction_toJSON); static JSC_DECLARE_HOST_FUNCTION(jsDOMURLConstructorFunction_createObjectURL); static JSC_DECLARE_HOST_FUNCTION(jsDOMURLConstructorFunction_revokeObjectURL); +static JSC_DECLARE_HOST_FUNCTION(jsDOMURLConstructorFunction_canParse); static JSC_DECLARE_HOST_FUNCTION(jsDOMURLPrototypeFunction_toString); // Attributes @@ -131,6 +132,7 @@ using JSDOMURLDOMConstructor = JSDOMConstructor<JSDOMURL>; static const HashTableValue JSDOMURLConstructorTableValues[] = { { "createObjectURL"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMURLConstructorFunction_createObjectURL, 1 } }, { "revokeObjectURL"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMURLConstructorFunction_revokeObjectURL, 1 } }, + { "canParse"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMURLConstructorFunction_canParse, 2 } }, }; static inline EncodedJSValue constructJSDOMURL1(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) @@ -688,6 +690,33 @@ JSC_DEFINE_HOST_FUNCTION(jsDOMURLConstructorFunction_revokeObjectURL, (JSGlobalO return IDLOperation<JSDOMURL>::callStatic<jsDOMURLConstructorFunction_revokeObjectURLBody>(*lexicalGlobalObject, *callFrame, "revokeObjectURL"); } +static inline JSC::EncodedJSValue jsDOMURLConstructorFunction_canParseBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto url = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + + EnsureStillAliveScope argument1 = callFrame->argument(1); + String base; + if (!argument1.value().isUndefinedOrNull()) { + base = convert<IDLUSVString>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + } + + return JSValue::encode(jsBoolean(DOMURL::canParse(url, base))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMURLConstructorFunction_canParse, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSDOMURL>::callStatic<jsDOMURLConstructorFunction_canParseBody>(*lexicalGlobalObject, *callFrame, "canParse"); +} + #if ENABLE(MEDIA_SOURCE) static inline JSC::EncodedJSValue jsDOMURLConstructorFunction_createObjectURL2Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) { diff --git a/src/bun.js/bindings/webcore/JSEventEmitter.cpp b/src/bun.js/bindings/webcore/JSEventEmitter.cpp index 959cbd8d7..e81af9549 100644 --- a/src/bun.js/bindings/webcore/JSEventEmitter.cpp +++ b/src/bun.js/bindings/webcore/JSEventEmitter.cpp @@ -109,9 +109,10 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSEventEmitterDOMConstructor: if constexpr (IsExceptionOr<decltype(object)>) RETURN_IF_EXCEPTION(throwScope, {}); - if (JSValue maxListeners = castedThis->getIfPropertyExists(lexicalGlobalObject, JSC::Identifier::fromString(vm, "defaultMaxListeners"_s))) { - if (maxListeners.isUInt32()) - object->setMaxListeners(maxListeners.toUInt32(lexicalGlobalObject)); + JSValue maxListeners = castedThis->getIfPropertyExists(lexicalGlobalObject, JSC::Identifier::fromString(vm, "defaultMaxListeners"_s)); + RETURN_IF_EXCEPTION(throwScope, {}); + if (maxListeners && maxListeners.isUInt32()) { + object->setMaxListeners(maxListeners.toUInt32(lexicalGlobalObject)); } static_assert(TypeOrExceptionOrUnderlyingType<decltype(object)>::isRef); auto jsValue = toJSNewlyCreated<IDLInterface<EventEmitter>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); diff --git a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp index 2ae8dd547..421a042e5 100644 --- a/src/bun.js/bindings/webcore/JSFetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/JSFetchHeaders.cpp @@ -245,17 +245,11 @@ JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_getAll, (JSGlobalObject return JSValue::encode(array); } -JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_getSetCookie, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +JSC_DEFINE_HOST_FUNCTION(fetchHeadersGetSetCookie, (JSC::JSGlobalObject * lexicalGlobalObject, VM& vm, WebCore::FetchHeaders* impl)) { - auto& vm = JSC::getVM(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); - JSFetchHeaders* castedThis = jsDynamicCast<JSFetchHeaders*>(callFrame->thisValue()); - if (UNLIKELY(!castedThis)) { - return JSValue::encode(jsUndefined()); - } - auto& impl = castedThis->wrapped(); - auto values = impl.getSetCookieHeaders(); + auto values = impl->getSetCookieHeaders(); unsigned count = values.size(); if (!count) { @@ -263,20 +257,31 @@ JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_getSetCookie, (JSGlobal } JSC::JSArray* array = constructEmptyArray(lexicalGlobalObject, nullptr, count); - RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined())); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); if (UNLIKELY(!array)) { throwOutOfMemoryError(lexicalGlobalObject, scope); - return JSValue::encode(jsUndefined()); + return encodedJSValue(); } for (unsigned i = 0; i < count; ++i) { array->putDirectIndex(lexicalGlobalObject, i, jsString(vm, values[i])); - RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined())); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); } return JSValue::encode(array); } +JSC_DEFINE_HOST_FUNCTION(jsFetchHeadersPrototypeFunction_getSetCookie, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + JSFetchHeaders* castedThis = jsDynamicCast<JSFetchHeaders*>(callFrame->thisValue()); + if (UNLIKELY(!castedThis)) { + return JSValue::encode(jsUndefined()); + } + auto& impl = castedThis->wrapped(); + return fetchHeadersGetSetCookie(lexicalGlobalObject, vm, &impl); +} + /* Hash table for prototype */ static const HashTableValue JSFetchHeadersPrototypeTableValues[] = { @@ -324,7 +329,7 @@ void JSFetchHeaders::finishCreation(VM& vm) void JSFetchHeaders::computeMemoryCost() { m_memoryCost = wrapped().memoryCost(); - globalObject()->vm().heap.reportExtraMemoryAllocated(m_memoryCost); + globalObject()->vm().heap.reportExtraMemoryAllocated(this, m_memoryCost); } JSObject* JSFetchHeaders::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) @@ -688,7 +693,6 @@ extern void* _ZTVN7WebCore12FetchHeadersE[]; JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<FetchHeaders>&& impl) { - if constexpr (std::is_polymorphic_v<FetchHeaders>) { #if ENABLE(BINDING_INTEGRITY) const void* actualVTablePointer = getVTablePointer(impl.ptr()); diff --git a/src/bun.js/bindings/webcore/JSFetchHeaders.h b/src/bun.js/bindings/webcore/JSFetchHeaders.h index 4efcc5f5f..58b61bbbb 100644 --- a/src/bun.js/bindings/webcore/JSFetchHeaders.h +++ b/src/bun.js/bindings/webcore/JSFetchHeaders.h @@ -97,4 +97,6 @@ template<> struct JSDOMWrapperConverterTraits<FetchHeaders> { using ToWrappedReturnType = FetchHeaders*; }; +JSC::EncodedJSValue fetchHeadersGetSetCookie(JSC::JSGlobalObject* lexicalGlobalObject, VM& vm, WebCore::FetchHeaders* impl); + } // namespace WebCore diff --git a/src/bun.js/bindings/webcore/JSMessageEvent.cpp b/src/bun.js/bindings/webcore/JSMessageEvent.cpp index 68414fe46..0a7ca6a5f 100644 --- a/src/bun.js/bindings/webcore/JSMessageEvent.cpp +++ b/src/bun.js/bindings/webcore/JSMessageEvent.cpp @@ -295,7 +295,7 @@ void JSMessageEvent::finishCreation(VM& vm) // static_assert(!std::is_base_of<ActiveDOMObject, MessageEvent>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); - vm.heap.reportExtraMemoryAllocated(wrapped().memoryCost()); + vm.heap.reportExtraMemoryAllocated(this, wrapped().memoryCost()); } JSObject* JSMessageEvent::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) diff --git a/src/bun.js/bindings/webcore/JSReadableStream.cpp b/src/bun.js/bindings/webcore/JSReadableStream.cpp index 3fea3d44f..0a0ef3b23 100644 --- a/src/bun.js/bindings/webcore/JSReadableStream.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStream.cpp @@ -108,7 +108,7 @@ template<> FunctionExecutable* JSReadableStreamDOMConstructor::initializeExecuta static const HashTableValue JSReadableStreamPrototypeTableValues[] = { { "constructor"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsReadableStreamConstructor, 0 } }, - { "locked"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamLockedCodeGenerator, 0 } }, + { "locked"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinAccessorType, readableStreamLockedCodeGenerator, 0 } }, { "cancel"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamCancelCodeGenerator, 0 } }, { "getReader"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamGetReaderCodeGenerator, 0 } }, { "pipeTo"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamPipeToCodeGenerator, 1 } }, diff --git a/src/bun.js/bindings/webcore/JSReadableStreamDefaultController.cpp b/src/bun.js/bindings/webcore/JSReadableStreamDefaultController.cpp index fea3ffc8c..b15084041 100644 --- a/src/bun.js/bindings/webcore/JSReadableStreamDefaultController.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStreamDefaultController.cpp @@ -108,7 +108,7 @@ template<> FunctionExecutable* JSReadableStreamDefaultControllerDOMConstructor:: static const HashTableValue JSReadableStreamDefaultControllerPrototypeTableValues[] = { { "constructor"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsReadableStreamDefaultControllerConstructor, 0 } }, - { "desiredSize"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamDefaultControllerDesiredSizeCodeGenerator, 0 } }, + { "desiredSize"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinAccessorType, readableStreamDefaultControllerDesiredSizeCodeGenerator, 0 } }, { "enqueue"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamDefaultControllerEnqueueCodeGenerator, 0 } }, { "close"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamDefaultControllerCloseCodeGenerator, 0 } }, { "error"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamDefaultControllerErrorCodeGenerator, 0 } }, diff --git a/src/bun.js/bindings/webcore/JSReadableStreamDefaultReader.cpp b/src/bun.js/bindings/webcore/JSReadableStreamDefaultReader.cpp index 55b89ad46..68b587a92 100644 --- a/src/bun.js/bindings/webcore/JSReadableStreamDefaultReader.cpp +++ b/src/bun.js/bindings/webcore/JSReadableStreamDefaultReader.cpp @@ -108,7 +108,7 @@ template<> FunctionExecutable* JSReadableStreamDefaultReaderDOMConstructor::init static const HashTableValue JSReadableStreamDefaultReaderPrototypeTableValues[] = { { "constructor"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsReadableStreamDefaultReaderConstructor, 0 } }, - { "closed"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamDefaultReaderClosedCodeGenerator, 0 } }, + { "closed"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Accessor | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinAccessorType, readableStreamDefaultReaderClosedCodeGenerator, 0 } }, { "read"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamDefaultReaderReadCodeGenerator, 0 } }, { "readMany"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamDefaultReaderReadManyCodeGenerator, 0 } }, { "cancel"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, readableStreamDefaultReaderCancelCodeGenerator, 0 } }, diff --git a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp index 0d401fa00..4c0f0e912 100644 --- a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp +++ b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp @@ -182,6 +182,7 @@ static const HashTableValue JSURLSearchParamsPrototypeTableValues[] = { { "toString"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsURLSearchParamsPrototypeFunction_toString, 0 } }, { "toJSON"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsURLSearchParamsPrototypeFunction_toJSON, 0 } }, { "length"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsURLSearchParamsPrototype_getLength, 0 } }, + { "size"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, jsURLSearchParamsPrototype_getLength, 0 } }, }; const ClassInfo JSURLSearchParamsPrototype::s_info = { "URLSearchParams"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSURLSearchParamsPrototype) }; diff --git a/src/bun.js/bindings/webcore/MessagePort.cpp b/src/bun.js/bindings/webcore/MessagePort.cpp index da2bd32e8..b463791df 100644 --- a/src/bun.js/bindings/webcore/MessagePort.cpp +++ b/src/bun.js/bindings/webcore/MessagePort.cpp @@ -141,7 +141,7 @@ MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext, const M , m_identifier(local) , m_remoteIdentifier(remote) { - LOG(MessagePorts, "Created MessagePort %s (%p) in process %" PRIu64, m_identifier.logString().utf8().data(), this, ProcessIdent::identifier().toUInt64()); + // LOG(MessagePorts, "Created MessagePort %s (%p) in process %" PRIu64, m_identifier.logString().utf8().data(), this, ProcessIdent::identifier().toUInt64()); Locker locker { allMessagePortsLock }; allMessagePorts().set(m_identifier, this); @@ -157,7 +157,7 @@ MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext, const M MessagePort::~MessagePort() { - LOG(MessagePorts, "Destroyed MessagePort %s (%p) in process %" PRIu64, m_identifier.logString().utf8().data(), this, ProcessIdent::identifier().toUInt64()); + // LOG(MessagePorts, "Destroyed MessagePort %s (%p) in process %" PRIu64, m_identifier.logString().utf8().data(), this, ProcessIdent::identifier().toUInt64()); ASSERT(allMessagePortsLock.isLocked()); @@ -175,7 +175,7 @@ void MessagePort::entangle() ExceptionOr<void> MessagePort::postMessage(JSC::JSGlobalObject& state, JSC::JSValue messageValue, StructuredSerializeOptions&& options) { - LOG(MessagePorts, "Attempting to post message to port %s (to be received by port %s)", m_identifier.logString().utf8().data(), m_remoteIdentifier.logString().utf8().data()); + // LOG(MessagePorts, "Attempting to post message to port %s (to be received by port %s)", m_identifier.logString().utf8().data(), m_remoteIdentifier.logString().utf8().data()); Vector<RefPtr<MessagePort>> ports; auto messageData = SerializedScriptValue::create(state, messageValue, WTFMove(options.transfer), ports, SerializationForStorage::No, SerializationContext::WorkerPostMessage); @@ -202,7 +202,7 @@ ExceptionOr<void> MessagePort::postMessage(JSC::JSGlobalObject& state, JSC::JSVa MessageWithMessagePorts message { messageData.releaseReturnValue(), WTFMove(transferredPorts) }; - LOG(MessagePorts, "Actually posting message to port %s (to be received by port %s)", m_identifier.logString().utf8().data(), m_remoteIdentifier.logString().utf8().data()); + // LOG(MessagePorts, "Actually posting message to port %s (to be received by port %s)", m_identifier.logString().utf8().data(), m_remoteIdentifier.logString().utf8().data()); ScriptExecutionContextIdentifier contextId = contextIdForMessagePortId(m_remoteIdentifier); @@ -280,7 +280,7 @@ void MessagePort::dispatchMessages() auto messagesTakenHandler = [this, protectedThis = Ref { *this }](Vector<MessageWithMessagePorts>&& messages, CompletionHandler<void()>&& completionCallback) mutable { auto scopeExit = makeScopeExit(WTFMove(completionCallback)); - LOG(MessagePorts, "MessagePort %s (%p) dispatching %zu messages", m_identifier.logString().utf8().data(), this, messages.size()); + // LOG(MessagePorts, "MessagePort %s (%p) dispatching %zu messages", m_identifier.logString().utf8().data(), this, messages.size()); auto* context = scriptExecutionContext(); if (!context || !context->jsGlobalObject()) @@ -382,7 +382,7 @@ ExceptionOr<Vector<TransferredMessagePort>> MessagePort::disentanglePorts(Vector Vector<RefPtr<MessagePort>> MessagePort::entanglePorts(ScriptExecutionContext& context, Vector<TransferredMessagePort>&& transferredPorts) { - LOG(MessagePorts, "Entangling %zu transferred ports to ScriptExecutionContext %s (%p)", transferredPorts.size(), context.url().string().utf8().data(), &context); + // LOG(MessagePorts, "Entangling %zu transferred ports to ScriptExecutionContext %s (%p)", transferredPorts.size(), context.url().string().utf8().data(), &context); if (transferredPorts.isEmpty()) return {}; diff --git a/src/bun.js/bindings/webcore/MessagePortChannel.cpp b/src/bun.js/bindings/webcore/MessagePortChannel.cpp index 031679204..425fb8c11 100644 --- a/src/bun.js/bindings/webcore/MessagePortChannel.cpp +++ b/src/bun.js/bindings/webcore/MessagePortChannel.cpp @@ -75,7 +75,7 @@ void MessagePortChannel::entanglePortWithProcess(const MessagePortIdentifier& po ASSERT(port == m_ports[0] || port == m_ports[1]); size_t i = port == m_ports[0] ? 0 : 1; - LOG(MessagePorts, "MessagePortChannel %s (%p) entangling port %s (that port has %zu messages available)", logString().utf8().data(), this, port.logString().utf8().data(), m_pendingMessages[i].size()); + // LOG(MessagePorts, "MessagePortChannel %s (%p) entangling port %s (that port has %zu messages available)", logString().utf8().data(), this, port.logString().utf8().data(), m_pendingMessages[i].size()); ASSERT(!m_processes[i] || *m_processes[i] == process); m_processes[i] = process; @@ -85,7 +85,7 @@ void MessagePortChannel::entanglePortWithProcess(const MessagePortIdentifier& po void MessagePortChannel::disentanglePort(const MessagePortIdentifier& port) { - LOG(MessagePorts, "MessagePortChannel %s (%p) disentangling port %s", logString().utf8().data(), this, port.logString().utf8().data()); + // LOG(MessagePorts, "MessagePortChannel %s (%p) disentangling port %s", logString().utf8().data(), this, port.logString().utf8().data()); ASSERT(port == m_ports[0] || port == m_ports[1]); size_t i = port == m_ports[0] ? 0 : 1; @@ -123,7 +123,7 @@ bool MessagePortChannel::postMessageToRemote(MessageWithMessagePorts&& message, size_t i = remoteTarget == m_ports[0] ? 0 : 1; m_pendingMessages[i].append(WTFMove(message)); - LOG(MessagePorts, "MessagePortChannel %s (%p) now has %zu messages pending on port %s", logString().utf8().data(), this, m_pendingMessages[i].size(), remoteTarget.logString().utf8().data()); + // LOG(MessagePorts, "MessagePortChannel %s (%p) now has %zu messages pending on port %s", logString().utf8().data(), this, m_pendingMessages[i].size(), remoteTarget.logString().utf8().data()); if (m_pendingMessages[i].size() == 1) { m_pendingMessageProtectors[i] = this; @@ -136,7 +136,7 @@ bool MessagePortChannel::postMessageToRemote(MessageWithMessagePorts&& message, void MessagePortChannel::takeAllMessagesForPort(const MessagePortIdentifier& port, CompletionHandler<void(Vector<MessageWithMessagePorts>&&, CompletionHandler<void()>&&)>&& callback) { - LOG(MessagePorts, "MessagePortChannel %p taking all messages for port %s", this, port.logString().utf8().data()); + // LOG(MessagePorts, "MessagePortChannel %p taking all messages for port %s", this, port.logString().utf8().data()); ASSERT(port == m_ports[0] || port == m_ports[1]); size_t i = port == m_ports[0] ? 0 : 1; @@ -153,7 +153,7 @@ void MessagePortChannel::takeAllMessagesForPort(const MessagePortIdentifier& por ++m_messageBatchesInFlight; - LOG(MessagePorts, "There are %zu messages to take for port %s. Taking them now, messages in flight is now %" PRIu64, result.size(), port.logString().utf8().data(), m_messageBatchesInFlight); + // LOG(MessagePorts, "There are %zu messages to take for port %s. Taking them now, messages in flight is now %" PRIu64, result.size(), port.logString().utf8().data(), m_messageBatchesInFlight); auto size = result.size(); callback(WTFMove(result), [size, this, port, protectedThis = WTFMove(m_pendingMessageProtectors[i])] { @@ -162,7 +162,7 @@ void MessagePortChannel::takeAllMessagesForPort(const MessagePortIdentifier& por UNUSED_PARAM(size); #endif --m_messageBatchesInFlight; - LOG(MessagePorts, "Message port channel %s was notified that a batch of %zu message port messages targeted for port %s just completed dispatch, in flight is now %" PRIu64, logString().utf8().data(), size, port.logString().utf8().data(), m_messageBatchesInFlight); + // LOG(MessagePorts, "Message port channel %s was notified that a batch of %zu message port messages targeted for port %s just completed dispatch, in flight is now %" PRIu64, logString().utf8().data(), size, port.logString().utf8().data(), m_messageBatchesInFlight); }); } diff --git a/src/bun.js/bindings/webcore/MessagePortChannelProvider.cpp b/src/bun.js/bindings/webcore/MessagePortChannelProvider.cpp index 7675a2e75..cde0d0dd4 100644 --- a/src/bun.js/bindings/webcore/MessagePortChannelProvider.cpp +++ b/src/bun.js/bindings/webcore/MessagePortChannelProvider.cpp @@ -38,7 +38,8 @@ static MessagePortChannelProviderImpl* globalProvider; MessagePortChannelProvider& MessagePortChannelProvider::singleton() { - ASSERT(isMainThread()); + // TODO: I think this assertion is relevant. Bun will call this on the Worker's thread + // ASSERT(isMainThread()); static std::once_flag onceFlag; std::call_once(onceFlag, [] { if (!globalProvider) diff --git a/src/bun.js/bindings/webcore/MessagePortChannelRegistry.cpp b/src/bun.js/bindings/webcore/MessagePortChannelRegistry.cpp index 5096357f2..a92262f63 100644 --- a/src/bun.js/bindings/webcore/MessagePortChannelRegistry.cpp +++ b/src/bun.js/bindings/webcore/MessagePortChannelRegistry.cpp @@ -30,6 +30,9 @@ #include <wtf/CompletionHandler.h> #include <wtf/MainThread.h> +// ASSERT(isMainThread()) is used alot here, and I think it may be required, but i'm not 100% sure. +// we totally are calling these off the main thread in many cases in Bun, so ........ + namespace WebCore { MessagePortChannelRegistry::MessagePortChannelRegistry() = default; @@ -41,15 +44,15 @@ MessagePortChannelRegistry::~MessagePortChannelRegistry() void MessagePortChannelRegistry::didCreateMessagePortChannel(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2) { - LOG(MessagePorts, "Registry: Creating MessagePortChannel %p linking %s and %s", this, port1.logString().utf8().data(), port2.logString().utf8().data()); - ASSERT(isMainThread()); + // LOG(MessagePorts, "Registry: Creating MessagePortChannel %p linking %s and %s", this, port1.logString().utf8().data(), port2.logString().utf8().data()); + // ASSERT(isMainThread()); MessagePortChannel::create(*this, port1, port2); } void MessagePortChannelRegistry::messagePortChannelCreated(MessagePortChannel& channel) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); auto result = m_openChannels.ensure(channel.port1(), [channel = &channel] { return channel; @@ -64,7 +67,7 @@ void MessagePortChannelRegistry::messagePortChannelCreated(MessagePortChannel& c void MessagePortChannelRegistry::messagePortChannelDestroyed(MessagePortChannel& channel) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); ASSERT(m_openChannels.get(channel.port1()) == &channel); ASSERT(m_openChannels.get(channel.port2()) == &channel); @@ -72,12 +75,12 @@ void MessagePortChannelRegistry::messagePortChannelDestroyed(MessagePortChannel& m_openChannels.remove(channel.port1()); m_openChannels.remove(channel.port2()); - LOG(MessagePorts, "Registry: After removing channel %s there are %u channels left in the registry:", channel.logString().utf8().data(), m_openChannels.size()); + // LOG(MessagePorts, "Registry: After removing channel %s there are %u channels left in the registry:", channel.logString().utf8().data(), m_openChannels.size()); } void MessagePortChannelRegistry::didEntangleLocalToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote, ProcessIdentifier process) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); // The channel might be gone if the remote side was closed. auto* channel = m_openChannels.get(local); @@ -91,7 +94,7 @@ void MessagePortChannelRegistry::didEntangleLocalToRemote(const MessagePortIdent void MessagePortChannelRegistry::didDisentangleMessagePort(const MessagePortIdentifier& port) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); // The channel might be gone if the remote side was closed. auto* channel = m_openChannels.get(port); @@ -103,17 +106,17 @@ void MessagePortChannelRegistry::didDisentangleMessagePort(const MessagePortIden void MessagePortChannelRegistry::didCloseMessagePort(const MessagePortIdentifier& port) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); - LOG(MessagePorts, "Registry: MessagePort %s closed in registry", port.logString().utf8().data()); + // LOG(MessagePorts, "Registry: MessagePort %s closed in registry", port.logString().utf8().data()); auto* channel = m_openChannels.get(port); if (!channel) return; #ifndef NDEBUG - if (channel && channel->hasAnyMessagesPendingOrInFlight()) - LOG(MessagePorts, "Registry: (Note) The channel closed for port %s had messages pending or in flight", port.logString().utf8().data()); + // if (channel && channel->hasAnyMessagesPendingOrInFlight()) + // LOG(MessagePorts, "Registry: (Note) The channel closed for port %s had messages pending or in flight", port.logString().utf8().data()); #endif channel->closePort(port); @@ -124,14 +127,14 @@ void MessagePortChannelRegistry::didCloseMessagePort(const MessagePortIdentifier bool MessagePortChannelRegistry::didPostMessageToRemote(MessageWithMessagePorts&& message, const MessagePortIdentifier& remoteTarget) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); - LOG(MessagePorts, "Registry: Posting message to MessagePort %s in registry", remoteTarget.logString().utf8().data()); + // LOG(MessagePorts, "Registry: Posting message to MessagePort %s in registry", remoteTarget.logString().utf8().data()); // The channel might be gone if the remote side was closed. auto* channel = m_openChannels.get(remoteTarget); if (!channel) { - LOG(MessagePorts, "Registry: Could not find MessagePortChannel for port %s; It was probably closed. Message will be dropped.", remoteTarget.logString().utf8().data()); + // LOG(MessagePorts, "Registry: Could not find MessagePortChannel for port %s; It was probably closed. Message will be dropped.", remoteTarget.logString().utf8().data()); return false; } @@ -140,9 +143,9 @@ bool MessagePortChannelRegistry::didPostMessageToRemote(MessageWithMessagePorts& void MessagePortChannelRegistry::takeAllMessagesForPort(const MessagePortIdentifier& port, CompletionHandler<void(Vector<MessageWithMessagePorts>&&, CompletionHandler<void()>&&)>&& callback) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); - LOG(MessagePorts, "Registry: Taking all messages for MessagePort %s", port.logString().utf8().data()); + // LOG(MessagePorts, "Registry: Taking all messages for MessagePort %s", port.logString().utf8().data()); // The channel might be gone if the remote side was closed. auto* channel = m_openChannels.get(port); @@ -156,9 +159,9 @@ void MessagePortChannelRegistry::takeAllMessagesForPort(const MessagePortIdentif std::optional<MessageWithMessagePorts> MessagePortChannelRegistry::tryTakeMessageForPort(const MessagePortIdentifier& port) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); - LOG(MessagePorts, "Registry: Trying to take a message for MessagePort %s", port.logString().utf8().data()); + // LOG(MessagePorts, "Registry: Trying to take a message for MessagePort %s", port.logString().utf8().data()); // The channel might be gone if the remote side was closed. auto* channel = m_openChannels.get(port); @@ -170,7 +173,7 @@ std::optional<MessageWithMessagePorts> MessagePortChannelRegistry::tryTakeMessag MessagePortChannel* MessagePortChannelRegistry::existingChannelContainingPort(const MessagePortIdentifier& port) { - ASSERT(isMainThread()); + // ASSERT(isMainThread()); return m_openChannels.get(port); } diff --git a/src/bun.js/bindings/webcore/WebCoreTypedArrayController.cpp b/src/bun.js/bindings/webcore/WebCoreTypedArrayController.cpp index ca8c79aef..5c8f4fbea 100644 --- a/src/bun.js/bindings/webcore/WebCoreTypedArrayController.cpp +++ b/src/bun.js/bindings/webcore/WebCoreTypedArrayController.cpp @@ -35,6 +35,16 @@ #include "JavaScriptCore/JSArrayBuffer.h" +extern "C" Zig::GlobalObject* Bun__getDefaultGlobal(); +static inline WebCore::JSDOMGlobalObject* getDefaultGlobal(JSC::JSGlobalObject* lexicalGlobalObject) +{ + if (auto* global = jsDynamicCast<WebCore::JSDOMGlobalObject*>(lexicalGlobalObject)) { + return global; + } + + return Bun__getDefaultGlobal(); +} + namespace WebCore { WebCoreTypedArrayController::WebCoreTypedArrayController(bool allowAtomicsWait) @@ -46,7 +56,7 @@ WebCoreTypedArrayController::~WebCoreTypedArrayController() = default; JSC::JSArrayBuffer* WebCoreTypedArrayController::toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSGlobalObject* globalObject, JSC::ArrayBuffer* buffer) { - return JSC::jsCast<JSC::JSArrayBuffer*>(WebCore::toJS(lexicalGlobalObject, JSC::jsCast<JSDOMGlobalObject*>(globalObject), buffer)); + return JSC::jsCast<JSC::JSArrayBuffer*>(WebCore::toJS(lexicalGlobalObject, getDefaultGlobal(globalObject), buffer)); } void WebCoreTypedArrayController::registerWrapper(JSC::JSGlobalObject* globalObject, JSC::ArrayBuffer* native, JSC::JSArrayBuffer* wrapper) diff --git a/src/bun.js/bindings/webcore/WebSocket.cpp b/src/bun.js/bindings/webcore/WebSocket.cpp index c1a4054f5..4f7f933c5 100644 --- a/src/bun.js/bindings/webcore/WebSocket.cpp +++ b/src/bun.js/bindings/webcore/WebSocket.cpp @@ -161,7 +161,6 @@ WebSocket::WebSocket(ScriptExecutionContext& context) { m_state = CONNECTING; m_hasPendingActivity.store(true); - ref(); } WebSocket::~WebSocket() @@ -650,7 +649,7 @@ ExceptionOr<void> WebSocket::close(std::optional<unsigned short> optionalCode, c ExceptionOr<void> WebSocket::terminate() { - LOG(Network, "WebSocket %p terminate()", this); + // LOG(Network, "WebSocket %p terminate()", this); if (m_state == CLOSING || m_state == CLOSED) return {}; @@ -692,7 +691,7 @@ ExceptionOr<void> WebSocket::terminate() ExceptionOr<void> WebSocket::ping() { auto message = WTF::String::number(WTF::jsCurrentTime()); - LOG(Network, "WebSocket %p ping() Sending Timestamp '%s'", this, message.data()); + // LOG(Network, "WebSocket %p ping() Sending Timestamp '%s'", this, message.data()); if (m_state == CONNECTING) return Exception { InvalidStateError }; @@ -711,7 +710,7 @@ ExceptionOr<void> WebSocket::ping() ExceptionOr<void> WebSocket::ping(const String& message) { - LOG(Network, "WebSocket %p ping() Sending String '%s'", this, message.utf8().data()); + // LOG(Network, "WebSocket %p ping() Sending String '%s'", this, message.utf8().data()); if (m_state == CONNECTING) return Exception { InvalidStateError }; @@ -731,7 +730,7 @@ ExceptionOr<void> WebSocket::ping(const String& message) ExceptionOr<void> WebSocket::ping(ArrayBuffer& binaryData) { - LOG(Network, "WebSocket %p ping() Sending ArrayBuffer %p", this, &binaryData); + // LOG(Network, "WebSocket %p ping() Sending ArrayBuffer %p", this, &binaryData); if (m_state == CONNECTING) return Exception { InvalidStateError }; @@ -751,7 +750,7 @@ ExceptionOr<void> WebSocket::ping(ArrayBuffer& binaryData) ExceptionOr<void> WebSocket::ping(ArrayBufferView& arrayBufferView) { - LOG(Network, "WebSocket %p ping() Sending ArrayBufferView %p", this, &arrayBufferView); + // LOG(Network, "WebSocket %p ping() Sending ArrayBufferView %p", this, &arrayBufferView); if (m_state == CONNECTING) return Exception { InvalidStateError }; @@ -774,7 +773,7 @@ ExceptionOr<void> WebSocket::ping(ArrayBufferView& arrayBufferView) ExceptionOr<void> WebSocket::pong() { auto message = WTF::String::number(WTF::jsCurrentTime()); - LOG(Network, "WebSocket %p pong() Sending Timestamp '%s'", this, message.data()); + // LOG(Network, "WebSocket %p pong() Sending Timestamp '%s'", this, message.data()); if (m_state == CONNECTING) return Exception { InvalidStateError }; @@ -793,7 +792,7 @@ ExceptionOr<void> WebSocket::pong() ExceptionOr<void> WebSocket::pong(const String& message) { - LOG(Network, "WebSocket %p pong() Sending String '%s'", this, message.utf8().data()); + // LOG(Network, "WebSocket %p pong() Sending String '%s'", this, message.utf8().data()); if (m_state == CONNECTING) return Exception { InvalidStateError }; @@ -813,7 +812,7 @@ ExceptionOr<void> WebSocket::pong(const String& message) ExceptionOr<void> WebSocket::pong(ArrayBuffer& binaryData) { - LOG(Network, "WebSocket %p pong() Sending ArrayBuffer %p", this, &binaryData); + // LOG(Network, "WebSocket %p pong() Sending ArrayBuffer %p", this, &binaryData); if (m_state == CONNECTING) return Exception { InvalidStateError }; @@ -833,7 +832,7 @@ ExceptionOr<void> WebSocket::pong(ArrayBuffer& binaryData) ExceptionOr<void> WebSocket::pong(ArrayBufferView& arrayBufferView) { - LOG(Network, "WebSocket %p pong() Sending ArrayBufferView %p", this, &arrayBufferView); + // LOG(Network, "WebSocket %p pong() Sending ArrayBufferView %p", this, &arrayBufferView); if (m_state == CONNECTING) return Exception { InvalidStateError }; @@ -1431,7 +1430,7 @@ extern "C" void WebSocket__didAbruptClose(WebCore::WebSocket* webSocket, int32_t { webSocket->didFailWithErrorCode(errorCode); } -extern "C" void WebSocket__didClose(WebCore::WebSocket* webSocket, uint16_t errorCode, const BunString *reason) +extern "C" void WebSocket__didClose(WebCore::WebSocket* webSocket, uint16_t errorCode, const BunString* reason) { WTF::String wtf_reason = Bun::toWTFString(*reason); webSocket->didClose(0, errorCode, WTFMove(wtf_reason)); diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyAES.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyAES.cpp index 17cbf48d9..ce23ce5dd 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyAES.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoKeyAES.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "CryptoKeyAES.h" - +#include "../wtf-bindings.h" #if ENABLE(WEB_CRYPTO) #include "CryptoAesKeyAlgorithm.h" @@ -107,7 +107,7 @@ JsonWebKey CryptoKeyAES::exportJwk() const { JsonWebKey result; result.kty = "oct"_s; - result.k = base64URLEncodeToString(m_key); + result.k = Bun::base64URLEncodeToString(m_key); result.key_ops = usages(); result.ext = extractable(); return result; diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyEC.h b/src/bun.js/bindings/webcrypto/CryptoKeyEC.h index f2cf7383f..8e8f5eb35 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyEC.h +++ b/src/bun.js/bindings/webcrypto/CryptoKeyEC.h @@ -91,6 +91,8 @@ public: String namedCurveString() const; PlatformECKey platformKey() const { return m_platformKey.get(); } static bool isValidECAlgorithm(CryptoAlgorithmIdentifier); + static RefPtr<CryptoKeyEC> platformImportSpki(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyEC> platformImportPkcs8(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); private: CryptoKeyEC(CryptoAlgorithmIdentifier, NamedCurve, CryptoKeyType, PlatformECKeyContainer&&, bool extractable, CryptoKeyUsageBitmap); @@ -104,8 +106,6 @@ private: static RefPtr<CryptoKeyEC> platformImportRaw(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); static RefPtr<CryptoKeyEC> platformImportJWKPublic(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, bool extractable, CryptoKeyUsageBitmap); static RefPtr<CryptoKeyEC> platformImportJWKPrivate(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, Vector<uint8_t>&& d, bool extractable, CryptoKeyUsageBitmap); - static RefPtr<CryptoKeyEC> platformImportSpki(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); - static RefPtr<CryptoKeyEC> platformImportPkcs8(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); Vector<uint8_t> platformExportRaw() const; bool platformAddFieldElements(JsonWebKey&) const; Vector<uint8_t> platformExportSpki() const; diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyECOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyECOpenSSL.cpp index bb5dc5e62..c2b363b32 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyECOpenSSL.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoKeyECOpenSSL.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "CryptoKeyEC.h" +#include "../wtf-bindings.h" #if ENABLE(WEB_CRYPTO) @@ -408,15 +409,15 @@ bool CryptoKeyEC::platformAddFieldElements(JsonWebKey& jwk) const auto x = BIGNUMPtr(BN_new()); auto y = BIGNUMPtr(BN_new()); if (1 == EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key), publicKey, x.get(), y.get(), ctx.get())) { - jwk.x = base64URLEncodeToString(convertToBytesExpand(x.get(), keySizeInBytes)); - jwk.y = base64URLEncodeToString(convertToBytesExpand(y.get(), keySizeInBytes)); + jwk.x = Bun::base64URLEncodeToString(convertToBytesExpand(x.get(), keySizeInBytes)); + jwk.y = Bun::base64URLEncodeToString(convertToBytesExpand(y.get(), keySizeInBytes)); } } if (type() == Type::Private) { const BIGNUM* privateKey = EC_KEY_get0_private_key(key); if (privateKey) - jwk.d = base64URLEncodeToString(convertToBytes(privateKey)); + jwk.d = Bun::base64URLEncodeToString(convertToBytes(privateKey)); } return true; } diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.cpp index aafb3b2fe..9428998cb 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "CryptoKeyHMAC.h" +#include "../wtf-bindings.h" #if ENABLE(WEB_CRYPTO) @@ -69,6 +70,13 @@ CryptoKeyHMAC::CryptoKeyHMAC(Vector<uint8_t>&& key, CryptoAlgorithmIdentifier ha CryptoKeyHMAC::~CryptoKeyHMAC() = default; + +RefPtr<CryptoKeyHMAC> CryptoKeyHMAC::generateFromBytes(void* data, size_t byteLength, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap usages) { + + Vector<uint8_t> vec_data((uint8_t*)data, byteLength); + return adoptRef(new CryptoKeyHMAC(vec_data, hash, extractable, usages)); +} + RefPtr<CryptoKeyHMAC> CryptoKeyHMAC::generate(size_t lengthBits, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap usages) { if (!lengthBits) { @@ -118,11 +126,13 @@ RefPtr<CryptoKeyHMAC> CryptoKeyHMAC::importJwk(size_t lengthBits, CryptoAlgorith return CryptoKeyHMAC::importRaw(lengthBits, hash, WTFMove(*octetSequence), extractable, usages); } + JsonWebKey CryptoKeyHMAC::exportJwk() const -{ +{ + JsonWebKey result; result.kty = "oct"_s; - result.k = base64URLEncodeToString(m_key); + result.k = Bun::base64URLEncodeToString(m_key); result.key_ops = usages(); result.ext = extractable(); return result; diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.h b/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.h index 0c7ba38cb..714888019 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.h +++ b/src/bun.js/bindings/webcrypto/CryptoKeyHMAC.h @@ -43,9 +43,11 @@ public: { return adoptRef(*new CryptoKeyHMAC(key, hash, extractable, usage)); } + virtual ~CryptoKeyHMAC(); static RefPtr<CryptoKeyHMAC> generate(size_t lengthBits, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyHMAC> generateFromBytes(void* data, size_t byteLength, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap); static RefPtr<CryptoKeyHMAC> importRaw(size_t lengthBits, CryptoAlgorithmIdentifier hash, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); using CheckAlgCallback = Function<bool(CryptoAlgorithmIdentifier, const String&)>; static RefPtr<CryptoKeyHMAC> importJwk(size_t lengthBits, CryptoAlgorithmIdentifier hash, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap, CheckAlgCallback&&); diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyOKP.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyOKP.cpp index b7dc55018..4b5d8d588 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyOKP.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoKeyOKP.cpp @@ -119,14 +119,13 @@ RefPtr<CryptoKeyOKP> CryptoKeyOKP::importRaw(CryptoAlgorithmIdentifier identifie return create(identifier, namedCurve, usages & CryptoKeyUsageSign ? CryptoKeyType::Private : CryptoKeyType::Public, WTFMove(keyData), extractable, usages); } -RefPtr<CryptoKeyOKP> CryptoKeyOKP::importJwk(CryptoAlgorithmIdentifier identifier, NamedCurve namedCurve, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages) -{ +RefPtr<CryptoKeyOKP> CryptoKeyOKP::importJwkInternal(CryptoAlgorithmIdentifier identifier, NamedCurve namedCurve, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages, bool onlyPublic) { if (!isPlatformSupportedCurve(namedCurve)) return nullptr; switch (namedCurve) { case NamedCurve::Ed25519: - if (!keyData.d.isEmpty()) { + if (!keyData.d.isEmpty() && !onlyPublic) { if (usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageVerify | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) return nullptr; } else { @@ -137,8 +136,6 @@ RefPtr<CryptoKeyOKP> CryptoKeyOKP::importJwk(CryptoAlgorithmIdentifier identifie return nullptr; if (keyData.crv != "Ed25519"_s) return nullptr; - if (!keyData.alg.isEmpty() && keyData.alg != "EdDSA"_s) - return nullptr; if (usages && !keyData.use.isEmpty() && keyData.use != "sig"_s) return nullptr; if (keyData.key_ops && ((keyData.usages & usages) != usages)) @@ -153,12 +150,14 @@ RefPtr<CryptoKeyOKP> CryptoKeyOKP::importJwk(CryptoAlgorithmIdentifier identifie break; } - if (!keyData.d.isNull()) { - // FIXME: Validate keyData.x is paired with keyData.d - auto d = base64URLDecode(keyData.d); - if (!d) - return nullptr; - return create(identifier, namedCurve, CryptoKeyType::Private, WTFMove(*d), extractable, usages); + if(!onlyPublic){ + if (!keyData.d.isNull()) { + // FIXME: Validate keyData.x is paired with keyData.d + auto d = base64URLDecode(keyData.d); + if (!d) + return nullptr; + return create(identifier, namedCurve, CryptoKeyType::Private, WTFMove(*d), extractable, usages); + } } if (keyData.x.isNull()) @@ -168,6 +167,14 @@ RefPtr<CryptoKeyOKP> CryptoKeyOKP::importJwk(CryptoAlgorithmIdentifier identifie if (!x) return nullptr; return create(identifier, namedCurve, CryptoKeyType::Public, WTFMove(*x), extractable, usages); +} + +RefPtr<CryptoKeyOKP> CryptoKeyOKP::importPublicJwk(CryptoAlgorithmIdentifier identifier, NamedCurve namedCurve, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages) { + return importJwkInternal(identifier, namedCurve, WTFMove(keyData), extractable, usages, true); +} +RefPtr<CryptoKeyOKP> CryptoKeyOKP::importJwk(CryptoAlgorithmIdentifier identifier, NamedCurve namedCurve, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages) +{ + return importJwkInternal(identifier, namedCurve, WTFMove(keyData), extractable, usages, false); } ExceptionOr<Vector<uint8_t>> CryptoKeyOKP::exportRaw() const diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyOKP.h b/src/bun.js/bindings/webcrypto/CryptoKeyOKP.h index cc1fe2c73..4d521227f 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyOKP.h +++ b/src/bun.js/bindings/webcrypto/CryptoKeyOKP.h @@ -48,6 +48,7 @@ public: WEBCORE_EXPORT static ExceptionOr<CryptoKeyPair> generatePair(CryptoAlgorithmIdentifier, NamedCurve, bool extractable, CryptoKeyUsageBitmap); WEBCORE_EXPORT static RefPtr<CryptoKeyOKP> importRaw(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); + static RefPtr<CryptoKeyOKP> importPublicJwk(CryptoAlgorithmIdentifier, NamedCurve, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap); static RefPtr<CryptoKeyOKP> importJwk(CryptoAlgorithmIdentifier, NamedCurve, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap); static RefPtr<CryptoKeyOKP> importSpki(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); static RefPtr<CryptoKeyOKP> importPkcs8(CryptoAlgorithmIdentifier, NamedCurve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap); @@ -88,6 +89,7 @@ private: Vector<uint8_t> platformExportRaw() const; Vector<uint8_t> platformExportSpki() const; Vector<uint8_t> platformExportPkcs8() const; + static RefPtr<CryptoKeyOKP> importJwkInternal(CryptoAlgorithmIdentifier identifier, NamedCurve namedCurve, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages, bool onlyPublic); NamedCurve m_curve; KeyMaterial m_data; diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp index ea3a4d498..82e352d0a 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoKeyOKPOpenSSL.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "CryptoKeyOKP.h" - +#include "../wtf-bindings.h" #if ENABLE(WEB_CRYPTO) #include "JsonWebKey.h" @@ -296,9 +296,9 @@ String CryptoKeyOKP::generateJwkD() const ASSERT(type() == CryptoKeyType::Private); if (namedCurve() == NamedCurve::Ed25519) { ASSERT(m_exportKey); - return base64URLEncodeToString(*m_exportKey); + return Bun::base64URLEncodeToString(*m_exportKey); } - return base64URLEncodeToString(m_data); + return Bun::base64URLEncodeToString(m_data); } CryptoKeyOKP::KeyMaterial CryptoKeyOKP::ed25519PublicFromPrivate(const KeyMaterial& seed) @@ -333,15 +333,15 @@ CryptoKeyOKP::KeyMaterial CryptoKeyOKP::ed25519PrivateFromSeed(KeyMaterial&& see String CryptoKeyOKP::generateJwkX() const { if (type() == CryptoKeyType::Public) - return base64URLEncodeToString(m_data); + return Bun::base64URLEncodeToString(m_data); ASSERT(type() == CryptoKeyType::Private); if (namedCurve() == NamedCurve::Ed25519) - return base64URLEncodeToString(WTFMove(ed25519PublicFromPrivate(const_cast<KeyMaterial&>(m_data)))); + return Bun::base64URLEncodeToString(WTFMove(ed25519PublicFromPrivate(const_cast<KeyMaterial&>(m_data)))); ASSERT(namedCurve() == NamedCurve::X25519); - return base64URLEncodeToString(WTFMove(x25519PublicFromPrivate(const_cast<KeyMaterial&>(m_data)))); + return Bun::base64URLEncodeToString(WTFMove(x25519PublicFromPrivate(const_cast<KeyMaterial&>(m_data)))); } CryptoKeyOKP::KeyMaterial CryptoKeyOKP::platformExportRaw() const diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyRSA.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyRSA.cpp index 273218721..859767107 100644 --- a/src/bun.js/bindings/webcrypto/CryptoKeyRSA.cpp +++ b/src/bun.js/bindings/webcrypto/CryptoKeyRSA.cpp @@ -28,6 +28,7 @@ #include "CryptoKeyRSAComponents.h" #include "JsonWebKey.h" +#include "../wtf-bindings.h" #include <wtf/text/Base64.h> #if ENABLE(WEB_CRYPTO) @@ -143,30 +144,30 @@ JsonWebKey CryptoKeyRSA::exportJwk() const return result; // public key - result.n = base64URLEncodeToString(rsaComponents->modulus()); - result.e = base64URLEncodeToString(rsaComponents->exponent()); + result.n = Bun::base64URLEncodeToString(rsaComponents->modulus()); + result.e = Bun::base64URLEncodeToString(rsaComponents->exponent()); if (rsaComponents->type() == CryptoKeyRSAComponents::Type::Public) return result; // private key - result.d = base64URLEncodeToString(rsaComponents->privateExponent()); + result.d = Bun::base64URLEncodeToString(rsaComponents->privateExponent()); if (!rsaComponents->hasAdditionalPrivateKeyParameters()) return result; - result.p = base64URLEncodeToString(rsaComponents->firstPrimeInfo().primeFactor); - result.q = base64URLEncodeToString(rsaComponents->secondPrimeInfo().primeFactor); - result.dp = base64URLEncodeToString(rsaComponents->firstPrimeInfo().factorCRTExponent); - result.dq = base64URLEncodeToString(rsaComponents->secondPrimeInfo().factorCRTExponent); - result.qi = base64URLEncodeToString(rsaComponents->secondPrimeInfo().factorCRTCoefficient); + result.p = Bun::base64URLEncodeToString(rsaComponents->firstPrimeInfo().primeFactor); + result.q = Bun::base64URLEncodeToString(rsaComponents->secondPrimeInfo().primeFactor); + result.dp = Bun::base64URLEncodeToString(rsaComponents->firstPrimeInfo().factorCRTExponent); + result.dq = Bun::base64URLEncodeToString(rsaComponents->secondPrimeInfo().factorCRTExponent); + result.qi = Bun::base64URLEncodeToString(rsaComponents->secondPrimeInfo().factorCRTCoefficient); if (rsaComponents->otherPrimeInfos().isEmpty()) return result; Vector<RsaOtherPrimesInfo> oth; for (const auto& info : rsaComponents->otherPrimeInfos()) { RsaOtherPrimesInfo otherInfo; - otherInfo.r = base64URLEncodeToString(info.primeFactor); - otherInfo.d = base64URLEncodeToString(info.factorCRTExponent); - otherInfo.t = base64URLEncodeToString(info.factorCRTCoefficient); + otherInfo.r = Bun::base64URLEncodeToString(info.primeFactor); + otherInfo.d = Bun::base64URLEncodeToString(info.factorCRTExponent); + otherInfo.t = Bun::base64URLEncodeToString(info.factorCRTCoefficient); oth.append(WTFMove(otherInfo)); } result.oth = WTFMove(oth); diff --git a/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp b/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp index d2ec84afb..5b38d78c9 100644 --- a/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp +++ b/src/bun.js/bindings/webcrypto/JSCryptoKey.cpp @@ -196,6 +196,8 @@ void JSCryptoKey::finishCreation(VM& vm) // static_assert(!std::is_base_of<ActiveDOMObject, CryptoKey>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); } + + JSObject* JSCryptoKey::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) { return JSCryptoKeyPrototype::create(vm, &globalObject, JSCryptoKeyPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); diff --git a/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp b/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp index 39ed1ff31..067421303 100644 --- a/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp +++ b/src/bun.js/bindings/webcrypto/JSJsonWebKey.cpp @@ -256,7 +256,7 @@ template<> JsonWebKey convertDictionary<JsonWebKey>(JSGlobalObject& lexicalGloba return result; } -JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const JsonWebKey& dictionary) +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const JsonWebKey& dictionary, bool ignoreExtAndKeyOps) { auto& vm = JSC::getVM(&lexicalGlobalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -293,7 +293,7 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J RETURN_IF_EXCEPTION(throwScope, { }); result->putDirect(vm, JSC::Identifier::fromString(vm, "e"_s), eValue); } - if (!IDLBoolean::isNullValue(dictionary.ext)) { + if (!ignoreExtAndKeyOps && !IDLBoolean::isNullValue(dictionary.ext)) { auto extValue = toJS<IDLBoolean>(lexicalGlobalObject, throwScope, IDLBoolean::extractValueFromNullable(dictionary.ext)); RETURN_IF_EXCEPTION(throwScope, { }); result->putDirect(vm, JSC::Identifier::fromString(vm, "ext"_s), extValue); @@ -303,7 +303,7 @@ JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject& lexicalGlobalObject, J RETURN_IF_EXCEPTION(throwScope, { }); result->putDirect(vm, JSC::Identifier::fromString(vm, "k"_s), kValue); } - if (!IDLSequence<IDLEnumeration<CryptoKeyUsage>>::isNullValue(dictionary.key_ops)) { + if (!ignoreExtAndKeyOps && !IDLSequence<IDLEnumeration<CryptoKeyUsage>>::isNullValue(dictionary.key_ops)) { auto key_opsValue = toJS<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(lexicalGlobalObject, globalObject, throwScope, IDLSequence<IDLEnumeration<CryptoKeyUsage>>::extractValueFromNullable(dictionary.key_ops)); RETURN_IF_EXCEPTION(throwScope, { }); result->putDirect(vm, JSC::Identifier::fromString(vm, "key_ops"_s), key_opsValue); diff --git a/src/bun.js/bindings/webcrypto/JSJsonWebKey.h b/src/bun.js/bindings/webcrypto/JSJsonWebKey.h index 07e7960be..c1b287c4d 100644 --- a/src/bun.js/bindings/webcrypto/JSJsonWebKey.h +++ b/src/bun.js/bindings/webcrypto/JSJsonWebKey.h @@ -29,7 +29,7 @@ namespace WebCore { template<> JsonWebKey convertDictionary<JsonWebKey>(JSC::JSGlobalObject&, JSC::JSValue); -JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const JsonWebKey&); +JSC::JSObject* convertDictionaryToJS(JSC::JSGlobalObject&, JSDOMGlobalObject&, const JsonWebKey&, bool ignoreExtAndKeyOps = false); } // namespace WebCore diff --git a/src/bun.js/bindings/wtf-bindings.cpp b/src/bun.js/bindings/wtf-bindings.cpp index d05fb255b..2ec3d7ee8 100644 --- a/src/bun.js/bindings/wtf-bindings.cpp +++ b/src/bun.js/bindings/wtf-bindings.cpp @@ -237,4 +237,24 @@ extern "C" size_t WTF__base64URLEncode(const unsigned char* __restrict inputData destinationDataBuffer[didx++] = '='; return destinationDataBufferSize; -}
\ No newline at end of file +} + +namespace Bun { +String base64URLEncodeToString(Vector<uint8_t> data) +{ + auto size = data.size(); + size_t encodedLength = ((size * 4) + 2) / 3; + if (!encodedLength) + return String(); + + LChar* ptr; + auto result = String::createUninitialized(encodedLength, ptr); + if (UNLIKELY(!ptr)) { + RELEASE_ASSERT_NOT_REACHED(); + return String(); + } + encodedLength = WTF__base64URLEncode(data.data(), data.size(), ptr, encodedLength); + RELEASE_ASSERT(result.length() == encodedLength); + return result; +} +} diff --git a/src/bun.js/bindings/wtf-bindings.h b/src/bun.js/bindings/wtf-bindings.h index 1721b0e1c..3df543934 100644 --- a/src/bun.js/bindings/wtf-bindings.h +++ b/src/bun.js/bindings/wtf-bindings.h @@ -4,3 +4,7 @@ #include "wtf/text/ASCIIFastPath.h" extern "C" void WTF__copyLCharsFromUCharSource(LChar* destination, const UChar* source, size_t length); + +namespace Bun { +String base64URLEncodeToString(Vector<uint8_t> data); +}
\ No newline at end of file |