diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTModuleMethodTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTModuleMethodTests.m index 1fb9f5527..b11bffa26 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTModuleMethodTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTModuleMethodTests.m @@ -15,6 +15,7 @@ #import #import +#import "RCTBridgeModule.h" #import "RCTModuleMethod.h" #import "RCTLog.h" @@ -30,7 +31,7 @@ static BOOL RCTLogsError(void (^block)(void)) return loggedError; } -@interface RCTModuleMethodTests : XCTestCase +@interface RCTModuleMethodTests : XCTestCase @end @@ -39,6 +40,8 @@ static BOOL RCTLogsError(void (^block)(void)) CGRect _s; } ++ (NSString *)moduleName { return nil; } + - (void)doFooWithBar:(__unused NSString *)bar { } - (void)testNonnull diff --git a/React/Base/RCTBatchedBridge.m b/React/Base/RCTBatchedBridge.m index 47e868fae..ad0cc39ee 100644 --- a/React/Base/RCTBatchedBridge.m +++ b/React/Base/RCTBatchedBridge.m @@ -794,9 +794,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR RCTProfileEndEvent(0, @"objc_call", nil); - dispatch_async(dispatch_get_main_queue(), ^{ - [self.perfStats.jsGraph onTick:displayLink.timestamp]; - }); + RCT_IF_DEV( + dispatch_async(dispatch_get_main_queue(), ^{ + [self.perfStats.jsGraph onTick:displayLink.timestamp]; + }); + ) } - (void)_mainThreadUpdate:(CADisplayLink *)displayLink diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 543012602..4334be311 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -71,10 +71,11 @@ void RCTRegisterModule(Class moduleClass) */ NSString *RCTBridgeModuleNameForClass(Class cls) { - NSString *name = nil; - if ([cls respondsToSelector:NSSelectorFromString(@"moduleName")]) { - name = [cls valueForKey:@"moduleName"]; - } +#if RCT_DEV + RCTAssert([cls conformsToProtocol:@protocol(RCTBridgeModule)], @"Bridge module classes must conform to RCTBridgeModule"); +#endif + + NSString *name = [cls moduleName]; if (name.length == 0) { name = NSStringFromClass(cls); } diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index 4d9c4c1fa..782c5dffa 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -52,6 +52,21 @@ extern dispatch_queue_t RCTJSThread; * Provides the interface needed to register a bridge module. */ @protocol RCTBridgeModule + +/** + * Place this macro in your class implementation to automatically register + * your module with the bridge when it loads. The optional js_name argument + * will be used as the JS module name. If omitted, the JS module name will + * match the Objective-C class name. + */ +#define RCT_EXPORT_MODULE(js_name) \ +RCT_EXTERN void RCTRegisterModule(Class); \ ++ (NSString *)moduleName { return @#js_name; } \ ++ (void)load { RCTRegisterModule(self); } + +// Implemented by RCT_EXPORT_MODULE ++ (NSString *)moduleName; + @optional /** @@ -85,17 +100,6 @@ extern dispatch_queue_t RCTJSThread; */ @property (nonatomic, strong, readonly) dispatch_queue_t methodQueue; -/** - * Place this macro in your class implementation to automatically register - * your module with the bridge when it loads. The optional js_name argument - * will be used as the JS module name. If omitted, the JS module name will - * match the Objective-C class name. - */ -#define RCT_EXPORT_MODULE(js_name) \ - RCT_EXTERN void RCTRegisterModule(Class); \ - + (NSString *)moduleName { return @#js_name; } \ - + (void)load { RCTRegisterModule(self); } - /** * Wrap the parameter line of your method implementation with this macro to * expose it to JS. By default the exposed method will match the first part of diff --git a/React/Base/RCTEventDispatcher.h b/React/Base/RCTEventDispatcher.h index 6f390d55c..114d91586 100644 --- a/React/Base/RCTEventDispatcher.h +++ b/React/Base/RCTEventDispatcher.h @@ -69,7 +69,7 @@ RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName); * This class wraps the -[RCTBridge enqueueJSCall:args:] method, and * provides some convenience methods for generating event calls. */ -@interface RCTEventDispatcher : NSObject +@interface RCTEventDispatcher : NSObject /** * Send an application-specific event that does not relate to a specific diff --git a/React/Base/RCTEventDispatcher.m b/React/Base/RCTEventDispatcher.m index af5f30eed..484cf2f0a 100644 --- a/React/Base/RCTEventDispatcher.m +++ b/React/Base/RCTEventDispatcher.m @@ -81,7 +81,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) @end -@interface RCTEventDispatcher() +@interface RCTEventDispatcher() @end diff --git a/React/Base/RCTPerfStats.m b/React/Base/RCTPerfStats.m index 13ea44f70..ba841dc67 100644 --- a/React/Base/RCTPerfStats.m +++ b/React/Base/RCTPerfStats.m @@ -112,6 +112,15 @@ RCT_EXPORT_MODULE() @end +@implementation RCTBridge (RCTPerfStats) + +- (RCTPerfStats *)perfStats +{ + return self.modules[RCTBridgeModuleNameForClass([RCTPerfStats class])]; +} + +@end + #else @implementation RCTPerfStats @@ -121,13 +130,13 @@ RCT_EXPORT_MODULE() @end -#endif - @implementation RCTBridge (RCTPerfStats) - (RCTPerfStats *)perfStats { - return self.modules[RCTBridgeModuleNameForClass([RCTPerfStats class])]; + return nil; } @end + +#endif diff --git a/React/Modules/RCTDevLoadingView.m b/React/Modules/RCTDevLoadingView.m index 8968c07f1..b716b2483 100644 --- a/React/Modules/RCTDevLoadingView.m +++ b/React/Modules/RCTDevLoadingView.m @@ -116,6 +116,8 @@ RCT_EXPORT_MODULE() @implementation RCTDevLoadingView ++ (NSString *)moduleName { return nil; } + @end #endif diff --git a/React/Modules/RCTRedBox.m b/React/Modules/RCTRedBox.m index b715d7669..810830c9d 100644 --- a/React/Modules/RCTRedBox.m +++ b/React/Modules/RCTRedBox.m @@ -327,6 +327,7 @@ RCT_EXPORT_MODULE() @implementation RCTRedBox ++ (NSString *)moduleName { return nil; } - (void)showError:(NSError *)message {} - (void)showErrorMessage:(NSString *)message {} - (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details {}