diff --git a/framework/ios/base/bridge/HippyBridge.h b/framework/ios/base/bridge/HippyBridge.h index 5563a61ac91..642c1d98d5b 100644 --- a/framework/ios/base/bridge/HippyBridge.h +++ b/framework/ios/base/bridge/HippyBridge.h @@ -256,6 +256,10 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass); - (id)moduleForName:(NSString *)moduleName; - (id)moduleForClass:(Class)moduleClass; +/// Get ModuleData by name +/// - Parameter moduleName: JS name of module +- (nullable HippyModuleData *)moduleDataForName:(NSString *)moduleName; + /** * Convenience method for retrieving all modules conforming to a given protocol. * Modules will be sychronously instantiated if they haven't already been, diff --git a/framework/ios/base/bridge/HippyBridge.mm b/framework/ios/base/bridge/HippyBridge.mm index c4f7bba4321..839a7303526 100644 --- a/framework/ios/base/bridge/HippyBridge.mm +++ b/framework/ios/base/bridge/HippyBridge.mm @@ -327,6 +327,13 @@ - (id)moduleForClass:(Class)moduleClass { return [_moduleSetup moduleForClass:moduleClass]; } +- (HippyModuleData *)moduleDataForName:(NSString *)moduleName { + if (moduleName) { + return _moduleSetup.moduleDataByName[moduleName]; + } + return nil; +} + - (void)addImageProviderClass:(Class)cls { HippyAssertParam(cls); @synchronized (self) { diff --git a/framework/ios/base/modules/HippyModuleData.h b/framework/ios/base/modules/HippyModuleData.h index e481a26d66d..958d92f4a8b 100644 --- a/framework/ios/base/modules/HippyModuleData.h +++ b/framework/ios/base/modules/HippyModuleData.h @@ -49,9 +49,11 @@ * Returns the module methods. Note that this will gather the methods the first * time it is called and then memoize the results. */ -@property (nonatomic, copy, readonly) NSArray> *methods; +@property (nonatomic, readonly) NSArray> *methods; -@property (nonatomic, copy, readonly) NSDictionary> *methodsByName; +/// Returns the module methods by name. Note that this will gather the methods the first +/// time it is called and then memoize the results. +@property (nonatomic, readonly) NSDictionary> *methodsByName; /** * Returns YES if module instance has already been initialized; NO otherwise. diff --git a/framework/ios/base/modules/HippyModuleData.mm b/framework/ios/base/modules/HippyModuleData.mm index e96494c7647..7c1a3974e3d 100644 --- a/framework/ios/base/modules/HippyModuleData.mm +++ b/framework/ios/base/modules/HippyModuleData.mm @@ -221,41 +221,58 @@ - (NSString *)name { return HippyBridgeModuleNameForClass(_moduleClass); } -- (NSArray> *)methods { - if (!_methods) { - NSMutableArray> *moduleMethods = [NSMutableArray new]; - - if ([_moduleClass instancesRespondToSelector:@selector(methodsToExport)]) { - [moduleMethods addObjectsFromArray:[self.instance methodsToExport]]; +- (void)collectAllModuleMethods { + NSMutableArray> *moduleMethods = [NSMutableArray new]; + NSMutableDictionary> *moduleMethodsByName = [NSMutableDictionary new]; + + if ([_moduleClass instancesRespondToSelector:@selector(methodsToExport)]) { + NSArray> *exportMethods = [self.instance methodsToExport]; + [moduleMethods addObjectsFromArray:exportMethods]; + for (id method in exportMethods) { + moduleMethodsByName[method.JSMethodName] = method; } - - unsigned int methodCount; - Class cls = _moduleClass; - while (cls && cls != [NSObject class] && cls != [NSProxy class]) { - Method *methods = class_copyMethodList(object_getClass(cls), &methodCount); - - for (unsigned int i = 0; i < methodCount; i++) { - Method method = methods[i]; - SEL selector = method_getName(method); - if ([NSStringFromSelector(selector) hasPrefix:@"__hippy_export__"]) { - IMP imp = method_getImplementation(method); - NSArray *entries = ((NSArray * (*)(id, SEL)) imp)(_moduleClass, selector); - id moduleMethod = [[HippyModuleMethod alloc] initWithMethodSignature:entries[1] JSMethodName:entries[0] - moduleClass:_moduleClass]; - - [moduleMethods addObject:moduleMethod]; - } + } + + unsigned int methodCount; + Class cls = _moduleClass; + while (cls && cls != [NSObject class] && cls != [NSProxy class]) { + Method *methods = class_copyMethodList(object_getClass(cls), &methodCount); + + for (unsigned int i = 0; i < methodCount; i++) { + Method method = methods[i]; + SEL selector = method_getName(method); + if ([NSStringFromSelector(selector) hasPrefix:@"__hippy_export__"]) { + IMP imp = method_getImplementation(method); + NSArray *entries = ((NSArray * (*)(id, SEL)) imp)(_moduleClass, selector); + id moduleMethod = [[HippyModuleMethod alloc] initWithMethodSignature:entries[1] JSMethodName:entries[0] + moduleClass:_moduleClass]; + [moduleMethods addObject:moduleMethod]; + moduleMethodsByName[moduleMethod.JSMethodName] = moduleMethod; } - - free(methods); - cls = class_getSuperclass(cls); } + + free(methods); + cls = class_getSuperclass(cls); + } + _methods = moduleMethods; + _methodsByName = moduleMethodsByName; +} - _methods = [moduleMethods copy]; +- (NSArray> *)methods { + if (!_methods) { + [self collectAllModuleMethods]; } return _methods; } +- (NSDictionary> *)methodsByName { + if (!_methodsByName) { + [self collectAllModuleMethods]; + } + return _methodsByName; +} + + - (void)gatherConstants { if (_hasConstantsToExport && !_constantsToExport) { (void)[self instance]; diff --git a/framework/ios/base/modules/HippyModuleMethod.mm b/framework/ios/base/modules/HippyModuleMethod.mm index 903500d60e5..0ac4f61637e 100644 --- a/framework/ios/base/modules/HippyModuleMethod.mm +++ b/framework/ios/base/modules/HippyModuleMethod.mm @@ -62,10 +62,9 @@ @implementation HippyModuleMethod { @synthesize arguments = _arguments; -static void HippyLogArgumentError( - __unused HippyModuleMethod *method, __unused NSUInteger index, __unused id valueOrType, __unused const char *issue) { - HippyLogError(nil, - @"Argument %tu (%@) of %@.%@ %s", index, valueOrType, HippyBridgeModuleNameForClass(method->_moduleClass), method.JSMethodName, issue); +static void HippyLogArgumentError(HippyModuleMethod *method, NSUInteger index, id valueOrType, const char *issue) { + HippyLogError(@"Argument %tu (%@) of %@.%@ %s", + index, valueOrType, HippyBridgeModuleNameForClass(method->_moduleClass), method.JSMethodName, issue); } // returns YES if the selector ends in a colon (indicating that there is at @@ -162,6 +161,23 @@ - (instancetype)initWithMethodSignature:(NSString *)methodSignature JSMethodName return self; } +static void enqueueBlockCallback(HippyBridge *bridge, HippyModuleMethod *moduleMethod, NSNumber *json, NSArray *args) { + if (!bridge || !moduleMethod) { + return; + } + BOOL shouldEnqueueCallback = YES; + if ([[bridge methodInterceptor] respondsToSelector:@selector(shouldCallbackBeInvokedWithModuleName:methodName:callbackId:arguments:)]) { + NSString *moduleName = HippyBridgeModuleNameForClass(moduleMethod.moduleClass); + shouldEnqueueCallback = [[bridge methodInterceptor] shouldCallbackBeInvokedWithModuleName:moduleName + methodName:[moduleMethod JSMethodName] + callbackId:json + arguments:args]; + } + if (shouldEnqueueCallback) { + [bridge enqueueCallback:json args:args]; + } +} + - (void)processMethodSignature { NSArray *arguments; _selector = HippyParseMethodSignature(_methodSignature, &arguments); @@ -193,39 +209,14 @@ - (void)processMethodSignature { CFBridgingRetain(value) __weak HippyModuleMethod *weakSelf = self; - void (^addBlockArgument)(void) = ^{ - HIPPY_ARG_BLOCK(if (HIPPY_DEBUG && json && ![json isKindOfClass:[NSNumber class]]) { - HippyLogArgumentError(weakSelf, index, json, "should be a function"); - return NO; - } - __weak HippyBridge *weakBridge = bridge; - Hippy_BLOCK_ARGUMENT(^(NSArray *args) { - __strong HippyBridge *strongBridge = weakBridge; - __strong HippyModuleMethod *strongSelf = weakSelf; - if (!strongBridge || !strongSelf) { - return; - } - BOOL shouldEnqueueCallback = YES; - if ([[strongBridge methodInterceptor] respondsToSelector:@selector(shouldCallbackBeInvokedWithModuleName:methodName:callbackId:arguments:)]) { - NSString *moduleName = HippyBridgeModuleNameForClass(strongSelf->_moduleClass); - shouldEnqueueCallback = - [[strongBridge methodInterceptor] shouldCallbackBeInvokedWithModuleName:moduleName - methodName:[strongSelf JSMethodName] - callbackId:json - arguments:args]; - } - if (shouldEnqueueCallback) { - [strongBridge enqueueCallback:json args:args]; - } - });) - }; - + for (NSUInteger i = 2; i < numberOfArguments; i++) { const char *objcType = [methodSignature getArgumentTypeAtIndex:i]; BOOL isNullableType = NO; HippyMethodArgument *argument = arguments[i - 2]; NSString *typeName = argument.type; SEL selector = HippyConvertSelectorForType(typeName); + static const char *blockType = @encode(__typeof(^ {})); if ([HippyConvert respondsToSelector:selector]) { switch (objcType[0]) { #define HIPPY_CASE(_value, _type) \ @@ -287,101 +278,78 @@ - (void)processMethodSignature { } default: { - static const char *blockType = @encode(__typeof(^ { - })); if (!strcmp(objcType, blockType)) { - addBlockArgument(); + HIPPY_ARG_BLOCK(if (HIPPY_DEBUG && json && ![json isKindOfClass:[NSNumber class]]) { + HippyLogArgumentError(weakSelf, index, json, "should be a function"); + return NO; + } + __weak HippyBridge *weakBridge = bridge; + Hippy_BLOCK_ARGUMENT(^(NSArray *args) { + enqueueBlockCallback(weakBridge, weakSelf, json, args); + });) } else { - HippyLogError(nil, @"Unsupported argument type '%@' in method %@.", typeName, [self methodName]); + HippyLogError(@"Unsupported argument type '%@' in method %@.", typeName, [self methodName]); } } } } else if ([typeName isEqualToString:@"HippyResponseSenderBlock"]) { - addBlockArgument(); - } else if ([typeName isEqualToString:@"HippyResponseErrorBlock"]) { - HIPPY_ARG_BLOCK( - - if (HIPPY_DEBUG && json && ![json isKindOfClass:[NSNumber class]]) { - HippyLogArgumentError(weakSelf, index, json, "should be a function"); - return NO; - } - __weak HippyBridge *weakBridge = bridge; - Hippy_BLOCK_ARGUMENT(^(NSError *error) { - __strong HippyBridge *strongBridge = weakBridge; - __strong HippyModuleMethod *strongSelf = weakSelf; - if (!strongBridge || !strongSelf) { - return; - } - NSArray *errorArgs = @[HippyJSErrorFromNSError(error)]; - BOOL shouldEnqueueCallback = YES; - if ([[strongBridge methodInterceptor] respondsToSelector:@selector(shouldCallbackBeInvokedWithModuleName:methodName:callbackId:arguments:)]) { - NSString *moduleName = HippyBridgeModuleNameForClass(strongSelf->_moduleClass); - shouldEnqueueCallback = - [[strongBridge methodInterceptor] shouldCallbackBeInvokedWithModuleName:moduleName - methodName:[strongSelf JSMethodName] - callbackId:json - arguments:errorArgs]; - } - if (shouldEnqueueCallback) { - [strongBridge enqueueCallback:json args:errorArgs]; - } - });) - } else if ([typeName isEqualToString:@"HippyPromiseResolveBlock"]) { - HippyAssert(i == numberOfArguments - 2, @"The HippyPromiseResolveBlock must be the second to last parameter in -[%@ %@]", _moduleClass, _methodSignature); - HIPPY_ARG_BLOCK(if (HIPPY_DEBUG && ![json isKindOfClass:[NSNumber class]]) { - HippyLogArgumentError(weakSelf, index, json, "should be a promise resolver function"); + HIPPY_ARG_BLOCK(if (HIPPY_DEBUG && json && ![json isKindOfClass:[NSNumber class]]) { + HippyLogArgumentError(weakSelf, index, json, "should be a function"); return NO; } __weak HippyBridge *weakBridge = bridge; - Hippy_BLOCK_ARGUMENT(^(id result) { - __strong HippyBridge *strongBridge = weakBridge; - __strong HippyModuleMethod *strongSelf = weakSelf; - if (!strongBridge || !strongSelf) { - return; - } - NSArray *args = result ? @[result] : @[]; - BOOL shouldEnqueueCallback = YES; - if ([[strongBridge methodInterceptor] respondsToSelector:@selector(shouldCallbackBeInvokedWithModuleName:methodName:callbackId:arguments:)]) { - NSString *moduleName = HippyBridgeModuleNameForClass(strongSelf->_moduleClass); - shouldEnqueueCallback = - [[strongBridge methodInterceptor] shouldCallbackBeInvokedWithModuleName:moduleName - methodName:[strongSelf JSMethodName] - callbackId:json - arguments:args]; - } - if (shouldEnqueueCallback) { - [strongBridge enqueueCallback:json args:args]; - } + Hippy_BLOCK_ARGUMENT(^(NSArray *args) { + enqueueBlockCallback(weakBridge, weakSelf, json, args); });) - } else if ([typeName isEqualToString:@"HippyPromiseRejectBlock"]) { - HippyAssert( - i == numberOfArguments - 1, @"The HippyPromiseRejectBlock must be the last parameter in -[%@ %@]", _moduleClass, _methodSignature); - HIPPY_ARG_BLOCK(if (HIPPY_DEBUG && ![json isKindOfClass:[NSNumber class]]) { - HippyLogArgumentError(weakSelf, index, json, "should be a promise rejecter function"); + } else if ([typeName isEqualToString:@"HippyResponseErrorBlock"]) { + HIPPY_ARG_BLOCK(if (HIPPY_DEBUG && json && ![json isKindOfClass:[NSNumber class]]) { + HippyLogArgumentError(weakSelf, index, json, "should be a function"); return NO; } __weak HippyBridge *weakBridge = bridge; - Hippy_BLOCK_ARGUMENT(^(NSString *code, NSString *message, NSError *error) { - __strong HippyBridge *strongBridge = weakBridge; - __strong HippyModuleMethod *strongSelf = weakSelf; - if (!strongBridge || !strongSelf) { - return; + Hippy_BLOCK_ARGUMENT(^(NSError *error) { + NSArray *errorArgs = @[HippyJSErrorFromNSError(error)]; + enqueueBlockCallback(weakBridge, weakSelf, json, errorArgs); + });) + } else if ([typeName isEqualToString:@"HippyPromiseResolveBlock"]) { + if (i != numberOfArguments - 2) { + HippyLogWarn(@"HippyPromiseResolveBlock should be the second to last parameter in -[%@ %@]", _moduleClass, _methodSignature); + } + HIPPY_ARG_BLOCK( + if (!json) { + HippyLogArgumentError(weakSelf, index, json, "should be a promise resolver function"); + return NO; } - NSDictionary *errorJSON = HippyJSErrorFromCodeMessageAndNSError(code, message, error); - NSArray *args = @[errorJSON]; - BOOL shouldEnqueueCallback = YES; - if ([[strongBridge methodInterceptor] respondsToSelector:@selector(shouldCallbackBeInvokedWithModuleName:methodName:callbackId:arguments:)]) { - NSString *moduleName = HippyBridgeModuleNameForClass(strongSelf->_moduleClass); - shouldEnqueueCallback = - [[strongBridge methodInterceptor] shouldCallbackBeInvokedWithModuleName:moduleName - methodName:[strongSelf JSMethodName] - callbackId:json - arguments:args]; + id blockArg = nil; + if (![json isKindOfClass:[NSNumber class]]) { + // In Hippy3.0, Dom Nodes call function by method name directly, + // so it is not a Number anymore. + // See NativeRenderManager::CallFunction() for more. + blockArg = json; + } else { + __weak HippyBridge *weakBridge = bridge; + blockArg = ^(id result){ + NSArray *args = result ? @[result] : @[]; + enqueueBlockCallback(weakBridge, weakSelf, json, args); + }; } - if (shouldEnqueueCallback) { - [strongBridge enqueueCallback:json args:args]; + Hippy_BLOCK_ARGUMENT(blockArg); + ) + } else if ([typeName isEqualToString:@"HippyPromiseRejectBlock"]) { + HippyAssert(i == numberOfArguments - 1, + @"HippyPromiseRejectBlock must be the last parameter in -[%@ %@]", _moduleClass, _methodSignature); + HIPPY_ARG_BLOCK( + if (HIPPY_DEBUG && ![json isKindOfClass:[NSNumber class]]) { + HippyLogArgumentError(weakSelf, index, json, "should be a promise rejecter function"); + return NO; } - });) + __weak HippyBridge *weakBridge = bridge; + Hippy_BLOCK_ARGUMENT(^(NSString *code, NSString *message, NSError *error) { + NSDictionary *errorJSON = HippyJSErrorFromCodeMessageAndNSError(code, message, error); + NSArray *args = @[errorJSON]; + enqueueBlockCallback(weakBridge, weakSelf, json, args); + }); + ) } else if ([HippyTurboModuleManager isTurboModule:typeName]) { [argumentBlocks addObject:^(__unused HippyBridge * bridge, NSUInteger index, id json) { [invocation setArgument:&json atIndex:(index) + 2]; @@ -390,9 +358,7 @@ - (void)processMethodSignature { }]; } else { // Unknown argument type - HippyLogError(nil, @"Unknown argument type '%@' in method %@. Extend HippyConvert" - " to support this type.", - typeName, [self methodName]); + HippyLogError(@"Unknown argument type '%@' in method %@. Extend HippyConvert to support this type.", typeName, [self methodName]); } if (HIPPY_DEBUG) { diff --git a/renderer/native/ios/renderer/HippyComponentData.h b/renderer/native/ios/renderer/HippyComponentData.h index b5014a3b283..5403beb3de9 100644 --- a/renderer/native/ios/renderer/HippyComponentData.h +++ b/renderer/native/ios/renderer/HippyComponentData.h @@ -69,7 +69,7 @@ - (NSDictionary *)eventNameMap; -- (NSDictionary *)methodsByName; + - (HippyViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(NSDictionary *)registry; diff --git a/renderer/native/ios/renderer/HippyComponentData.mm b/renderer/native/ios/renderer/HippyComponentData.mm index 6b4c32352c9..46bb1e329dc 100644 --- a/renderer/native/ios/renderer/HippyComponentData.mm +++ b/renderer/native/ios/renderer/HippyComponentData.mm @@ -56,7 +56,6 @@ @interface HippyComponentData () { NSMutableDictionary *_eventNameMap; BOOL _implementsUIBlockToAmendWithRenderObjectRegistry; __weak HippyViewManager *_manager; - NSDictionary *_methodsByName; } @end @@ -426,89 +425,6 @@ - (void)setProps:(NSDictionary *)props forShadowView:(HippyShado return [_eventNameMap copy]; } -- (NSDictionary *)methodsByName { - if (!_methodsByName) { - [self methods]; - } - return [_methodsByName copy]; -} - -- (void)methods { - if (!_methodsByName) { - NSMutableDictionary *methodsDic = [NSMutableDictionary dictionary]; - unsigned int methodCount; - Class cls = _managerClass; - while (cls && cls != [NSObject class] && cls != [NSProxy class]) { - Method *methods = class_copyMethodList(object_getClass(cls), &methodCount); - for (unsigned int i = 0; i < methodCount; i++) { - Method method = methods[i]; - SEL selector = method_getName(method); - if ([NSStringFromSelector(selector) hasPrefix:@"__hippy_export__"]) { - IMP imp = method_getImplementation(method); - NSArray *entries = ((NSArray * (*)(id, SEL)) imp)(_managerClass, selector); - NSString *JSMethodName = [self JSMethodNameFromEntries:entries]; - NSString *selectorString = [self selectorStringFromSignature:entries[1]]; - NSValue *selectorPointer = [NSValue valueWithPointer:NSSelectorFromString(selectorString)]; - [methodsDic setObject:selectorPointer forKey:JSMethodName]; - } - } - free(methods); - cls = class_getSuperclass(cls); - } - _methodsByName = [methodsDic copy]; - } -} - -- (NSString *)JSMethodNameFromEntries:(NSArray *)entries { - NSAssert(2 == [entries count], @"entries should contains 2 items, one is js method, the other is method signature"); - NSString *jsName = [entries firstObject]; - if ([jsName length] > 0) { - return jsName; - } - NSString *signature = [entries lastObject]; - NSRange range = [signature rangeOfString:@":"]; - if (NSNotFound != range.location) { - jsName = [signature substringToIndex:range.location]; - jsName = [jsName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - return jsName; - } - return @""; -} - -- (NSString *)selectorStringFromSignature:(NSString *)signature { - // signature = @"createView:(nonnull NSNumber *)hippyTag viewName:(NSString *)viewName rootTag:(nonnull NSNumber *)rootTag tagName:(NSString *)tagName props:(NSDictionary *)props"; - // signature = @"startBatch"; - // signature = @"endBatch:"; - // signature = @"startBatch:::"; - // signature = @"startBatch:_::"; - NSArray *colonsComponent = [signature componentsSeparatedByString:@":"]; - NSUInteger colonsComponentCount = [colonsComponent count]; - NSMutableString *selString = [NSMutableString stringWithCapacity:64]; - if (1 == colonsComponentCount) { - [selString appendString:signature]; - } - else { - for (NSUInteger i = 0; i < colonsComponentCount; i++) { - if (i == colonsComponentCount - 1) { - break; - } - NSString *signaturePart = colonsComponent[i]; - signaturePart = [signaturePart stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - NSUInteger lastWhitespaceLocation = [signaturePart rangeOfString:@" " options:NSBackwardsSearch].location; - NSString *selPartString = nil; - if (NSNotFound == lastWhitespaceLocation) { - selPartString = signaturePart; - } - else { - selPartString = [signaturePart substringFromIndex:lastWhitespaceLocation + 1]; - } - [selString appendFormat:@"%@:", selPartString]; - } - } - NSAssert([selString length] > 0, @"signature parse failed"); - return [selString copy]; -} - - (HippyViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(NSDictionary *)registry { if (_implementsUIBlockToAmendWithRenderObjectRegistry) { return [[self manager] uiBlockToAmendWithShadowViewRegistry:registry]; diff --git a/renderer/native/ios/renderer/HippyUIManager+Private.h b/renderer/native/ios/renderer/HippyUIManager+Private.h index a8a8b95ddfa..ce496e6e83a 100644 --- a/renderer/native/ios/renderer/HippyUIManager+Private.h +++ b/renderer/native/ios/renderer/HippyUIManager+Private.h @@ -106,15 +106,13 @@ class HippyValue; * @param hippyTag id of target view whose function invokes * @param params parameters of function to be invoked * @param cb A callback for the return value of function - * - * @result Function return result */ -- (id)dispatchFunction:(const std::string &)functionName - viewName:(const std::string &)viewName - viewTag:(int32_t)hippyTag - onRootNode:(std::weak_ptr)rootNode - params:(const footstone::value::HippyValue &)params - callback:(hippy::CallFunctionCallback)cb; +- (void)dispatchFunction:(const std::string &)functionName + viewName:(const std::string &)viewName + viewTag:(int32_t)hippyTag + onRootNode:(std::weak_ptr)rootNode + params:(const footstone::value::HippyValue &)params + callback:(hippy::CallFunctionCallback)cb; /** diff --git a/renderer/native/ios/renderer/HippyUIManager.mm b/renderer/native/ios/renderer/HippyUIManager.mm index ceff718e424..3512b59423c 100644 --- a/renderer/native/ios/renderer/HippyUIManager.mm +++ b/renderer/native/ios/renderer/HippyUIManager.mm @@ -51,6 +51,9 @@ #include "objc/runtime.h" #include +#import "HippyModuleData.h" +#import "HippyModuleMethod.h" + using HippyValue = footstone::value::HippyValue; using DomArgument = hippy::dom::DomArgument; using DomManager = hippy::DomManager; @@ -1070,15 +1073,15 @@ - (void)batchOnRootNode:(std::weak_ptr)rootNode { } } -- (id)dispatchFunction:(const std::string &)functionName - viewName:(const std::string &)viewName - viewTag:(int32_t)componentTag - onRootNode:(std::weak_ptr)rootNode - params:(const HippyValue &)params - callback:(CallFunctionCallback)cb { +- (void)dispatchFunction:(const std::string &)functionName + viewName:(const std::string &)viewName + viewTag:(int32_t)componentTag + onRootNode:(std::weak_ptr)rootNode + params:(const HippyValue &)params + callback:(CallFunctionCallback)cb { NSString *name = [NSString stringWithUTF8String:functionName.c_str()]; DomValueType type = params.GetType(); - NSMutableArray *finalParams = [NSMutableArray arrayWithCapacity:8]; + NSMutableArray *finalParams = [NSMutableArray array]; [finalParams addObject:@(componentTag)]; if (DomValueType::kArray == type) { NSArray * paramsArray = DomValueToOCType(¶ms); @@ -1088,15 +1091,12 @@ - (id)dispatchFunction:(const std::string &)functionName [finalParams addObject:param]; } } + } else if (DomValueType::kNull == type) { + // no op + } else { + NSAssert(NO, @"Unsupported params type"); } - else if (DomValueType::kNull == type) { - - } - else { - //TODO - NSAssert(NO, @"目前hippy底层会封装DomValue为Array类型。可能第三方接入者不一定会将其封装为Array"); - [finalParams addObject:[NSNull null]]; - } + if (cb) { HippyPromiseResolveBlock senderBlock = ^(id senderParams) { std::shared_ptr domArgument = std::make_shared([senderParams toDomArgument]); @@ -1104,37 +1104,24 @@ - (id)dispatchFunction:(const std::string &)functionName }; [finalParams addObject:senderBlock]; } + NSString *nativeModuleName = [NSString stringWithUTF8String:viewName.c_str()]; - - HippyViewManager *viewManager = [self viewManagerForViewName:nativeModuleName]; HippyComponentData *componentData = [self componentDataForViewName:nativeModuleName]; - NSValue *selectorPointer = [componentData.methodsByName objectForKey:name]; - SEL selector = (SEL)[selectorPointer pointerValue]; - if (!selector) { - return nil; - } - @try { - NSMethodSignature *methodSignature = [viewManager methodSignatureForSelector:selector]; - NSAssert(methodSignature, @"method signature creation failure"); - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - for (NSInteger i = 0; i < [finalParams count]; i++) { - id object = finalParams[i]; - [invocation setArgument:&object atIndex:i+2]; - } - [invocation invokeWithTarget:viewManager]; - void *returnValue = nil; - if (strcmp(invocation.methodSignature.methodReturnType, "@") == 0) { - [invocation getReturnValue:&returnValue]; - return (__bridge id)returnValue; + HippyModuleData *moduleData = [self.bridge moduleDataForName:nativeModuleName]; + id method = moduleData.methodsByName[name]; + if (method) { + @try { + [method invokeWithBridge:_bridge module:componentData.manager arguments:finalParams]; + } @catch (NSException *exception) { + NSString *errMsg = [NSString stringWithFormat:@"Exception '%@' was thrown while invoking %@ on component %@ with params %@", + exception, name, nativeModuleName, finalParams]; + HippyFatal(HippyErrorWithMessage(errMsg)); } - return nil; - } @catch (NSException *exception) { - NSString *message = [NSString stringWithFormat:@"Exception '%@' was thrown while invoking %@ on component target %@ with params %@", exception, name, nativeModuleName, finalParams]; - NSError *error = HippyErrorWithMessage(message); - HippyFatal(error); - return nil; + } else { + NSString *errMsg = [NSString stringWithFormat:@"No corresponding method(%@ of %@) was found!", name, nativeModuleName]; + HippyFatal(HippyErrorWithMessage(errMsg)); } + return; } - (void)registerExtraComponent:(NSArray *)extraComponents {