From be0b109886222d2160df4c118c77e7da4ce34831 Mon Sep 17 00:00:00 2001 From: Martin Bektchiev Date: Tue, 18 Sep 2018 18:24:49 +0300 Subject: [PATCH] fix(objc-call): Don't crash when calling an optional protocol method refs #978 --- src/NativeScript/Metadata/Metadata.h | 7 ++++++- src/NativeScript/ObjC/ObjCMethodCall.h | 2 ++ src/NativeScript/ObjC/ObjCMethodCall.mm | 8 +++++++- src/metadata-generator | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/NativeScript/Metadata/Metadata.h b/src/NativeScript/Metadata/Metadata.h index 09a5cc471..61cb818a7 100644 --- a/src/NativeScript/Metadata/Metadata.h +++ b/src/NativeScript/Metadata/Metadata.h @@ -25,13 +25,15 @@ enum MetaFlags { FunctionReturnsUnmanaged = 3, FunctionIsVariadic = 5, FunctionOwnsReturnedCocoaObject = 4, + MemberIsOptional = 0, // Mustn't equal any Method or Property flag since it can be applicable to both MethodIsInitializer = 1, MethodIsVariadic = 2, MethodIsNullTerminatedVariadic = 3, MethodOwnsReturnedCocoaObject = 4, MethodHasErrorOutParameter = 5, PropertyHasGetter = 2, - PropertyHasSetter = 3 + PropertyHasSetter = 3, + }; /// This enum describes the possible ObjectiveC entity types. @@ -581,6 +583,9 @@ struct VarMeta : Meta { }; struct MemberMeta : Meta { + bool isOptional() const { + return this->flag(MetaFlags::MemberIsOptional); + } }; struct MethodMeta : MemberMeta { diff --git a/src/NativeScript/ObjC/ObjCMethodCall.h b/src/NativeScript/ObjC/ObjCMethodCall.h index 5d9f0ce6a..920cbecd7 100644 --- a/src/NativeScript/ObjC/ObjCMethodCall.h +++ b/src/NativeScript/ObjC/ObjCMethodCall.h @@ -66,6 +66,8 @@ class ObjCMethodCall : public FFICall { bool _hasErrorOutParameter; + bool _isOptional; + bool _isInitializer; SEL _selector; diff --git a/src/NativeScript/ObjC/ObjCMethodCall.mm b/src/NativeScript/ObjC/ObjCMethodCall.mm index 6633edfff..4be12b9ee 100644 --- a/src/NativeScript/ObjC/ObjCMethodCall.mm +++ b/src/NativeScript/ObjC/ObjCMethodCall.mm @@ -34,6 +34,7 @@ Base::initializeFFI(vm, { &preInvocation, &postInvocation }, returnTypeCell, parameterTypesCells, 2); this->_retainsReturnedCocoaObjects = metadata->ownsReturnedCocoaObject(); + this->_isOptional = metadata->isOptional(); this->_isInitializer = metadata->isInitializer(); this->_hasErrorOutParameter = metadata->hasErrorOutParameter(); @@ -130,7 +131,12 @@ static bool isJavaScriptDerived(JSC::JSValue value) { bool isInstance = !class_isMetaClass(object_getClass(target)); NSLog(@"> %@[%@ %@]", isInstance ? @"-" : @"+", NSStringFromClass(object_getClass(target)), NSStringFromSelector(call->_selector)); #endif - invocation.setArgument(0, target); + if (call->_isOptional && ![target respondsToSelector:call->_selector]) { + // Unimplemented optional method: Silently perform a dummy call to nil object + invocation.setArgument(0, nil); + } else { + invocation.setArgument(0, target); + } invocation.setArgument(1, call->_selector); invocation.function = call->_msgSend; } diff --git a/src/metadata-generator b/src/metadata-generator index 78acbc095..9790c66de 160000 --- a/src/metadata-generator +++ b/src/metadata-generator @@ -1 +1 @@ -Subproject commit 78acbc095d976fa99453490779e61e60949c837a +Subproject commit 9790c66de825f16957b4274e6762615f6ea7c231