This commit is contained in:
Jarred Sumner
2025-03-28 20:23:49 -07:00
committed by GitHub
parent f0dfa109bb
commit f38d35f7c9
56 changed files with 191 additions and 1011 deletions

View File

@@ -31,7 +31,8 @@
"test/bundler/native-plugin.test.ts", // parser doesn't handle import metadata "test/bundler/native-plugin.test.ts", // parser doesn't handle import metadata
"test/bundler/transpiler/with-statement-works.js", // parser doesn't allow `with` statement "test/bundler/transpiler/with-statement-works.js", // parser doesn't allow `with` statement
"test/js/node/module/extensions-fixture", // these files are not meant to be linted "test/js/node/module/extensions-fixture", // these files are not meant to be linted
"test/cli/run/module-type-fixture" "test/cli/run/module-type-fixture",
"test/bundler/transpiler/with-statement-works.js" // parser doesn't allow `with` statement
], ],
"overrides": [ "overrides": [
{ {

View File

@@ -1,181 +0,0 @@
#include "JSCommonJSExtensions.h"
#include "ZigGlobalObject.h"
namespace Bun {
using namespace JSC;
const JSC::ClassInfo JSCommonJSExtensions::s_info = { "CommonJSExtensions"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSCommonJSExtensions) };
// These functions are implemented as no-ops because it doesn't seem like any
// projects call them directly. They are defined separately so that assigning
// one to the other can be detected and use the corresponding loader.
JSC_DEFINE_HOST_FUNCTION(jsLoaderJS, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
throwTypeError(globalObject, scope, "Calling Module._extensions[\".js\"] directly is not implemented."_s);
return JSValue::encode({});
}
JSC_DEFINE_HOST_FUNCTION(jsLoaderJSON, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
throwTypeError(globalObject, scope, "Calling Module._extensions[\".json\"] directly is not implemented."_s);
return JSValue::encode({});
}
JSC_DEFINE_HOST_FUNCTION(jsLoaderNode, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
throwTypeError(globalObject, scope, "Calling Module._extensions[\".node\"] directly is not implemented."_s);
return JSValue::encode({});
}
JSC_DEFINE_HOST_FUNCTION(jsLoaderTS, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
throwTypeError(globalObject, scope, "Calling Module._extensions[\".ts\"] directly is not implemented."_s);
return JSValue::encode({});
}
void JSCommonJSExtensions::finishCreation(JSC::VM& vm)
{
Base::finishCreation(vm);
ASSERT(inherits(info()));
Zig::GlobalObject* global = defaultGlobalObject(globalObject());
JSC::JSFunction* fnLoadJS = JSC::JSFunction::create(
vm,
global,
2,
""_s,
jsLoaderJS,
JSC::ImplementationVisibility::Public,
JSC::Intrinsic::NoIntrinsic,
JSC::callHostFunctionAsConstructor);
JSC::JSFunction* fnLoadJSON = JSC::JSFunction::create(
vm,
global,
2,
""_s,
jsLoaderJSON,
JSC::ImplementationVisibility::Public,
JSC::Intrinsic::NoIntrinsic,
JSC::callHostFunctionAsConstructor);
JSC::JSFunction* fnLoadNode = JSC::JSFunction::create(
vm,
global,
2,
""_s,
jsLoaderNode,
JSC::ImplementationVisibility::Public,
JSC::Intrinsic::NoIntrinsic,
JSC::callHostFunctionAsConstructor);
JSC::JSFunction* fnLoadTS = JSC::JSFunction::create(
vm,
global,
2,
""_s,
jsLoaderTS,
JSC::ImplementationVisibility::Public,
JSC::Intrinsic::NoIntrinsic,
JSC::callHostFunctionAsConstructor);
this->putDirect(vm, JSC::Identifier::fromString(vm, ".js"_s), fnLoadJS, 0);
this->putDirect(vm, JSC::Identifier::fromString(vm, ".json"_s), fnLoadJSON, 0);
this->putDirect(vm, JSC::Identifier::fromString(vm, ".node"_s), fnLoadNode, 0);
this->putDirect(vm, JSC::Identifier::fromString(vm, ".ts"_s), fnLoadTS, 0);
this->putDirect(vm, JSC::Identifier::fromString(vm, ".cts"_s), fnLoadTS, 0);
this->putDirect(vm, JSC::Identifier::fromString(vm, ".mjs"_s), fnLoadJS, 0);
this->putDirect(vm, JSC::Identifier::fromString(vm, ".mts"_s), fnLoadTS, 0);
}
extern "C" void NodeModuleModule__onRequireExtensionModify(
Zig::GlobalObject* globalObject,
const BunString* key,
uint32_t kind,
JSC::JSValue value);
void onAssign(Zig::GlobalObject* globalObject, JSC::PropertyName propertyName, JSC::JSValue value)
{
if (propertyName.isSymbol()) return;
auto* name = propertyName.publicName();
if (!name->startsWith("."_s)) return;
BunString ext = Bun::toString(name);
uint32_t kind = 0;
if (value.isCallable()) {
JSC::CallData callData = JSC::getCallData(value);
if (callData.type == JSC::CallData::Type::Native) {
auto* untaggedPtr = callData.native.function.untaggedPtr();
if (untaggedPtr == &jsLoaderJS) {
kind = 1;
} else if (untaggedPtr == &jsLoaderJSON) {
kind = 2;
} else if (untaggedPtr == &jsLoaderNode) {
kind = 3;
} else if (untaggedPtr == &jsLoaderTS) {
kind = 4;
}
}
} else {
kind = -1;
}
NodeModuleModule__onRequireExtensionModify(globalObject, &ext, kind, value);
}
bool JSCommonJSExtensions::defineOwnProperty(JSC::JSObject* object, JSC::JSGlobalObject* globalObject, JSC::PropertyName propertyName, const JSC::PropertyDescriptor& descriptor, bool shouldThrow)
{
JSValue value = descriptor.value();
if (value) {
onAssign(defaultGlobalObject(globalObject), propertyName, value);
} else {
onAssign(defaultGlobalObject(globalObject), propertyName, JSC::jsUndefined());
}
return Base::defineOwnProperty(object, globalObject, propertyName, descriptor, shouldThrow);
}
bool JSCommonJSExtensions::put(JSC::JSCell* cell, JSC::JSGlobalObject* globalObject, JSC::PropertyName propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot)
{
onAssign(defaultGlobalObject(globalObject), propertyName, value);
return Base::put(cell, globalObject, propertyName, value, slot);
}
bool JSCommonJSExtensions::deleteProperty(JSC::JSCell* cell, JSC::JSGlobalObject* globalObject, JSC::PropertyName propertyName, JSC::DeletePropertySlot& slot)
{
bool deleted = Base::deleteProperty(cell, globalObject, propertyName, slot);
if (deleted) {
onAssign(defaultGlobalObject(globalObject), propertyName, JSC::jsUndefined());
}
return deleted;
}
extern "C" uint32_t JSCommonJSExtensions__appendFunction(Zig::GlobalObject* globalObject, JSC::JSValue value)
{
JSCommonJSExtensions* extensions = globalObject->lazyRequireExtensionsObject();
extensions->m_registeredFunctions.append(JSC::WriteBarrier<Unknown>());
extensions->m_registeredFunctions.last().set(globalObject->vm(), extensions, value);
return extensions->m_registeredFunctions.size() - 1;
}
extern "C" void JSCommonJSExtensions__setFunction(Zig::GlobalObject* globalObject, uint32_t index, JSC::JSValue value)
{
JSCommonJSExtensions* extensions = globalObject->lazyRequireExtensionsObject();
extensions->m_registeredFunctions[index].set(globalObject->vm(), globalObject, value);
}
extern "C" uint32_t JSCommonJSExtensions__swapRemove(Zig::GlobalObject* globalObject, uint32_t index)
{
JSCommonJSExtensions* extensions = globalObject->lazyRequireExtensionsObject();
ASSERT(extensions->m_registeredFunctions.size() > 0);
if (extensions->m_registeredFunctions.size() == 1) {
extensions->m_registeredFunctions.clear();
return index;
}
ASSERT(index < extensions->m_registeredFunctions.size());
if (index < (extensions->m_registeredFunctions.size() - 1)) {
JSValue last = extensions->m_registeredFunctions.takeLast().get();
extensions->m_registeredFunctions[index].set(globalObject->vm(), globalObject, last);
return extensions->m_registeredFunctions.size();
} else {
extensions->m_registeredFunctions.removeLast();
return index;
}
}
} // namespace Bun

View File

@@ -1,58 +0,0 @@
#pragma once
#include "root.h"
#include "headers-handwritten.h"
#include "BunClientData.h"
namespace Bun {
// require.extensions & Module._extensions
class JSCommonJSExtensions : public JSC::JSDestructibleObject {
public:
using Base = JSC::JSDestructibleObject;
static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::OverridesPut;
~JSCommonJSExtensions();
WTF::Vector<JSC::WriteBarrier<JSC::Unknown>> m_registeredFunctions;
static JSCommonJSExtensions* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
{
JSCommonJSExtensions* ptr = new (NotNull, JSC::allocateCell<JSCommonJSExtensions>(vm)) JSCommonJSExtensions(vm, structure);
ptr->finishCreation(vm);
return ptr;
}
DECLARE_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<JSCommonJSExtensions, WebCore::UseCustomHeapCellType::No>(
vm,
[](auto& spaces) { return spaces.m_clientSubspaceForJSCommonJSExtensions.get(); },
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSCommonJSExtensions = std::forward<decltype(space)>(space); },
[](auto& spaces) { return spaces.m_subspaceForJSCommonJSExtensions.get(); },
[](auto& spaces, auto&& space) { spaces.m_subspaceForJSCommonJSExtensions = std::forward<decltype(space)>(space); });
}
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());
}
protected:
static bool defineOwnProperty(JSC::JSObject*, JSC::JSGlobalObject*, JSC::PropertyName, const JSC::PropertyDescriptor&, bool shouldThrow);
static bool put(JSC::JSCell*, JSC::JSGlobalObject*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);
static bool deleteProperty(JSC::JSCell*, JSC::JSGlobalObject*, JSC::PropertyName, JSC::DeletePropertySlot&);
private:
JSCommonJSExtensions(JSC::VM& vm, JSC::Structure* structure)
: Base(vm, structure)
{
}
void finishCreation(JSC::VM&);
};
} // namespace Bun

View File

@@ -76,7 +76,6 @@
#include "wtf/NakedPtr.h" #include "wtf/NakedPtr.h"
#include "wtf/URL.h" #include "wtf/URL.h"
#include "wtf/text/StringImpl.h" #include "wtf/text/StringImpl.h"
#include "JSCommonJSExtensions.h"
extern "C" bool Bun__isBunMain(JSC::JSGlobalObject* global, const BunString*); extern "C" bool Bun__isBunMain(JSC::JSGlobalObject* global, const BunString*);
@@ -299,31 +298,12 @@ JSC_DEFINE_CUSTOM_SETTER(jsRequireCacheSetter,
return true; return true;
} }
JSC_DEFINE_CUSTOM_GETTER(jsRequireExtensionsGetter, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
{
Zig::GlobalObject* thisObject = jsCast<Zig::GlobalObject*>(globalObject);
return JSValue::encode(thisObject->lazyRequireExtensionsObject());
}
JSC_DEFINE_CUSTOM_SETTER(jsRequireExtensionsSetter,
(JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue,
JSC::EncodedJSValue value, JSC::PropertyName propertyName))
{
JSObject* thisObject = jsDynamicCast<JSObject*>(JSValue::decode(thisValue));
if (!thisObject)
return false;
thisObject->putDirect(globalObject->vm(), propertyName, JSValue::decode(value), 0);
return true;
}
static const HashTableValue RequireResolveFunctionPrototypeValues[] = { static const HashTableValue RequireResolveFunctionPrototypeValues[] = {
{ "paths"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, requireResolvePathsFunction, 1 } }, { "paths"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, requireResolvePathsFunction, 1 } },
}; };
static const HashTableValue RequireFunctionPrototypeValues[] = { static const HashTableValue RequireFunctionPrototypeValues[] = {
{ "cache"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsRequireCacheGetter, jsRequireCacheSetter } }, { "cache"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsRequireCacheGetter, jsRequireCacheSetter } },
{ "extensions"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor), NoIntrinsic, { HashTableValue::GetterSetterType, jsRequireExtensionsGetter, jsRequireExtensionsSetter } },
}; };
Structure* RequireFunctionPrototype::createStructure( Structure* RequireFunctionPrototype::createStructure(
@@ -386,6 +366,13 @@ void RequireFunctionPrototype::finishCreation(JSC::VM& vm)
JSC::Identifier::fromString(vm, "main"_s), JSC::Identifier::fromString(vm, "main"_s),
JSC::GetterSetter::create(vm, globalObject, requireDotMainFunction, requireDotMainFunction), JSC::GetterSetter::create(vm, globalObject, requireDotMainFunction, requireDotMainFunction),
PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | 0); PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | 0);
auto extensions = constructEmptyObject(globalObject);
extensions->putDirect(vm, JSC::Identifier::fromString(vm, ".js"_s), jsBoolean(true), 0);
extensions->putDirect(vm, JSC::Identifier::fromString(vm, ".json"_s), jsBoolean(true), 0);
extensions->putDirect(vm, JSC::Identifier::fromString(vm, ".node"_s), jsBoolean(true), 0);
this->putDirect(vm, JSC::Identifier::fromString(vm, "extensions"_s), extensions, 0);
} }
JSC_DEFINE_CUSTOM_GETTER(getterFilename, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) JSC_DEFINE_CUSTOM_GETTER(getterFilename, (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName))
@@ -1164,6 +1151,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlo
// This is always a new JSCommonJSModule object; cast cannot fail. // This is always a new JSCommonJSModule object; cast cannot fail.
JSCommonJSModule* child = jsCast<JSCommonJSModule*>(callframe->uncheckedArgument(1)); JSCommonJSModule* child = jsCast<JSCommonJSModule*>(callframe->uncheckedArgument(1));
BunString specifierStr = Bun::toString(specifier);
BunString referrerStr = Bun::toString(referrer); BunString referrerStr = Bun::toString(referrer);
BunString typeAttributeStr = { BunStringTag::Dead }; BunString typeAttributeStr = { BunStringTag::Dead };
String typeAttribute = String(); String typeAttribute = String();
@@ -1194,7 +1182,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionRequireCommonJS, (JSGlobalObject * lexicalGlo
globalObject, globalObject,
child, child,
specifierValue, specifierValue,
specifier, &specifierStr,
&referrerStr, &referrerStr,
LIKELY(typeAttribute.isEmpty()) LIKELY(typeAttribute.isEmpty())
? nullptr ? nullptr

View File

@@ -37,8 +37,6 @@
#include "JSCommonJSModule.h" #include "JSCommonJSModule.h"
#include "../modules/_NativeModule.h" #include "../modules/_NativeModule.h"
#include "JSCommonJSExtensions.h"
namespace Bun { namespace Bun {
using namespace JSC; using namespace JSC;
using namespace Zig; using namespace Zig;
@@ -569,39 +567,11 @@ JSValue resolveAndFetchBuiltinModule(
return {}; return {};
} }
void evaluateCommonJSCustomExtension(
Zig::GlobalObject* globalObject,
JSCommonJSModule* target,
String filename,
JSValue filenameValue,
uint32_t extensionIndex)
{
auto& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
Bun::JSCommonJSExtensions* extensions = globalObject->lazyRequireExtensionsObject();
JSValue extension = extensions->m_registeredFunctions[extensionIndex].get();
if (!extension || !extension.isCallable()) {
throwTypeError(globalObject, scope, makeString("require.extension is not a function"_s));
return;
}
JSC::CallData callData = JSC::getCallData(extension.asCell());
if (callData.type == JSC::CallData::Type::None) {
throwTypeError(globalObject, scope, makeString("require.extension is not a function"_s));
return;
}
MarkedArgumentBuffer arguments;
arguments.append(target);
arguments.append(filenameValue);
JSC::profiledCall(globalObject, ProfilingReason::API, extension, callData, target, arguments);
RETURN_IF_EXCEPTION(scope, );
}
JSValue fetchCommonJSModule( JSValue fetchCommonJSModule(
Zig::GlobalObject* globalObject, Zig::GlobalObject* globalObject,
JSCommonJSModule* target, JSCommonJSModule* target,
JSValue specifierValue, JSValue specifierValue,
String specifierWtfString, BunString* specifier,
BunString* referrer, BunString* referrer,
BunString* typeAttribute) BunString* typeAttribute)
{ {
@@ -614,15 +584,13 @@ JSValue fetchCommonJSModule(
ErrorableResolvedSource* res = &resValue; ErrorableResolvedSource* res = &resValue;
ResolvedSourceCodeHolder sourceCodeHolder(res); ResolvedSourceCodeHolder sourceCodeHolder(res);
BunString specifier = Bun::toString(specifierWtfString);
bool wasModuleMock = false; bool wasModuleMock = false;
// When "bun test" is enabled, allow users to override builtin modules // When "bun test" is enabled, allow users to override builtin modules
// This is important for being able to trivially mock things like the filesystem. // This is important for being able to trivially mock things like the filesystem.
if (isBunTest) { if (isBunTest) {
if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, &specifier, wasModuleMock)) { if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier, wasModuleMock)) {
JSValue promiseOrCommonJSModule = handleVirtualModuleResult<true>(globalObject, virtualModuleResult, res, &specifier, referrer, wasModuleMock, target); JSValue promiseOrCommonJSModule = handleVirtualModuleResult<true>(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock, target);
RETURN_IF_EXCEPTION(scope, {}); RETURN_IF_EXCEPTION(scope, {});
// If we assigned module.exports to the virtual module, we're done here. // If we assigned module.exports to the virtual module, we're done here.
@@ -638,7 +606,7 @@ JSValue fetchCommonJSModule(
RELEASE_AND_RETURN(scope, JSValue {}); RELEASE_AND_RETURN(scope, JSValue {});
} }
case JSPromise::Status::Pending: { case JSPromise::Status::Pending: {
JSC::throwTypeError(globalObject, scope, makeString("require() async module \""_s, specifierWtfString, "\" is unsupported. use \"await import()\" instead."_s)); JSC::throwTypeError(globalObject, scope, makeString("require() async module \""_s, specifier->toWTFString(BunString::ZeroCopy), "\" is unsupported. use \"await import()\" instead."_s));
RELEASE_AND_RETURN(scope, JSValue {}); RELEASE_AND_RETURN(scope, JSValue {});
} }
case JSPromise::Status::Fulfilled: { case JSPromise::Status::Fulfilled: {
@@ -657,7 +625,7 @@ JSValue fetchCommonJSModule(
} }
} }
if (auto builtin = fetchBuiltinModuleWithoutResolution(globalObject, &specifier, res)) { if (auto builtin = fetchBuiltinModuleWithoutResolution(globalObject, specifier, res)) {
if (!res->success) { if (!res->success) {
RELEASE_AND_RETURN(scope, builtin); RELEASE_AND_RETURN(scope, builtin);
} }
@@ -668,8 +636,8 @@ JSValue fetchCommonJSModule(
// When "bun test" is NOT enabled, disable users from overriding builtin modules // When "bun test" is NOT enabled, disable users from overriding builtin modules
if (!isBunTest) { if (!isBunTest) {
if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, &specifier, wasModuleMock)) { if (JSC::JSValue virtualModuleResult = Bun::runVirtualModule(globalObject, specifier, wasModuleMock)) {
JSValue promiseOrCommonJSModule = handleVirtualModuleResult<true>(globalObject, virtualModuleResult, res, &specifier, referrer, wasModuleMock, target); JSValue promiseOrCommonJSModule = handleVirtualModuleResult<true>(globalObject, virtualModuleResult, res, specifier, referrer, wasModuleMock, target);
RETURN_IF_EXCEPTION(scope, {}); RETURN_IF_EXCEPTION(scope, {});
// If we assigned module.exports to the virtual module, we're done here. // If we assigned module.exports to the virtual module, we're done here.
@@ -685,7 +653,7 @@ JSValue fetchCommonJSModule(
RELEASE_AND_RETURN(scope, JSValue {}); RELEASE_AND_RETURN(scope, JSValue {});
} }
case JSPromise::Status::Pending: { case JSPromise::Status::Pending: {
JSC::throwTypeError(globalObject, scope, makeString("require() async module \""_s, specifierWtfString, "\" is unsupported. use \"await import()\" instead."_s)); JSC::throwTypeError(globalObject, scope, makeString("require() async module \""_s, specifier->toWTFString(BunString::ZeroCopy), "\" is unsupported. use \"await import()\" instead."_s));
RELEASE_AND_RETURN(scope, JSValue {}); RELEASE_AND_RETURN(scope, JSValue {});
} }
case JSPromise::Status::Fulfilled: { case JSPromise::Status::Fulfilled: {
@@ -721,9 +689,9 @@ JSValue fetchCommonJSModule(
RELEASE_AND_RETURN(scope, jsNumber(-1)); RELEASE_AND_RETURN(scope, jsNumber(-1));
} }
Bun__transpileFile(bunVM, globalObject, &specifier, referrer, typeAttribute, res, false, true); Bun__transpileFile(bunVM, globalObject, specifier, referrer, typeAttribute, res, false);
if (res->success && res->result.value.isCommonJSModule) { if (res->success && res->result.value.isCommonJSModule) {
target->evaluate(globalObject, specifierWtfString, res->result.value); target->evaluate(globalObject, specifier->toWTFString(BunString::ZeroCopy), res->result.value);
RETURN_IF_EXCEPTION(scope, {}); RETURN_IF_EXCEPTION(scope, {});
RELEASE_AND_RETURN(scope, target); RELEASE_AND_RETURN(scope, target);
} }
@@ -765,10 +733,6 @@ JSValue fetchCommonJSModule(
target->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), value, 0); target->putDirect(vm, WebCore::clientData(vm)->builtinNames().exportsPublicName(), value, 0);
target->hasEvaluated = true; target->hasEvaluated = true;
RELEASE_AND_RETURN(scope, target); RELEASE_AND_RETURN(scope, target);
} else if (res->result.value.tag == SyntheticModuleType::CommonJSCustomExtension) {
evaluateCommonJSCustomExtension(globalObject, target, specifierWtfString, specifierValue, res->result.value.cjsCustomExtensionIndex);
RETURN_IF_EXCEPTION(scope, {});
RELEASE_AND_RETURN(scope, target);
} }
auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value); auto&& provider = Zig::SourceProvider::create(globalObject, res->result.value);
@@ -896,12 +860,12 @@ static JSValue fetchESMSourceCode(
} }
if constexpr (allowPromise) { if constexpr (allowPromise) {
auto* pendingCtx = Bun__transpileFile(bunVM, globalObject, specifier, referrer, typeAttribute, res, true, false); auto* pendingCtx = Bun__transpileFile(bunVM, globalObject, specifier, referrer, typeAttribute, res, true);
if (pendingCtx) { if (pendingCtx) {
return pendingCtx; return pendingCtx;
} }
} else { } else {
Bun__transpileFile(bunVM, globalObject, specifier, referrer, typeAttribute, res, false, false); Bun__transpileFile(bunVM, globalObject, specifier, referrer, typeAttribute, res, false);
} }
if (res->success && res->result.value.isCommonJSModule) { if (res->success && res->result.value.isCommonJSModule) {

View File

@@ -110,7 +110,7 @@ JSValue fetchCommonJSModule(
Zig::GlobalObject* globalObject, Zig::GlobalObject* globalObject,
JSCommonJSModule* moduleObject, JSCommonJSModule* moduleObject,
JSValue specifierValue, JSValue specifierValue,
String specifier, BunString* specifier,
BunString* referrer, BunString* referrer,
BunString* typeAttribute); BunString* typeAttribute);

View File

@@ -81,154 +81,3 @@ pub fn _stat(path: []const u8) i32 {
.directory => 1, // Returns 1 for directories. .directory => 1, // Returns 1 for directories.
}; };
} }
pub const CustomLoader = union(enum) {
loader: bun.options.Loader,
/// Retrieve via WriteBarrier in `global->lazyRequireExtensionsObject().get(index)`
custom: u32,
pub const Packed = enum(u32) {
const loader_start: u32 = std.math.maxInt(u32) - 4;
js = loader_start,
json = loader_start + 1,
napi = loader_start + 2,
ts = loader_start + 3,
/// custom
_,
pub fn pack(loader: CustomLoader) Packed {
return switch (loader) {
.loader => |basic| switch (basic) {
.js => .js,
.json => .json,
.napi => .napi,
.ts => .ts,
else => brk: {
bun.debugAssert(false);
break :brk .js;
},
},
.custom => |custom| @enumFromInt(custom),
};
}
pub fn unpack(self: Packed) CustomLoader {
return switch (self) {
.js => .{ .loader = .js },
.json => .{ .loader = .json },
.napi => .{ .loader = .napi },
.ts => .{ .loader = .ts },
_ => .{ .custom = @intFromEnum(self) },
};
}
};
};
extern fn JSCommonJSExtensions__appendFunction(global: *JSC.JSGlobalObject, value: JSC.JSValue) u32;
extern fn JSCommonJSExtensions__setFunction(global: *JSC.JSGlobalObject, index: u32, value: JSC.JSValue) void;
/// Returns the index of the last value, which must have it's references updated to `index`
extern fn JSCommonJSExtensions__swapRemove(global: *JSC.JSGlobalObject, index: u32) u32;
// Memory management is complicated because JSValues are stored in gc-visitable
// WriteBarriers in C++ but the hash map for extensions is in Zig for flexibility.
fn onRequireExtensionModify(global: *JSC.JSGlobalObject, str: []const u8, kind: i32, value: JSC.JSValue) !void {
bun.assert(kind >= -1 and kind <= 4);
const vm = global.bunVM();
const list = &vm.commonjs_custom_extensions;
defer vm.transpiler.resolver.opts.extra_cjs_extensions = list.keys();
const is_built_in = bun.options.defaultLoaders.get(str) != null;
if (kind >= 0) {
const loader: CustomLoader = switch (kind) {
1 => .{ .loader = .js },
2 => .{ .loader = .json },
3 => .{ .loader = .napi },
4 => .{ .loader = .ts },
else => .{ .custom = undefined }, // to be filled in later
};
const gop = try list.getOrPut(bun.default_allocator, str);
if (!gop.found_existing) {
const dupe = try bun.default_allocator.dupe(u8, str);
errdefer bun.default_allocator.free(dupe);
gop.key_ptr.* = dupe;
if (is_built_in) {
vm.has_mutated_built_in_extensions += 1;
}
gop.value_ptr.* = .pack(switch (loader) {
.loader => loader,
.custom => .{
.custom = JSCommonJSExtensions__appendFunction(global, value),
},
});
} else {
const existing = gop.value_ptr.*.unpack();
if (existing == .custom and loader != .custom) {
swapRemoveExtension(vm, existing.custom);
}
gop.value_ptr.* = .pack(switch (loader) {
.loader => loader,
.custom => .{
.custom = if (existing == .custom) new: {
JSCommonJSExtensions__setFunction(global, existing.custom, value);
break :new existing.custom;
} else JSCommonJSExtensions__appendFunction(global, value),
},
});
}
} else if (list.fetchSwapRemove(str)) |prev| {
bun.default_allocator.free(prev.key);
if (is_built_in) {
vm.has_mutated_built_in_extensions -= 1;
}
switch (prev.value.unpack()) {
.loader => {},
.custom => |index| swapRemoveExtension(vm, index),
}
}
}
fn swapRemoveExtension(vm: *JSC.VirtualMachine, index: u32) void {
const last_index = JSCommonJSExtensions__swapRemove(vm.global, index);
if (last_index == index) return;
// Find and rewrite the last index to the new index.
// Since packed structs are sugar over the backing int, this code can use
// the simd path in the standard library search.
const find: u32 = @intFromEnum(CustomLoader.Packed.pack(.{ .custom = last_index }));
const values = vm.commonjs_custom_extensions.values();
const values_reinterpret = bun.reinterpretSlice(u32, values);
const i = std.mem.indexOfScalar(u32, values_reinterpret, find) orelse
return bun.debugAssert(false);
values[i] = .pack(.{ .custom = last_index });
}
pub fn findLongestRegisteredExtension(vm: *JSC.VirtualMachine, filename: []const u8) ?CustomLoader {
const basename = std.fs.path.basename(filename);
var next: usize = 0;
while (bun.strings.indexOfCharPos(basename, '.', next)) |i| {
next = i + 1;
if (i == 0) continue;
const ext = basename[i..];
if (vm.commonjs_custom_extensions.get(ext)) |value| {
return value.unpack();
}
}
return null;
}
fn onRequireExtensionModifyBinding(
global: *JSC.JSGlobalObject,
str: *const bun.String,
kind: i32,
value: JSC.JSValue,
) callconv(.c) void {
var sfa_state = std.heap.stackFallback(8192, bun.default_allocator);
const alloc = sfa_state.get();
const str_slice = str.toUTF8(alloc);
defer str_slice.deinit();
onRequireExtensionModify(global, str_slice.slice(), kind, value) catch |err| switch (err) {
error.OutOfMemory => bun.outOfMemory(),
};
}
comptime {
@export(&onRequireExtensionModifyBinding, .{ .name = "NodeModuleModule__onRequireExtensionModify" });
}

View File

@@ -13,15 +13,13 @@ pub const ResolvedSource = extern struct {
is_commonjs_module: bool = false, is_commonjs_module: bool = false,
/// When .tag is .common_js_custom_extension, this is special-cased to hold hash: u32 = 0,
/// the index of the extension, since the module is stored in a WriteBarrier.
cjs_custom_extension_index: u32 = 0,
allocator: ?*anyopaque = null, allocator: ?*anyopaque = null,
jsvalue_for_export: JSValue = .zero, jsvalue_for_export: JSValue = .zero,
tag: Tag = .javascript, tag: Tag = Tag.javascript,
/// This is for source_code /// This is for source_code
source_code_needs_deref: bool = true, source_code_needs_deref: bool = true,

View File

@@ -2938,6 +2938,18 @@ void GlobalObject::finishCreation(VM& vm)
init.set(crypto); init.set(crypto);
}); });
m_lazyRequireCacheObject.initLater(
[](const Initializer<JSObject>& init) {
JSC::VM& vm = init.vm;
JSC::JSGlobalObject* globalObject = init.owner;
auto* function = JSFunction::create(vm, globalObject, static_cast<JSC::FunctionExecutable*>(commonJSCreateRequireCacheCodeGenerator(vm)), globalObject);
NakedPtr<JSC::Exception> returnedException = nullptr;
auto result = JSC::profiledCall(globalObject, ProfilingReason::API, function, JSC::getCallData(function), globalObject, ArgList(), returnedException);
init.set(result.toObject(globalObject));
});
m_lazyTestModuleObject.initLater( m_lazyTestModuleObject.initLater(
[](const Initializer<JSObject>& init) { [](const Initializer<JSObject>& init) {
JSC::JSGlobalObject* globalObject = init.owner; JSC::JSGlobalObject* globalObject = init.owner;

View File

@@ -56,13 +56,6 @@ class GlobalInternals;
#include <js_native_api.h> #include <js_native_api.h>
#include <node_api.h> #include <node_api.h>
namespace Bun {
class JSCommonJSExtensions;
class InternalModuleRegistry;
class JSMockModule;
class JSMockFunction;
}
namespace WebCore { namespace WebCore {
class WorkerGlobalScope; class WorkerGlobalScope;
class SubtleCrypto; class SubtleCrypto;
@@ -269,7 +262,6 @@ public:
JSObject* processBindingFs() const { return m_processBindingFs.getInitializedOnMainThread(this); } JSObject* processBindingFs() const { return m_processBindingFs.getInitializedOnMainThread(this); }
JSObject* lazyRequireCacheObject() const { return m_lazyRequireCacheObject.getInitializedOnMainThread(this); } JSObject* lazyRequireCacheObject() const { return m_lazyRequireCacheObject.getInitializedOnMainThread(this); }
Bun::JSCommonJSExtensions* lazyRequireExtensionsObject() const { return m_lazyRequireExtensionsObject.getInitializedOnMainThread(this); }
Structure* NodeVMGlobalObjectStructure() const { return m_cachedNodeVMGlobalObjectStructure.getInitializedOnMainThread(this); } Structure* NodeVMGlobalObjectStructure() const { return m_cachedNodeVMGlobalObjectStructure.getInitializedOnMainThread(this); }
Structure* globalProxyStructure() const { return m_cachedGlobalProxyStructure.getInitializedOnMainThread(this); } Structure* globalProxyStructure() const { return m_cachedGlobalProxyStructure.getInitializedOnMainThread(this); }
@@ -594,7 +586,6 @@ public:
LazyProperty<JSGlobalObject, Structure> m_JSResizableOrGrowableSharedBufferSubclassStructure; LazyProperty<JSGlobalObject, Structure> m_JSResizableOrGrowableSharedBufferSubclassStructure;
LazyProperty<JSGlobalObject, JSWeakMap> m_vmModuleContextMap; LazyProperty<JSGlobalObject, JSWeakMap> m_vmModuleContextMap;
LazyProperty<JSGlobalObject, JSObject> m_lazyRequireCacheObject; LazyProperty<JSGlobalObject, JSObject> m_lazyRequireCacheObject;
LazyProperty<JSGlobalObject, Bun::JSCommonJSExtensions> m_lazyRequireExtensionsObject;
LazyProperty<JSGlobalObject, JSObject> m_lazyTestModuleObject; LazyProperty<JSGlobalObject, JSObject> m_lazyTestModuleObject;
LazyProperty<JSGlobalObject, JSObject> m_lazyPreloadTestModuleObject; LazyProperty<JSGlobalObject, JSObject> m_lazyPreloadTestModuleObject;
LazyProperty<JSGlobalObject, JSObject> m_testMatcherUtilsObject; LazyProperty<JSGlobalObject, JSObject> m_testMatcherUtilsObject;

View File

@@ -342,30 +342,30 @@ pub fn initialize(eval_mode: bool) void {
JSCInitialize( JSCInitialize(
std.os.environ.ptr, std.os.environ.ptr,
std.os.environ.len, std.os.environ.len,
onJSCInvalidEnvVar, struct {
pub fn callback(name: [*]const u8, len: usize) callconv(.C) void {
Output.prettyErrorln(
\\<r><red>error<r><d>:<r> invalid JSC environment variable
\\
\\ <b>{s}<r>
\\
\\For a list of options, see this file:
\\
\\ 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.
\\
\\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.
,
.{name[0..len]},
);
bun.Global.exit(1);
}
}.callback,
eval_mode, eval_mode,
); );
} }
pub fn onJSCInvalidEnvVar(name: [*]const u8, len: usize) callconv(.C) void {
Output.prettyErrorln(
\\<r><red>error<r><d>:<r> invalid JSC environment variable
\\
\\ <b>{s}<r>
\\
\\For a list of options, see this file:
\\
\\ 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.
\\
\\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.
,
.{name[0..len]},
);
bun.Global.exit(1);
}
/// Returns null on error. Use windows API to lookup the actual error. /// Returns null on error. Use windows API to lookup the actual error.
/// The reason this function is in zig is so that we can use our own utf16-conversion functions. /// The reason this function is in zig is so that we can use our own utf16-conversion functions.
/// ///

View File

@@ -106,7 +106,7 @@ typedef struct ResolvedSource {
BunString source_code; BunString source_code;
BunString source_url; BunString source_url;
bool isCommonJSModule; bool isCommonJSModule;
uint32_t cjsCustomExtensionIndex; uint32_t hash;
void* allocator; void* allocator;
JSC::EncodedJSValue jsvalue_for_export; JSC::EncodedJSValue jsvalue_for_export;
uint32_t tag; uint32_t tag;
@@ -347,9 +347,7 @@ extern "C" JSC::JSInternalPromise* Bun__transpileFile(
BunString* specifier, BunString* specifier,
BunString* referrer, BunString* referrer,
const BunString* typeAttribute, const BunString* typeAttribute,
ErrorableResolvedSource* result, ErrorableResolvedSource* result, bool allowPromise);
bool allowPromise,
bool isCommonJSRequire);
extern "C" bool Bun__fetchBuiltinModule( extern "C" bool Bun__fetchBuiltinModule(
void* bunVM, void* bunVM,

View File

@@ -37,7 +37,6 @@ public:
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBundlerPlugin; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBundlerPlugin;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNodeVMScript; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNodeVMScript;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSCommonJSModule; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSCommonJSModule;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSCommonJSExtensions;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSMockImplementation; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSMockImplementation;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSModuleMock; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSModuleMock;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSMockFunction; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSMockFunction;

View File

@@ -37,7 +37,6 @@ public:
std::unique_ptr<IsoSubspace> m_subspaceForBundlerPlugin; std::unique_ptr<IsoSubspace> m_subspaceForBundlerPlugin;
std::unique_ptr<IsoSubspace> m_subspaceForNodeVMScript; std::unique_ptr<IsoSubspace> m_subspaceForNodeVMScript;
std::unique_ptr<IsoSubspace> m_subspaceForJSCommonJSModule; std::unique_ptr<IsoSubspace> m_subspaceForJSCommonJSModule;
std::unique_ptr<IsoSubspace> m_subspaceForJSCommonJSExtensions;
std::unique_ptr<IsoSubspace> m_subspaceForJSMockImplementation; std::unique_ptr<IsoSubspace> m_subspaceForJSMockImplementation;
std::unique_ptr<IsoSubspace> m_subspaceForJSModuleMock; std::unique_ptr<IsoSubspace> m_subspaceForJSModuleMock;
std::unique_ptr<IsoSubspace> m_subspaceForJSMockFunction; std::unique_ptr<IsoSubspace> m_subspaceForJSMockFunction;

View File

@@ -74,7 +74,6 @@ const PackageManager = @import("../install/install.zig").PackageManager;
const IPC = @import("ipc.zig"); const IPC = @import("ipc.zig");
const DNSResolver = @import("api/bun/dns_resolver.zig").DNSResolver; const DNSResolver = @import("api/bun/dns_resolver.zig").DNSResolver;
const Watcher = bun.Watcher; const Watcher = bun.Watcher;
const node_module_module = @import("./bindings/NodeModuleModule.zig");
const ModuleLoader = JSC.ModuleLoader; const ModuleLoader = JSC.ModuleLoader;
const FetchFlags = JSC.FetchFlags; const FetchFlags = JSC.FetchFlags;
@@ -901,7 +900,7 @@ pub const VirtualMachine = struct {
is_inside_deferred_task_queue: bool = false, is_inside_deferred_task_queue: bool = false,
// defaults off. .on("message") will set it to true unless overridden // defaults off. .on("message") will set it to true unles overridden
// process.channel.unref() will set it to false and mark it overridden // process.channel.unref() will set it to false and mark it overridden
// on disconnect it will be disabled // on disconnect it will be disabled
channel_ref: bun.Async.KeepAlive = .{}, channel_ref: bun.Async.KeepAlive = .{},
@@ -910,18 +909,6 @@ pub const VirtualMachine = struct {
// if one disconnect event listener should be ignored // if one disconnect event listener should be ignored
channel_ref_should_ignore_one_disconnect_event_listener: bool = false, channel_ref_should_ignore_one_disconnect_event_listener: bool = false,
/// A set of extensions that exist in the require.extensions map. Keys
/// contain the leading '.'. Value is either a loader for built in
/// functions, or an index into JSCommonJSExtensions.
///
/// `.keys() == transpiler.resolver.opts.extra_cjs_extensions`, so
/// mutations in this map must update the resolver.
commonjs_custom_extensions: bun.StringArrayHashMapUnmanaged(node_module_module.CustomLoader.Packed) = .empty,
/// Incremented when the `require.extensions` for a built-in extension is mutated.
/// An example is mutating `require.extensions['.js']` to intercept all '.js' files.
/// The value is decremented when defaults are restored.
has_mutated_built_in_extensions: u32 = 0,
pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSGlobalObject, JSValue) void; pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSGlobalObject, JSValue) void;
pub const OnException = fn (*ZigException) void; pub const OnException = fn (*ZigException) void;
@@ -2380,6 +2367,7 @@ pub const VirtualMachine = struct {
.source_code = bun.String.init(""), .source_code = bun.String.init(""),
.specifier = specifier, .specifier = specifier,
.source_url = specifier.createIfDifferent(source_url), .source_url = specifier.createIfDifferent(source_url),
.hash = 0,
.allocator = null, .allocator = null,
.source_code_needs_deref = false, .source_code_needs_deref = false,
}; };
@@ -2394,6 +2382,7 @@ pub const VirtualMachine = struct {
.source_code = bun.String.init(source.impl), .source_code = bun.String.init(source.impl),
.specifier = specifier, .specifier = specifier,
.source_url = specifier.createIfDifferent(source_url), .source_url = specifier.createIfDifferent(source_url),
.hash = source.hash,
.allocator = source, .allocator = source,
.source_code_needs_deref = false, .source_code_needs_deref = false,
}; };

View File

@@ -42,7 +42,6 @@ const JSC = bun.JSC;
const MarkedArrayBuffer = @import("./base.zig").MarkedArrayBuffer; const MarkedArrayBuffer = @import("./base.zig").MarkedArrayBuffer;
const getAllocator = @import("./base.zig").getAllocator; const getAllocator = @import("./base.zig").getAllocator;
const JSValue = bun.JSC.JSValue; const JSValue = bun.JSC.JSValue;
const node_module_module = @import("./bindings/NodeModuleModule.zig");
const JSGlobalObject = bun.JSC.JSGlobalObject; const JSGlobalObject = bun.JSC.JSGlobalObject;
const ExceptionValueRef = bun.JSC.ExceptionValueRef; const ExceptionValueRef = bun.JSC.ExceptionValueRef;
@@ -79,6 +78,7 @@ inline fn jsSyntheticModule(name: ResolvedSource.Tag, specifier: String) Resolve
.source_code = bun.String.empty, .source_code = bun.String.empty,
.specifier = specifier, .specifier = specifier,
.source_url = bun.String.static(@tagName(name)), .source_url = bun.String.static(@tagName(name)),
.hash = 0,
.tag = name, .tag = name,
.source_code_needs_deref = false, .source_code_needs_deref = false,
}; };
@@ -568,6 +568,7 @@ pub const RuntimeTranspilerStore = struct {
break :brk result; break :brk result;
}, },
}, },
.hash = 0,
.is_commonjs_module = entry.metadata.module_type == .cjs, .is_commonjs_module = entry.metadata.module_type == .cjs,
.tag = this.resolved_source.tag, .tag = this.resolved_source.tag,
}; };
@@ -581,6 +582,7 @@ pub const RuntimeTranspilerStore = struct {
.allocator = null, .allocator = null,
.source_code = bun.String.createLatin1(parse_result.source.contents), .source_code = bun.String.createLatin1(parse_result.source.contents),
.already_bundled = true, .already_bundled = true,
.hash = 0,
.bytecode_cache = if (bytecode_slice.len > 0) bytecode_slice.ptr else null, .bytecode_cache = if (bytecode_slice.len > 0) bytecode_slice.ptr else null,
.bytecode_cache_size = bytecode_slice.len, .bytecode_cache_size = bytecode_slice.len,
.is_commonjs_module = parse_result.already_bundled.isCommonJS(), .is_commonjs_module = parse_result.already_bundled.isCommonJS(),
@@ -682,6 +684,7 @@ pub const RuntimeTranspilerStore = struct {
.allocator = null, .allocator = null,
.source_code = source_code, .source_code = source_code,
.is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs, .is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs,
.hash = 0,
.tag = this.resolved_source.tag, .tag = this.resolved_source.tag,
}; };
} }
@@ -1444,6 +1447,8 @@ pub const ModuleLoader = struct {
.specifier = String.init(specifier), .specifier = String.init(specifier),
.source_url = String.init(path.text), .source_url = String.init(path.text),
.is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs, .is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs,
.hash = 0,
}; };
} }
@@ -1504,6 +1509,7 @@ pub const ModuleLoader = struct {
.source_code = bun.String.empty, .source_code = bun.String.empty,
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
}; };
} }
} }
@@ -1735,6 +1741,8 @@ pub const ModuleLoader = struct {
.source_code = bun.String.createUTF8(parse_result.source.contents), .source_code = bun.String.createUTF8(parse_result.source.contents),
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
.tag = ResolvedSource.Tag.json_for_object_loader, .tag = ResolvedSource.Tag.json_for_object_loader,
}; };
} }
@@ -1749,6 +1757,7 @@ pub const ModuleLoader = struct {
}, },
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
}; };
} }
@@ -1758,6 +1767,7 @@ pub const ModuleLoader = struct {
.allocator = null, .allocator = null,
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
.jsvalue_for_export = JSValue.createEmptyObject(jsc_vm.global, 0), .jsvalue_for_export = JSValue.createEmptyObject(jsc_vm.global, 0),
.tag = .exports_object, .tag = .exports_object,
}; };
@@ -1767,6 +1777,7 @@ pub const ModuleLoader = struct {
.allocator = null, .allocator = null,
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
.jsvalue_for_export = parse_result.ast.parts.@"[0]"().stmts[0].data.s_expr.value.toJS(allocator, globalObject orelse jsc_vm.global) catch |e| panic("Unexpected JS error: {s}", .{@errorName(e)}), .jsvalue_for_export = parse_result.ast.parts.@"[0]"().stmts[0].data.s_expr.value.toJS(allocator, globalObject orelse jsc_vm.global) catch |e| panic("Unexpected JS error: {s}", .{@errorName(e)}),
.tag = .exports_object, .tag = .exports_object,
}; };
@@ -1780,6 +1791,7 @@ pub const ModuleLoader = struct {
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.already_bundled = true, .already_bundled = true,
.hash = 0,
.bytecode_cache = if (bytecode_slice.len > 0) bytecode_slice.ptr else null, .bytecode_cache = if (bytecode_slice.len > 0) bytecode_slice.ptr else null,
.bytecode_cache_size = bytecode_slice.len, .bytecode_cache_size = bytecode_slice.len,
.is_commonjs_module = parse_result.already_bundled.isCommonJS(), .is_commonjs_module = parse_result.already_bundled.isCommonJS(),
@@ -1798,6 +1810,7 @@ pub const ModuleLoader = struct {
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.is_commonjs_module = true, .is_commonjs_module = true,
.hash = 0,
.tag = .javascript, .tag = .javascript,
}; };
} }
@@ -1826,6 +1839,7 @@ pub const ModuleLoader = struct {
}, },
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
.is_commonjs_module = entry.metadata.module_type == .cjs, .is_commonjs_module = entry.metadata.module_type == .cjs,
.tag = brk: { .tag = brk: {
if (entry.metadata.module_type == .cjs and parse_result.source.path.isFile()) { if (entry.metadata.module_type == .cjs and parse_result.source.path.isFile()) {
@@ -1956,6 +1970,7 @@ pub const ModuleLoader = struct {
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs, .is_commonjs_module = parse_result.ast.has_commonjs_export_names or parse_result.ast.exports_kind == .cjs,
.hash = 0,
.tag = tag, .tag = tag,
}; };
}, },
@@ -1998,6 +2013,7 @@ pub const ModuleLoader = struct {
// .source_code = ZigString.init(jsc_vm.allocator.dupe(u8, parse_result.source.contents) catch unreachable), // .source_code = ZigString.init(jsc_vm.allocator.dupe(u8, parse_result.source.contents) catch unreachable),
// .specifier = ZigString.init(specifier), // .specifier = ZigString.init(specifier),
// .source_url = input_specifier.createIfDifferent(path.text), // .source_url = input_specifier.createIfDifferent(path.text),
// .hash = 0,
// .tag = ResolvedSource.Tag.wasm, // .tag = ResolvedSource.Tag.wasm,
// }; // };
// }, // },
@@ -2023,6 +2039,7 @@ pub const ModuleLoader = struct {
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.tag = .esm, .tag = .esm,
.hash = 0,
}; };
} }
@@ -2082,6 +2099,7 @@ pub const ModuleLoader = struct {
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.tag = .esm, .tag = .esm,
.hash = 0,
}; };
}, },
@@ -2092,6 +2110,7 @@ pub const ModuleLoader = struct {
.source_code = bun.String.empty, .source_code = bun.String.empty,
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
.tag = .esm, .tag = .esm,
}; };
} }
@@ -2106,6 +2125,7 @@ pub const ModuleLoader = struct {
.jsvalue_for_export = html_bundle.toJS(globalObject.?), .jsvalue_for_export = html_bundle.toJS(globalObject.?),
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
.tag = .export_default_object, .tag = .export_default_object,
}; };
}, },
@@ -2117,6 +2137,7 @@ pub const ModuleLoader = struct {
.source_code = bun.String.empty, .source_code = bun.String.empty,
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
.tag = .esm, .tag = .esm,
}; };
} }
@@ -2188,6 +2209,7 @@ pub const ModuleLoader = struct {
.jsvalue_for_export = value, .jsvalue_for_export = value,
.specifier = input_specifier, .specifier = input_specifier,
.source_url = input_specifier.createIfDifferent(path.text), .source_url = input_specifier.createIfDifferent(path.text),
.hash = 0,
.tag = .export_default_object, .tag = .export_default_object,
}; };
}, },
@@ -2255,7 +2277,6 @@ pub const ModuleLoader = struct {
type_attribute: ?*const bun.String, type_attribute: ?*const bun.String,
ret: *JSC.ErrorableResolvedSource, ret: *JSC.ErrorableResolvedSource,
allow_promise: bool, allow_promise: bool,
is_commonjs_require: bool,
) ?*anyopaque { ) ?*anyopaque {
JSC.markBinding(@src()); JSC.markBinding(@src());
var log = logger.Log.init(jsc_vm.transpiler.allocator); var log = logger.Log.init(jsc_vm.transpiler.allocator);
@@ -2273,63 +2294,13 @@ pub const ModuleLoader = struct {
var virtual_source_to_use: ?logger.Source = null; var virtual_source_to_use: ?logger.Source = null;
var blob_to_deinit: ?JSC.WebCore.Blob = null; var blob_to_deinit: ?JSC.WebCore.Blob = null;
var lr = options.getLoaderAndVirtualSource(_specifier.slice(), jsc_vm, &virtual_source_to_use, &blob_to_deinit, type_attribute_str) catch { const lr = options.getLoaderAndVirtualSource(_specifier.slice(), jsc_vm, &virtual_source_to_use, &blob_to_deinit, type_attribute_str) catch {
ret.* = JSC.ErrorableResolvedSource.err(error.JSErrorObject, globalObject.MODULE_NOT_FOUND("Blob not found", .{}).toJS().asVoid()); ret.* = JSC.ErrorableResolvedSource.err(error.JSErrorObject, globalObject.MODULE_NOT_FOUND("Blob not found", .{}).toJS().asVoid());
return null; return null;
}; };
defer if (blob_to_deinit) |*blob| blob.deinit(); defer if (blob_to_deinit) |*blob| blob.deinit();
if (is_commonjs_require and jsc_vm.has_mutated_built_in_extensions > 0) brk: { const module_type: options.ModuleType = if (lr.package_json) |pkg| pkg.module_type else .unknown;
@branchHint(.unlikely);
if (node_module_module.findLongestRegisteredExtension(jsc_vm, _specifier.slice())) |entry| {
switch (entry) {
.loader => |loader| {
lr.loader = loader;
break :brk;
},
.custom => |index| {
ret.* = JSC.ErrorableResolvedSource.ok(ResolvedSource{
.allocator = null,
.source_code = bun.String.empty,
.specifier = .empty,
.source_url = .empty,
.cjs_custom_extension_index = index,
.tag = .common_js_custom_extension,
});
return null;
},
}
}
}
const module_type: options.ModuleType = brk: {
const ext = lr.path.name.ext;
// regular expression /.[cm][jt]s$/
if (ext.len == ".cjs".len) {
if (strings.eqlComptimeIgnoreLen(ext, ".cjs"))
break :brk .cjs;
if (strings.eqlComptimeIgnoreLen(ext, ".mjs"))
break :brk .esm;
if (strings.eqlComptimeIgnoreLen(ext, ".cts"))
break :brk .cjs;
if (strings.eqlComptimeIgnoreLen(ext, ".mts"))
break :brk .esm;
}
// regular expression /.[jt]s$/
if (ext.len == ".ts".len) {
if (strings.eqlComptimeIgnoreLen(ext, ".js") or
strings.eqlComptimeIgnoreLen(ext, ".ts"))
{
// Use the package.json module type if it exists
break :brk if (lr.package_json) |pkg|
pkg.module_type
else
.unknown;
}
}
// For JSX TSX and other extensions, let the file contents.
break :brk .unknown;
};
const pkg_name: ?[]const u8 = if (lr.package_json) |pkg| const pkg_name: ?[]const u8 = if (lr.package_json) |pkg|
if (pkg.name.len > 0) pkg.name else null if (pkg.name.len > 0) pkg.name else null
else else
@@ -2396,48 +2367,19 @@ pub const ModuleLoader = struct {
} }
} }
const synchronous_loader: options.Loader = lr.loader orelse loader: { const synchronous_loader = lr.loader orelse loader: {
if (jsc_vm.has_loaded or jsc_vm.is_in_preload) { if (jsc_vm.has_loaded or jsc_vm.is_in_preload) {
// Extensionless files in this context are treated as the JS loader // Extensionless files in this context are treated as the JS loader
if (lr.path.name.ext.len == 0) { if (lr.path.name.ext.len == 0) {
break :loader .tsx; break :loader options.Loader.tsx;
} }
// Unknown extensions are to be treated as file loader // Unknown extensions are to be treated as file loader
if (is_commonjs_require) { break :loader options.Loader.file;
if (jsc_vm.commonjs_custom_extensions.entries.len > 0 and
jsc_vm.has_mutated_built_in_extensions == 0)
{
@branchHint(.unlikely);
if (node_module_module.findLongestRegisteredExtension(jsc_vm, lr.path.text)) |entry| {
switch (entry) {
.loader => |loader| break :loader loader,
.custom => |index| {
ret.* = JSC.ErrorableResolvedSource.ok(ResolvedSource{
.allocator = null,
.source_code = bun.String.empty,
.specifier = .empty,
.source_url = .empty,
.cjs_custom_extension_index = index,
.tag = .common_js_custom_extension,
});
return null;
},
}
}
}
// For Node.js compatibility, requiring a file with an
// unknown extension will be treated as a JS file
break :loader .ts;
}
// For ESM, Bun treats unknown extensions as file loader
break :loader .file;
} else { } else {
// Unless it's potentially the main module // Unless it's potentially the main module
// This is important so that "bun run ./foo-i-have-no-extension" works // This is important so that "bun run ./foo-i-have-no-extension" works
break :loader .tsx; break :loader options.Loader.tsx;
} }
}; };
@@ -2509,6 +2451,7 @@ pub const ModuleLoader = struct {
.source_code = bun.String.createUTF8(jsc_vm.entry_point.source.contents), .source_code = bun.String.createUTF8(jsc_vm.entry_point.source.contents),
.specifier = specifier, .specifier = specifier,
.source_url = specifier, .source_url = specifier,
.hash = 0,
.tag = .esm, .tag = .esm,
.source_code_needs_deref = true, .source_code_needs_deref = true,
}, },
@@ -2524,6 +2467,7 @@ pub const ModuleLoader = struct {
.source_code = String.init(Runtime.Runtime.sourceCode()), .source_code = String.init(Runtime.Runtime.sourceCode()),
.specifier = specifier, .specifier = specifier,
.source_url = specifier, .source_url = specifier,
.hash = Runtime.Runtime.versionHash(),
}, },
inline else => |tag| jsSyntheticModule(@field(ResolvedSource.Tag, @tagName(tag)), specifier), inline else => |tag| jsSyntheticModule(@field(ResolvedSource.Tag, @tagName(tag)), specifier),
}; };
@@ -2543,6 +2487,7 @@ pub const ModuleLoader = struct {
.source_code = bun.String.createUTF8(entry.source.contents), .source_code = bun.String.createUTF8(entry.source.contents),
.specifier = specifier, .specifier = specifier,
.source_url = specifier.dupeRef(), .source_url = specifier.dupeRef(),
.hash = 0,
}; };
} }
} else if (jsc_vm.standalone_module_graph) |graph| { } else if (jsc_vm.standalone_module_graph) |graph| {
@@ -2564,6 +2509,7 @@ pub const ModuleLoader = struct {
.source_code = bun.String.static(code), .source_code = bun.String.static(code),
.specifier = specifier, .specifier = specifier,
.source_url = specifier.dupeRef(), .source_url = specifier.dupeRef(),
.hash = 0,
.source_code_needs_deref = false, .source_code_needs_deref = false,
}; };
} }
@@ -2573,6 +2519,7 @@ pub const ModuleLoader = struct {
.source_code = file.toWTFString(), .source_code = file.toWTFString(),
.specifier = specifier, .specifier = specifier,
.source_url = specifier.dupeRef(), .source_url = specifier.dupeRef(),
.hash = 0,
.source_code_needs_deref = false, .source_code_needs_deref = false,
.bytecode_cache = if (file.bytecode.len > 0) file.bytecode.ptr else null, .bytecode_cache = if (file.bytecode.len > 0) file.bytecode.ptr else null,
.bytecode_cache_size = file.bytecode.len, .bytecode_cache_size = file.bytecode.len,

View File

@@ -12,7 +12,6 @@
#include <JavaScriptCore/JSInternalPromise.h> #include <JavaScriptCore/JSInternalPromise.h>
#include "JavaScriptCore/Completion.h" #include "JavaScriptCore/Completion.h"
#include "JavaScriptCore/JSNativeStdFunction.h" #include "JavaScriptCore/JSNativeStdFunction.h"
#include "JSCommonJSExtensions.h"
#include "PathInlines.h" #include "PathInlines.h"
#include "ZigGlobalObject.h" #include "ZigGlobalObject.h"
@@ -563,12 +562,6 @@ static JSValue getModuleCacheObject(VM& vm, JSObject* moduleObject)
->lazyRequireCacheObject(); ->lazyRequireCacheObject();
} }
static JSValue getModuleExtensionsObject(VM& vm, JSObject* moduleObject)
{
return jsCast<Zig::GlobalObject*>(moduleObject->globalObject())
->lazyRequireExtensionsObject();
}
static JSValue getModuleDebugObject(VM& vm, JSObject* moduleObject) static JSValue getModuleDebugObject(VM& vm, JSObject* moduleObject)
{ {
return JSC::constructEmptyObject(moduleObject->globalObject()); return JSC::constructEmptyObject(moduleObject->globalObject());
@@ -581,6 +574,13 @@ static JSValue getPathCacheObject(VM& vm, JSObject* moduleObject)
vm, globalObject->nullPrototypeObjectStructure()); vm, globalObject->nullPrototypeObjectStructure());
} }
static JSValue getModuleExtensionsObject(VM& vm, JSObject* moduleObject)
{
auto* globalObject = defaultGlobalObject(moduleObject->globalObject());
return globalObject->requireFunctionUnbound()->getIfPropertyExists(
globalObject, Identifier::fromString(vm, "extensions"_s));
}
static JSValue getSourceMapFunction(VM& vm, JSObject* moduleObject) static JSValue getSourceMapFunction(VM& vm, JSObject* moduleObject)
{ {
auto* globalObject = defaultGlobalObject(moduleObject->globalObject()); auto* globalObject = defaultGlobalObject(moduleObject->globalObject());
@@ -951,27 +951,6 @@ void addNodeModuleConstructorProperties(JSC::VM& vm,
JSC::NoIntrinsic, jsFunctionResolveFileName); JSC::NoIntrinsic, jsFunctionResolveFileName);
init.set(resolveFilenameFunction); init.set(resolveFilenameFunction);
}); });
globalObject->m_lazyRequireCacheObject.initLater(
[](const Zig::GlobalObject::Initializer<JSObject>& init) {
JSC::VM& vm = init.vm;
JSC::JSGlobalObject* globalObject = init.owner;
auto* function = JSFunction::create(vm, globalObject, static_cast<JSC::FunctionExecutable*>(commonJSCreateRequireCacheCodeGenerator(vm)), globalObject);
NakedPtr<JSC::Exception> returnedException = nullptr;
auto result = JSC::profiledCall(globalObject, ProfilingReason::API, function, JSC::getCallData(function), globalObject, ArgList(), returnedException);
ASSERT(!returnedException);
init.set(result.toObject(globalObject));
});
globalObject->m_lazyRequireExtensionsObject.initLater(
[](const Zig::GlobalObject::Initializer<Bun::JSCommonJSExtensions>& init) {
JSC::VM& vm = init.vm;
JSC::JSGlobalObject* globalObject = init.owner;
init.set(JSCommonJSExtensions::create(vm, globalObject, JSCommonJSExtensions::createStructure(vm, globalObject, globalObject->nullPrototype())));
});
} }
JSC_DEFINE_HOST_FUNCTION(jsFunctionIsModuleResolveFilenameSlowPathEnabled, JSC_DEFINE_HOST_FUNCTION(jsFunctionIsModuleResolveFilenameSlowPathEnabled,

View File

@@ -395,6 +395,7 @@ writeIfNotChanged(
path.join(CODEGEN_DIR, "ResolvedSourceTag.zig"), path.join(CODEGEN_DIR, "ResolvedSourceTag.zig"),
`// zig fmt: off `// zig fmt: off
pub const ResolvedSourceTag = enum(u32) { pub const ResolvedSourceTag = enum(u32) {
// Predefined
javascript = 0, javascript = 0,
package_json_type_module = 1, package_json_type_module = 1,
package_json_type_commonjs = 2, package_json_type_commonjs = 2,
@@ -403,12 +404,11 @@ pub const ResolvedSourceTag = enum(u32) {
file = 5, file = 5,
esm = 6, esm = 6,
json_for_object_loader = 7, json_for_object_loader = 7,
/// Generate an object with "default" set to all the exports, including a "default" property /// Generate an object with "default" set to all the exports, including a "default" propert
exports_object = 8, exports_object = 8,
/// Generate a module that only exports default the input JSValue /// Generate a module that only exports default the input JSValue
export_default_object = 9, export_default_object = 9,
/// Signal upwards that the matching value in 'require.extensions' should be used.
common_js_custom_extension = 10,
// Built in modules are loaded through InternalModuleRegistry by numerical ID. // Built in modules are loaded through InternalModuleRegistry by numerical ID.
// In this enum are represented as \`(1 << 9) & id\` // In this enum are represented as \`(1 << 9) & id\`
@@ -438,7 +438,6 @@ writeIfNotChanged(
JSONForObjectLoader = 7, JSONForObjectLoader = 7,
ExportsObject = 8, ExportsObject = 8,
ExportDefaultObject = 9, ExportDefaultObject = 9,
CommonJSCustomExtension = 10,
// Built in modules are loaded through InternalModuleRegistry by numerical ID. // Built in modules are loaded through InternalModuleRegistry by numerical ID.
// In this enum are represented as \`(1 << 9) & id\` // In this enum are represented as \`(1 << 9) & id\`
InternalModuleRegistryFlag = 1 << 9, InternalModuleRegistryFlag = 1 << 9,

View File

@@ -484,7 +484,7 @@ declare function $createCommonJSModule(
id: string, id: string,
exports: any, exports: any,
hasEvaluated: boolean, hasEvaluated: boolean,
parent: JSCommonJSModule | undefined, parent: ?JSCommonJSModule,
): JSCommonJSModule; ): JSCommonJSModule;
declare function $evaluateCommonJSModule( declare function $evaluateCommonJSModule(
moduleToEvaluate: JSCommonJSModule, moduleToEvaluate: JSCommonJSModule,

View File

@@ -3590,6 +3590,9 @@ pub const Parser = struct {
} }
} }
const did_import_fast_refresh = false;
_ = did_import_fast_refresh;
// This is a workaround for broken module environment checks in packages like lodash-es // This is a workaround for broken module environment checks in packages like lodash-es
// https://github.com/lodash/lodash/issues/5660 // https://github.com/lodash/lodash/issues/5660
var force_esm = false; var force_esm = false;
@@ -3961,13 +3964,7 @@ pub const Parser = struct {
switch (p.options.module_type) { switch (p.options.module_type) {
// ".cjs" or ".cts" or ("type: commonjs" and (".js" or ".jsx" or ".ts" or ".tsx")) // ".cjs" or ".cts" or ("type: commonjs" and (".js" or ".jsx" or ".ts" or ".tsx"))
.cjs => { .cjs => {
// There are no commonjs-only features used (require is allowed in ESM) exports_kind = .cjs;
bun.assert(!uses_exports_ref and
!uses_module_ref and
!p.has_top_level_return and
!p.has_with_scope);
// Use ESM if the file has ES module syntax (import)
exports_kind = if (p.has_es_module_syntax) .esm else .cjs;
}, },
.esm => { .esm => {
exports_kind = .esm; exports_kind = .esm;

View File

@@ -80,9 +80,9 @@ pub fn stringHashMapFromArrays(comptime t: type, allocator: std.mem.Allocator, k
} }
pub const ExternalModules = struct { pub const ExternalModules = struct {
node_modules: std.BufSet, node_modules: std.BufSet = undefined,
abs_paths: std.BufSet, abs_paths: std.BufSet = undefined,
patterns: []const WildcardPattern, patterns: []const WildcardPattern = undefined,
pub const WildcardPattern = struct { pub const WildcardPattern = struct {
prefix: string, prefix: string,
@@ -1700,7 +1700,7 @@ pub const BundleOptions = struct {
main_fields: []const string = Target.DefaultMainFields.get(Target.browser), main_fields: []const string = Target.DefaultMainFields.get(Target.browser),
/// TODO: remove this in favor accessing bundler.log /// TODO: remove this in favor accessing bundler.log
log: *logger.Log, log: *logger.Log,
external: ExternalModules, external: ExternalModules = ExternalModules{},
entry_points: []const string, entry_points: []const string,
entry_naming: []const u8 = "", entry_naming: []const u8 = "",
asset_naming: []const u8 = "", asset_naming: []const u8 = "",
@@ -1708,9 +1708,6 @@ pub const BundleOptions = struct {
public_path: []const u8 = "", public_path: []const u8 = "",
extension_order: ResolveFileExtensions = .{}, extension_order: ResolveFileExtensions = .{},
main_field_extension_order: []const string = &Defaults.MainFieldExtensionOrder, main_field_extension_order: []const string = &Defaults.MainFieldExtensionOrder,
/// This list applies to all extension resolution cases. The runtime uses
/// this for implementing `require.extensions`
extra_cjs_extensions: []const []const u8 = &.{},
out_extensions: bun.StringHashMap(string), out_extensions: bun.StringHashMap(string),
import_path_format: ImportPathFormat = ImportPathFormat.relative, import_path_format: ImportPathFormat = ImportPathFormat.relative,
defines_loaded: bool = false, defines_loaded: bool = false,

View File

@@ -604,7 +604,7 @@ pub const PackageJSON = struct {
null, null,
) catch |err| { ) catch |err| {
if (err != error.IsDir) { if (err != error.IsDir) {
r.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Cannot read file \"{s}\": {s}", .{ input_path, @errorName(err) }) catch unreachable; r.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Cannot read file \"{s}\": {s}", .{ r.prettyPath(fs.Path.init(input_path)), @errorName(err) }) catch unreachable;
} }
return null; return null;
@@ -618,7 +618,7 @@ pub const PackageJSON = struct {
const key_path = fs.Path.init(package_json_path); const key_path = fs.Path.init(package_json_path);
var json_source = logger.Source.initPathString(key_path.text, entry.contents); var json_source = logger.Source.initPathString(key_path.text, entry.contents);
json_source.path.pretty = json_source.path.text; json_source.path.pretty = r.prettyPath(json_source.path);
const json: js_ast.Expr = (r.caches.json.parsePackageJSON(r.log, json_source, allocator, true) catch |err| { const json: js_ast.Expr = (r.caches.json.parsePackageJSON(r.log, json_source, allocator, true) catch |err| {
if (Environment.isDebug) { if (Environment.isDebug) {

View File

@@ -2565,6 +2565,11 @@ pub const Resolver = struct {
return result; return result;
} }
// TODO:
pub fn prettyPath(_: *ThisResolver, path: Path) string {
return path.text;
}
pub fn binDirs(_: *const ThisResolver) []const string { pub fn binDirs(_: *const ThisResolver) []const string {
if (!bin_folders_loaded) return &[_]string{}; if (!bin_folders_loaded) return &[_]string{};
return bin_folders.constSlice(); return bin_folders.constSlice();
@@ -2828,7 +2833,7 @@ pub const Resolver = struct {
r.dir_cache.markNotFound(queue_top.result); r.dir_cache.markNotFound(queue_top.result);
rfs.entries.markNotFound(cached_dir_entry_result); rfs.entries.markNotFound(cached_dir_entry_result);
if (comptime enable_logging) { if (comptime enable_logging) {
const pretty = queue_top.unsafe_path; const pretty = r.prettyPath(Path.init(queue_top.unsafe_path));
r.log.addErrorFmt( r.log.addErrorFmt(
null, null,
@@ -3466,68 +3471,54 @@ pub const Resolver = struct {
} }
pub fn loadAsIndex(r: *ThisResolver, dir_info: *DirInfo, extension_order: []const string) ?MatchResult { pub fn loadAsIndex(r: *ThisResolver, dir_info: *DirInfo, extension_order: []const string) ?MatchResult {
const rfs = &r.fs.fs;
// Try the "index" file with extensions // Try the "index" file with extensions
for (extension_order) |ext| { for (extension_order) |ext| {
if (loadIndexWithExtension(r, dir_info, ext)) |result| { var ext_buf = bufs(.extension_path);
return result;
}
}
for (r.opts.extra_cjs_extensions) |ext| {
if (loadIndexWithExtension(r, dir_info, ext)) |result| {
return result;
}
}
return null; var base = ext_buf[0 .. "index".len + ext.len];
} base[0.."index".len].* = "index".*;
bun.copy(u8, base["index".len..], ext);
fn loadIndexWithExtension(r: *ThisResolver, dir_info: *DirInfo, ext: string) ?MatchResult { if (dir_info.getEntries(r.generation)) |entries| {
const rfs = &r.fs.fs; if (entries.get(base)) |lookup| {
if (lookup.entry.kind(rfs, r.store_fd) == .file) {
const out_buf = brk: {
if (lookup.entry.abs_path.isEmpty()) {
const parts = [_]string{ dir_info.abs_path, base };
const out_buf_ = r.fs.absBuf(&parts, bufs(.index));
lookup.entry.abs_path =
PathString.init(r.fs.dirname_store.append(@TypeOf(out_buf_), out_buf_) catch unreachable);
}
break :brk lookup.entry.abs_path.slice();
};
var ext_buf = bufs(.extension_path); if (r.debug_logs) |*debug| {
debug.addNoteFmt("Found file: \"{s}\"", .{out_buf});
var base = ext_buf[0 .. "index".len + ext.len];
base[0.."index".len].* = "index".*;
bun.copy(u8, base["index".len..], ext);
if (dir_info.getEntries(r.generation)) |entries| {
if (entries.get(base)) |lookup| {
if (lookup.entry.kind(rfs, r.store_fd) == .file) {
const out_buf = brk: {
if (lookup.entry.abs_path.isEmpty()) {
const parts = [_]string{ dir_info.abs_path, base };
const out_buf_ = r.fs.absBuf(&parts, bufs(.index));
lookup.entry.abs_path =
PathString.init(r.fs.dirname_store.append(@TypeOf(out_buf_), out_buf_) catch unreachable);
} }
break :brk lookup.entry.abs_path.slice();
};
if (r.debug_logs) |*debug| { if (dir_info.package_json) |package_json| {
debug.addNoteFmt("Found file: \"{s}\"", .{out_buf}); return MatchResult{
} .path_pair = .{ .primary = Path.init(out_buf) },
.diff_case = lookup.diff_case,
.package_json = package_json,
.dirname_fd = dir_info.getFileDescriptor(),
};
}
if (dir_info.package_json) |package_json| {
return MatchResult{ return MatchResult{
.path_pair = .{ .primary = Path.init(out_buf) }, .path_pair = .{ .primary = Path.init(out_buf) },
.diff_case = lookup.diff_case, .diff_case = lookup.diff_case,
.package_json = package_json,
.dirname_fd = dir_info.getFileDescriptor(), .dirname_fd = dir_info.getFileDescriptor(),
}; };
} }
return MatchResult{
.path_pair = .{ .primary = Path.init(out_buf) },
.diff_case = lookup.diff_case,
.dirname_fd = dir_info.getFileDescriptor(),
};
} }
} }
}
if (r.debug_logs) |*debug| { if (r.debug_logs) |*debug| {
debug.addNoteFmt("Failed to find file: \"{s}/{s}\"", .{ dir_info.abs_path, base }); debug.addNoteFmt("Failed to find file: \"{s}/{s}\"", .{ dir_info.abs_path, base });
}
} }
return null; return null;
@@ -3751,7 +3742,7 @@ pub const Resolver = struct {
} }
pub fn loadAsFile(r: *ThisResolver, path: string, extension_order: []const string) ?LoadResult { pub fn loadAsFile(r: *ThisResolver, path: string, extension_order: []const string) ?LoadResult {
const rfs: *Fs.FileSystem.RealFS = &r.fs.fs; var rfs: *Fs.FileSystem.RealFS = &r.fs.fs;
if (r.debug_logs) |*debug| { if (r.debug_logs) |*debug| {
debug.addNoteFmt("Attempting to load \"{s}\" as a file", .{path}); debug.addNoteFmt("Attempting to load \"{s}\" as a file", .{path});
@@ -3783,7 +3774,7 @@ pub const Resolver = struct {
r.allocator, r.allocator,
"Cannot read directory \"{s}\": {s}", "Cannot read directory \"{s}\": {s}",
.{ .{
dir_path, r.prettyPath(Path.init(dir_path)),
@errorName(dir_entry.err.original_err), @errorName(dir_entry.err.original_err),
}, },
) catch {}; ) catch {};
@@ -3827,14 +3818,35 @@ pub const Resolver = struct {
// Try the path with extensions // Try the path with extensions
bun.copy(u8, bufs(.load_as_file), path); bun.copy(u8, bufs(.load_as_file), path);
for (extension_order) |ext| { for (extension_order) |ext| {
if (loadExtension(r, base, path, ext, entries)) |result| { var buffer = bufs(.load_as_file)[0 .. path.len + ext.len];
return result; bun.copy(u8, buffer[path.len..], ext);
} const file_name = buffer[path.len - base.len .. buffer.len];
}
for (r.opts.extra_cjs_extensions) |ext| { if (r.debug_logs) |*debug| {
if (loadExtension(r, base, path, ext, entries)) |result| { debug.addNoteFmt("Checking for file \"{s}\" ", .{buffer});
return result; }
if (entries.get(file_name)) |query| {
if (query.entry.kind(rfs, r.store_fd) == .file) {
if (r.debug_logs) |*debug| {
debug.addNoteFmt("Found file \"{s}\" ", .{buffer});
}
// now that we've found it, we allocate it.
return LoadResult{
.path = brk: {
query.entry.abs_path = if (query.entry.abs_path.isEmpty())
PathString.init(r.fs.dirname_store.append(@TypeOf(buffer), buffer) catch unreachable)
else
query.entry.abs_path;
break :brk query.entry.abs_path.slice();
},
.diff_case = query.diff_case,
.dirname_fd = entries.fd,
.file_fd = query.entry.cache.fd,
};
}
} }
} }
@@ -3919,42 +3931,6 @@ pub const Resolver = struct {
return null; return null;
} }
fn loadExtension(r: *ThisResolver, base: string, path: string, ext: string, entries: *Fs.FileSystem.DirEntry) ?LoadResult {
const rfs: *Fs.FileSystem.RealFS = &r.fs.fs;
const buffer = bufs(.load_as_file)[0 .. path.len + ext.len];
bun.copy(u8, buffer[path.len..], ext);
const file_name = buffer[path.len - base.len .. buffer.len];
if (r.debug_logs) |*debug| {
debug.addNoteFmt("Checking for file \"{s}\" ", .{buffer});
}
if (entries.get(file_name)) |query| {
if (query.entry.kind(rfs, r.store_fd) == .file) {
if (r.debug_logs) |*debug| {
debug.addNoteFmt("Found file \"{s}\" ", .{buffer});
}
// now that we've found it, we allocate it.
return .{
.path = brk: {
query.entry.abs_path = if (query.entry.abs_path.isEmpty())
PathString.init(r.fs.dirname_store.append(@TypeOf(buffer), buffer) catch unreachable)
else
query.entry.abs_path;
break :brk query.entry.abs_path.slice();
},
.diff_case = query.diff_case,
.dirname_fd = entries.fd,
.file_fd = query.entry.cache.fd,
};
}
}
return null;
}
fn dirInfoUncached( fn dirInfoUncached(
r: *ThisResolver, r: *ThisResolver,
info: *DirInfo, info: *DirInfo,
@@ -4162,7 +4138,8 @@ pub const Resolver = struct {
tsconfigpath, tsconfigpath,
if (FeatureFlags.store_file_descriptors) fd else .zero, if (FeatureFlags.store_file_descriptors) fd else .zero,
) catch |err| brk: { ) catch |err| brk: {
const pretty = tsconfigpath; const pretty = r.prettyPath(Path.init(tsconfigpath));
if (err == error.ENOENT or err == error.FileNotFound) { if (err == error.ENOENT or err == error.FileNotFound) {
r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot find tsconfig file {}", .{bun.fmt.QuotedFormatter{ .text = pretty }}) catch {}; r.log.addErrorFmt(null, logger.Loc.Empty, r.allocator, "Cannot find tsconfig file {}", .{bun.fmt.QuotedFormatter{ .text = pretty }}) catch {};
} else if (err != error.ParseErrorAlreadyLogged and err != error.IsDir and err != error.EISDIR) { } else if (err != error.ParseErrorAlreadyLogged and err != error.IsDir and err != error.EISDIR) {

View File

@@ -1177,21 +1177,21 @@ pub const Transpiler = struct {
transpiler.log, transpiler.log,
&source, &source,
) catch null) orelse return null) { ) catch null) orelse return null) {
.ast => |value| .{ .ast => |value| ParseResult{
.ast = value, .ast = value,
.source = source, .source = source,
.loader = loader, .loader = loader,
.input_fd = input_fd, .input_fd = input_fd,
.runtime_transpiler_cache = this_parse.runtime_transpiler_cache, .runtime_transpiler_cache = this_parse.runtime_transpiler_cache,
}, },
.cached => .{ .cached => ParseResult{
.ast = undefined, .ast = undefined,
.runtime_transpiler_cache = this_parse.runtime_transpiler_cache, .runtime_transpiler_cache = this_parse.runtime_transpiler_cache,
.source = source, .source = source,
.loader = loader, .loader = loader,
.input_fd = input_fd, .input_fd = input_fd,
}, },
.already_bundled => |already_bundled| .{ .already_bundled => |already_bundled| ParseResult{
.ast = undefined, .ast = undefined,
.already_bundled = switch (already_bundled) { .already_bundled = switch (already_bundled) {
.bun => .source_code, .bun => .source_code,

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1,3 +0,0 @@
import * as fs from "node:fs";
console.log(eval("typeof module === 'undefined'"));
+fs;

View File

@@ -1,3 +0,0 @@
{
"type": "commonjs"
}

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1 +0,0 @@
console.log(eval("typeof module === 'undefined'"));

View File

@@ -1,3 +0,0 @@
import * as fs from "node:fs";
console.log(eval("typeof module === 'undefined'"));
+fs;

View File

@@ -1,3 +0,0 @@
{
"type": "module"
}

View File

@@ -1,54 +0,0 @@
import { bunEnv, bunExe } from "harness";
import { join } from "path";
import { expect, test } from "bun:test";
// module type -> file extensions -> expected module type
const table = {
cjs: {
'hello.cjs': 'commonjs',
'hello.js': 'commonjs',
'hello.mjs': 'module',
'hello.ts': 'commonjs',
'hello.tsx': 'module',
'hello.cts': 'commonjs',
'hello.jsx': 'module',
'hello.mts': 'module',
// files using ES import and no exports will be detected as module
"import.cjs": "module",
},
esm: {
'hello.cjs': 'commonjs',
'hello.js': 'module',
'hello.mjs': 'module',
'hello.ts': 'module',
'hello.tsx': 'module',
'hello.cts': 'commonjs',
'hello.jsx': 'module',
'hello.mts': 'module',
// files using ES import and no exports will be detected as module
"import.cjs": "module",
},
};
test("detect module type", () => {
const expected = Object.entries(table).map(([moduleType, extensions]) => {
return Object.entries(extensions).map(([extension, expected]) => {
return `${moduleType} ${extension} -> ${expected}`;
});
}).flat();
const actual = Object.entries(table).map(([moduleType, extensions]) => {
return Object.entries(extensions).map(([extension, expected]) => {
const proc = Bun.spawnSync({
cmd: [bunExe(), "run", join(import.meta.dir, 'module-type-fixture', moduleType, extension)],
env: bunEnv,
});
if (proc.exitCode !== 0) {
throw new Error(`Failed to run ${moduleType} ${extension}: ${proc.stderr.toString('utf8').trim()}`);
}
return `${moduleType} ${extension} -> ${proc.stdout.toString('utf8').trim() === "false" ? "commonjs" : "module"}`;
});
}).flat();
expect(actual).toEqual(expected);
});

View File

@@ -27,7 +27,7 @@ const words: Record<string, { reason: string; limit?: number; regex?: boolean }>
"alloc.ptr !=": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" }, "alloc.ptr !=": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" },
"== alloc.ptr": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" }, "== alloc.ptr": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" },
"!= alloc.ptr": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" }, "!= alloc.ptr": { reason: "The std.mem.Allocator context pointer can be undefined, which makes this comparison undefined behavior" },
[String.raw`: [a-zA-Z0-9_\.\*\?\[\]\(\)]+ = undefined,`]: { reason: "Do not default a struct field to undefined", limit: 244, regex: true }, [String.raw`: [a-zA-Z0-9_\.\*\?\[\]\(\)]+ = undefined,`]: { reason: "Do not default a struct field to undefined", limit: 246, regex: true },
"usingnamespace": { reason: "This brings Bun away from incremental / faster compile times.", limit: 494 }, "usingnamespace": { reason: "This brings Bun away from incremental / faster compile times.", limit: 494 },
}; };
const words_keys = [...Object.keys(words)]; const words_keys = [...Object.keys(words)];

View File

@@ -1 +0,0 @@
module.exports = 'fail'

View File

@@ -1 +0,0 @@
module.exports = 'a unmodified';

View File

@@ -1 +0,0 @@
{ "hello": "world" }

View File

@@ -1,4 +0,0 @@
declare const y: string;
enum J { x = "hello " }
const hello: string = "world";
module.exports = J.x + hello!;

View File

@@ -1 +0,0 @@
{ "hello

View File

@@ -1 +0,0 @@
module.exports = 'c dot custom'

View File

@@ -1 +0,0 @@
module.exports = 'd.js'

View File

@@ -1,4 +0,0 @@
declare const y: string;
enum J { x = "hello" }
const hello: string = " world";
module.exports = J.x + hello!;

View File

@@ -1,76 +0,0 @@
import { test, mock, expect } from "bun:test";
import path from "path";
test("require.extensions shape makes sense", () => {
const extensions = require.extensions;
expect(extensions).toBeDefined();
expect(typeof extensions).toBe("object");
expect(extensions[".js"]).toBeFunction();
expect(extensions[".json"]).toBeFunction();
expect(extensions[".node"]).toBeFunction();
// When --experimental-strip-types is passed, TypeScript files can be loaded.
expect(extensions[".cts"]).toBeFunction();
expect(extensions[".ts"]).toBeFunction();
expect(extensions[".mjs"]).toBeFunction();
expect(extensions[".mts"]).toBeFunction();
});
test("custom require extension 1", () => {
const custom = require.extensions['.custom'] = mock(function (module, filename) {
expect(filename).toBe(path.join(import.meta.dir, 'extensions-fixture', 'c.custom'));
(module as any)._compile(`module.exports = 'custom';`, filename);
});
const mod = require('./extensions-fixture/c');
expect(mod).toBe('custom');
expect(custom.mock.calls.length).toBe(1);
delete require.extensions['.custom'];
expect(() => require('./extensions-fixture/c')).toThrow(/Cannot find module/);
expect(require('./extensions-fixture/c.custom')).toBe('custom'); // already loaded
delete require.cache[require.resolve('./extensions-fixture/c.custom')];
expect(custom.mock.calls.length).toBe(1);
expect(require('./extensions-fixture/c.custom')).toBe('c dot custom'); // use js loader
});
test("custom require extension overwrite default loader", () => {
const original = require.extensions['.js'];
try {
const custom = require.extensions['.js'] = mock(function (module, filename) {
expect(filename).toBe(path.join(import.meta.dir, 'extensions-fixture', 'd.js'));
(module as any)._compile(`module.exports = 'custom';`, filename);
});
const mod = require('./extensions-fixture/d');
expect(mod).toBe('custom');
expect(custom.mock.calls.length).toBe(1);
require.extensions['.js'] = original;
expect(require('./extensions-fixture/d')).toBe('custom'); // already loaded
delete require.cache[require.resolve('./extensions-fixture/d')];
expect(custom.mock.calls.length).toBe(1);
expect(require('./extensions-fixture/d')).toBe('d.js'); // use js loader
} finally {
require.extensions['.js'] = original;
}
});
test("custom require extension overwrite default loader with other default loader", () => {
const original = require.extensions['.js'];
try {
require.extensions['.js'] = require.extensions['.ts']!;
const mod = require('./extensions-fixture/e.js'); // should not enter JS
expect(mod).toBe('hello world');
} finally {
require.extensions['.js'] = original;
}
});
test("test that assigning properties weirdly wont do anything bad", () => {
const original = require.extensions['.js'];
try {
function f1() {}
function f2() {}
require.extensions['.js'] = f1;
require.extensions['.abc'] = f2;
require.extensions['.js'] = f2;
require.extensions['.js'] = undefined;
require.extensions['.abc'] = undefined;
require.extensions['.abc'] = f1;
require.extensions['.js'] = f2;
} finally {
require.extensions['.js'] = original;
}
});

View File

@@ -1,93 +0,0 @@
'use strict';
// Refs: https://github.com/nodejs/node/issues/4778
const common = require('../common');
const assert = require('assert');
const fs = require('fs');
const Module = require('module');
const tmpdir = require('../common/tmpdir');
const file = tmpdir.resolve('test-extensions.foo.bar');
const dotfile = tmpdir.resolve('.bar');
const dotfileWithExtension = tmpdir.resolve('.foo.bar');
tmpdir.refresh();
fs.writeFileSync(file, 'console.log(__filename);', 'utf8');
fs.writeFileSync(dotfile, 'console.log(__filename);', 'utf8');
fs.writeFileSync(dotfileWithExtension, 'console.log(__filename);', 'utf8');
{
require.extensions['.bar'] = common.mustNotCall();
require.extensions['.foo.bar'] = common.mustCall();
const modulePath = tmpdir.resolve('test-extensions');
require(modulePath);
require(file);
delete require.cache[file];
delete require.extensions['.bar'];
delete require.extensions['.foo.bar'];
Module._pathCache = { __proto__: null };
}
{
require.extensions['.foo.bar'] = common.mustCall();
const modulePath = tmpdir.resolve('test-extensions');
require(modulePath);
assert.throws(
() => require(`${modulePath}.foo`),
(err) => err.message.startsWith(`Cannot find module '${modulePath}.foo'`)
);
require(`${modulePath}.foo.bar`);
delete require.cache[file];
delete require.extensions['.foo.bar'];
Module._pathCache = { __proto__: null };
}
{
const modulePath = tmpdir.resolve('test-extensions');
assert.throws(
() => require(modulePath),
(err) => err.message.startsWith(`Cannot find module '${modulePath}'`)
);
delete require.cache[file];
Module._pathCache = { __proto__: null };
}
{
require.extensions['.bar'] = common.mustNotCall();
require.extensions['.foo.bar'] = common.mustCall();
const modulePath = tmpdir.resolve('test-extensions.foo');
require(modulePath);
delete require.cache[file];
delete require.extensions['.bar'];
delete require.extensions['.foo.bar'];
Module._pathCache = { __proto__: null };
}
{
require.extensions['.foo.bar'] = common.mustNotCall();
const modulePath = tmpdir.resolve('test-extensions.foo');
assert.throws(
() => require(modulePath),
(err) => err.message.startsWith(`Cannot find module '${modulePath}'`)
);
delete require.extensions['.foo.bar'];
Module._pathCache = { __proto__: null };
}
{
require.extensions['.bar'] = common.mustNotCall();
require(dotfile);
delete require.cache[dotfile];
delete require.extensions['.bar'];
Module._pathCache = { __proto__: null };
}
{
require.extensions['.bar'] = common.mustCall();
require.extensions['.foo.bar'] = common.mustNotCall();
require(dotfileWithExtension);
delete require.cache[dotfileWithExtension];
delete require.extensions['.bar'];
delete require.extensions['.foo.bar'];
Module._pathCache = { __proto__: null };
}