From 2ccfe007fbf1b9475ee446a498e930f9616d86e2 Mon Sep 17 00:00:00 2001 From: luomy Date: Mon, 24 Jul 2023 20:36:36 +0800 Subject: [PATCH] fix(ios): jsi api runs on cpp thread should use autorelease scope --- ios/sdk/module/turbo/HippyOCTurboModule.mm | 449 +++++++++--------- .../module/turbo/HippyTurboModuleManager.mm | 99 ++-- ios/sdk/module/turbo/NSObject+HippyTurbo.mm | 56 ++- 3 files changed, 319 insertions(+), 285 deletions(-) diff --git a/ios/sdk/module/turbo/HippyOCTurboModule.mm b/ios/sdk/module/turbo/HippyOCTurboModule.mm index 7ab518df0b8..c7b54914905 100644 --- a/ios/sdk/module/turbo/HippyOCTurboModule.mm +++ b/ios/sdk/module/turbo/HippyOCTurboModule.mm @@ -77,27 +77,29 @@ - (void)saveTurboWrapper:(std::shared_ptr)name turbo:(std::unique_ptr< this_val:(const std::shared_ptr&) this_val args:(const std::shared_ptr*) args count:(size_t) count { - // get method name - unicode_string_view name; - if (!ctx->GetValueString(this_val, &name)) { - return ctx->CreateNull(); - } - std::string methodName = StringViewUtils::ToU8StdStr(name); - - __weak HippyOCTurboModule *weakSelf = self; - - // get argument - NSMutableArray *argumentArray = @[].mutableCopy; - for (NSInteger i = 0; i < count; ++i) { - std::shared_ptr ctxValue = *(args + i); - [argumentArray addObject:convertCtxValueToObjcObject(ctx, ctxValue, weakSelf)?: [NSNull null]]; - } + @autoreleasepool { + // get method name + unicode_string_view name; + if (!ctx->GetValueString(this_val, &name)) { + return ctx->CreateNull(); + } + std::string methodName = StringViewUtils::ToU8StdStr(name); + + __weak HippyOCTurboModule *weakSelf = self; - id objcRes = [weakSelf invokeObjCMethodWithName:[NSString stringWithUTF8String:methodName.c_str()] - argumentCount:count - argumentArray:argumentArray]; - std::shared_ptr result = convertObjcObjectToCtxValue(ctx, objcRes, weakSelf); - return result; + // get argument + NSMutableArray *argumentArray = @[].mutableCopy; + for (NSInteger i = 0; i < count; ++i) { + std::shared_ptr ctxValue = *(args + i); + [argumentArray addObject:convertCtxValueToObjcObject(ctx, ctxValue, weakSelf)?: [NSNull null]]; + } + + id objcRes = [weakSelf invokeObjCMethodWithName:[NSString stringWithUTF8String:methodName.c_str()] + argumentCount:count + argumentArray:argumentArray]; + std::shared_ptr result = convertObjcObjectToCtxValue(ctx, objcRes, weakSelf); + return result; + } } - (id)invokeObjCMethodWithName:(NSString *)methodName @@ -113,34 +115,36 @@ - (id)invokeObjCMethodWithName:(NSString *)methodName argumentCount:(NSInteger)argumentCount argumentArray:(NSArray *)argumentArray object:(NSObject *)obj { - NSArray> *moduleMethods = [obj hippyTurboModuleMethods]; - id method; - for (id m in moduleMethods) { - if ([m.JSMethodName isEqualToString:methodName]) { - method = m; - break; + @autoreleasepool { + NSArray> *moduleMethods = [obj hippyTurboModuleMethods]; + id method; + for (id m in moduleMethods) { + if ([m.JSMethodName isEqualToString:methodName]) { + method = m; + break; + } } - } - - if (HIPPY_DEBUG && !method) { - HippyLogError(@"Unknown methodID: %@ for module:%@", methodName, obj); - return nil; - } - @try { - id value = [method invokeWithBridge:_bridge module:obj arguments:argumentArray]; - return value; - } @catch (NSException *exception) { - // Pass on JS exceptions - if ([exception.name hasPrefix:HippyFatalExceptionName]) { - @throw exception; + if (HIPPY_DEBUG && !method) { + HippyLogError(@"Unknown methodID: %@ for module:%@", methodName, obj); + return nil; } - NSString *message = [NSString stringWithFormat:@"Exception '%@' was thrown while invoking %@ on target %@ with params %@", exception, - method.JSMethodName, NSStringFromClass([self class]) ,argumentArray]; - NSError *error = HippyErrorWithMessageAndModuleName(message, self.bridge.moduleName); - HippyFatal(error); - return nil; + @try { + id value = [method invokeWithBridge:_bridge module:obj arguments:argumentArray]; + return value; + } @catch (NSException *exception) { + // Pass on JS exceptions + if ([exception.name hasPrefix:HippyFatalExceptionName]) { + @throw exception; + } + + NSString *message = [NSString stringWithFormat:@"Exception '%@' was thrown while invoking %@ on target %@ with params %@", exception, + method.JSMethodName, NSStringFromClass([self class]) ,argumentArray]; + NSError *error = HippyErrorWithMessageAndModuleName(message, self.bridge.moduleName); + HippyFatal(error); + return nil; + } } } @@ -149,29 +153,30 @@ - (id)invokeObjCMethodWithName:(NSString *)methodName static std::shared_ptr convertObjcObjectToCtxValue(const std::shared_ptr &context, id objcObject, HippyOCTurboModule *module) { - - std::shared_ptr result; - - if ([objcObject isKindOfClass:[NSString class]]) { - std::string str = [((NSString *)objcObject) UTF8String]; - unicode_string_view str_view(StringViewUtils::ToU8Pointer(str.c_str())); - result = context->CreateString(str_view); - } else if ([objcObject isKindOfClass:[NSNumber class]]) { - if ([objcObject isKindOfClass:[@YES class]]) { - result = context->CreateBoolean(((NSNumber *)objcObject).boolValue); - } else { - result = context->CreateNumber(((NSNumber *)objcObject).doubleValue); - } - } else if ([objcObject isKindOfClass:[NSDictionary class]]) { - result = convertNSDictionaryToCtxValue(context, objcObject, module); - } else if ([objcObject isKindOfClass:[NSArray class]]) { - result = convertNSArrayToCtxValue(context, objcObject, module); - } else if ([objcObject isKindOfClass:[NSObject class]]) { - result = convertNSObjectToCtxValue(context, objcObject, module); - } else { - result = context->CreateNull(); + @autoreleasepool { + std::shared_ptr result; + + if ([objcObject isKindOfClass:[NSString class]]) { + std::string str = [((NSString *)objcObject) UTF8String]; + unicode_string_view str_view(StringViewUtils::ToU8Pointer(str.c_str())); + result = context->CreateString(str_view); + } else if ([objcObject isKindOfClass:[NSNumber class]]) { + if ([objcObject isKindOfClass:[@YES class]]) { + result = context->CreateBoolean(((NSNumber *)objcObject).boolValue); + } else { + result = context->CreateNumber(((NSNumber *)objcObject).doubleValue); + } + } else if ([objcObject isKindOfClass:[NSDictionary class]]) { + result = convertNSDictionaryToCtxValue(context, objcObject, module); + } else if ([objcObject isKindOfClass:[NSArray class]]) { + result = convertNSArrayToCtxValue(context, objcObject, module); + } else if ([objcObject isKindOfClass:[NSObject class]]) { + result = convertNSObjectToCtxValue(context, objcObject, module); + } else { + result = context->CreateNull(); + } + return result; } - return result; } static std::shared_ptr convertNSDictionaryToCtxValue(const std::shared_ptr &context, @@ -193,71 +198,76 @@ - (id)invokeObjCMethodWithName:(NSString *)methodName const char* json = [str UTF8String]; result = context->CreateObject(json); */ - - if (!dict) { - return context->CreateNull(); - } - - std::shared_ptr jscCtx = std::static_pointer_cast(context); - JSClassDefinition cls_def = kJSClassDefinitionEmpty; - cls_def.className = [@"Object" UTF8String]; - JSClassRef cls_ref = JSClassCreate(&cls_def); - JSObjectRef jsObj = JSObjectMake(jscCtx->context_, cls_ref, (__bridge void *)dict); - JSClassRelease(cls_ref); - for (NSString *propertyName in dict) { - id propValue = [dict objectForKey:propertyName]; - std::shared_ptr propRef = convertObjcObjectToCtxValue(jscCtx, propValue, module); - std::shared_ptr ctx_value = - std::static_pointer_cast(propRef); - JSValueRef valueRef = ctx_value->value_; + @autoreleasepool { + if (!dict) { + return context->CreateNull(); + } - JSStringRef propName = JSStringCreateWithCFString((__bridge CFStringRef)propertyName); - JSValueRef jsError = NULL; - JSObjectSetProperty(jscCtx->context_, - jsObj, - propName, - valueRef, - kJSPropertyAttributeNone, - &jsError); - JSStringRelease(propName); + std::shared_ptr jscCtx = std::static_pointer_cast(context); + JSClassDefinition cls_def = kJSClassDefinitionEmpty; + cls_def.className = [@"Object" UTF8String]; + JSClassRef cls_ref = JSClassCreate(&cls_def); + JSObjectRef jsObj = JSObjectMake(jscCtx->context_, cls_ref, (__bridge void *)dict); + JSClassRelease(cls_ref); + for (NSString *propertyName in dict) { + id propValue = [dict objectForKey:propertyName]; + std::shared_ptr propRef = convertObjcObjectToCtxValue(jscCtx, propValue, module); + std::shared_ptr ctx_value = + std::static_pointer_cast(propRef); + JSValueRef valueRef = ctx_value->value_; + + JSStringRef propName = JSStringCreateWithCFString((__bridge CFStringRef)propertyName); + JSValueRef jsError = NULL; + JSObjectSetProperty(jscCtx->context_, + jsObj, + propName, + valueRef, + kJSPropertyAttributeNone, + &jsError); + JSStringRelease(propName); + } + return std::make_shared(jscCtx->context_, jsObj); } - return std::make_shared(jscCtx->context_, jsObj); } static std::shared_ptr convertNSArrayToCtxValue(const std::shared_ptr &context, NSArray *array, HippyOCTurboModule *module) { - if (!array) { - return context->CreateNull(); - } - - size_t size = static_cast(array.count); - std::shared_ptr buffer[size]; - for (size_t idx = 0; idx < array.count; idx++) { - buffer[idx] = convertObjcObjectToCtxValue(context, array[idx], module); + @autoreleasepool { + if (!array) { + return context->CreateNull(); + } + + size_t size = static_cast(array.count); + std::shared_ptr buffer[size]; + for (size_t idx = 0; idx < array.count; idx++) { + buffer[idx] = convertObjcObjectToCtxValue(context, array[idx], module); + } + return context->CreateArray(size, buffer); } - return context->CreateArray(size, buffer); } static std::shared_ptr convertNSObjectToCtxValue(const std::shared_ptr &context, id objcObject, HippyOCTurboModule *module) { - std::shared_ptr jscCtx = std::static_pointer_cast(context); - if ([objcObject isKindOfClass:[HippyOCTurboModule class]]) { - NSString *name = [[objcObject class] turboModuleName]; - HippyJSCExecutor *jsExecutor = (HippyJSCExecutor *)module.bridge.javaScriptExecutor; - JSValueRef jsValueObj = [jsExecutor JSTurboObjectWithName:name]; - JSObjectRef jsObj = JSValueToObject(jscCtx->context_, jsValueObj, NULL); - - JSGlobalContextRef globalContextRef = JSContextGetGlobalContext(jscCtx->context_); - JSContext *ctx = [JSContext contextWithJSGlobalContextRef:globalContextRef]; - JSValue *jsValue = [JSValue valueWithJSValueRef:jsValueObj inContext:ctx]; - HippyTurboModuleManager *turboManager = module.bridge.turboModuleManager; - [turboManager bindJSObject:jsValue toModuleName:name]; - - return std::make_shared(jscCtx->context_, jsObj); + @autoreleasepool { + std::shared_ptr jscCtx = std::static_pointer_cast(context); + if ([objcObject isKindOfClass:[HippyOCTurboModule class]]) { + NSString *name = [[objcObject class] turboModuleName]; + HippyJSCExecutor *jsExecutor = (HippyJSCExecutor *)module.bridge.javaScriptExecutor; + JSValueRef jsValueObj = [jsExecutor JSTurboObjectWithName:name]; + JSObjectRef jsObj = JSValueToObject(jscCtx->context_, jsValueObj, NULL); + + JSGlobalContextRef globalContextRef = JSContextGetGlobalContext(jscCtx->context_); + JSContext *ctx = [JSContext contextWithJSGlobalContextRef:globalContextRef]; + JSValue *jsValue = [JSValue valueWithJSValueRef:jsValueObj inContext:ctx]; + HippyTurboModuleManager *turboManager = module.bridge.turboModuleManager; + [turboManager bindJSObject:jsValue toModuleName:name]; + + return std::make_shared(jscCtx->context_, jsObj); + } + return std::make_shared(jscCtx->context_, JSValueMakeNull(jscCtx->context_)); } - return std::make_shared(jscCtx->context_, JSValueMakeNull(jscCtx->context_)); } #pragma mark - @@ -273,130 +283,139 @@ - (id)invokeObjCMethodWithName:(NSString *)methodName static id convertCtxValueToObjcObject(const std::shared_ptr &context, const std::shared_ptr &value, HippyOCTurboModule *module) { - - std::shared_ptr jscCtx = std::static_pointer_cast(context); - std::shared_ptr jscValue = std::static_pointer_cast(value); - - id objcObject; - double numberResult; - bool boolResult; - unicode_string_view result; - - if (context->IsNullOrUndefined(value)) { - objcObject = nil; - } else if (context->GetValueNumber(value, &numberResult)) { - objcObject = @(numberResult); - } else if (context->GetValueBoolean(value, &boolResult)) { - objcObject = @(boolResult); - } else if (context->GetValueString(value, &result)) { - std::string resultStr = StringViewUtils::ToU8StdStr(result); - objcObject = [NSString stringWithUTF8String:resultStr.c_str()]; - } else if (JSValueIsObject(jscCtx->context_, jscValue->value_)) { - if (context->IsArray(value)) { - objcObject = convertJSIArrayToNSArray(jscCtx, jscValue, module); - } else if (context->IsFunction(value)) { - // HippyResponseSenderBlock - // NOTE: 方法必须走promise -// return ^(NSArray *result) { -// size_t argumentCount = static_cast(result.count); -// std::shared_ptr argumets[argumentCount]; -// for(NSUInteger i = 0; i< result.count; i++){ -// size_t index = static_cast(i); -// argumets[index] = convertObjcObjectToCtxValue(context, result[i]); -// } -// context->CallFunction(value, argumentCount, argumets); -// }; - objcObject = @(0); - } else { - objcObject = convertJSIObjectToTurboObject(jscCtx, jscValue, module); - if (!objcObject) { - //map - objcObject = convertJSIObjectToNSDictionary(jscCtx, jscValue, module); + @autoreleasepool { + std::shared_ptr jscCtx = std::static_pointer_cast(context); + std::shared_ptr jscValue = std::static_pointer_cast(value); + + id objcObject; + double numberResult; + bool boolResult; + unicode_string_view result; + + if (context->IsNullOrUndefined(value)) { + objcObject = nil; + } else if (context->GetValueNumber(value, &numberResult)) { + objcObject = @(numberResult); + } else if (context->GetValueBoolean(value, &boolResult)) { + objcObject = @(boolResult); + } else if (context->GetValueString(value, &result)) { + std::string resultStr = StringViewUtils::ToU8StdStr(result); + objcObject = [NSString stringWithUTF8String:resultStr.c_str()]; + } else if (JSValueIsObject(jscCtx->context_, jscValue->value_)) { + if (context->IsArray(value)) { + objcObject = convertJSIArrayToNSArray(jscCtx, jscValue, module); + } else if (context->IsFunction(value)) { + // HippyResponseSenderBlock + // NOTE: 方法必须走promise + // return ^(NSArray *result) { + // size_t argumentCount = static_cast(result.count); + // std::shared_ptr argumets[argumentCount]; + // for(NSUInteger i = 0; i< result.count; i++){ + // size_t index = static_cast(i); + // argumets[index] = convertObjcObjectToCtxValue(context, result[i]); + // } + // context->CallFunction(value, argumentCount, argumets); + // }; + objcObject = @(0); + } else { + objcObject = convertJSIObjectToTurboObject(jscCtx, jscValue, module); + if (!objcObject) { + //map + objcObject = convertJSIObjectToNSDictionary(jscCtx, jscValue, module); + } } + } else if (context->GetValueJson(value, &result)) { + objcObject = convertJSIObjectToNSObject(jscCtx, jscValue); } - } else if (context->GetValueJson(value, &result)) { - objcObject = convertJSIObjectToNSObject(jscCtx, jscValue); + return objcObject; } - return objcObject; } static id convertJSIObjectToNSObject(const std::shared_ptr &context, const std::shared_ptr &value) { - unicode_string_view result; - if (!context->GetValueJson(value, &result)) { - return nil; - } - std::string resultStr = StringViewUtils::ToU8StdStr(result); - NSString *jsonString = [NSString stringWithCString:resultStr.c_str() encoding:[NSString defaultCStringEncoding]]; - NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; - NSError *error; - id objcObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; - if (error) { - HippyLogError(@"JSONObjectWithData error:%@", error); + @autoreleasepool { + unicode_string_view result; + if (!context->GetValueJson(value, &result)) { + return nil; + } + std::string resultStr = StringViewUtils::ToU8StdStr(result); + NSString *jsonString = [NSString stringWithCString:resultStr.c_str() encoding:[NSString defaultCStringEncoding]]; + NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + id objcObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + if (error) { + HippyLogError(@"JSONObjectWithData error:%@", error); + } + return objcObject; } - return objcObject; } static NSArray *convertJSIArrayToNSArray(const std::shared_ptr &context, const std::shared_ptr &value, HippyOCTurboModule *module) { - size_t length = context->GetArrayLength(value); - NSMutableArray *result = [NSMutableArray new]; - for (uint32_t i = 0; i < length; i++) { - std::shared_ptr v = context->CopyArrayElement(value, i); - [result addObject:convertCtxValueToObjcObject(context, v, module) ?: [NSNull null]]; + @autoreleasepool { + size_t length = context->GetArrayLength(value); + NSMutableArray *result = [NSMutableArray new]; + for (uint32_t i = 0; i < length; i++) { + std::shared_ptr v = context->CopyArrayElement(value, i); + [result addObject:convertCtxValueToObjcObject(context, v, module) ?: [NSNull null]]; + } + return [result copy]; } - return [result copy]; } static NSObject *convertJSIObjectToTurboObject(const std::shared_ptr &context, const std::shared_ptr &value, - HippyOCTurboModule *module) { - JSGlobalContextRef globalContextRef = JSContextGetGlobalContext(context->context_); - JSContext *ctx = [JSContext contextWithJSGlobalContextRef:globalContextRef]; - JSValue *jsValue = [JSValue valueWithJSValueRef:value->value_ inContext:ctx]; - HippyTurboModuleManager *turboManager = module.bridge.turboModuleManager; - NSString *moduleNameStr = [turboManager turboModuleNameForJSObject:jsValue]; - - if (moduleNameStr) { - HippyOCTurboModule *turboModule = [module.bridge turboModuleWithName:moduleNameStr]; - return turboModule; + HippyOCTurboModule *module) { + @autoreleasepool { + JSGlobalContextRef globalContextRef = JSContextGetGlobalContext(context->context_); + JSContext *ctx = [JSContext contextWithJSGlobalContextRef:globalContextRef]; + JSValue *jsValue = [JSValue valueWithJSValueRef:value->value_ inContext:ctx]; + HippyTurboModuleManager *turboManager = module.bridge.turboModuleManager; + NSString *moduleNameStr = [turboManager turboModuleNameForJSObject:jsValue]; + + if (moduleNameStr) { + HippyOCTurboModule *turboModule = [module.bridge turboModuleWithName:moduleNameStr]; + return turboModule; + } + return nil; } - return nil; } static NSDictionary *convertJSIObjectToNSDictionary(const std::shared_ptr &context, const std::shared_ptr &value, HippyOCTurboModule *module) { - JSValueRef exception = nullptr; - JSObjectRef object = JSValueToObject(context->context_, value->value_, &exception); - if (exception) { - HippyLogInfo(@"JSValueToObject throw exception:%@", exception); - id jsonObj = convertJSIObjectToNSObject(context, value); - if (jsonObj && [jsonObj isKindOfClass:[NSDictionary class]]) { - return (NSDictionary *)jsonObj; + @autoreleasepool { + JSValueRef exception = nullptr; + JSObjectRef object = JSValueToObject(context->context_, value->value_, &exception); + if (exception) { + HippyLogInfo(@"JSValueToObject throw exception:%@", exception); + id jsonObj = convertJSIObjectToNSObject(context, value); + if (jsonObj && [jsonObj isKindOfClass:[NSDictionary class]]) { + return (NSDictionary *)jsonObj; + } + HippyLogError(@"convertJSIJsonToDict failed:%@", jsonObj); + return nil; } - HippyLogError(@"convertJSIJsonToDict failed:%@", jsonObj); - return nil; - } - - JSPropertyNameArrayRef names = JSObjectCopyPropertyNames(context->context_, object); - size_t len = JSPropertyNameArrayGetCount(names); - - NSMutableDictionary *result = [NSMutableDictionary new]; - for (size_t i = 0; i < len; i++) { - JSStringRef str = JSPropertyNameArrayGetNameAtIndex(names, i); - size_t max_size = JSStringGetMaximumUTF8CStringSize(str); - char* buf = new char[max_size]; - JSStringGetUTF8CString(str, buf, max_size); - id objcValue = convertCtxValueToObjcObject(context, - context->CopyNamedProperty(value, buf), - module) ?: [NSNull null]; - [result setObject:objcValue forKey:[NSString stringWithUTF8String:buf]]; - delete[] buf; + + JSPropertyNameArrayRef names = JSObjectCopyPropertyNames(context->context_, object); + size_t len = JSPropertyNameArrayGetCount(names); + + NSMutableDictionary *result = [NSMutableDictionary new]; + for (size_t i = 0; i < len; i++) { + JSStringRef str = JSPropertyNameArrayGetNameAtIndex(names, i); + size_t max_size = JSStringGetMaximumUTF8CStringSize(str); + char* buf = new char[max_size]; + JSStringGetUTF8CString(str, buf, max_size); + id objcValue = convertCtxValueToObjcObject(context, + context->CopyNamedProperty(value, buf), + module) ?: [NSNull null]; + [result setObject:objcValue forKey:[NSString stringWithUTF8String:buf]]; + delete[] buf; + } + JSPropertyNameArrayRelease(names); + return [result copy]; } - JSPropertyNameArrayRelease(names); - return [result copy]; } @end diff --git a/ios/sdk/module/turbo/HippyTurboModuleManager.mm b/ios/sdk/module/turbo/HippyTurboModuleManager.mm index cd013e512dd..cd97c7133df 100644 --- a/ios/sdk/module/turbo/HippyTurboModuleManager.mm +++ b/ios/sdk/module/turbo/HippyTurboModuleManager.mm @@ -90,12 +90,14 @@ - (void)dealloc { - (instancetype)initWithBridge:(HippyBridge *)bridge delegate:(id) delegate { self = [self init]; if (self) { - _bridge = bridge; - _delegate = delegate; - _turboModuleCache = @{}.mutableCopy; - _bindingInfos = @{}.mutableCopy; - _cacheQueue = dispatch_queue_create("com.tencent.hippy.turboCache", DISPATCH_QUEUE_SERIAL); - _bindingQueue = dispatch_queue_create("com.tencent.hippy.turboBinding", DISPATCH_QUEUE_SERIAL); + @autoreleasepool { + _bridge = bridge; + _delegate = delegate; + _turboModuleCache = @{}.mutableCopy; + _bindingInfos = @{}.mutableCopy; + _cacheQueue = dispatch_queue_create("com.tencent.hippy.turboCache", DISPATCH_QUEUE_SERIAL); + _bindingQueue = dispatch_queue_create("com.tencent.hippy.turboBinding", DISPATCH_QUEUE_SERIAL); + } } return self; } @@ -116,51 +118,56 @@ + (BOOL)isTurboModule:(NSString *)name { } - (__kindof HippyOCTurboModule *)turboModuleWithName:(NSString *)name { - - if (!name || name.length == 0) { - return nil; - } - - __kindof HippyOCTurboModule __block * module; - dispatch_sync(_cacheQueue, ^{ - if ([self.turboModuleCache.allKeys containsObject:name]) { - module = [self.turboModuleCache objectForKey:name]; - } else { - Class moduleCls = [HippyTurboModuleMap objectForKey:name] ? : [HippyOCTurboModule class]; - if ([moduleCls conformsToProtocol:@protocol(HippyTurboModuleImpProtocol)]) { - module = [[moduleCls alloc] initWithName:name bridge:_bridge]; - [self.turboModuleCache setObject:module forKey:name]; + @autoreleasepool { + if (!name || name.length == 0) { + return nil; + } + + __kindof HippyOCTurboModule __block * module; + dispatch_sync(_cacheQueue, ^{ + if ([self.turboModuleCache.allKeys containsObject:name]) { + module = [self.turboModuleCache objectForKey:name]; } else { - HippyAssert(NO, @"moduleClass of %@ is not conformsToProtocol(HippyTurboModuleImpProtocol)!", name); + Class moduleCls = [HippyTurboModuleMap objectForKey:name] ? : [HippyOCTurboModule class]; + if ([moduleCls conformsToProtocol:@protocol(HippyTurboModuleImpProtocol)]) { + module = [[moduleCls alloc] initWithName:name bridge:_bridge]; + [self.turboModuleCache setObject:module forKey:name]; + } else { + HippyAssert(NO, @"moduleClass of %@ is not conformsToProtocol(HippyTurboModuleImpProtocol)!", name); + } } - } - }); - return module; + }); + return module; + } } - (void)bindJSObject:(JSValue *)jsObj toModuleName:(NSString *)moduleName { - HippyTurboBindInfo *info = [[HippyTurboBindInfo alloc] init]; - info.moduleName = moduleName; - info.managedJsObject = [[JSManagedValue alloc] initWithValue:jsObj]; - dispatch_sync(_bindingQueue, ^{ - [self.bindingInfos setObject:info forKey:@(self.moduleStorageCount++)]; - }); + @autoreleasepool { + HippyTurboBindInfo *info = [[HippyTurboBindInfo alloc] init]; + info.moduleName = moduleName; + info.managedJsObject = [[JSManagedValue alloc] initWithValue:jsObj]; + dispatch_sync(_bindingQueue, ^{ + [self.bindingInfos setObject:info forKey:@(self.moduleStorageCount++)]; + }); + } } - (NSString *)turboModuleNameForJSObject:(JSValue *)jsObj { - HippyTurboBindInfo __block * bindInfo = nil; - dispatch_sync(_bindingQueue, ^{ - [self.bindingInfos enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, HippyTurboBindInfo * _Nonnull obj, BOOL * _Nonnull stop) { - if (obj.managedJsObject.value == jsObj) { - bindInfo = obj; - *stop = YES; - } - }]; - }); - if (bindInfo) { - return bindInfo.moduleName; + @autoreleasepool { + HippyTurboBindInfo __block * bindInfo = nil; + dispatch_sync(_bindingQueue, ^{ + [self.bindingInfos enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, HippyTurboBindInfo * _Nonnull obj, BOOL * _Nonnull stop) { + if (obj.managedJsObject.value == jsObj) { + bindInfo = obj; + *stop = YES; + } + }]; + }); + if (bindInfo) { + return bindInfo.moduleName; + } + return nil; } - return nil; } @end @@ -169,11 +176,15 @@ - (NSString *)turboModuleNameForJSObject:(JSValue *)jsObj { @implementation HippyBridge (HippyTurboModuleManager) - (HippyTurboModuleManager *)turboModuleManager { - return objc_getAssociatedObject(self, @selector(turboModuleManager)); + @autoreleasepool { + return objc_getAssociatedObject(self, @selector(turboModuleManager)); + } } - (void)setTurboModuleManager:(HippyTurboModuleManager *)turboModuleManager { - objc_setAssociatedObject(self, @selector(turboModuleManager), turboModuleManager, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + @autoreleasepool { + objc_setAssociatedObject(self, @selector(turboModuleManager), turboModuleManager, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } } @end diff --git a/ios/sdk/module/turbo/NSObject+HippyTurbo.mm b/ios/sdk/module/turbo/NSObject+HippyTurbo.mm index 9c25731b4c1..07005311985 100644 --- a/ios/sdk/module/turbo/NSObject+HippyTurbo.mm +++ b/ios/sdk/module/turbo/NSObject+HippyTurbo.mm @@ -31,39 +31,43 @@ @implementation NSObject (HippyTurbo) - (NSArray> *)hippyTurboSetupModuleMethods { - NSMutableArray> *moduleMethods = [NSMutableArray new]; - unsigned int methodCount; - Class cls = [self class]; - 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_turbo__"]) { - IMP imp = method_getImplementation(method); - NSArray *entries = ((NSArray * (*)(id, SEL)) imp)(cls, selector); - id moduleMethod = [[HippyModuleMethod alloc] initWithMethodSignature:entries[1] JSMethodName:entries[0] - moduleClass:cls]; - [moduleMethods addObject:moduleMethod]; + @autoreleasepool { + NSMutableArray> *moduleMethods = [NSMutableArray new]; + unsigned int methodCount; + Class cls = [self class]; + 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_turbo__"]) { + IMP imp = method_getImplementation(method); + NSArray *entries = ((NSArray * (*)(id, SEL)) imp)(cls, selector); + id moduleMethod = [[HippyModuleMethod alloc] initWithMethodSignature:entries[1] JSMethodName:entries[0] + moduleClass:cls]; + [moduleMethods addObject:moduleMethod]; + } } - } - free(methods); - cls = class_getSuperclass(cls); + free(methods); + cls = class_getSuperclass(cls); + } + return [moduleMethods copy]; } - return [moduleMethods copy]; } - (NSArray> *)hippyTurboModuleMethods { - NSArray> *hippyTurboModules = objc_getAssociatedObject(self, @selector(hippyTurboModuleMethods)); - if (!hippyTurboModules || hippyTurboModules.count == 0) { - hippyTurboModules = [self hippyTurboSetupModuleMethods]; - objc_setAssociatedObject(self, - @selector(hippyTurboModuleMethods), - hippyTurboModules, - OBJC_ASSOCIATION_COPY_NONATOMIC); + @autoreleasepool { + NSArray> *hippyTurboModules = objc_getAssociatedObject(self, @selector(hippyTurboModuleMethods)); + if (!hippyTurboModules || hippyTurboModules.count == 0) { + hippyTurboModules = [self hippyTurboSetupModuleMethods]; + objc_setAssociatedObject(self, + @selector(hippyTurboModuleMethods), + hippyTurboModules, + OBJC_ASSOCIATION_COPY_NONATOMIC); + } + return hippyTurboModules; } - return hippyTurboModules; } @end