Skip to content

Commit b6d497e

Browse files
committed
feat: more robust commonjs vs esm conditional handling
1 parent 9c482b8 commit b6d497e

File tree

1 file changed

+58
-1
lines changed

1 file changed

+58
-1
lines changed

NativeScript/runtime/ModuleInternal.mm

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,41 @@ bool IsLikelyOptionalModule(const std::string& moduleName) {
129129

130130
moduleName = tns::ToString(isolate, info[0].As<v8::String>());
131131
callingModuleDirName = tns::ToString(isolate, info[1].As<v8::String>());
132-
if (moduleName.length() > 0 && moduleName[0] != '/') {
132+
133+
// Special handling for "./" - resolve to main entry point from package.json
134+
if (moduleName == "./") {
135+
id mainValue = Runtime::GetAppConfigValue("main");
136+
NSString* mainEntry = nil;
137+
138+
if (mainValue && [mainValue isKindOfClass:[NSString class]]) {
139+
mainEntry = (NSString*)mainValue;
140+
} else {
141+
// Fallback to "index" if no main field found
142+
mainEntry = @"index";
143+
}
144+
145+
// Try the main entry with different extensions
146+
NSString* basePath = [[NSString stringWithUTF8String:RuntimeConfig.ApplicationPath.c_str()]
147+
stringByAppendingPathComponent:mainEntry];
148+
149+
// Check if file exists as-is
150+
if (tns::Exists([basePath fileSystemRepresentation])) {
151+
fullPath = basePath;
152+
}
153+
// Try with .js extension
154+
else if (tns::Exists(
155+
[[basePath stringByAppendingPathExtension:@"js"] fileSystemRepresentation])) {
156+
fullPath = [basePath stringByAppendingPathExtension:@"js"];
157+
}
158+
// Try with .mjs extension
159+
else if (tns::Exists(
160+
[[basePath stringByAppendingPathExtension:@"mjs"] fileSystemRepresentation])) {
161+
fullPath = [basePath stringByAppendingPathExtension:@"mjs"];
162+
} else {
163+
// If none found, default to .js (let the loading system handle the error)
164+
fullPath = [basePath stringByAppendingPathExtension:@"js"];
165+
}
166+
} else if (moduleName.length() > 0 && moduleName[0] != '/') {
133167
if (moduleName[0] == '.') {
134168
fullPath = [[NSString stringWithUTF8String:callingModuleDirName.c_str()]
135169
stringByAppendingPathComponent:[NSString stringWithUTF8String:moduleName.c_str()]];
@@ -371,6 +405,17 @@ bool IsLikelyOptionalModule(const std::string& moduleName) {
371405
return moduleObj;
372406
}
373407

408+
// Check if this is the main application bundle (webpack-style IIFE)
409+
std::string appPath = RuntimeConfig.ApplicationPath;
410+
std::string bundlePath = appPath + "/bundle.js";
411+
412+
if (modulePath == bundlePath) {
413+
// Main application bundle is a webpack-style IIFE that executes immediately
414+
// It doesn't return a function, so we just create an empty exports object
415+
tempModule.SaveToCache();
416+
return moduleObj;
417+
}
418+
374419
// Classic CommonJS path – expect a factory function.
375420
if (!scriptValue->IsFunction()) {
376421
throw NativeScriptException(isolate,
@@ -683,6 +728,18 @@ ScriptOrigin origin(
683728
return tns::ToV8String(isolate, sourceText);
684729
}
685730

731+
// Check if this is the main application bundle (webpack-style IIFE)
732+
// Main bundles typically end with "bundle.js" and are in the app root
733+
std::string appPath = RuntimeConfig.ApplicationPath;
734+
std::string bundlePath = appPath + "/bundle.js";
735+
736+
if (path == bundlePath) {
737+
// Main application bundle should not be wrapped in CommonJS factory
738+
// as it's typically a webpack-style IIFE that executes immediately
739+
std::string sourceText = tns::ReadText(path);
740+
return tns::ToV8String(isolate, sourceText);
741+
}
742+
686743
// Worker .js files should use CommonJS wrapping like regular .js files
687744
// This ensures proper runtime context and global object setup
688745

0 commit comments

Comments
 (0)