Skip to content

Commit d036c75

Browse files
committed
fix: native methods expecting a NSError arg will now throw a JS exception if the error arg is not passed
1 parent 9bb09ec commit d036c75

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

NativeScript/runtime/Interop.mm

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1523,7 +1523,38 @@ inline bool isBool() {
15231523
NSError* error = errorPtr[0];
15241524
std::free(errorRef);
15251525
if (error) {
1526-
throw NativeScriptException([[error localizedDescription] UTF8String]);
1526+
// Create JS Error with localizedDescription, attach code, domain and nativeException,
1527+
// and throw it into V8 so JS catch handlers receive it (with proper stack).
1528+
Isolate* isolate = methodCall.context_->GetIsolate();
1529+
Local<Context> context = isolate->GetCurrentContext();
1530+
1531+
Local<Value> jsErrVal = Exception::Error(tns::ToV8String(isolate, [[error localizedDescription] UTF8String]));
1532+
if (jsErrVal.IsEmpty() || !jsErrVal->IsObject()) {
1533+
// Fallback: if for some reason we cannot create an Error object, throw a generic NativeScriptException
1534+
throw NativeScriptException([[error localizedDescription] UTF8String]);
1535+
}
1536+
1537+
Local<Object> jsErrObj = jsErrVal.As<Object>();
1538+
1539+
// Attach the NSError code (number) and domain (string)
1540+
jsErrObj->Set(context, tns::ToV8String(isolate, "code"), Number::New(isolate, (double)[error code])).FromMaybe(false);
1541+
if (error.domain) {
1542+
jsErrObj->Set(context, tns::ToV8String(isolate, "domain"), tns::ToV8String(isolate, [error.domain UTF8String])).FromMaybe(false);
1543+
} else {
1544+
jsErrObj->Set(context, tns::ToV8String(isolate, "domain"), Null(isolate)).FromMaybe(false);
1545+
}
1546+
1547+
// Wrap the native NSError instance into a JS object and attach as nativeException
1548+
ObjCDataWrapper* wrapper = new ObjCDataWrapper(error);
1549+
Local<Value> nativeWrapper = ArgConverter::CreateJsWrapper(context, wrapper, Local<Object>(), true);
1550+
jsErrObj->Set(context, tns::ToV8String(isolate, "nativeException"), nativeWrapper).FromMaybe(false);
1551+
1552+
// Ensure the Error has a proper 'name' property.
1553+
jsErrObj->Set(context, tns::ToV8String(isolate, "name"), tns::ToV8String(isolate, "NSError")).FromMaybe(false);
1554+
1555+
// Throw the JS Error with full stack information — V8 will populate the stack for the created Error object.
1556+
isolate->ThrowException(jsErrObj);
1557+
return Local<Value>();
15271558
}
15281559
}
15291560

0 commit comments

Comments
 (0)