diff options
author | 2023-05-29 21:01:39 -0700 | |
---|---|---|
committer | 2023-05-29 21:01:39 -0700 | |
commit | 052df7d48c4b4c0e82810bf49a136d644883d3b5 (patch) | |
tree | b3eb3ebd5a86dccb42fc72d0c3b87fcddd3e44ed | |
parent | 5990a9528f12be86cf95f4b46a3ecfa14f8ea97a (diff) | |
download | bun-052df7d48c4b4c0e82810bf49a136d644883d3b5.tar.gz bun-052df7d48c4b4c0e82810bf49a136d644883d3b5.tar.zst bun-052df7d48c4b4c0e82810bf49a136d644883d3b5.zip |
Cleanup CommonJS changes (#3112)bun-v0.6.5
* Add more GC in test
* Fix handling of functions and re-assignments in CommonJS
* Increase timeout
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r-- | src/bun.js/bindings/CommonJSModuleRecord.cpp | 263 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/DOMIsoSubspaces.h | 2 | ||||
-rw-r--r-- | src/bun.js/builtins/BunBuiltinNames.h | 1 | ||||
-rw-r--r-- | src/bun.js/builtins/WebCoreJSBuiltins.cpp | 8 | ||||
-rw-r--r-- | src/bun.js/builtins/ts/ImportMetaObject.ts | 11 | ||||
-rw-r--r-- | src/bundler/bundle_v2.zig | 1 | ||||
-rw-r--r-- | test/cli/run/require-cache-fixture.cjs | 9 | ||||
-rw-r--r-- | test/js/bun/websocket/websocket-server.test.ts | 2 |
9 files changed, 248 insertions, 50 deletions
diff --git a/src/bun.js/bindings/CommonJSModuleRecord.cpp b/src/bun.js/bindings/CommonJSModuleRecord.cpp index c77027983..8b4fdf60a 100644 --- a/src/bun.js/bindings/CommonJSModuleRecord.cpp +++ b/src/bun.js/bindings/CommonJSModuleRecord.cpp @@ -1,3 +1,38 @@ +/** + * How this works + * + * CommonJS modules are transpiled by Bun's transpiler to the following: + * + * (function (exports, require, module) { ... code })(exports, require, module) + * + * 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 ...`) + * + * 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. + * + * After the CommonJS module is executed, we: + * - Store the exports value in the requireMap (again) + * - Loop through the keys of the exports object and re-export as ES Module + * named exports + * + * 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 + * + * 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" #include "headers-handwritten.h" #include "ZigGlobalObject.h" @@ -31,13 +66,136 @@ namespace Bun { using namespace JSC; -JSC::Structure* createCommonJSModuleStructure( +static Structure* internalCreateCommonJSModuleStructure( + Zig::GlobalObject* globalObject); + +class JSCommonJSModule final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesPut; + + mutable JSC::WriteBarrier<JSC::Unknown> m_exportsObject; + mutable JSC::WriteBarrier<JSC::JSString> m_id; + + void finishCreation(JSC::VM& vm, JSC::JSValue exportsObject, JSC::JSString* id) + { + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + m_exportsObject.set(vm, this, exportsObject); + m_id.set(vm, this, id); + + this->putDirectOffset( + vm, + 0, + exportsObject); + + this->putDirectOffset( + vm, + 1, + id); + + this->putDirectOffset( + vm, + 2, + id); + } + + static JSCommonJSModule* create( + JSC::VM& vm, + JSC::Structure* structure, + JSC::JSValue exportsObject, + JSC::JSString* id) + { + JSCommonJSModule* cell = new (NotNull, JSC::allocateCell<JSCommonJSModule>(vm)) JSCommonJSModule(vm, structure); + cell->finishCreation(vm, exportsObject, id); + return cell; + } + + JSValue exportsObject() + { + return m_exportsObject.get(); + } + + JSValue id() + { + return m_id.get(); + } + + DECLARE_VISIT_CHILDREN; + + static bool put( + JSC::JSCell* cell, + JSC::JSGlobalObject* globalObject, + JSC::PropertyName propertyName, + JSC::JSValue value, + JSC::PutPropertySlot& slot) + { + JSCommonJSModule* thisObject = jsCast<JSCommonJSModule*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + auto& vm = globalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto* clientData = WebCore::clientData(vm); + bool result = Base::put(thisObject, globalObject, propertyName, value, slot); + if (result) { + // Whenever you call module.exports = ... in a module, we need to: + // + // - Update the internal exports object + // - Update the require map + // + if (propertyName == clientData->builtinNames().exportsPublicName()) { + thisObject->m_exportsObject.set(vm, thisObject, value); + Zig::GlobalObject* zigGlobalObject = jsCast<Zig::GlobalObject*>(globalObject); + zigGlobalObject->requireMap()->set(globalObject, thisObject->id(), value); + RETURN_IF_EXCEPTION(throwScope, false); + } + } + + RELEASE_AND_RETURN(throwScope, result); + } + + static JSC::Structure* createStructure( + JSC::JSGlobalObject* globalObject) + { + return internalCreateCommonJSModuleStructure(reinterpret_cast<Zig::GlobalObject*>(globalObject)); + } + + 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<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); }); + } + + JSCommonJSModule(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } +}; + +Structure* createCommonJSModuleStructure( + Zig::GlobalObject* globalObject) +{ + return JSCommonJSModule::createStructure(globalObject); +} + +static Structure* internalCreateCommonJSModuleStructure( Zig::GlobalObject* globalObject) { auto& vm = globalObject->vm(); - JSC::Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype( + JSC::Structure* structure = JSC::Structure::create( + vm, globalObject, globalObject->objectPrototype(), + JSC::TypeInfo(JSC::ObjectType, JSCommonJSModule::StructureFlags), + JSCommonJSModule::info(), + JSC::NonArray, 4); JSC::PropertyOffset offset; @@ -74,34 +232,34 @@ JSC::Structure* createCommonJSModuleStructure( return structure; } -JSC::JSObject* createCommonJSModuleObject( +template<typename Visitor> +void JSCommonJSModule::visitChildrenImpl(JSCell* cell, Visitor& visitor) +{ + JSCommonJSModule* thisObject = jsCast<JSCommonJSModule*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + visitor.append(thisObject->m_exportsObject); + visitor.append(thisObject->m_id); +} + +DEFINE_VISIT_CHILDREN(JSCommonJSModule); +const JSC::ClassInfo JSCommonJSModule::s_info = { "Module"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCommonJSModule) }; + +JSCommonJSModule* createCommonJSModuleObject( Zig::GlobalObject* globalObject, - const ResolvedSource& source, const WTF::String& sourceURL, JSC::JSValue exportsObjectValue, JSC::JSValue requireFunctionValue) + const ResolvedSource& source, + const WTF::String& sourceURL, + JSC::JSValue exportsObjectValue, + JSC::JSValue requireFunctionValue) { auto& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - - JSC::JSObject* moduleObject = JSC::constructEmptyObject( - vm, - globalObject->CommonJSModuleObjectStructure()); - - RETURN_IF_EXCEPTION(scope, nullptr); - - moduleObject->putDirectOffset( - vm, - 0, - exportsObjectValue); - auto* jsSourceURL = JSC::jsString(vm, sourceURL); - moduleObject->putDirectOffset( - vm, - 1, - jsSourceURL); - moduleObject->putDirectOffset( + JSCommonJSModule* moduleObject = JSCommonJSModule::create( vm, - 2, - // TODO: filename should be substring + globalObject->CommonJSModuleObjectStructure(), + exportsObjectValue, jsSourceURL); moduleObject->putDirectOffset( @@ -146,21 +304,33 @@ JSC::SourceCode createCommonJSModule( auto& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); auto sourceCodeString = Zig::toString(source.source_code); + auto* requireMapKey = jsString(vm, sourceURL); + + JSC::JSObject* exportsObject = source.commonJSExportsLen < 64 + ? JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), source.commonJSExportsLen) + : JSC::constructEmptyObject(globalObject, globalObject->objectPrototype()); + + if (!globalObject->requireMap()->has(globalObject, requireMapKey)) { + globalObject->requireMap()->set(globalObject, requireMapKey, exportsObject); + } + JSC::SourceCode inputSource( JSC::StringSourceProvider::create(sourceCodeString, JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(sourceURL)), sourceURL, TextPosition())); + JSC::Structure* scopeExtensionObjectStructure = globalObject->commonJSFunctionArgumentsStructure(); JSC::JSObject* scopeExtensionObject = JSC::constructEmptyObject( vm, - globalObject->commonJSFunctionArgumentsStructure()); + scopeExtensionObjectStructure); auto* requireFunction = Zig::ImportMetaObject::createRequireFunction(vm, globalObject, sourceURL); - JSC::JSObject* exportsObject = source.commonJSExportsLen < 64 - ? JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), source.commonJSExportsLen) - : JSC::constructEmptyObject(globalObject, globalObject->objectPrototype()); - auto* moduleObject = createCommonJSModuleObject(globalObject, source, sourceURL, exportsObject, requireFunction); + auto* moduleObject = createCommonJSModuleObject(globalObject, + source, + sourceURL, + exportsObject, + requireFunction); scopeExtensionObject->putDirectOffset( vm, 0, @@ -180,47 +350,54 @@ JSC::SourceCode createCommonJSModule( globalObject, inputSource, DerivedContextType::None, NeedsClassFieldInitializer::No, PrivateBrandRequirement::None, false, false, EvalContextType::None, nullptr, nullptr, ECMAMode::sloppy()); - RETURN_IF_EXCEPTION(throwScope, void()); - - if (UNLIKELY(!executable)) { + if (UNLIKELY(!executable && !throwScope.exception())) { throwSyntaxError(globalObject, throwScope, "Failed to compile CommonJS module."_s); + } + + if (UNLIKELY(throwScope.exception())) { + globalObject->requireMap()->remove(globalObject, requireMapKey); return; } - auto* contextScope = JSC::JSWithScope::create(vm, globalObject, globalObject->globalScope(), scopeExtensionObject); - auto* requireMapKey = jsString(vm, sourceURL); + auto catchScope = DECLARE_CATCH_SCOPE(vm); - globalObject->requireMap()->set(globalObject, requireMapKey, exportsObject); + JSC::JSWithScope* withScope = JSC::JSWithScope::create(vm, globalObject, globalObject->globalScope(), scopeExtensionObject); + + vm.interpreter.executeEval(executable, globalObject, withScope); - auto catchScope = DECLARE_CATCH_SCOPE(vm); - vm.interpreter.executeEval(executable, globalObject, contextScope); if (UNLIKELY(catchScope.exception())) { auto returnedException = catchScope.exception(); catchScope.clearException(); - globalObject->requireMap()->remove(globalObject, requireMapKey); JSC::throwException(globalObject, throwScope, returnedException); } - if (throwScope.exception()) + if (throwScope.exception()) { + globalObject->requireMap()->remove(globalObject, requireMapKey); return; + } - JSValue result = moduleObject->getDirect(0); + JSValue result = moduleObject->exportsObject(); - if (result != exportsObject) - globalObject->requireMap()->set(globalObject, requireMapKey, result); + globalObject->requireMap()->set(globalObject, requireMapKey, result); exportNames.append(vm.propertyNames->defaultKeyword); exportValues.append(result); + + // This exists to tell ImportMetaObject.ts that this is a CommonJS module. exportNames.append(Identifier::fromUid(vm.symbolRegistry().symbolForKey("CommonJS"_s))); exportValues.append(jsNumber(0)); + // This strong reference exists because otherwise it will crash when the finalizer runs. + exportNames.append(Identifier::fromUid(vm.symbolRegistry().symbolForKey("module"_s))); + exportValues.append(moduleObject); + if (result.isObject()) { auto* exports = asObject(result); auto* structure = exports->structure(); uint32_t size = structure->inlineSize() + structure->outOfLineSize(); - exportNames.reserveCapacity(size); - exportValues.ensureCapacity(size); + exportNames.reserveCapacity(size + 3); + exportValues.ensureCapacity(size + 3); if (canPerformFastEnumeration(structure)) { exports->structure()->forEachProperty(vm, [&](const PropertyTableEntry& entry) -> bool { diff --git a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h index 75fff16a0..626b512be 100644 --- a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h +++ b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h @@ -33,6 +33,7 @@ public: std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForRequireResolveFunction; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBundlerPlugin; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNodeVMScript; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCommonJSModuleRecord; #include "ZigGeneratedClasses+DOMClientIsoSubspaces.h" /* --- bun --- */ diff --git a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h index 2b392a49d..c5767702a 100644 --- a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h +++ b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h @@ -33,6 +33,8 @@ public: std::unique_ptr<IsoSubspace> m_subspaceForRequireResolveFunction; std::unique_ptr<IsoSubspace> m_subspaceForBundlerPlugin; std::unique_ptr<IsoSubspace> m_subspaceForNodeVMScript; + std::unique_ptr<IsoSubspace> m_subspaceForCommonJSModuleRecord; + #include "ZigGeneratedClasses+DOMIsoSubspaces.h" /*-- BUN --*/ diff --git a/src/bun.js/builtins/BunBuiltinNames.h b/src/bun.js/builtins/BunBuiltinNames.h index 735141faa..640d122ca 100644 --- a/src/bun.js/builtins/BunBuiltinNames.h +++ b/src/bun.js/builtins/BunBuiltinNames.h @@ -84,6 +84,7 @@ using namespace JSC; macro(errno) \ macro(errorSteps) \ macro(execArgv) \ + macro(exports) \ macro(extname) \ macro(failureKind) \ macro(fatal) \ diff --git a/src/bun.js/builtins/WebCoreJSBuiltins.cpp b/src/bun.js/builtins/WebCoreJSBuiltins.cpp index d572ad023..b6a0863a7 100644 --- a/src/bun.js/builtins/WebCoreJSBuiltins.cpp +++ b/src/bun.js/builtins/WebCoreJSBuiltins.cpp @@ -2196,9 +2196,9 @@ const char* const s_importMetaObjectLoadCJS2ESMCode = "(function (_){\"use stric const JSC::ConstructAbility s_importMetaObjectRequireESMCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_importMetaObjectRequireESMCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_importMetaObjectRequireESMCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_importMetaObjectRequireESMCodeLength = 406; +const int s_importMetaObjectRequireESMCodeLength = 419; static const JSC::Intrinsic s_importMetaObjectRequireESMCodeIntrinsic = JSC::NoIntrinsic; -const char* const s_importMetaObjectRequireESMCode = "(function (a){\"use strict\";var _=@Loader.registry.@get(a);if(!_||!_.evaluated)_=@loadCJS2ESM(a);if(!_||!_.evaluated||!_.module)@throwTypeError(`require() failed to evaluate module \"${a}\". This is an internal consistentency error.`);var i=@Loader.getModuleNamespaceObject(_.module),u=i.default,E=u\?.[@commonJSSymbol];if(E===0||i[@commonJSSymbol]===0)return u;else if(E&&@isCallable(u))return u();return i})\n"; +const char* const s_importMetaObjectRequireESMCode = "(function (a){\"use strict\";var i=@Loader.registry.@get(a);if(!i||!i.evaluated)i=@loadCJS2ESM(a);if(!i||!i.evaluated||!i.module)@throwTypeError(`require() failed to evaluate module \"${a}\". This is an internal consistentency error.`);var u=@Loader.getModuleNamespaceObject(i.module);if(u[@commonJSSymbol]===0)return;var E=u.default,_=E\?.[@commonJSSymbol];if(_===0)return E;else if(_&&@isCallable(E))return E();return u})\n"; // internalRequire const JSC::ConstructAbility s_importMetaObjectInternalRequireCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; @@ -2212,9 +2212,9 @@ const char* const s_importMetaObjectInternalRequireCode = "(function (n){\"use s const JSC::ConstructAbility s_importMetaObjectCreateRequireCacheCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; const JSC::ConstructorKind s_importMetaObjectCreateRequireCacheCodeConstructorKind = JSC::ConstructorKind::None; const JSC::ImplementationVisibility s_importMetaObjectCreateRequireCacheCodeImplementationVisibility = JSC::ImplementationVisibility::Public; -const int s_importMetaObjectCreateRequireCacheCodeLength = 888; +const int s_importMetaObjectCreateRequireCacheCodeLength = 891; static const JSC::Intrinsic s_importMetaObjectCreateRequireCacheCodeIntrinsic = JSC::NoIntrinsic; -const char* const s_importMetaObjectCreateRequireCacheCode = "(function (){\"use strict\";class r{id;parent;filename;children=[];paths=[];constructor(_){this.id=_;const c=_.lastIndexOf(\"/\");if(c!==-1&&_.length>c+1)this.filename=_.substring(c+1);else this.filename=_}get loaded(){return!0}require(_){return @internalRequire(@resolveSync(_,this.id))}get exports(){return @requireMap.@get(this.id)\?\?{}}set exports(_){@requireMap.@set(this.id,_)}}var w=new Map;return new Proxy({},{get(_,c){if(@requireMap.@get(c)){var b=w.@get(c);if(!b)b=new r(c),w.@set(c,b);return b}},set(_,c,t){if(!w.@has(c))w.@set(c,new r(c));return @requireMap.@set(c,t\?.exports),!0},has(_,c){return @requireMap.@has(c)},deleteProperty(_,c){return w.@delete(c),@requireMap.@delete(c),@Loader.registry.@delete(c)},ownKeys(_){return[...@requireMap.@keys()]},getPrototypeOf(_){return null},getOwnPropertyDescriptor(_,c){if(@requireMap.@has(c))return{configurable:!0,enumerable:!0}}})})\n"; +const char* const s_importMetaObjectCreateRequireCacheCode = "(function (){\"use strict\";class r{id;parent;filename;children=[];paths=[];constructor(w){this.id=w;const c=w.lastIndexOf(\"/\");if(c!==-1&&w.length>c+1)this.filename=w.substring(c+1);else this.filename=w}get loaded(){return!0}require(w){return @internalRequire(@resolveSync(w,this.id))}get exports(){return @requireMap.@get(this.id)\?\?{}}set exports(w){@requireMap.@set(this.id,w)}}var _=new Map;return new Proxy({},{get(w,c){if(@requireMap.@get(c)){var g=_.@get(c);if(!g)g=new r(c),_.@set(c,g);return g}},set(w,c,b){if(!_.@has(c))_.@set(c,new r(c));return @requireMap.@set(c,b\?.exports),!0},has(w,c){return @requireMap.@has(c)},deleteProperty(w,c){return _.@delete(c),@requireMap.@delete(c),@Loader.registry.@delete(c),!0},ownKeys(w){return[...@requireMap.@keys()]},getPrototypeOf(w){return null},getOwnPropertyDescriptor(w,c){if(@requireMap.@has(c))return{configurable:!0,enumerable:!0}}})})\n"; // require const JSC::ConstructAbility s_importMetaObjectRequireCodeConstructAbility = JSC::ConstructAbility::CannotConstruct; diff --git a/src/bun.js/builtins/ts/ImportMetaObject.ts b/src/bun.js/builtins/ts/ImportMetaObject.ts index 9255a591f..2df0f0c98 100644 --- a/src/bun.js/builtins/ts/ImportMetaObject.ts +++ b/src/bun.js/builtins/ts/ImportMetaObject.ts @@ -91,9 +91,15 @@ export function requireESM(this: ImportMetaObject, resolved) { throw new TypeError(`require() failed to evaluate module "${resolved}". This is an internal consistentency error.`); } var exports = Loader.getModuleNamespaceObject(entry.module); + if (exports[$commonJSSymbol] === 0) { + // CommonJS module created via `Bun::CommonJSModuleRecord` + // We will refer to the requireMap to get the exports + return; + } + var commonJS = exports.default; var cjs = commonJS?.[$commonJSSymbol]; - if (cjs === 0 || exports[$commonJSSymbol] === 0) { + if (cjs === 0) { return commonJS; } else if (cjs && $isCallable(commonJS)) { return commonJS(); @@ -209,7 +215,8 @@ export function createRequireCache() { deleteProperty(target, key: string) { moduleMap.$delete(key); $requireMap.$delete(key); - return Loader.registry.$delete(key); + Loader.registry.$delete(key); + return true; }, ownKeys(target) { diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index b0012c25c..967bfaa36 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -8572,6 +8572,7 @@ const LinkerContext = struct { .const_values = c.graph.const_values, .minify_whitespace = c.options.minify_whitespace, .minify_syntax = c.options.minify_syntax, + .module_type = c.options.output_format, .allocator = allocator, .to_esm_ref = toESMRef, diff --git a/test/cli/run/require-cache-fixture.cjs b/test/cli/run/require-cache-fixture.cjs index 0186c4b75..012f60589 100644 --- a/test/cli/run/require-cache-fixture.cjs +++ b/test/cli/run/require-cache-fixture.cjs @@ -1,3 +1,6 @@ +// So it could be run in Node.js +const Bun = (globalThis.Bun ??= { gc() {} }); + const foo = require("./require-cache-fixture-b.cjs"); exports.foo = foo; @@ -6,10 +9,16 @@ if (require.cache[require.resolve("./require-cache-fixture-b.cjs")].exports !== throw new Error("exports.foo !== require.cache[require.resolve('./require-cache-fixture-b')]"); } +Bun.gc(true); + delete require.cache[require.resolve("./require-cache-fixture-b.cjs")]; +Bun.gc(true); + exports.bar = require("./require-cache-fixture-b.cjs"); +Bun.gc(true); + if (require.cache[require.resolve("./require-cache-fixture-b.cjs")].exports !== exports.bar) { throw new Error("exports.bar !== require.cache[require.resolve('./require-cache-fixture-b')]"); } diff --git a/test/js/bun/websocket/websocket-server.test.ts b/test/js/bun/websocket/websocket-server.test.ts index 7259fc8b6..7d43c7e65 100644 --- a/test/js/bun/websocket/websocket-server.test.ts +++ b/test/js/bun/websocket/websocket-server.test.ts @@ -1037,7 +1037,7 @@ describe("websocket server", () => { }); expect(serverCounter).toBe(sendQueue.length); server.stop(true); - }); + }, 10_000); it("can close with reason and code #2631", done => { let timeout: any; let server = Bun.serve({ |