@@ -114,14 +114,17 @@ bool IsLikelyOptionalModule(const std::string& moduleName) {
114
114
void ModuleInternal::RequireCallback (const FunctionCallbackInfo<Value>& info) {
115
115
Isolate* isolate = info.GetIsolate ();
116
116
117
+ // Declare these outside try block so they're available in catch
118
+ std::string moduleName;
119
+ std::string callingModuleDirName;
120
+ NSString * fullPath = nil ;
121
+
117
122
try {
118
123
ModuleInternal* moduleInternal =
119
124
static_cast <ModuleInternal*>(info.Data ().As <External>()->Value ());
120
125
121
- std::string moduleName = tns::ToString (isolate, info[0 ].As <v8::String>());
122
- std::string callingModuleDirName = tns::ToString (isolate, info[1 ].As <v8::String>());
123
-
124
- NSString * fullPath;
126
+ moduleName = tns::ToString (isolate, info[0 ].As <v8::String>());
127
+ callingModuleDirName = tns::ToString (isolate, info[1 ].As <v8::String>());
125
128
if (moduleName.length () > 0 && moduleName[0 ] != ' /' ) {
126
129
if (moduleName[0 ] == ' .' ) {
127
130
fullPath = [[NSString stringWithUTF8String: callingModuleDirName.c_str ()]
@@ -173,7 +176,50 @@ bool IsLikelyOptionalModule(const std::string& moduleName) {
173
176
info.GetReturnValue ().Set (exportsObj);
174
177
}
175
178
} catch (NativeScriptException& ex) {
176
- ex.ReThrowToV8 (isolate);
179
+ // Add context about the require call
180
+ std::string contextMsg = " Error in require() call:" ;
181
+ contextMsg += " \n Requested module: '" + moduleName + " '" ;
182
+ contextMsg += " \n Called from: " + callingModuleDirName;
183
+ if (fullPath != nil ) {
184
+ contextMsg += " \n Resolved path: " + std::string ([fullPath UTF8String ]);
185
+ }
186
+
187
+ // Add JavaScript stack trace to show who called require
188
+ Local<StackTrace> stackTrace =
189
+ StackTrace::CurrentStackTrace (isolate, 10 , StackTrace::StackTraceOptions::kDetailed );
190
+ std::string jsStackTrace = " " ;
191
+ if (!stackTrace.IsEmpty ()) {
192
+ for (int i = 0 ; i < stackTrace->GetFrameCount (); i++) {
193
+ Local<StackFrame> frame = stackTrace->GetFrame (isolate, i);
194
+ Local<v8::String> scriptName = frame->GetScriptName ();
195
+ Local<v8::String> functionName = frame->GetFunctionName ();
196
+ int lineNumber = frame->GetLineNumber ();
197
+ int columnNumber = frame->GetColumn ();
198
+
199
+ jsStackTrace += " \n at " ;
200
+ std::string funcName = tns::ToString (isolate, functionName);
201
+ std::string scriptNameStr = tns::ToString (isolate, scriptName);
202
+
203
+ if (!funcName.empty ()) {
204
+ jsStackTrace += funcName + " (" ;
205
+ } else {
206
+ jsStackTrace += " <anonymous> (" ;
207
+ }
208
+ jsStackTrace += scriptNameStr + " :" + std::to_string (lineNumber) + " :" +
209
+ std::to_string (columnNumber) + " )" ;
210
+ }
211
+ }
212
+
213
+ contextMsg += " \n\n JavaScript stack trace:" + jsStackTrace;
214
+ contextMsg += " \n\n Original error:\n " + ex.getMessage ();
215
+
216
+ // Include original stack trace if available
217
+ if (!ex.getStackTrace ().empty ()) {
218
+ contextMsg += " \n\n Original stack trace:\n " + ex.getStackTrace ();
219
+ }
220
+
221
+ NativeScriptException contextEx (isolate, contextMsg);
222
+ contextEx.ReThrowToV8 (isolate);
177
223
}
178
224
}
179
225
@@ -191,7 +237,20 @@ bool IsLikelyOptionalModule(const std::string& moduleName) {
191
237
192
238
Local<Object> moduleObj;
193
239
Local<Value> exportsObj;
194
- std::string path = this ->ResolvePath (isolate, baseDir, moduleName);
240
+ std::string path;
241
+
242
+ try {
243
+ path = this ->ResolvePath (isolate, baseDir, moduleName);
244
+ } catch (NativeScriptException& ex) {
245
+ // Add context about the module resolution
246
+ std::string contextMsg = " Failed to resolve module: '" + moduleName + " '" ;
247
+ contextMsg += " \n Base directory: " + baseDir;
248
+ contextMsg += " \n Module name: " + moduleName;
249
+ contextMsg += " \n\n Original error:\n " + ex.getMessage ();
250
+
251
+ throw NativeScriptException (isolate, contextMsg);
252
+ }
253
+
195
254
if (path.empty ()) {
196
255
// Create placeholder module for optional modules
197
256
if (IsLikelyOptionalModule (moduleName)) {
@@ -531,7 +590,20 @@ ScriptOrigin origin(
531
590
// Return empty string to indicate optional module not found
532
591
return std::string ();
533
592
}
534
- throw NativeScriptException (" The specified module does not exist: " + moduleName);
593
+
594
+ // Create a detailed error message with context
595
+ std::string errorMsg = " Module not found: '" + moduleName + " '" ;
596
+ errorMsg += " \n Base directory: " + baseDir;
597
+ errorMsg += " \n Attempted paths:" ;
598
+
599
+ // Show the original path attempt
600
+ NSString * originalPath =
601
+ [[baseDirStr stringByAppendingPathComponent: moduleNameStr] stringByStandardizingPath ];
602
+ errorMsg += " \n - " + std::string ([originalPath UTF8String ]);
603
+ errorMsg +=
604
+ " \n - " + std::string ([[originalPath stringByAppendingPathExtension: @" mjs" ] UTF8String ]);
605
+
606
+ throw NativeScriptException (isolate, errorMsg);
535
607
}
536
608
537
609
if (isDirectory == NO ) {
@@ -569,7 +641,14 @@ throw NativeScriptException("Unable to locate main entry in " +
569
641
// Return empty string to indicate optional module not found
570
642
return std::string ();
571
643
}
572
- throw NativeScriptException (" The specified module does not exist: " + moduleName);
644
+
645
+ // Create a detailed error message with context for package.json resolution
646
+ std::string errorMsg = " Module not found: '" + moduleName + " '" ;
647
+ errorMsg += " \n Base directory: " + baseDir;
648
+ errorMsg += " \n Attempted final paths:" ;
649
+ errorMsg += " \n - " + std::string ([fullPath UTF8String ]);
650
+
651
+ throw NativeScriptException (isolate, errorMsg);
573
652
}
574
653
575
654
return [fullPath UTF8String ];
0 commit comments