diff --git a/src/bun.js/bindings/BunClientData.h b/src/bun.js/bindings/BunClientData.h index e0f8fb3034..5b28bb5801 100644 --- a/src/bun.js/bindings/BunClientData.h +++ b/src/bun.js/bindings/BunClientData.h @@ -190,6 +190,11 @@ static inline BunBuiltinNames& builtinNames(JSC::VM& vm) } // namespace WebCore +inline void* bunVM(JSC::VM& vm) +{ + return WebCore::clientData(vm)->bunVM; +} + namespace WebCore { using JSVMClientData = WebCore::JSVMClientData; using JSHeapData = WebCore::JSHeapData; diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 30d3f4ba71..c2172c7716 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -474,14 +474,13 @@ JSC_DEFINE_HOST_FUNCTION(functionBunDeepMatch, (JSGlobalObject * globalObject, J JSC_DEFINE_HOST_FUNCTION(functionBunNanoseconds, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto* global = reinterpret_cast(globalObject); - uint64_t time = Bun__readOriginTimer(global->bunVM()); + uint64_t time = Bun__readOriginTimer(bunVM(globalObject)); return JSValue::encode(jsNumber(time)); } JSC_DEFINE_HOST_FUNCTION(functionPathToFileURL, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - auto& globalObject = *reinterpret_cast(lexicalGlobalObject); + auto& globalObject = *defaultGlobalObject(lexicalGlobalObject); auto& vm = globalObject.vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); auto pathValue = callFrame->argument(0); diff --git a/src/bun.js/bindings/BunPlugin.cpp b/src/bun.js/bindings/BunPlugin.cpp index ad0628687d..8570bce362 100644 --- a/src/bun.js/bindings/BunPlugin.cpp +++ b/src/bun.js/bindings/BunPlugin.cpp @@ -29,8 +29,6 @@ #include "CommonJSModuleRecord.h" #include "isBuiltinModule.h" -extern "C" Zig::GlobalObject* Bun__getDefaultGlobalObject(); - namespace Zig { extern "C" void Bun__onDidAppendPlugin(void* bunVM, JSGlobalObject* globalObject); @@ -136,10 +134,7 @@ static EncodedJSValue jsFunctionAppendVirtualModulePluginBody(JSC::JSGlobalObjec return JSValue::encode(jsUndefined()); } - Zig::GlobalObject* global = JSC::jsDynamicCast(globalObject); - if (!global) { - global = Bun__getDefaultGlobalObject(); - } + Zig::GlobalObject* global = defaultGlobalObject(globalObject); if (global->onLoadPlugins.virtualModules == nullptr) { global->onLoadPlugins.virtualModules = new BunPlugin::VirtualModuleMap; @@ -207,10 +202,7 @@ static JSC::EncodedJSValue jsFunctionAppendOnResolvePluginBody(JSC::JSGlobalObje static JSC::EncodedJSValue jsFunctionAppendOnResolvePluginGlobal(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target) { - Zig::GlobalObject* global = Zig::jsDynamicCast(globalObject); - if (!global) { - global = Bun__getDefaultGlobalObject(); - } + Zig::GlobalObject* global = defaultGlobalObject(globalObject); auto& plugins = global->onResolvePlugins; auto callback = Bun__onDidAppendPlugin; @@ -219,10 +211,7 @@ static JSC::EncodedJSValue jsFunctionAppendOnResolvePluginGlobal(JSC::JSGlobalOb static JSC::EncodedJSValue jsFunctionAppendOnLoadPluginGlobal(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callframe, BunPluginTarget target) { - Zig::GlobalObject* global = Zig::jsDynamicCast(globalObject); - if (!global) { - global = Bun__getDefaultGlobalObject(); - } + Zig::GlobalObject* global = defaultGlobalObject(globalObject); auto& plugins = global->onLoadPlugins; auto callback = Bun__onDidAppendPlugin; @@ -377,10 +366,7 @@ JSFunction* BunPlugin::Group::find(JSC::JSGlobalObject* globalObject, String& pa void BunPlugin::OnLoad::addModuleMock(JSC::VM& vm, const String& path, JSC::JSObject* mockObject) { - Zig::GlobalObject* globalObject = jsDynamicCast(mockObject->globalObject()); - if (!globalObject) { - globalObject = Bun__getDefaultGlobalObject(); - } + Zig::GlobalObject* globalObject = defaultGlobalObject(mockObject->globalObject()); if (globalObject->onLoadPlugins.virtualModules == nullptr) { globalObject->onLoadPlugins.virtualModules = new BunPlugin::VirtualModuleMap; @@ -490,7 +476,7 @@ BUN_DECLARE_HOST_FUNCTION(JSMock__jsModuleMock); extern "C" JSC_DEFINE_HOST_FUNCTION(JSMock__jsModuleMock, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callframe)) { JSC::VM& vm = lexicalGlobalObject->vm(); - Zig::GlobalObject* globalObject = jsDynamicCast(lexicalGlobalObject); + Zig::GlobalObject* globalObject = defaultGlobalObject(lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); if (UNLIKELY(!globalObject)) { scope.throwException(lexicalGlobalObject, JSC::createTypeError(lexicalGlobalObject, "Cannot run mock from a different global context"_s)); diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 8fa943778b..8ba8181c68 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -112,9 +112,8 @@ static bool processIsExiting = false; extern "C" uint8_t Bun__getExitCode(void*); extern "C" uint8_t Bun__setExitCode(void*, uint8_t); -extern "C" void* Bun__getVM(); extern "C" bool Bun__closeChildIPC(JSGlobalObject*); -extern "C" Zig::GlobalObject* Bun__getDefaultGlobalObject(); + extern "C" bool Bun__GlobalObject__hasIPC(JSGlobalObject*); extern "C" bool Bun__ensureProcessIPCInitialized(JSGlobalObject*); extern "C" const char* Bun__githubURL; @@ -491,10 +490,9 @@ extern "C" void Process__dispatchOnExit(Zig::GlobalObject* globalObject, uint8_t } JSC_DEFINE_HOST_FUNCTION(Process_functionUptime, - (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) + (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) { - Zig::GlobalObject* globalObject_ = reinterpret_cast(globalObject); - double now = static_cast(Bun__readOriginTimer(globalObject_->bunVM())); + double now = static_cast(Bun__readOriginTimer(bunVM(lexicalGlobalObject))); double result = (now / 1000000.0) / 1000.0; return JSC::JSValue::encode(JSC::jsNumber(result)); } @@ -510,18 +508,15 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionExit, RETURN_IF_EXCEPTION(throwScope, JSC::JSValue::encode(JSC::JSValue {})); exitCode = static_cast(extiCode32); - Bun__setExitCode(Bun__getVM(), exitCode); + Bun__setExitCode(bunVM(globalObject), exitCode); } else if (!arg0.isUndefinedOrNull()) { throwTypeError(globalObject, throwScope, "The \"code\" argument must be an integer"_s); return JSC::JSValue::encode(JSC::JSValue {}); } else { - exitCode = Bun__getExitCode(Bun__getVM()); + exitCode = Bun__getExitCode(bunVM(globalObject)); } - auto* zigGlobal = jsDynamicCast(globalObject); - if (UNLIKELY(!zigGlobal)) { - zigGlobal = Bun__getDefaultGlobalObject(); - } + auto* zigGlobal = defaultGlobalObject(globalObject); auto process = jsCast(zigGlobal->processObject()); process->m_isExitCodeObservable = true; @@ -539,10 +534,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_setUncaughtExceptionCaptureCallback, throwTypeError(globalObject, throwScope, "The \"callback\" argument must be callable or null"_s); return JSC::JSValue::encode(JSC::JSValue {}); } - auto* zigGlobal = jsDynamicCast(globalObject); - if (UNLIKELY(!zigGlobal)) { - zigGlobal = Bun__getDefaultGlobalObject(); - } + auto* zigGlobal = defaultGlobalObject(globalObject); jsCast(zigGlobal->processObject())->setUncaughtExceptionCaptureCallback(arg0); return JSC::JSValue::encode(jsUndefined()); } @@ -550,10 +542,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_setUncaughtExceptionCaptureCallback, JSC_DEFINE_HOST_FUNCTION(Process_hasUncaughtExceptionCaptureCallback, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { - auto* zigGlobal = jsDynamicCast(globalObject); - if (UNLIKELY(!zigGlobal)) { - zigGlobal = Bun__getDefaultGlobalObject(); - } + auto* zigGlobal = defaultGlobalObject(globalObject); JSValue cb = jsCast(zigGlobal->processObject())->getUncaughtExceptionCaptureCallback(); if (cb.isEmpty() || !cb.isCell()) { return JSValue::encode(jsBoolean(false)); @@ -1883,14 +1872,12 @@ static JSValue constructStdioWriteStream(JSC::JSGlobalObject* globalObject, int static JSValue constructStdout(VM& vm, JSObject* processObject) { - auto* globalObject = Bun__getDefaultGlobalObject(); - return constructStdioWriteStream(globalObject, 1); + return constructStdioWriteStream(processObject->globalObject(), 1); } static JSValue constructStderr(VM& vm, JSObject* processObject) { - auto* globalObject = Bun__getDefaultGlobalObject(); - return constructStdioWriteStream(globalObject, 2); + return constructStdioWriteStream(processObject->globalObject(), 2); } #if OS(WINDOWS) @@ -1899,7 +1886,7 @@ static JSValue constructStderr(VM& vm, JSObject* processObject) static JSValue constructStdin(VM& vm, JSObject* processObject) { - auto* globalObject = Bun__getDefaultGlobalObject(); + auto* globalObject = processObject->globalObject(); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSFunction* getStdioWriteStream = JSC::JSFunction::create(vm, globalObject, processObjectInternalsGetStdinStreamCodeGenerator(vm), globalObject); JSC::MarkedArgumentBuffer args; @@ -2236,13 +2223,10 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionReallyExit, (JSGlobalObject * globalObj throwTypeError(globalObject, throwScope, "The \"code\" argument must be an integer"_s); return JSC::JSValue::encode(JSC::JSValue {}); } else { - exitCode = Bun__getExitCode(Bun__getVM()); + exitCode = Bun__getExitCode(bunVM(globalObject)); } - auto* zigGlobal = jsDynamicCast(globalObject); - if (UNLIKELY(!zigGlobal)) { - zigGlobal = Bun__getDefaultGlobalObject(); - } + auto* zigGlobal = defaultGlobalObject(globalObject); Bun__Process__exit(zigGlobal, exitCode); return JSC::JSValue::encode(jsUndefined()); } @@ -2326,11 +2310,7 @@ static Process* getProcessObject(JSC::JSGlobalObject* lexicalGlobalObject, JSVal // Handle "var memoryUsage = process.memoryUsage; memoryUsage()" if (UNLIKELY(!process)) { // Handle calling this function from inside a node:vm - Zig::GlobalObject* zigGlobalObject = jsDynamicCast(lexicalGlobalObject); - - if (UNLIKELY(!zigGlobalObject)) { - zigGlobalObject = Bun__getDefaultGlobalObject(); - } + Zig::GlobalObject* zigGlobalObject = defaultGlobalObject(lexicalGlobalObject); return jsCast(zigGlobalObject->processObject()); } @@ -2583,10 +2563,7 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionMemoryUsageRSS, JSC_DEFINE_HOST_FUNCTION(Process_functionOpenStdin, (JSGlobalObject * globalObject, CallFrame* callFrame)) { auto& vm = globalObject->vm(); - Zig::GlobalObject* global = jsDynamicCast(globalObject); - if (UNLIKELY(!global)) { - global = Bun__getDefaultGlobalObject(); - } + Zig::GlobalObject* global = defaultGlobalObject(globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); if (JSValue stdinValue = global->processObject()->getIfPropertyExists(globalObject, Identifier::fromString(vm, "stdin"_s))) { diff --git a/src/bun.js/bindings/ErrorCode.cpp b/src/bun.js/bindings/ErrorCode.cpp index d1481cf1cf..2191c4bd63 100644 --- a/src/bun.js/bindings/ErrorCode.cpp +++ b/src/bun.js/bindings/ErrorCode.cpp @@ -1,6 +1,7 @@ #include "root.h" +#include "ZigGlobalObject.h" #include "DOMException.h" #include "JavaScriptCore/Error.h" #include "JavaScriptCore/ErrorType.h" @@ -27,8 +28,6 @@ #include "ErrorCode.h" -extern "C" Zig::GlobalObject* Bun__getDefaultGlobalObject(); - static JSC::JSObject* createErrorPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::ErrorType type, WTF::ASCIILiteral name, WTF::ASCIILiteral code, bool isDOMExceptionPrototype = false) { JSC::JSObject* prototype; @@ -36,11 +35,7 @@ static JSC::JSObject* createErrorPrototype(JSC::VM& vm, JSC::JSGlobalObject* glo // Inherit from DOMException // But preserve the error.stack property. if (isDOMExceptionPrototype) { - auto* domGlobalObject = JSC::jsDynamicCast(globalObject); - if (UNLIKELY(!domGlobalObject)) { - domGlobalObject = Bun__getDefaultGlobalObject(); - } - // TODO: node:vm? + auto* domGlobalObject = defaultGlobalObject(globalObject); prototype = JSC::constructEmptyObject(globalObject, WebCore::JSDOMException::prototype(vm, *domGlobalObject)); } else { switch (type) { diff --git a/src/bun.js/bindings/JSDOMWrapperCache.h b/src/bun.js/bindings/JSDOMWrapperCache.h index e06f2607d8..7fa9a8d3e7 100644 --- a/src/bun.js/bindings/JSDOMWrapperCache.h +++ b/src/bun.js/bindings/JSDOMWrapperCache.h @@ -221,7 +221,7 @@ template inline void setSubclassStructureIfNeeded(JSC::JSGlob auto* functionGlobalObject = JSC::getFunctionRealm(lexicalGlobalObject, newTarget); RETURN_IF_EXCEPTION(scope, void()); - auto* newTargetGlobalObject = JSC::jsCast(functionGlobalObject); + auto* newTargetGlobalObject = defaultGlobalObject(functionGlobalObject); auto* baseStructure = getDOMStructure(vm, *newTargetGlobalObject); auto* subclassStructure = JSC::InternalFunction::createSubclassStructure(lexicalGlobalObject, newTarget, baseStructure); RETURN_IF_EXCEPTION(scope, void()); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 78cf870c59..99f91b9156 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -248,7 +248,7 @@ extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(c } extern "C" void* Bun__getVM(); -extern "C" Zig::GlobalObject* Bun__getDefaultGlobalObject(); + extern "C" void Bun__setDefaultGlobalObject(Zig::GlobalObject* globalObject); // Error.captureStackTrace may cause computeErrorInfo to be called twice @@ -592,7 +592,7 @@ static String computeErrorInfoWithoutPrepareStackTrace( } if (UNLIKELY(!globalObject)) { - globalObject = Bun__getDefaultGlobalObject(); + globalObject = defaultGlobalObject(); } return Bun::formatStackTrace(vm, globalObject, lexicalGlobalObject, name, message, line, column, sourceURL, stackTrace, errorInstance); @@ -672,7 +672,7 @@ static String computeErrorInfo(JSC::VM& vm, Vector& stackTrace, Ordi // Error.prepareStackTrace - https://v8.dev/docs/stack-trace-api#customizing-stack-traces if (!globalObject) { // node:vm will use a different JSGlobalObject - globalObject = Bun__getDefaultGlobalObject(); + globalObject = defaultGlobalObject(); auto* errorConstructor = lexicalGlobalObject->m_errorStructure.constructor(lexicalGlobalObject); if (JSValue prepareStackTrace = errorConstructor->getIfPropertyExists(lexicalGlobalObject, Identifier::fromString(vm, "prepareStackTrace"_s))) { @@ -708,7 +708,7 @@ static String computeErrorInfoWrapper(JSC::VM& vm, Vector& stackTrac static void checkIfNextTickWasCalledDuringMicrotask(JSC::VM& vm) { - auto* globalObject = Bun__getDefaultGlobalObject(); + auto* globalObject = defaultGlobalObject(); if (auto nextTickQueueValue = globalObject->m_nextTickQueue.get()) { auto* queue = jsCast(nextTickQueueValue); globalObject->resetOnEachMicrotaskTick(); @@ -718,7 +718,7 @@ static void checkIfNextTickWasCalledDuringMicrotask(JSC::VM& vm) static void cleanupAsyncHooksData(JSC::VM& vm) { - auto* globalObject = Bun__getDefaultGlobalObject(); + auto* globalObject = defaultGlobalObject(); globalObject->m_asyncContextData.get()->putInternalField(vm, 0, jsUndefined()); globalObject->asyncHooksNeedsCleanup = false; if (!globalObject->m_nextTickQueue) { @@ -797,7 +797,7 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(void* console_client, vm.setOnComputeErrorInfo(computeErrorInfoWrapper); vm.setOnEachMicrotaskTick([](JSC::VM& vm) -> void { - auto* globalObject = Bun__getDefaultGlobalObject(); + auto* globalObject = defaultGlobalObject(); if (auto nextTickQueue = globalObject->m_nextTickQueue.get()) { globalObject->resetOnEachMicrotaskTick(); Bun::JSNextTickQueue* queue = jsCast(nextTickQueue); @@ -2520,12 +2520,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionDefaultErrorPrepareStackTrace, (JSGlobalObjec { auto& vm = lexicalGlobalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - Zig::GlobalObject* globalObject = jsDynamicCast(lexicalGlobalObject); - - if (!globalObject) { - // node:vm will use a different JSGlobalObject - globalObject = Bun__getDefaultGlobalObject(); - } + auto* globalObject = defaultGlobalObject(lexicalGlobalObject); auto errorObject = jsDynamicCast(callFrame->argument(0)); auto callSites = jsDynamicCast(callFrame->argument(1)); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 96eaddc954..7b67d27f5c 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -623,4 +623,40 @@ using JSDOMGlobalObject = Zig::GlobalObject; } #endif +// Do not use this directly. +namespace ___private___ { +extern "C" Zig::GlobalObject* Bun__getDefaultGlobalObject(); +inline Zig::GlobalObject* getDefaultGlobalObject() +{ + return Bun__getDefaultGlobalObject(); +} +} + +inline Zig::GlobalObject* defaultGlobalObject(JSC::JSGlobalObject* lexicalGlobalObject) +{ + auto* globalObject = jsDynamicCast(lexicalGlobalObject); + if (!globalObject) { + return ___private___::getDefaultGlobalObject(); + } + return globalObject; +} +inline Zig::GlobalObject* defaultGlobalObject() +{ + return ___private___::getDefaultGlobalObject(); +} + +inline void* bunVM(JSC::JSGlobalObject* lexicalGlobalObject) +{ + if (auto* globalObject = jsDynamicCast(lexicalGlobalObject)) { + return globalObject->bunVM(); + } + + return WebCore::clientData(lexicalGlobalObject->vm())->bunVM; +} + +inline void* bunVM(Zig::GlobalObject* globalObject) +{ + return globalObject->bunVM(); +} + #endif diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 2d122605e6..10c4335b99 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -115,6 +115,15 @@ JSC::SourceCode generateSourceCode(WTF::String keyString, JSC::VM& vm, JSC::JSOb // #include #define NAPI_OBJECT_EXPECTED napi_object_expected +static inline Zig::GlobalObject* defaultGlobalObject(napi_env env) +{ + if (env) { + return defaultGlobalObject(toJS(env)); + } + + return defaultGlobalObject(); +} + class NapiRefWeakHandleOwner final : public JSC::WeakHandleOwner { public: void finalize(JSC::Handle, void* context) final @@ -186,8 +195,6 @@ void NapiRef::clear() // class Reference // } -extern "C" Zig::GlobalObject* Bun__getDefaultGlobalObject(); - WTF_MAKE_ISO_ALLOCATED_IMPL(NapiRef); static uint32_t getPropertyAttributes(napi_property_attributes attributes_) @@ -816,14 +823,10 @@ node_api_create_external_string_latin1(napi_env env, #if NAPI_VERBOSE printf("[napi] string finalize_callback\n"); #endif - finalize_callback(reinterpret_cast(Bun__getDefaultGlobalObject()), nullptr, hint); + finalize_callback(reinterpret_cast(defaultGlobalObject()), nullptr, hint); } }); - JSGlobalObject* globalObject = toJS(env); - // globalObject is allowed to be null here - if (UNLIKELY(!globalObject)) { - globalObject = Bun__getDefaultGlobalObject(); - } + JSGlobalObject* globalObject = defaultGlobalObject(env); JSString* out = JSC::jsString(globalObject->vm(), WTF::String(impl)); ensureStillAliveHere(out); @@ -858,14 +861,10 @@ node_api_create_external_string_utf16(napi_env env, #endif if (finalize_callback) { - finalize_callback(reinterpret_cast(Bun__getDefaultGlobalObject()), nullptr, hint); + finalize_callback(reinterpret_cast(defaultGlobalObject()), nullptr, hint); } }); - JSGlobalObject* globalObject = toJS(env); - // globalObject is allowed to be null here - if (UNLIKELY(!globalObject)) { - globalObject = Bun__getDefaultGlobalObject(); - } + JSGlobalObject* globalObject = defaultGlobalObject(env); JSString* out = JSC::jsString(globalObject->vm(), WTF::String(impl)); ensureStillAliveHere(out); @@ -877,7 +876,7 @@ node_api_create_external_string_utf16(napi_env env, extern "C" void napi_module_register(napi_module* mod) { - auto* globalObject = Bun__getDefaultGlobalObject(); + auto* globalObject = defaultGlobalObject(); JSC::VM& vm = globalObject->vm(); auto keyStr = WTF::String::fromUTF8(mod->nm_modname); globalObject->napiModuleRegisterCallCount++; @@ -1239,7 +1238,6 @@ static JSValue createErrorForNapi(napi_env env, napi_value code, napi_value msg, } } - auto* error = constructor(globalObject, message); if (codeValue && error) { diff --git a/src/bun.js/bindings/v8/V8Isolate.cpp b/src/bun.js/bindings/v8/V8Isolate.cpp index 80e173814a..7ddca0beee 100644 --- a/src/bun.js/bindings/v8/V8Isolate.cpp +++ b/src/bun.js/bindings/v8/V8Isolate.cpp @@ -1,12 +1,13 @@ #include "V8Isolate.h" #include "V8HandleScope.h" +#include "ZigGlobalObject.h" namespace v8 { // Returns the isolate inside which the current thread is running or nullptr. Isolate* Isolate::TryGetCurrent() { - auto* global = Bun__getDefaultGlobalObject(); + auto* global = defaultGlobalObject(); return global ? reinterpret_cast(&global->V8GlobalInternals()->roots) : nullptr; } @@ -14,7 +15,7 @@ Isolate* Isolate::TryGetCurrent() // Returns the isolate inside which the current thread is running. Isolate* Isolate::GetCurrent() { - auto* global = Bun__getDefaultGlobalObject(); + auto* global = defaultGlobalObject(); return global ? reinterpret_cast(&global->V8GlobalInternals()->roots) : nullptr; } diff --git a/src/bun.js/bindings/v8/node.cpp b/src/bun.js/bindings/v8/node.cpp index 1cf41766de..f8a5d23ae4 100644 --- a/src/bun.js/bindings/v8/node.cpp +++ b/src/bun.js/bindings/v8/node.cpp @@ -35,7 +35,7 @@ void RemoveEnvironmentCleanupHook(v8::Isolate* isolate, void node_module_register(void* opaque_mod) { // TODO unify this with napi_module_register - auto* globalObject = Bun__getDefaultGlobalObject(); + auto* globalObject = defaultGlobalObject(); auto& vm = globalObject->vm(); auto* mod = reinterpret_cast(opaque_mod); // Error: The module '/Users/ben/code/bun/test/v8/v8-module/build/Release/v8tests.node' diff --git a/src/bun.js/bindings/v8/v8.h b/src/bun.js/bindings/v8/v8.h index d6c6e584c4..8ffd8970fc 100644 --- a/src/bun.js/bindings/v8/v8.h +++ b/src/bun.js/bindings/v8/v8.h @@ -18,7 +18,5 @@ Bun__panic(utf8.data(), utf8.length()); \ } while (0) -extern "C" Zig::GlobalObject* Bun__getDefaultGlobalObject(); - namespace v8 { } diff --git a/src/bun.js/bindings/webcore/Performance.cpp b/src/bun.js/bindings/webcore/Performance.cpp index 5961997b90..b1866eb7b7 100644 --- a/src/bun.js/bindings/webcore/Performance.cpp +++ b/src/bun.js/bindings/webcore/Performance.cpp @@ -52,6 +52,7 @@ // #include "ResourceResponse.h" #include "ScriptExecutionContext.h" #include +#include "BunClientData.h" namespace WebCore { @@ -78,9 +79,7 @@ void Performance::contextDestroyed() DOMHighResTimeStamp Performance::now() const { - auto* globalObject = scriptExecutionContext()->globalObject(); - auto* bunVM = jsCast(globalObject)->bunVM(); - auto nowNano = Bun__readOriginTimer(bunVM); + auto nowNano = Bun__readOriginTimer(bunVM(scriptExecutionContext()->vm())); return static_cast(nowNano) / 1000000.0; } @@ -172,7 +171,7 @@ Vector> Performance::getEntriesByType(const String& ent // if (m_navigationTiming && entryType == "navigation"_s) // entries.append(m_navigationTiming); - + // if (entryType == "resource"_s) // entries.appendVector(m_resourceTimingBuffer); @@ -453,7 +452,7 @@ void Performance::scheduleTaskIfNeeded() return; m_hasScheduledTimingBufferDeliveryTask = true; - context->postTask([protectedThis = Ref { *this }, this] (ScriptExecutionContext& context) { + context->postTask([protectedThis = Ref { *this }, this](ScriptExecutionContext& context) { m_hasScheduledTimingBufferDeliveryTask = false; for (auto& observer : copyToVector(m_observers)) observer->deliver(); diff --git a/src/bun.js/bindings/webcore/WebCoreTypedArrayController.cpp b/src/bun.js/bindings/webcore/WebCoreTypedArrayController.cpp index 169772d7c7..a5d3a8daaa 100644 --- a/src/bun.js/bindings/webcore/WebCoreTypedArrayController.cpp +++ b/src/bun.js/bindings/webcore/WebCoreTypedArrayController.cpp @@ -35,14 +35,9 @@ #include -extern "C" Zig::GlobalObject* Bun__getDefaultGlobalObject(); static inline WebCore::JSDOMGlobalObject* getDefaultGlobal(JSC::JSGlobalObject* lexicalGlobalObject) { - if (auto* global = jsDynamicCast(lexicalGlobalObject)) { - return global; - } - - return Bun__getDefaultGlobalObject(); + return defaultGlobalObject(lexicalGlobalObject); } namespace WebCore { diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index 72f39f568c..ff499e1c10 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -618,7 +618,7 @@ JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${name}::construct(JSC::JSGlobalObj auto* constructor = globalObject->${className(typeName)}Constructor(); Structure* structure = globalObject->${className(typeName)}Structure(); if (UNLIKELY(constructor != newTarget)) { - auto* functionGlobalObject = reinterpret_cast( + auto* functionGlobalObject = defaultGlobalObject( // ShadowRealm functions belong to a different global object. getFunctionRealm(globalObject, newTarget) ); diff --git a/test/js/node/vm/vm.test.ts b/test/js/node/vm/vm.test.ts index 3b17d6e19c..9372899432 100644 --- a/test/js/node/vm/vm.test.ts +++ b/test/js/node/vm/vm.test.ts @@ -6,7 +6,7 @@ describe("runInContext()", () => { testRunInContext({ fn: runInContext, isIsolated: true }); test("options can be a string", () => { const context = createContext(); - const result = runInContext("new Error().stack;", context, "test-filename.js" ); + const result = runInContext("new Error().stack;", context, "test-filename.js"); expect(result).toContain("test-filename.js"); }); }); @@ -15,7 +15,7 @@ describe("runInNewContext()", () => { testRunInContext({ fn: runInNewContext, isIsolated: true, isNew: true }); test("options can be a string", () => { test("options can be a string", () => { - const result = runInNewContext("new Error().stack;", {}, "test-filename.js" ); + const result = runInNewContext("new Error().stack;", {}, "test-filename.js"); expect(result).toContain("test-filename.js"); }); }); @@ -24,7 +24,7 @@ describe("runInNewContext()", () => { describe("runInThisContext()", () => { testRunInContext({ fn: runInThisContext }); test("options can be a string", () => { - const result = runInThisContext("new Error().stack;", "test-filename.js" ); + const result = runInThisContext("new Error().stack;", "test-filename.js"); expect(result).toContain("test-filename.js"); }); }); @@ -298,3 +298,135 @@ function randomProps(propsNumber = 0) { } return props; } + +// https://github.com/oven-sh/bun/issues/13629 +test("can extend generated globals & WebCore globals", async () => { + const vm = require("vm"); + + for (let j = 0; j < 100; j++) { + const context = vm.createContext({ + URL, + urlProto: URL.prototype, + console, + Response, + }); + + const code = /*js*/ ` +class ExtendedDOMGlobal extends URL { + constructor(url) { + super(url); + } + + get searchParams() { + return super.searchParams; + } +} + +class ExtendedExtendedDOMGlobal extends ExtendedDOMGlobal { + constructor(url) { + super(url); + } + + get wowSuchGetter() { + return "wow such getter"; + } +} + +const response = new Response(); +class ExtendedZigGeneratedClass extends Response { + constructor(body) { + super(body); + } + + get ok() { + return super.ok; + } + + get custom() { + return true; + } +} + +class ExtendedExtendedZigGeneratedClass extends ExtendedZigGeneratedClass { + constructor(body) { + super(body); + } + + get custom() { + return 42; + } +} + +const resp = new ExtendedZigGeneratedClass("empty"); +const resp2 = new ExtendedExtendedZigGeneratedClass("empty"); + +const url = new ExtendedDOMGlobal("https://example.com/path?foo=bar&baz=qux"); +const url2 = new ExtendedExtendedDOMGlobal("https://example.com/path?foo=bar&baz=qux"); +if (url.ok !== true) { + throw new Error("bad"); +} + +if (url2.wowSuchGetter !== "wow such getter") { + throw new Error("bad"); +} + +if (!response.ok) { + throw new Error("bad"); +} + +URL.prototype.ok = false; + +if (url.ok !== false) { + throw new Error("bad"); +} + +url.searchParams.get("foo"); + +if (!resp.custom) { + throw new Error("expected getter"); +} + +if (resp2.custom !== 42) { + throw new Error("expected getter"); +} + +if (!resp2.ok) { + throw new Error("expected ok"); +} + +if (!(resp instanceof ExtendedZigGeneratedClass)) { + throw new Error("expected ExtendedZigGeneratedClass"); +} + +if (!(resp instanceof Response)) { + throw new Error("expected Response"); +} + +if (!(resp2 instanceof ExtendedExtendedZigGeneratedClass)) { + throw new Error("expected ExtendedExtendedZigGeneratedClass"); +} + +if (!(resp2 instanceof ExtendedZigGeneratedClass)) { + throw new Error("expected ExtendedZigGeneratedClass"); +} + +if (!(resp2 instanceof Response)) { + throw new Error("expected Response"); +} + +if (!resp.ok) { + throw new Error("expected ok"); +} + +resp.text().then((a) => { + if (a !== "empty") { + throw new Error("expected empty"); + } +}); + + `; + URL.prototype.ok = true; + await vm.runInContext(code, context); + delete URL.prototype.ok; + } +});