diff --git a/Examples/2048/2048.xcodeproj/project.pbxproj b/Examples/2048/2048.xcodeproj/project.pbxproj index d792a2d62..43fd7518b 100644 --- a/Examples/2048/2048.xcodeproj/project.pbxproj +++ b/Examples/2048/2048.xcodeproj/project.pbxproj @@ -159,7 +159,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = Facebook; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "2048" */; @@ -271,6 +271,7 @@ "/Users/sahrens/src/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Animation/build/Debug-iphoneos", ); OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = 2048; }; name = Debug; @@ -291,6 +292,7 @@ "/Users/sahrens/src/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Animation/build/Debug-iphoneos", ); OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = 2048; }; name = Release; @@ -315,6 +317,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; diff --git a/Examples/2048/2048/Info.plist b/Examples/2048/2048/Info.plist index 1c298405a..610544546 100644 --- a/Examples/2048/2048/Info.plist +++ b/Examples/2048/2048/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -22,6 +22,11 @@ 1 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities diff --git a/Examples/Movies/Movies/Info.plist b/Examples/Movies/Movies/Info.plist index f76d0502a..f8c4225c4 100644 --- a/Examples/Movies/Movies/Info.plist +++ b/Examples/Movies/Movies/Info.plist @@ -47,5 +47,11 @@ UIViewControllerBasedStatusBarAppearance + NSAppTransportSecurity + + + NSAllowsArbitraryLoads + + diff --git a/Examples/SampleApp/iOS/Info.plist b/Examples/SampleApp/iOS/Info.plist index 0a56a6ea8..cddf0766c 100644 --- a/Examples/SampleApp/iOS/Info.plist +++ b/Examples/SampleApp/iOS/Info.plist @@ -38,5 +38,11 @@ NSLocationWhenInUseUsageDescription + NSAppTransportSecurity + + + NSAllowsArbitraryLoads + + diff --git a/Examples/TicTacToe/TicTacToe.xcodeproj/project.pbxproj b/Examples/TicTacToe/TicTacToe.xcodeproj/project.pbxproj index db9c36269..96c29bc3a 100644 --- a/Examples/TicTacToe/TicTacToe.xcodeproj/project.pbxproj +++ b/Examples/TicTacToe/TicTacToe.xcodeproj/project.pbxproj @@ -159,7 +159,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = Facebook; }; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "TicTacToe" */; @@ -268,6 +268,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = TicTacToe; }; name = Debug; @@ -285,6 +286,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = TicTacToe; }; name = Release; @@ -309,6 +311,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; diff --git a/Examples/TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcschemes/TicTacToe.xcscheme b/Examples/TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcschemes/TicTacToe.xcscheme index 5903ce6f4..193efdb7d 100644 --- a/Examples/TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcschemes/TicTacToe.xcscheme +++ b/Examples/TicTacToe/TicTacToe.xcodeproj/xcshareddata/xcschemes/TicTacToe.xcscheme @@ -1,6 +1,6 @@ + + - + - + CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -36,5 +36,11 @@ UIViewControllerBasedStatusBarAppearance + NSAppTransportSecurity + + + NSAllowsArbitraryLoads + + diff --git a/Examples/TicTacToe/TicTacToe/main.m b/Examples/TicTacToe/TicTacToe/main.m index 8954f343c..9c58a39a4 100644 --- a/Examples/TicTacToe/TicTacToe/main.m +++ b/Examples/TicTacToe/TicTacToe/main.m @@ -17,6 +17,6 @@ int main(int argc, char * argv[]) { @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } diff --git a/Examples/UIExplorer/TextExample.ios.js b/Examples/UIExplorer/TextExample.ios.js index b2fd717ad..ebc67b672 100644 --- a/Examples/UIExplorer/TextExample.ios.js +++ b/Examples/UIExplorer/TextExample.ios.js @@ -215,6 +215,11 @@ exports.examples = [ right right right right right right right right right right right right right + + justify: this text component's contents are laid out with "textAlign: justify" + and as you can see all of the lines except the last one span the + available width of the parent container. + ); }, diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj index 28361d706..c266cabcf 100644 --- a/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj +++ b/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj @@ -560,7 +560,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = Facebook; TargetAttributes = { 004D289D1AAF61C70097A701 = { @@ -850,6 +850,7 @@ XCTest, "-ObjC", ); + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -879,6 +880,7 @@ XCTest, "-ObjC", ); + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -898,6 +900,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.internal.uiexplorer.local; PRODUCT_NAME = UIExplorer; }; name = Debug; @@ -916,6 +919,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.internal.uiexplorer.local; PRODUCT_NAME = UIExplorer; }; name = Release; @@ -943,6 +947,7 @@ XCTest, "-ObjC", ); + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.React.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer"; }; @@ -968,6 +973,7 @@ XCTest, "-ObjC", ); + PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.React.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UIExplorer.app/UIExplorer"; }; @@ -981,18 +987,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -1002,10 +1013,16 @@ ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES; + GCC_WARN_STRICT_SELECTOR_MATCH = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1016,6 +1033,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Wextra", + "-Wall", + ); }; name = Debug; }; @@ -1027,12 +1048,16 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -1042,10 +1067,16 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES; + GCC_WARN_STRICT_SELECTOR_MATCH = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -1056,6 +1087,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Wextra", + "-Wall", + ); }; name = Release; }; diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/xcshareddata/xcschemes/UIExplorer.xcscheme b/Examples/UIExplorer/UIExplorer.xcodeproj/xcshareddata/xcschemes/UIExplorer.xcscheme index cb55d85b0..c3dcde8eb 100644 --- a/Examples/UIExplorer/UIExplorer.xcodeproj/xcshareddata/xcschemes/UIExplorer.xcscheme +++ b/Examples/UIExplorer/UIExplorer.xcodeproj/xcshareddata/xcschemes/UIExplorer.xcscheme @@ -1,6 +1,6 @@ + + diff --git a/Examples/UIExplorer/UIExplorer/AppDelegate.m b/Examples/UIExplorer/UIExplorer/AppDelegate.m index 5e707db41..6a5ad20e5 100644 --- a/Examples/UIExplorer/UIExplorer/AppDelegate.m +++ b/Examples/UIExplorer/UIExplorer/AppDelegate.m @@ -18,7 +18,7 @@ @implementation AppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +- (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *jsCodeLocation; diff --git a/Examples/UIExplorer/UIExplorer/Info.plist b/Examples/UIExplorer/UIExplorer/Info.plist index 349bd9a28..9e91b1cef 100644 --- a/Examples/UIExplorer/UIExplorer/Info.plist +++ b/Examples/UIExplorer/UIExplorer/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.internal.uiexplorer.local + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -38,5 +38,11 @@ UIViewControllerBasedStatusBarAppearance + NSAppTransportSecurity + + + NSAllowsArbitraryLoads + + diff --git a/Examples/UIExplorer/UIExplorer/main.m b/Examples/UIExplorer/UIExplorer/main.m index 8954f343c..9c58a39a4 100644 --- a/Examples/UIExplorer/UIExplorer/main.m +++ b/Examples/UIExplorer/UIExplorer/main.m @@ -17,6 +17,6 @@ int main(int argc, char * argv[]) { @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/Info.plist b/Examples/UIExplorer/UIExplorerIntegrationTests/Info.plist index 802c25416..ba72822e8 100644 --- a/Examples/UIExplorer/UIExplorerIntegrationTests/Info.plist +++ b/Examples/UIExplorer/UIExplorerIntegrationTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.React.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/IntegrationTestsTests.m b/Examples/UIExplorer/UIExplorerIntegrationTests/IntegrationTestsTests.m index ddd204f99..9783fca38 100644 --- a/Examples/UIExplorer/UIExplorerIntegrationTests/IntegrationTestsTests.m +++ b/Examples/UIExplorer/UIExplorerIntegrationTests/IntegrationTestsTests.m @@ -25,11 +25,12 @@ - (void)setUp { -#ifdef __LP64__ - RCTAssert(!__LP64__, @"Tests should be run on 32-bit device simulators (e.g. iPhone 5)"); +#if __LP64__ + #error Tests should be run on 32-bit device simulators (e.g. iPhone 5) #endif - NSString *version = [[UIDevice currentDevice] systemVersion]; - RCTAssert([version integerValue] == 8, @"Tests should be run on iOS 8.x, found %@", version); + + NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion]; + RCTAssert(version.majorVersion == 8 || version.minorVersion == 3, @"Tests should be run on iOS 8.3, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion); _runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerIntegrationTests/js/IntegrationTestsApp"); // If tests have changes, set recordMode = YES below and run the affected diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-UIExplorerApp.ios/testTextExampleSnapshot_1@2x.png b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-UIExplorerApp.ios/testTextExampleSnapshot_1@2x.png index f869159a2..f37869de3 100644 Binary files a/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-UIExplorerApp.ios/testTextExampleSnapshot_1@2x.png and b/Examples/UIExplorer/UIExplorerIntegrationTests/ReferenceImages/Examples-UIExplorer-UIExplorerApp.ios/testTextExampleSnapshot_1@2x.png differ diff --git a/Examples/UIExplorer/UIExplorerIntegrationTests/UIExplorerIntegrationTests.m b/Examples/UIExplorer/UIExplorerIntegrationTests/UIExplorerIntegrationTests.m index c1c5e5737..8ee424425 100644 --- a/Examples/UIExplorer/UIExplorerIntegrationTests/UIExplorerIntegrationTests.m +++ b/Examples/UIExplorer/UIExplorerIntegrationTests/UIExplorerIntegrationTests.m @@ -42,7 +42,7 @@ _runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerApp.ios"); // If tests have changes, set recordMode = YES below and run the affected - // tests on an iPhone5, iOS 8.1 simulator. + // tests on an iPhone5, iOS 8.3 simulator. _runner.recordMode = NO; } diff --git a/Examples/UIExplorer/UIExplorerUnitTests/Info.plist b/Examples/UIExplorer/UIExplorerUnitTests/Info.plist index 87e3a6175..ba72822e8 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/Info.plist +++ b/Examples/UIExplorer/UIExplorerUnitTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTAllocationTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTAllocationTests.m index 7eafce75e..aac517fc9 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTAllocationTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTAllocationTests.m @@ -158,7 +158,9 @@ RCT_EXPORT_MODULE(); - (void)testContentViewIsInvalidated { - RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil moduleProvider:nil launchOptions:nil]; + RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil + moduleProvider:nil + launchOptions:nil]; __weak id rootContentView; @autoreleasepool { RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@""]; diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m index 390459b1b..ea6af0805 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTBridgeTests.m @@ -42,17 +42,17 @@ RCT_EXPORT_MODULE() return YES; } -- (void)executeJSCall:(NSString *)name - method:(NSString *)method - arguments:(NSArray *)arguments - context:(NSNumber *)executorID +- (void)executeJSCall:(__unused NSString *)name + method:(__unused NSString *)method + arguments:(__unused NSArray *)arguments + context:(__unused NSNumber *)executorID callback:(RCTJavaScriptCallback)onComplete { onComplete(nil, nil); } -- (void)executeApplicationScript:(NSString *)script - sourceURL:(NSURL *)url +- (void)executeApplicationScript:(__unused NSString *)script + sourceURL:(__unused NSURL *)url onComplete:(RCTJavaScriptCompleteBlock)onComplete { onComplete(nil); diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTContextExecutorTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTContextExecutorTests.m index ba2bf87bb..743cc286b 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTContextExecutorTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTContextExecutorTests.m @@ -30,7 +30,7 @@ dispatch_semaphore_t doneSem = dispatch_semaphore_create(0); [_executor executeApplicationScript:@"var x = {toString: function() { throw 1; }}; nativeLoggingHook(x);" sourceURL:[NSURL URLWithString:@"file://"] - onComplete:^(id error){ + onComplete:^(__unused id error){ dispatch_semaphore_signal(doneSem); }]; dispatch_semaphore_wait(doneSem, DISPATCH_TIME_FOREVER); @@ -39,7 +39,7 @@ static uint64_t _get_time_nanoseconds(void) { - static struct mach_timebase_info tb_info = {0}; + static struct mach_timebase_info tb_info = {0, 0}; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ int ret = mach_timebase_info(&tb_info); @@ -114,7 +114,7 @@ static uint64_t _get_time_nanoseconds(void) } \ "; - [_executor executeApplicationScript:script sourceURL:[NSURL URLWithString:@"http://localhost:8081/"] onComplete:^(NSError *error) { + [_executor executeApplicationScript:script sourceURL:[NSURL URLWithString:@"http://localhost:8081/"] onComplete:^(__unused NSError *error) { NSMutableArray *params = [[NSMutableArray alloc] init]; id data = @1; for (int i = 0; i < 4; i++) { @@ -128,8 +128,8 @@ static uint64_t _get_time_nanoseconds(void) method:@"method" arguments:params context:RCTGetExecutorID(_executor) - callback:^(id json, NSError *__error) { - RCTAssert([json isEqual:@YES], @"Invalid return"); + callback:^(id json, __unused NSError *unused) { + XCTAssert([json isEqual:@YES], @"Invalid return"); }]; double run = _get_time_nanoseconds() - start; if ((j % frequency) == frequency - 1) { // Warmup diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTConvert_NSURLTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTConvert_NSURLTests.m index c36c09a8e..8897ee060 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTConvert_NSURLTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTConvert_NSURLTests.m @@ -13,7 +13,7 @@ #define TEST_URL(name, _input, _expectedURL) \ - (void)test_##name { \ NSURL *result = [RCTConvert NSURL:_input]; \ - NSURL *expected = [NSURL URLWithString:_expectedURL]; \ + NSURL *expected = (_expectedURL) ? [NSURL URLWithString:_expectedURL ?: @""] : nil; \ XCTAssertEqualObjects(result.absoluteURL, expected); \ } \ diff --git a/Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m b/Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m index 3a4f62027..388761a8f 100644 --- a/Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m +++ b/Examples/UIExplorer/UIExplorerUnitTests/RCTUIManagerTests.m @@ -136,7 +136,7 @@ // We need to keep these in array to keep them around NSMutableArray *viewsToRemove = [NSMutableArray array]; - for (NSInteger i = 0; i < removeAtIndices.count; i++) { + for (NSUInteger i = 0; i < removeAtIndices.count; i++) { NSNumber *reactTagToRemove = @([removeAtIndices[i] integerValue] + 1); UIView *viewToRemove = _uiManager.viewRegistry[reactTagToRemove]; [viewsToRemove addObject:viewToRemove]; @@ -160,7 +160,7 @@ instead have the following subviews %@", [containerView reactSubviews]); NSArray *expectedReactTags = @[@11, @5, @1, @2, @7, @8, @12, @10]; - for (NSInteger i = 0; i < [[containerView subviews] count]; i++) { + for (NSUInteger i = 0; i < containerView.subviews.count; i++) { XCTAssertEqualObjects([[containerView reactSubviews][i] reactTag], expectedReactTags[i], @"Expected subview at index %ld to have react tag #%@ but has tag #%@", (long)i, expectedReactTags[i], [[containerView reactSubviews][i] reactTag]); diff --git a/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj/project.pbxproj b/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj/project.pbxproj index 8434df87d..a73b70085 100644 --- a/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj/project.pbxproj +++ b/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj/project.pbxproj @@ -150,6 +150,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -158,6 +159,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Wextra", + "-Wall", + ); }; name = Debug; }; @@ -184,6 +189,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -192,6 +198,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Wextra", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/ActionSheetIOS/RCTActionSheetManager.m b/Libraries/ActionSheetIOS/RCTActionSheetManager.m index 4883aa647..a736387fe 100644 --- a/Libraries/ActionSheetIOS/RCTActionSheetManager.m +++ b/Libraries/ActionSheetIOS/RCTActionSheetManager.m @@ -37,7 +37,7 @@ RCT_EXPORT_MODULE() } RCT_EXPORT_METHOD(showActionSheetWithOptions:(NSDictionary *)options - failureCallback:(RCTResponseSenderBlock)failureCallback + failureCallback:(__unused RCTResponseSenderBlock)failureCallback successCallback:(RCTResponseSenderBlock)successCallback) { UIActionSheet *actionSheet = [[UIActionSheet alloc] init]; @@ -86,34 +86,29 @@ RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options } UIActivityViewController *share = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; UIViewController *ctrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; - if ([share respondsToSelector:@selector(setCompletionWithItemsHandler:)]) { - share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) { + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 + + if (![UIActivityViewController instancesRespondToSelector:@selector(setCompletionWithItemsHandler:)]) { + // Legacy iOS 7 implementation + share.completionHandler = ^(NSString *activityType, BOOL completed) { + successCallback(@[@(completed), RCTNullIfNil(activityType)]); + }; + } else + +#endif + + { + // iOS 8 version + share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, __unused NSArray *returnedItems, NSError *activityError) { if (activityError) { - failureCallback(@[[activityError localizedDescription]]); + failureCallback(@[RCTNullIfNil(activityError.localizedDescription)]); } else { successCallback(@[@(completed), RCTNullIfNil(activityType)]); } }; - } else { - -#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 - - if (![UIActivityViewController instancesRespondToSelector:@selector(completionWithItemsHandler)]) { - // Legacy iOS 7 implementation - share.completionHandler = ^(NSString *activityType, BOOL completed) { - successCallback(@[@(completed), RCTNullIfNil(activityType)]); - }; - } else - -#endif - - { - // iOS 8 version - share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) { - successCallback(@[@(completed), RCTNullIfNil(activityType)]); - }; - } } + [ctrl presentViewController:share animated:YES completion:nil]; } diff --git a/Libraries/AdSupport/RCTAdSupport.xcodeproj/project.pbxproj b/Libraries/AdSupport/RCTAdSupport.xcodeproj/project.pbxproj index 1b89d7bfa..238838a93 100644 --- a/Libraries/AdSupport/RCTAdSupport.xcodeproj/project.pbxproj +++ b/Libraries/AdSupport/RCTAdSupport.xcodeproj/project.pbxproj @@ -150,6 +150,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -163,6 +164,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -189,6 +194,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -202,6 +208,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/BatchedBridge/BatchedBridgedModules/RCTJSTimers.js b/Libraries/BatchedBridge/BatchedBridgedModules/RCTJSTimers.js deleted file mode 100644 index 08a126b00..000000000 --- a/Libraries/BatchedBridge/BatchedBridgedModules/RCTJSTimers.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule RCTJSTimers - * @flow - */ -'use strict'; - -var JSTimersExecution = require('JSTimersExecution'); - -var RCTJSTimers = JSTimersExecution; - -module.exports = RCTJSTimers; diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 0b3d8d4e3..00a27e3c1 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -183,6 +183,10 @@ var TextInput = React.createClass({ * Callback that is called when the text input's text changes. */ onChange: PropTypes.func, + /** + * Callback that is called when the text input's text changes. + * Changed text is passed as an argument to the callback handler. + */ onChangeText: PropTypes.func, /** * Callback that is called when text input ends. diff --git a/Libraries/CustomComponents/ListView/ListView.js b/Libraries/CustomComponents/ListView/ListView.js index 717f03847..857f476c1 100644 --- a/Libraries/CustomComponents/ListView/ListView.js +++ b/Libraries/CustomComponents/ListView/ListView.js @@ -262,7 +262,16 @@ var ListView = React.createClass({ componentWillReceiveProps: function(nextProps) { if (this.props.dataSource !== nextProps.dataSource) { - this.setState({prevRenderedRowsCount: 0}); + this.setState((state, props) => { + var rowsToRender = Math.min( + state.curRenderedRowsCount + props.pageSize, + props.dataSource.getRowCount() + ); + return { + prevRenderedRowsCount: 0, + curRenderedRowsCount: rowsToRender, + }; + }); } }, @@ -412,22 +421,21 @@ var ListView = React.createClass({ }, _pageInNewRows: function() { - var rowsToRender = Math.min( - this.state.curRenderedRowsCount + this.props.pageSize, - this.props.dataSource.getRowCount() - ); - this.setState( - { - prevRenderedRowsCount: this.state.curRenderedRowsCount, + this.setState((state, props) => { + var rowsToRender = Math.min( + state.curRenderedRowsCount + props.pageSize, + props.dataSource.getRowCount() + ); + return { + prevRenderedRowsCount: state.curRenderedRowsCount, curRenderedRowsCount: rowsToRender - }, - () => { - this._measureAndUpdateScrollProps(); - this.setState({ - prevRenderedRowsCount: this.state.curRenderedRowsCount, - }); - } - ); + }; + }, () => { + this._measureAndUpdateScrollProps(); + this.setState(state => ({ + prevRenderedRowsCount: state.curRenderedRowsCount, + })); + }); }, _getDistanceFromEnd: function(scrollProperties) { diff --git a/Libraries/Geolocation/RCTGeolocation.xcodeproj/project.pbxproj b/Libraries/Geolocation/RCTGeolocation.xcodeproj/project.pbxproj index ee79e7571..93d6a375f 100644 --- a/Libraries/Geolocation/RCTGeolocation.xcodeproj/project.pbxproj +++ b/Libraries/Geolocation/RCTGeolocation.xcodeproj/project.pbxproj @@ -150,6 +150,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -158,6 +159,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -184,6 +189,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -192,6 +198,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/Image/RCTImage.xcodeproj/project.pbxproj b/Libraries/Image/RCTImage.xcodeproj/project.pbxproj index 667995586..9e5427bf3 100644 --- a/Libraries/Image/RCTImage.xcodeproj/project.pbxproj +++ b/Libraries/Image/RCTImage.xcodeproj/project.pbxproj @@ -198,6 +198,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -206,6 +207,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -232,6 +237,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -240,6 +246,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/Image/RCTNetworkImageView.h b/Libraries/Image/RCTNetworkImageView.h index 55c7720ee..e04f71e32 100644 --- a/Libraries/Image/RCTNetworkImageView.h +++ b/Libraries/Image/RCTNetworkImageView.h @@ -13,8 +13,7 @@ @interface RCTNetworkImageView : UIView -- (instancetype)initWithFrame:(CGRect)frame - imageDownloader:(RCTImageDownloader *)imageDownloader NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithImageDownloader:(RCTImageDownloader *)imageDownloader NS_DESIGNATED_INITIALIZER; /** * An image that will appear while the view is loading the image from the network, diff --git a/Libraries/Image/RCTNetworkImageView.m b/Libraries/Image/RCTNetworkImageView.m index 89cddef59..5a286e020 100644 --- a/Libraries/Image/RCTNetworkImageView.m +++ b/Libraries/Image/RCTNetworkImageView.m @@ -9,6 +9,7 @@ #import "RCTNetworkImageView.h" +#import "RCTAssert.h" #import "RCTConvert.h" #import "RCTGIFImage.h" #import "RCTImageDownloader.h" @@ -25,16 +26,22 @@ id _downloadToken; } -- (instancetype)initWithFrame:(CGRect)frame imageDownloader:(RCTImageDownloader *)imageDownloader +- (instancetype)initWithImageDownloader:(RCTImageDownloader *)imageDownloader { - if ((self = [super initWithFrame:frame])) { + RCTAssertParam(imageDownloader); + + if ((self = [super initWithFrame:CGRectZero])) { _deferSentinel = 0; _imageDownloader = imageDownloader; self.userInteractionEnabled = NO; + self.contentMode = UIViewContentModeScaleAspectFill; } return self; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (NSURL *)imageURL { // We clear our imageURL when we are not in a window for a while, diff --git a/Libraries/Image/RCTNetworkImageViewManager.m b/Libraries/Image/RCTNetworkImageViewManager.m index 005b726cf..3fcd4a75b 100644 --- a/Libraries/Image/RCTNetworkImageViewManager.m +++ b/Libraries/Image/RCTNetworkImageViewManager.m @@ -22,9 +22,7 @@ RCT_EXPORT_MODULE() - (UIView *)view { - RCTNetworkImageView *view = [[RCTNetworkImageView alloc] initWithFrame:CGRectZero imageDownloader:[RCTImageDownloader sharedInstance]]; - view.contentMode = UIViewContentModeScaleAspectFill; - return view; + return [[RCTNetworkImageView alloc] initWithImageDownloader:[RCTImageDownloader sharedInstance]]; } RCT_REMAP_VIEW_PROPERTY(defaultImageSrc, defaultImage, UIImage) diff --git a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js index e87f44fca..2896b01ab 100644 --- a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js +++ b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js @@ -123,6 +123,7 @@ function setUpWebSockets() { function setupProfile() { console.profile = console.profile || GLOBAL.consoleProfile || function () {}; console.profileEnd = console.profileEnd || GLOBAL.consoleProfileEnd || function () {}; + require('BridgeProfiling').swizzleReactPerf(); } setUpRedBoxErrorHandler(); diff --git a/Libraries/Network/RCTDataManager.m b/Libraries/Network/RCTDataManager.m index 56e13af70..49ce6d754 100644 --- a/Libraries/Network/RCTDataManager.m +++ b/Libraries/Network/RCTDataManager.m @@ -134,12 +134,12 @@ typedef void (^RCTHTTPQueryResult)(NSError *error, NSDictionary *result); @implementation RCTActiveURLRequest -- (void)setResponse:(NSURLResponse *)response; +- (instancetype)init { - _response = response; - if (!_incrementalUpdates) { - _data = [[NSMutableData alloc] initWithCapacity:(NSUInteger)MAX(0, response.expectedContentLength)]; + if ((self = [super init])) { + _data = [[NSMutableData alloc] init]; } + return self; } @end @@ -164,6 +164,10 @@ typedef void (^RCTDataLoaderCallback)(NSData *data, NSString *MIMEType, NSError handler:(id)handler callback:(RCTDataLoaderCallback)callback { + RCTAssertParam(request); + RCTAssertParam(handler); + RCTAssertParam(callback); + if ((self = [super init])) { _callback = callback; _request = [[RCTActiveURLRequest alloc] init]; @@ -175,6 +179,11 @@ typedef void (^RCTDataLoaderCallback)(NSData *data, NSString *MIMEType, NSError return self; } +- (instancetype)init +{ + return [self initWithRequest:nil handler:nil callback:nil]; +} + - (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response { RCTAssert([requestToken isEqual:_requestToken], @"Shouldn't ever happen"); diff --git a/Libraries/Network/RCTNetwork.xcodeproj/project.pbxproj b/Libraries/Network/RCTNetwork.xcodeproj/project.pbxproj index dba7c65fa..becf442fa 100644 --- a/Libraries/Network/RCTNetwork.xcodeproj/project.pbxproj +++ b/Libraries/Network/RCTNetwork.xcodeproj/project.pbxproj @@ -162,6 +162,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -170,6 +171,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -196,6 +201,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -204,6 +210,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/Network/RCTReachability.m b/Libraries/Network/RCTReachability.m index e0711571b..7c5530127 100644 --- a/Libraries/Network/RCTReachability.m +++ b/Libraries/Network/RCTReachability.m @@ -9,6 +9,7 @@ #import "RCTReachability.h" +#import "RCTAssert.h" #import "RCTBridge.h" #import "RCTEventDispatcher.h" @@ -59,9 +60,12 @@ static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SC - (instancetype)initWithHost:(NSString *)host { + RCTAssertParam(host); + RCTAssert(![host hasPrefix:@"http"], @"Host value should just contain the domain, not the URL scheme."); + if ((self = [super init])) { _status = RCTReachabilityStateUnknown; - _reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [host UTF8String]); + _reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, host.UTF8String); SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL }; SCNetworkReachabilitySetCallback(_reachability, RCTReachabilityCallback, &context); SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); diff --git a/Libraries/PushNotificationIOS/PushNotificationIOS.js b/Libraries/PushNotificationIOS/PushNotificationIOS.js index adf8ecf5a..1781ddff1 100644 --- a/Libraries/PushNotificationIOS/PushNotificationIOS.js +++ b/Libraries/PushNotificationIOS/PushNotificationIOS.js @@ -121,6 +121,18 @@ class PushNotificationIOS { RCTPushNotificationManager.requestPermissions(requestedPermissions); } + /** + * Unregister for all remote notifications received via Apple Push Notification service. + * + * You should call this method in rare circumstances only, such as when a new version of + * the app removes support for all types of remote notifications. Users can temporarily + * prevent apps from receiving remote notifications through the Notifications section of + * the Settings app. Apps unregistered through this method can always re-register. + */ + static abandonPermissions() { + RCTPushNotificationManager.abandonPermissions(); + } + /** * See what push permissions are currently enabled. `callback` will be * invoked with a `permissions` object: diff --git a/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj/project.pbxproj b/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj/project.pbxproj index 1585e6c42..7b555c089 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj/project.pbxproj +++ b/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj/project.pbxproj @@ -147,6 +147,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -155,6 +156,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Wextra", + "-Wall", + ); }; name = Debug; }; @@ -182,6 +187,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -190,6 +196,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Wextra", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m index 1c034a9b7..6a9420819 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m @@ -61,18 +61,19 @@ RCT_EXPORT_MODULE() _initialNotification = [bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy]; } -+ (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings ++ (void)application:(__unused UIApplication *)application didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings *)notificationSettings { if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) { [application registerForRemoteNotifications]; } } -+ (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken ++ (void)application:(__unused UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSMutableString *hexString = [NSMutableString string]; - const unsigned char *bytes = [deviceToken bytes]; - for (int i = 0; i < [deviceToken length]; i++) { + NSUInteger deviceTokenLength = deviceToken.length; + const unsigned char *bytes = deviceToken.bytes; + for (NSUInteger i = 0; i < deviceTokenLength; i++) { [hexString appendFormat:@"%02x", bytes[i]]; } NSDictionary *userInfo = @{ @@ -83,7 +84,7 @@ RCT_EXPORT_MODULE() userInfo:userInfo]; } -+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification ++ (void)application:(__unused UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification { [[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived object:self @@ -147,6 +148,11 @@ RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions) } +RCT_EXPORT_METHOD(abandonPermissions) +{ + [[UIApplication sharedApplication] unregisterForRemoteNotifications]; +} + RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback) { NSUInteger types = 0; diff --git a/Libraries/RCTTest/RCTTest.xcodeproj/project.pbxproj b/Libraries/RCTTest/RCTTest.xcodeproj/project.pbxproj index 6ab58a8a2..f1165171f 100644 --- a/Libraries/RCTTest/RCTTest.xcodeproj/project.pbxproj +++ b/Libraries/RCTTest/RCTTest.xcodeproj/project.pbxproj @@ -188,6 +188,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -201,6 +202,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -227,6 +232,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -240,6 +246,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/RCTTest/RCTTestRunner.h b/Libraries/RCTTest/RCTTestRunner.h index 1b37ba492..21b558b8c 100644 --- a/Libraries/RCTTest/RCTTestRunner.h +++ b/Libraries/RCTTest/RCTTestRunner.h @@ -28,10 +28,10 @@ * macro instead of calling this directly. * * @param app The path to the app bundle without suffixes, e.g. IntegrationTests/IntegrationTestsApp - * @param referencesDir The path for snapshot references images. The RCTInitRunnerForApp macro uses + * @param referenceDir The path for snapshot references images. The RCTInitRunnerForApp macro uses * FB_REFERENCE_IMAGE_DIR for this automatically. */ -- (instancetype)initWithApp:(NSString *)app referenceDir:(NSString *)referenceDir; +- (instancetype)initWithApp:(NSString *)app referenceDir:(NSString *)referenceDir NS_DESIGNATED_INITIALIZER; /** * Simplest runTest function simply mounts the specified JS module with no diff --git a/Libraries/RCTTest/RCTTestRunner.m b/Libraries/RCTTest/RCTTestRunner.m index 8a7e739bb..11c57e0ba 100644 --- a/Libraries/RCTTest/RCTTestRunner.m +++ b/Libraries/RCTTest/RCTTestRunner.m @@ -10,6 +10,7 @@ #import "RCTTestRunner.h" #import "FBSnapshotTestController.h" +#import "RCTAssert.h" #import "RCTRedBox.h" #import "RCTRootView.h" #import "RCTTestModule.h" @@ -30,6 +31,9 @@ - (instancetype)initWithApp:(NSString *)app referenceDir:(NSString *)referenceDir { + RCTAssertParam(app); + RCTAssertParam(referenceDir); + if ((self = [super init])) { NSString *sanitizedAppName = [app stringByReplacingOccurrencesOfString:@"/" withString:@"-"]; sanitizedAppName = [sanitizedAppName stringByReplacingOccurrencesOfString:@"\\" withString:@"-"]; @@ -44,6 +48,8 @@ return self; } +RCT_NOT_IMPLEMENTED(-init) + - (void)setRecordMode:(BOOL)recordMode { _testController.recordMode = recordMode; diff --git a/Libraries/ReactNative/ReactNativeDefaultInjection.js b/Libraries/ReactNative/ReactNativeDefaultInjection.js index ce040c779..15a3e5400 100644 --- a/Libraries/ReactNative/ReactNativeDefaultInjection.js +++ b/Libraries/ReactNative/ReactNativeDefaultInjection.js @@ -40,7 +40,7 @@ var invariant = require('invariant'); // Just to ensure this gets packaged, since its only caller is from Native. require('RCTEventEmitter'); require('RCTLog'); -require('RCTJSTimers'); +require('JSTimersExecution'); function inject() { /** diff --git a/Libraries/Settings/RCTSettings.xcodeproj/project.pbxproj b/Libraries/Settings/RCTSettings.xcodeproj/project.pbxproj index 9cbc4e4dd..a0a5e1bf1 100644 --- a/Libraries/Settings/RCTSettings.xcodeproj/project.pbxproj +++ b/Libraries/Settings/RCTSettings.xcodeproj/project.pbxproj @@ -148,6 +148,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -156,6 +157,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -182,6 +187,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -190,6 +196,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/Storage/AsyncStorage.ios.js b/Libraries/Storage/AsyncStorage.ios.js index fe92f5c58..ed028db4b 100644 --- a/Libraries/Storage/AsyncStorage.ios.js +++ b/Libraries/Storage/AsyncStorage.ios.js @@ -19,14 +19,14 @@ var RCTAsyncRocksDBStorage = NativeModules.AsyncRocksDBStorage; var RCTAsyncStorage = RCTAsyncRocksDBStorage || RCTAsyncLocalStorage; /** - * AsyncStorage is a simple, asynchronous, persistent, global, key-value storage - * system. It should be used instead of LocalStorage. + * AsyncStorage is a simple, asynchronous, persistent, key-value storage + * system that is global to the app. It should be used instead of LocalStorage. * * It is recommended that you use an abstraction on top of AsyncStorage instead * of AsyncStorage directly for anything more than light usage since it * operates globally. * - * This JS code is a simple facad over the native iOS implementation to provide + * This JS code is a simple facade over the native iOS implementation to provide * a clear JS API, real Error objects, and simple non-multi functions. Each * method returns a `Promise` object. */ @@ -133,7 +133,7 @@ var AsyncStorage = { }, /** - * Gets *all* keys known to the system, for all callers, libraries, etc. Returns a `Promise` object. + * Gets *all* keys known to the app, for all callers, libraries, etc. Returns a `Promise` object. */ getAllKeys: function(callback?: ?(error: ?Error, keys: ?Array) => void): Promise { return new Promise((resolve, reject) => { diff --git a/Libraries/StyleSheet/StyleSheetValidation.js b/Libraries/StyleSheet/StyleSheetValidation.js index c4875222d..be59b2ec5 100644 --- a/Libraries/StyleSheet/StyleSheetValidation.js +++ b/Libraries/StyleSheet/StyleSheetValidation.js @@ -26,7 +26,7 @@ class StyleSheetValidation { if (allStylePropTypes[prop] === undefined) { var message1 = '"' + prop + '" is not a valid style property.'; var message2 = '\nValid style props: ' + - JSON.stringify(Object.keys(allStylePropTypes), null, ' '); + JSON.stringify(Object.keys(allStylePropTypes).sort(), null, ' '); styleError(message1, style, caller, message2); } var error = allStylePropTypes[prop]( diff --git a/Libraries/Text/RCTShadowRawText.m b/Libraries/Text/RCTShadowRawText.m index 87bfe9fa6..e99e1187b 100644 --- a/Libraries/Text/RCTShadowRawText.m +++ b/Libraries/Text/RCTShadowRawText.m @@ -20,4 +20,10 @@ } } +- (NSString *)description +{ + NSString *superDescription = super.description; + return [[superDescription substringToIndex:superDescription.length - 1] stringByAppendingFormat:@"; text: %@>", self.text]; +} + @end diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index 2dc275912..65bee774e 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -54,6 +54,12 @@ static css_dim_t RCTMeasure(void *context, float width) return self; } +- (NSString *)description +{ + NSString *superDescription = super.description; + return [[superDescription substringToIndex:superDescription.length - 1] stringByAppendingFormat:@"; text: %@>", [self attributedString].string]; +} + - (NSDictionary *)processUpdatedProperties:(NSMutableSet *)applierBlocks parentProperties:(NSDictionary *)parentProperties { diff --git a/Libraries/Text/RCTText.xcodeproj/project.pbxproj b/Libraries/Text/RCTText.xcodeproj/project.pbxproj index 224c7e6b9..ac1478fb0 100644 --- a/Libraries/Text/RCTText.xcodeproj/project.pbxproj +++ b/Libraries/Text/RCTText.xcodeproj/project.pbxproj @@ -186,6 +186,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -194,6 +195,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -220,6 +225,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -228,6 +234,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/Text/RCTTextView.m b/Libraries/Text/RCTTextView.m index fa5b2bf8a..31850be5a 100644 --- a/Libraries/Text/RCTTextView.m +++ b/Libraries/Text/RCTTextView.m @@ -25,6 +25,8 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { + RCTAssertParam(eventDispatcher); + if ((self = [super initWithFrame:CGRectZero])) { _contentInset = UIEdgeInsetsZero; _eventDispatcher = eventDispatcher; @@ -35,10 +37,12 @@ _textView.delegate = self; [self addSubview:_textView]; } - return self; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)updateFrames { // Adjust the insets so that they are as close as possible to single-line diff --git a/Libraries/Text/TextStylePropTypes.js b/Libraries/Text/TextStylePropTypes.js index 95a0f4cb8..450d26f33 100644 --- a/Libraries/Text/TextStylePropTypes.js +++ b/Libraries/Text/TextStylePropTypes.js @@ -26,8 +26,9 @@ var TextStylePropTypes = Object.assign(Object.create(ViewStylePropTypes), { lineHeight: ReactPropTypes.number, color: ReactPropTypes.string, containerBackgroundColor: ReactPropTypes.string, + // NOTE: "justify" is supported only on iOS textAlign: ReactPropTypes.oneOf( - ['auto' /*default*/, 'left', 'right', 'center'] + ['auto' /*default*/, 'left', 'right', 'center', 'justify'] ), writingDirection: ReactPropTypes.oneOf( ['auto' /*default*/, 'ltr', 'rtl'] diff --git a/Libraries/Utilities/BridgeProfiling.js b/Libraries/Utilities/BridgeProfiling.js index c94d84fdd..02685e01c 100644 --- a/Libraries/Utilities/BridgeProfiling.js +++ b/Libraries/Utilities/BridgeProfiling.js @@ -14,7 +14,7 @@ var GLOBAL = GLOBAL || this; var BridgeProfiling = { - profile(profileName: string, args?: any) { + profile(profileName?: string, args?: any) { if (GLOBAL.__BridgeProfilingIsProfiling) { if (args) { try { @@ -27,11 +27,30 @@ var BridgeProfiling = { } }, - profileEnd() { + profileEnd(profileName?: string) { if (GLOBAL.__BridgeProfilingIsProfiling) { - console.profileEnd(); + console.profileEnd(profileName); } }, + + swizzleReactPerf() { + var ReactPerf = require('ReactPerf'); + var originalMeasure = ReactPerf.measure; + ReactPerf.measure = function (objName, fnName, func) { + func = originalMeasure.call(ReactPerf, objName, fnName, func); + return function (component) { + BridgeProfiling.profile(); + var ret = func.apply(this, arguments); + if (GLOBAL.__BridgeProfilingIsProfiling) { + var name = this._instance && this._instance.constructor && + (this._instance.constructor.displayName || + this._instance.constructor.name); + BridgeProfiling.profileEnd(`${objName}.${fnName}(${name})`); + } + return ret; + }; + }; + }, }; module.exports = BridgeProfiling; diff --git a/Libraries/Utilities/MessageQueue.js b/Libraries/Utilities/MessageQueue.js index 8a56aa714..cac48a8e5 100644 --- a/Libraries/Utilities/MessageQueue.js +++ b/Libraries/Utilities/MessageQueue.js @@ -305,10 +305,12 @@ var MessageQueueMixin = { return guardReturn(this._callFunction, [moduleID, methodID, params], null, this); }, - _callFunction: function(moduleID, methodID, params) { - var moduleName = this._localModuleIDToModuleName[moduleID]; + _callFunction: function(moduleName, methodName, params) { + if (isFinite(moduleName)) { + moduleName = this._localModuleIDToModuleName[moduleName]; + methodName = this._localModuleNameToMethodIDToName[moduleName][methodName]; + } - var methodName = this._localModuleNameToMethodIDToName[moduleName][methodID]; if (DEBUG_SPY_MODE) { console.log( 'N->JS: ' + moduleName + '.' + methodName + diff --git a/Libraries/Vibration/RCTVibration.xcodeproj/project.pbxproj b/Libraries/Vibration/RCTVibration.xcodeproj/project.pbxproj index f8aec3fed..e4c3e4a2e 100644 --- a/Libraries/Vibration/RCTVibration.xcodeproj/project.pbxproj +++ b/Libraries/Vibration/RCTVibration.xcodeproj/project.pbxproj @@ -150,6 +150,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -163,6 +164,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -189,6 +194,7 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -202,6 +208,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; diff --git a/Libraries/WebSocket/RCTSRWebSocket.m b/Libraries/WebSocket/RCTSRWebSocket.m index 6d36d80b2..b65a847ee 100644 --- a/Libraries/WebSocket/RCTSRWebSocket.m +++ b/Libraries/WebSocket/RCTSRWebSocket.m @@ -246,8 +246,9 @@ static __strong NSData *CRLFCRLF; - (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; { + RCTAssertParam(request); + if ((self = [super init])) { - assert(request.URL); _url = request.URL; _urlRequest = request; @@ -255,23 +256,24 @@ static __strong NSData *CRLFCRLF; [self _RCTSR_commonInit]; } - return self; } +RCT_NOT_IMPLEMENTED(-init) + - (instancetype)initWithURLRequest:(NSURLRequest *)request; { return [self initWithURLRequest:request protocols:nil]; } -- (instancetype)initWithURL:(NSURL *)url; +- (instancetype)initWithURL:(NSURL *)URL; { - return [self initWithURL:url protocols:nil]; + return [self initWithURL:URL protocols:nil]; } -- (instancetype)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; +- (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray *)protocols; { - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; + NSURLRequest *request = URL ? [NSURLRequest requestWithURL:URL] : nil; return [self initWithURLRequest:request protocols:protocols]; } @@ -1610,7 +1612,7 @@ static NSRunLoop *networkRunLoop = nil; _runLoop = [NSRunLoop currentRunLoop]; dispatch_group_leave(_waitGroup); - NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate distantFuture] interval:0.0 target:nil selector:nil userInfo:nil repeats:NO]; + NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate distantFuture] interval:0.0 target:self selector:@selector(step) userInfo:nil repeats:NO]; [_runLoop addTimer:timer forMode:NSDefaultRunLoopMode]; while ([_runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) { } @@ -1618,6 +1620,11 @@ static NSRunLoop *networkRunLoop = nil; } } +- (void)step +{ + // Does nothing +} + - (NSRunLoop *)runLoop; { dispatch_group_wait(_waitGroup, DISPATCH_TIME_FOREVER); diff --git a/Libraries/WebSocket/RCTWebSocket.xcodeproj/project.pbxproj b/Libraries/WebSocket/RCTWebSocket.xcodeproj/project.pbxproj index f4ce6d206..d1c691d0f 100644 --- a/Libraries/WebSocket/RCTWebSocket.xcodeproj/project.pbxproj +++ b/Libraries/WebSocket/RCTWebSocket.xcodeproj/project.pbxproj @@ -151,6 +151,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -159,6 +160,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Debug; }; @@ -187,6 +192,7 @@ GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -195,6 +201,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Werror", + "-Wall", + ); }; name = Release; }; @@ -202,6 +212,7 @@ isa = XCBuildConfiguration; buildSettings = { EXECUTABLE_PREFIX = lib; + GCC_TREAT_WARNINGS_AS_ERRORS = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, @@ -218,6 +229,7 @@ isa = XCBuildConfiguration; buildSettings = { EXECUTABLE_PREFIX = lib; + GCC_TREAT_WARNINGS_AS_ERRORS = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, diff --git a/Libraries/WebSocket/RCTWebSocketExecutor.m b/Libraries/WebSocket/RCTWebSocketExecutor.m index c5c216fc7..0f8f433b0 100644 --- a/Libraries/WebSocket/RCTWebSocketExecutor.m +++ b/Libraries/WebSocket/RCTWebSocketExecutor.m @@ -43,7 +43,9 @@ RCT_EXPORT_MODULE() - (instancetype)initWithURL:(NSURL *)URL { - if (self = [super init]) { + RCTAssertParam(URL); + + if ((self = [super init])) { _url = URL; } return self; diff --git a/React/Base/RCTAssert.h b/React/Base/RCTAssert.h index 1fc5b9d32..c7a331b43 100644 --- a/React/Base/RCTAssert.h +++ b/React/Base/RCTAssert.h @@ -27,12 +27,6 @@ typedef void (^RCTAssertFunction)( NSString *message ); -/** - * Private logging function - ignore this. - */ -RCT_EXTERN void _RCTAssertFormat( - BOOL, const char *, int, const char *, NSString *, ...) NS_FORMAT_FUNCTION(5,6); - /** * This is the main assert macro that you should use. */ @@ -41,12 +35,19 @@ if (RCT_NSASSERT && !pass) { [[NSAssertionHandler currentHandler] handleFailureI file:@(__FILE__) lineNumber:__LINE__ description:__VA_ARGS__]; } \ _RCTAssertFormat(pass, __FILE__, __LINE__, __func__, __VA_ARGS__); \ } while (false) +RCT_EXTERN void _RCTAssertFormat(BOOL, const char *, int, const char *, NSString *, ...) NS_FORMAT_FUNCTION(5,6); + +/** + * Convenience macro for asserting that a parameter is non-nil/non-zero. + */ +#define RCTAssertParam(name) RCTAssert(name, \ +@"'%s' is a required parameter", #name) /** * Convenience macro for asserting that we're running on main thread. */ #define RCTAssertMainThread() RCTAssert([NSThread isMainThread], \ -@"This function must be called on the main thread"); +@"This function must be called on the main thread") /** * These methods get and set the current assert function called by the RCTAssert diff --git a/React/Base/RCTAssert.m b/React/Base/RCTAssert.m index 41369406c..3e76518dd 100644 --- a/React/Base/RCTAssert.m +++ b/React/Base/RCTAssert.m @@ -13,6 +13,15 @@ NSString *const RCTErrorDomain = @"RCTErrorDomain"; RCTAssertFunction RCTCurrentAssertFunction = nil; +NSException *_RCTNotImplementedException(SEL, Class); +NSException *_RCTNotImplementedException(SEL cmd, Class cls) +{ + NSString *msg = [NSString stringWithFormat:@"%s is not implemented " + "for the class %@", sel_getName(cmd), cls]; + return [NSException exceptionWithName:@"RCTNotDesignatedInitializerException" + reason:msg userInfo:nil]; +} + void _RCTAssertFormat( BOOL condition, const char *fileName, diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index 5c5cfe49b..35183437d 100644 --- a/React/Base/RCTBridge.h +++ b/React/Base/RCTBridge.h @@ -75,22 +75,15 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass); /** * This method is used to call functions in the JavaScript application context. * It is primarily intended for use by modules that require two-way communication - * with the JavaScript code. Method should be registered using the - * RCT_IMPORT_METHOD macro below. Attempting to call a method that has not been - * registered will result in an error. Safe to call from any thread. + * with the JavaScript code. Safe to call from any thread. */ - (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args; /** - * This macro is used to register a JS method to be called via the enqueueJSCall - * bridge method. You should place this macro inside any file that uses the - * imported method. If a method has already been registered by another class, it - * is not necessary to register it again, but it is good practice. Registering - * the same method more than once will not result in an error. + * DEPRECATED: Do not use. */ #define RCT_IMPORT_METHOD(module, method) \ -__attribute__((used, section("__DATA,RCTImport"))) \ -static const char *__rct_import_##module##_##method##__ = #module"."#method; + _Pragma("message(\"This macro is no longer required\")") /** * URL of the script that was loaded into the bridge. diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 5b63b1d0b..f8e9eeab7 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -13,11 +13,9 @@ #import #import -#import -#import - #import "RCTContextExecutor.h" #import "RCTConvert.h" +#import "RCTEventDispatcher.h" #import "RCTJavaScriptLoader.h" #import "RCTKeyCommands.h" #import "RCTLog.h" @@ -52,16 +50,6 @@ typedef NS_ENUM(NSUInteger, RCTJavaScriptFunctionKind) { RCTJavaScriptFunctionKindAsync, }; -#ifdef __LP64__ -typedef struct mach_header_64 *RCTHeaderValue; -typedef struct section_64 RCTHeaderSection; -#define RCTGetSectByNameFromHeader getsectbynamefromheader_64 -#else -typedef struct mach_header *RCTHeaderValue; -typedef struct section RCTHeaderSection; -#define RCTGetSectByNameFromHeader getsectbynamefromheader -#endif - #define RCTAssertJSThread() \ RCTAssert(![NSStringFromClass([_javaScriptExecutor class]) isEqualToString:@"RCTContextExecutor"] || \ [[[NSThread currentThread] name] isEqualToString:@"com.facebook.React.JavaScript"], \ @@ -112,40 +100,6 @@ NSString *RCTBridgeModuleNameForClass(Class cls) return name; } -/** - * This function scans all classes available at runtime and returns an array - * of all JSMethods registered. - */ -static NSArray *RCTJSMethods(void) -{ - static NSArray *JSMethods; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSMutableSet *uniqueMethods = [NSMutableSet set]; - - Dl_info info; - dladdr(&RCTJSMethods, &info); - - const RCTHeaderValue mach_header = (RCTHeaderValue)info.dli_fbase; - unsigned long size = 0; - const uint8_t *sectionData = getsectiondata(mach_header, "__DATA", "RCTImport", &size); - if (sectionData) { - for (const uint8_t *addr = sectionData; - addr < sectionData + size; - addr += sizeof(const char **)) { - - // Get data entry - NSString *entry = @(*(const char **)addr); - [uniqueMethods addObject:entry]; - } - } - - JSMethods = [uniqueMethods allObjects]; - }); - - return JSMethods; -} - // TODO: Can we just replace RCTMakeError with this function instead? static NSDictionary *RCTJSErrorFromNSError(NSError *error) { @@ -185,7 +139,7 @@ static NSDictionary *RCTJSErrorFromNSError(NSError *error) @property (nonatomic, weak) RCTBridge *parentBridge; -- (instancetype)initWithParentBridge:(RCTBridge *)bridge; +- (instancetype)initWithParentBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; - (void)_actuallyInvokeAndProcessModule:(NSString *)module method:(NSString *)method @@ -233,7 +187,7 @@ static NSDictionary *RCTJSErrorFromNSError(NSError *error) } NSMutableArray *argumentNames = [NSMutableArray array]; - [typeRegex enumerateMatchesInString:objCMethodName options:0 range:NSMakeRange(0, objCMethodName.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { + [typeRegex enumerateMatchesInString:objCMethodName options:0 range:NSMakeRange(0, objCMethodName.length) usingBlock:^(NSTextCheckingResult *result, __unused NSMatchingFlags flags, __unused BOOL *stop) { NSString *argumentName = [objCMethodName substringWithRange:[result rangeAtIndex:1]]; [argumentNames addObject:argumentName]; }]; @@ -267,7 +221,7 @@ static NSDictionary *RCTJSErrorFromNSError(NSError *error) NSMutableArray *argumentBlocks = [[NSMutableArray alloc] initWithCapacity:numberOfArguments - 2]; #define RCT_ARG_BLOCK(_logic) \ - [argumentBlocks addObject:^(RCTBridge *bridge, NSNumber *context, NSInvocation *invocation, NSUInteger index, id json) { \ + [argumentBlocks addObject:^(__unused RCTBridge *bridge, __unused NSNumber *context, NSInvocation *invocation, NSUInteger index, id json) { \ _logic \ [invocation setArgument:&value atIndex:index]; \ }]; \ @@ -287,7 +241,7 @@ static NSDictionary *RCTJSErrorFromNSError(NSError *error) method:@"invokeCallbackAndReturnFlushedQueue" arguments:@[json, args] context:context]; - } : ^(NSArray *unused) {}); + } : ^(__unused NSArray *unused) {}); ) }; @@ -334,7 +288,7 @@ case _value: { \ RCT_CONVERT_CASE('^', void *) case '{': { - [argumentBlocks addObject:^(RCTBridge *bridge, NSNumber *context, NSInvocation *invocation, NSUInteger index, id json) { + [argumentBlocks addObject:^(__unused RCTBridge *bridge, __unused NSNumber *context, NSInvocation *invocation, NSUInteger index, id json) { NSMethodSignature *methodSignature = [RCTConvert methodSignatureForSelector:selector]; void *returnValue = malloc(methodSignature.methodReturnLength); NSInvocation *_invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; @@ -485,7 +439,8 @@ static RCTSparseArray *RCTExportedMethodsByModuleID(void) dispatch_once(&onceToken, ^{ methodsByModuleID = [[RCTSparseArray alloc] initWithCapacity:[RCTModuleClassesByID count]]; - [RCTModuleClassesByID enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) { + [RCTModuleClassesByID enumerateObjectsUsingBlock: + ^(Class moduleClass, NSUInteger moduleID, __unused BOOL *stop) { methodsByModuleID[moduleID] = [[NSMutableArray alloc] init]; @@ -496,7 +451,8 @@ static RCTSparseArray *RCTExportedMethodsByModuleID(void) Method method = methods[i]; SEL selector = method_getName(method); if ([NSStringFromSelector(selector) hasPrefix:@"__rct_export__"]) { - NSArray *entries = ((NSArray *(*)(id, SEL))objc_msgSend)(moduleClass, selector); + IMP imp = method_getImplementation(method); + NSArray *entries = ((NSArray *(*)(id, SEL))imp)(moduleClass, selector); RCTModuleMethod *moduleMethod = [[RCTModuleMethod alloc] initWithObjCMethodName:entries[1] JSMethodName:entries[0] @@ -548,11 +504,13 @@ static NSDictionary *RCTRemoteModulesConfig(NSDictionary *modulesByName) dispatch_once(&onceToken, ^{ remoteModuleConfigByClassName = [[NSMutableDictionary alloc] init]; - [RCTModuleClassesByID enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) { + [RCTModuleClassesByID enumerateObjectsUsingBlock: + ^(Class moduleClass, NSUInteger moduleID, __unused BOOL *stop) { NSArray *methods = RCTExportedMethodsByModuleID()[moduleID]; NSMutableDictionary *methodsByName = [NSMutableDictionary dictionaryWithCapacity:methods.count]; - [methods enumerateObjectsUsingBlock:^(RCTModuleMethod *method, NSUInteger methodID, BOOL *_stop) { + [methods enumerateObjectsUsingBlock: + ^(RCTModuleMethod *method, NSUInteger methodID, __unused BOOL *_stop) { methodsByName[method.JSMethodName] = @{ @"methodID": @(methodID), @"type": method.functionKind == RCTJavaScriptFunctionKindAsync ? @"remoteAsync" : @"remote", @@ -570,7 +528,8 @@ static NSDictionary *RCTRemoteModulesConfig(NSDictionary *modulesByName) // Create config NSMutableDictionary *moduleConfig = [[NSMutableDictionary alloc] init]; - [modulesByName enumerateKeysAndObjectsUsingBlock:^(NSString *moduleName, id module, BOOL *stop) { + [modulesByName enumerateKeysAndObjectsUsingBlock: + ^(NSString *moduleName, id module, __unused BOOL *stop) { // Add constants NSMutableDictionary *config = remoteModuleConfigByClassName[NSStringFromClass([module class])]; @@ -589,80 +548,6 @@ static NSDictionary *RCTRemoteModulesConfig(NSDictionary *modulesByName) return moduleConfig; } -/** - * As above, but for local modules/methods, which represent JS classes - * and methods that will be called by the native code via the bridge. - * Structure is essentially the same as for remote modules: - * - * "ModuleName1": { - * "moduleID": 0, - * "methods": { - * "methodName1": { - * "methodID": 0, - * "type": "local" - * }, - * "methodName2": { - * "methodID": 1, - * "type": "local" - * }, - * etc... - * } - * }, - * etc... - */ -static NSMutableDictionary *RCTLocalModuleIDs; -static NSMutableDictionary *RCTLocalMethodIDs; -static NSMutableArray *RCTLocalModuleNames; -static NSMutableArray *RCTLocalMethodNames; -static NSDictionary *RCTLocalModulesConfig() -{ - static NSMutableDictionary *localModules; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - - RCTLocalModuleIDs = [[NSMutableDictionary alloc] init]; - RCTLocalMethodIDs = [[NSMutableDictionary alloc] init]; - RCTLocalModuleNames = [[NSMutableArray alloc] init]; - RCTLocalMethodNames = [[NSMutableArray alloc] init]; - - localModules = [[NSMutableDictionary alloc] init]; - for (NSString *moduleDotMethod in RCTJSMethods()) { - - NSArray *parts = [moduleDotMethod componentsSeparatedByString:@"."]; - RCTAssert(parts.count == 2, @"'%@' is not a valid JS method definition - expected 'Module.method' format.", moduleDotMethod); - - // Add module if it doesn't already exist - NSString *moduleName = parts[0]; - NSDictionary *module = localModules[moduleName]; - if (!module) { - module = @{ - @"moduleID": @(localModules.count), - @"methods": [[NSMutableDictionary alloc] init] - }; - localModules[moduleName] = module; - [RCTLocalModuleNames addObject:moduleName]; - } - - // Add method if it doesn't already exist - NSString *methodName = parts[1]; - NSMutableDictionary *methods = module[@"methods"]; - if (!methods[methodName]) { - methods[methodName] = @{ - @"methodID": @(methods.count), - @"type": @"local" - }; - [RCTLocalMethodNames addObject:methodName]; - } - - // Add module and method lookup - RCTLocalModuleIDs[moduleDotMethod] = module[@"moduleID"]; - RCTLocalMethodIDs[moduleDotMethod] = methods[methodName][@"methodID"]; - } - }); - - return localModules; -} - @interface RCTFrameUpdate (Private) - (instancetype)initWithDisplayLink:(CADisplayLink *)displayLink; @@ -687,6 +572,7 @@ static NSDictionary *RCTLocalModulesConfig() static id _latestJSExecutor; #if RCT_DEBUG + + (void)initialize { static dispatch_once_t onceToken; @@ -716,6 +602,7 @@ static id _latestJSExecutor; }); } + #endif - (instancetype)initWithBundleURL:(NSURL *)bundleURL @@ -725,11 +612,6 @@ static id _latestJSExecutor; RCTAssertMainThread(); if ((self = [super init])) { - /** - * Pre register modules - */ - RCTLocalModulesConfig(); - _bundleURL = bundleURL; _moduleProvider = block; _launchOptions = [launchOptions copy]; @@ -739,6 +621,8 @@ static id _latestJSExecutor; return self; } +RCT_NOT_IMPLEMENTED(-init) + - (void)dealloc { /** @@ -766,7 +650,7 @@ static id _latestJSExecutor; // reload in current mode [commands registerKeyCommandWithInput:@"r" modifierFlags:UIKeyModifierCommand - action:^(UIKeyCommand *command) { + action:^(__unused UIKeyCommand *command) { [weakSelf reload]; }]; @@ -774,6 +658,11 @@ static id _latestJSExecutor; } +- (RCTEventDispatcher *)eventDispatcher +{ + return self.modules[RCTBridgeModuleNameForClass([RCTEventDispatcher class])]; +} + - (void)reload { /** @@ -821,7 +710,7 @@ static id _latestJSExecutor; method:@"logIfNoNativeHook" arguments:@[level, message] context:RCTGetExecutorID(_latestJSExecutor) - callback:^(id json, NSError *error) {}]; + callback:^(__unused id json, __unused NSError *error) {}]; }); } @@ -842,7 +731,10 @@ static id _latestJSExecutor; [self.batchedBridge enqueueJSCall:moduleDotMethod args:args]; } -RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args context:(NSNumber *)context) +RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module + method:(__unused NSString *)method + arguments:(__unused NSArray *)args + context:(__unused NSNumber *)context) @end @@ -865,8 +757,12 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin - (instancetype)initWithParentBridge:(RCTBridge *)bridge { - if (self = [super init]) { - RCTAssertMainThread(); + RCTAssertMainThread(); + RCTAssertParam(bridge); + + if ((self = [super initWithBundleURL:bridge.bundleURL + moduleProvider:bridge.moduleProvider + launchOptions:bridge.launchOptions])) { _parentBridge = bridge; @@ -901,14 +797,11 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin return self; } -- (NSURL *)bundleURL +- (instancetype)initWithBundleURL:(__unused NSURL *)bundleURL + moduleProvider:(__unused RCTBridgeModuleProviderBlock)block + launchOptions:(__unused NSDictionary *)launchOptions { - return _parentBridge.bundleURL; -} - -- (NSDictionary *)launchOptions -{ - return _parentBridge.launchOptions; + return [self initWithParentBridge:nil]; } /** @@ -949,14 +842,15 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin // Register passed-in module instances NSMutableDictionary *preregisteredModules = [[NSMutableDictionary alloc] init]; - for (id module in _parentBridge.moduleProvider ? _parentBridge.moduleProvider() : nil) { + for (id module in self.moduleProvider ? self.moduleProvider() : nil) { preregisteredModules[RCTBridgeModuleNameForClass([module class])] = module; } // Instantiate modules _modulesByID = [[RCTSparseArray alloc] init]; NSMutableDictionary *modulesByName = [preregisteredModules mutableCopy]; - [RCTModuleClassesByID enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) { + [RCTModuleClassesByID enumerateObjectsUsingBlock: + ^(Class moduleClass, NSUInteger moduleID, __unused BOOL *stop) { NSString *moduleName = RCTModuleNamesByID[moduleID]; // Check if module instance has already been registered for this name id module = modulesByName[moduleName]; @@ -1006,7 +900,8 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin } // Get method queues - [_modulesByID enumerateObjectsUsingBlock:^(id module, NSNumber *moduleID, BOOL *stop) { + [_modulesByID enumerateObjectsUsingBlock: + ^(id module, NSNumber *moduleID, __unused BOOL *stop) { if ([module respondsToSelector:@selector(methodQueue)]) { dispatch_queue_t queue = [module methodQueue]; if (queue) { @@ -1018,7 +913,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin if ([module conformsToProtocol:@protocol(RCTFrameUpdateObserver)]) { [_frameUpdateObservers addObject:module]; - } + } }]; } @@ -1029,13 +924,13 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin // Inject module data into JS context NSString *configJSON = RCTJSONStringify(@{ @"remoteModuleConfig": RCTRemoteModulesConfig(_modulesByName), - @"localModulesConfig": RCTLocalModulesConfig() }, NULL); dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [_javaScriptExecutor injectJSONText:configJSON - asGlobalObjectNamed:@"__fbBatchedBridgeConfig" callback:^(id err) { - dispatch_semaphore_signal(semaphore); - }]; + asGlobalObjectNamed:@"__fbBatchedBridgeConfig" callback: + ^(__unused id err) { + dispatch_semaphore_signal(semaphore); + }]; dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW); @@ -1187,13 +1082,6 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin }]; } -/** - * - TODO (#5906496): When we build a `MessageQueue.m`, handling all the requests could - * cause both a queue of "responses". We would flush them here. However, we - * currently just expect each objc block to handle its own response sending - * using a `RCTResponseSenderBlock`. - */ - #pragma mark - RCTBridge methods /** @@ -1201,16 +1089,11 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin */ - (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args { - NSNumber *moduleID = RCTLocalModuleIDs[moduleDotMethod]; - RCTAssert(moduleID != nil, @"Module '%@' not registered.", - [[moduleDotMethod componentsSeparatedByString:@"."] firstObject]); - - NSNumber *methodID = RCTLocalMethodIDs[moduleDotMethod]; - RCTAssert(methodID != nil, @"Method '%@' not registered.", moduleDotMethod); + NSArray *ids = [moduleDotMethod componentsSeparatedByString:@"."]; [self _invokeAndProcessModule:@"BatchedBridge" method:@"callFunctionReturnFlushedQueue" - arguments:@[moduleID ?: @0, methodID ?: @0, args ?: @[]] + arguments:@[ids[0], ids[1], args ?: @[]] context:RCTGetExecutorID(_javaScriptExecutor)]; } @@ -1221,18 +1104,10 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin { RCTAssertJSThread(); - NSString *moduleDotMethod = @"RCTJSTimers.callTimers"; - NSNumber *moduleID = RCTLocalModuleIDs[moduleDotMethod]; - RCTAssert(moduleID != nil, @"Module '%@' not registered.", - [[moduleDotMethod componentsSeparatedByString:@"."] firstObject]); - - NSNumber *methodID = RCTLocalMethodIDs[moduleDotMethod]; - RCTAssert(methodID != nil, @"Method '%@' not registered.", moduleDotMethod); - dispatch_block_t block = ^{ [self _actuallyInvokeAndProcessModule:@"BatchedBridge" method:@"callFunctionReturnFlushedQueue" - arguments:@[moduleID, methodID, @[@[timer]]] + arguments:@[@"JSTimersExecution", @"callTimers", @[@[timer]]] context:RCTGetExecutorID(_javaScriptExecutor)]; }; @@ -1349,7 +1224,7 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin [[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:nil userInfo:nil]; - RCTJavaScriptCallback processResponse = ^(id json, NSError *error) { + RCTJavaScriptCallback processResponse = ^(id json, __unused NSError *error) { if (!self.isValid) { return; } @@ -1452,7 +1327,8 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin } // TODO: batchDidComplete is only used by RCTUIManager - can we eliminate this special case? - [_modulesByID enumerateObjectsUsingBlock:^(id module, NSNumber *moduleID, BOOL *stop) { + [_modulesByID enumerateObjectsUsingBlock: + ^(id module, NSNumber *moduleID, __unused BOOL *stop) { if ([module respondsToSelector:@selector(batchDidComplete)]) { [self dispatchBlock:^{ [module batchDidComplete]; @@ -1536,7 +1412,9 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin NSArray *calls = [_scheduledCallbacks.allObjects arrayByAddingObjectsFromArray:_scheduledCalls]; NSNumber *currentExecutorID = RCTGetExecutorID(_javaScriptExecutor); - calls = [calls filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSDictionary *call, NSDictionary *bindings) { + calls = [calls filteredArrayUsingPredicate: + [NSPredicate predicateWithBlock: + ^BOOL(NSDictionary *call, __unused NSDictionary *bindings) { return [call[@"context"] isEqualToNumber:currentExecutorID]; }]]; @@ -1599,13 +1477,16 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin NSMutableURLRequest *URLRequest = [NSMutableURLRequest requestWithURL:URL]; URLRequest.HTTPMethod = @"POST"; [URLRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; - NSURLSessionTask *task = [[NSURLSession sharedSession] uploadTaskWithRequest:URLRequest - fromData:[log dataUsingEncoding:NSUTF8StringEncoding] - completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - if (error) { - RCTLogError(@"%@", error.localizedDescription); - } - }]; + NSURLSessionTask *task = + [[NSURLSession sharedSession] uploadTaskWithRequest:URLRequest + fromData:[log dataUsingEncoding:NSUTF8StringEncoding] + completionHandler: + ^(__unused NSData *data, __unused NSURLResponse *response, NSError *error) { + if (error) { + RCTLogError(@"%@", error.localizedDescription); + } + }]; + [task resume]; }]; } diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index fc662778c..90090e847 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -176,7 +176,7 @@ extern const dispatch_queue_t RCTJSThread; * Like RCT_EXTERN_REMAP_METHOD, but allows setting a custom JavaScript name. */ #define RCT_EXTERN_REMAP_METHOD(js_name, method) \ - + (NSArray *)RCT_CONCAT(__rct_export__, __COUNTER__) { \ + + (NSArray *)RCT_CONCAT(__rct_export__, RCT_CONCAT(js_name, RCT_CONCAT(__LINE__, __COUNTER__))) { \ return @[@#js_name, @#method]; \ } \ diff --git a/React/Base/RCTCache.m b/React/Base/RCTCache.m index 6297771d2..9390069c4 100644 --- a/React/Base/RCTCache.m +++ b/React/Base/RCTCache.m @@ -12,6 +12,8 @@ #import #import +#import "RCTAssert.h" + static NSString *const RCTCacheSubdirectoryName = @"React"; static NSString *const RCTKeyExtendedAttributeName = @"com.facebook.React.RCTCacheManager.Key"; static NSMapTable *RCTLivingCachesByName; @@ -122,7 +124,8 @@ static BOOL RCTSetExtendedAttribute(NSURL *fileURL, NSString *key, NSString *val - (instancetype)initWithName:(NSString *)name { - NSParameterAssert(name.length < NAME_MAX); + RCTAssertParam(name); + RCTAssert(name.length < NAME_MAX, @"Name must be fewer than %i characters in length.", NAME_MAX); RCTCache *cachedCache = [RCTLivingCachesByName objectForKey:name]; if (cachedCache) { self = cachedCache; @@ -212,12 +215,12 @@ static BOOL RCTSetExtendedAttribute(NSURL *fileURL, NSString *key, NSString *val UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]; dispatch_group_t group = dispatch_group_create(); - [_storage enumerateKeysAndObjectsUsingBlock:^(NSString *key, RCTCacheRecord *record, BOOL *stop) { + for (RCTCacheRecord *record in _storage.allValues) { NSURL *fileURL = [_cacheDirectoryURL URLByAppendingPathComponent:record.UUID.UUIDString]; dispatch_group_async(group, record.queue, ^{ [_fileManager removeItemAtURL:fileURL error:NULL]; }); - }]; + } if (identifier != UIBackgroundTaskInvalid) { dispatch_group_notify(group, dispatch_get_main_queue(), ^{ diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index e244d988b..804faf87e 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -536,32 +536,32 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[ } // Parse color - NSUInteger red = -1; - NSUInteger green = -1; - NSUInteger blue = -1; + uint32_t red = 0, green = 0, blue = 0; CGFloat alpha = 1.0; if ([colorString hasPrefix:@"#"]) { if (colorString.length == 4) { // 3 digit hex - sscanf([colorString UTF8String], "#%01tX%01tX%01tX", &red, &green, &blue); + sscanf([colorString UTF8String], "#%01x%01x%01x", &red, &green, &blue); // expand to 6 digit hex red = red | (red << 4); green = green | (green << 4); blue = blue | (blue << 4); - } else if (colorString.length == 7) { // normal 6 digit hex - sscanf([colorString UTF8String], "#%02tX%02tX%02tX", &red, &green, &blue); + } else if (colorString.length == 7) { // 6 digit hex + sscanf(colorString.UTF8String, "#%02x%02x%02x", &red, &green, &blue); } else { - RCTLogError(@"Invalid hex color %@. Hex colors should be 3 or 6 digits long", colorString); + RCTLogError(@"Invalid hex color %@. Hex colors should be 3 or 6 digits long.", colorString); + alpha = -1; } } else if ([colorString hasPrefix:@"rgba("]) { double tmpAlpha; - sscanf([colorString UTF8String], "rgba(%zd,%zd,%zd,%lf)", &red, &green, &blue, &tmpAlpha); - alpha = tmpAlpha > 0.99 ? 1.0 : tmpAlpha; + sscanf(colorString.UTF8String, "rgba(%u,%u,%u,%lf)", &red, &green, &blue, &tmpAlpha); + alpha = tmpAlpha; } else if ([colorString hasPrefix:@"rgb("]) { - sscanf([colorString UTF8String], "rgb(%zd,%zd,%zd)", &red, &green, &blue); + sscanf(colorString.UTF8String, "rgb(%u,%u,%u)", &red, &green, &blue); } else { - RCTLogError(@"Unrecognized color format '%@', must be one of #hex|rgba|rgb", colorString); + RCTLogError(@"Unrecognized color format '%@', must be one of #hex|rgba|rgb or a valid CSS color name.", colorString); + alpha = -1; } - if (red == -1 || green == -1 || blue == -1 || alpha > 1.0 || alpha < 0.0) { + if (alpha < 0) { RCTLogError(@"Invalid color string '%@'", colorString); } else { color = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:alpha]; @@ -574,19 +574,19 @@ RCT_CGSTRUCT_CONVERTER(CGAffineTransform, (@[ } else { // Color array - color = [UIColor colorWithRed:[self double:json[0]] - green:[self double:json[1]] - blue:[self double:json[2]] - alpha:[json count] > 3 ? [self double:json[3]] : 1]; + color = [UIColor colorWithRed:[self CGFloat:json[0]] + green:[self CGFloat:json[1]] + blue:[self CGFloat:json[2]] + alpha:[json count] > 3 ? [self CGFloat:json[3]] : 1]; } } else if ([json isKindOfClass:[NSDictionary class]]) { // Color dictionary - color = [UIColor colorWithRed:[self double:json[@"r"]] - green:[self double:json[@"g"]] - blue:[self double:json[@"b"]] - alpha:[self double:json[@"a"] ?: @1]]; + color = [UIColor colorWithRed:[self CGFloat:json[@"r"]] + green:[self CGFloat:json[@"g"]] + blue:[self CGFloat:json[@"b"]] + alpha:[self CGFloat:json[@"a"] ?: @1]]; } else if (RCT_DEBUG && json && json != (id)kCFNull) { @@ -830,7 +830,7 @@ NSArray *RCTConvertArrayValue(SEL type, id json) { __block BOOL copy = NO; __block NSArray *values = json = [RCTConvert NSArray:json]; - [json enumerateObjectsUsingBlock:^(id jsonValue, NSUInteger idx, BOOL *stop) { + [json enumerateObjectsUsingBlock:^(id jsonValue, NSUInteger idx, __unused BOOL *stop) { id value = ((id(*)(Class, SEL, id))objc_msgSend)([RCTConvert class], type, jsonValue); if (copy) { if (value) { @@ -839,7 +839,7 @@ NSArray *RCTConvertArrayValue(SEL type, id json) } else if (value != jsonValue) { // Converted value is different, so we'll need to copy the array values = [[NSMutableArray alloc] initWithCapacity:values.count]; - for (NSInteger i = 0; i < idx; i++) { + for (NSUInteger i = 0; i < idx; i++) { [(NSMutableArray *)values addObject:json[i]]; } if (value) { @@ -876,7 +876,7 @@ static id RCTConvertPropertyListValue(id json) if ([json isKindOfClass:[NSDictionary class]]) { __block BOOL copy = NO; NSMutableDictionary *values = [[NSMutableDictionary alloc] initWithCapacity:[json count]]; - [json enumerateKeysAndObjectsUsingBlock:^(NSString *key, id jsonValue, BOOL *stop) { + [json enumerateKeysAndObjectsUsingBlock:^(NSString *key, id jsonValue, __unused BOOL *stop) { id value = RCTConvertPropertyListValue(jsonValue); if (value) { values[key] = value; @@ -889,7 +889,7 @@ static id RCTConvertPropertyListValue(id json) if ([json isKindOfClass:[NSArray class]]) { __block BOOL copy = NO; __block NSArray *values = json; - [json enumerateObjectsUsingBlock:^(id jsonValue, NSUInteger idx, BOOL *stop) { + [json enumerateObjectsUsingBlock:^(id jsonValue, NSUInteger idx, __unused BOOL *stop) { id value = RCTConvertPropertyListValue(jsonValue); if (copy) { if (value) { @@ -898,7 +898,7 @@ static id RCTConvertPropertyListValue(id json) } else if (value != jsonValue) { // Converted value is different, so we'll need to copy the array values = [[NSMutableArray alloc] initWithCapacity:values.count]; - for (NSInteger i = 0; i < idx; i++) { + for (NSUInteger i = 0; i < idx; i++) { [(NSMutableArray *)values addObject:json[i]]; } if (value) { diff --git a/React/Base/RCTDefines.h b/React/Base/RCTDefines.h index 7c6d88409..2e4fb3f61 100644 --- a/React/Base/RCTDefines.h +++ b/React/Base/RCTDefines.h @@ -61,9 +61,19 @@ #endif /** - * Concat two literals. Supports macro expansions - * - * i.e. RCT_CONCAT(foo, __FILE__) + * Concat two literals. Supports macro expansions, + * e.g. RCT_CONCAT(foo, __FILE__). */ #define RCT_CONCAT2(A, B) A ## B #define RCT_CONCAT(A, B) RCT_CONCAT2(A, B) + +/** + * Throw an assertion for unimplemented methods. + */ +#define RCT_NOT_IMPLEMENTED(method) \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wmissing-method-return-type\"") \ +_Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \ +RCT_EXTERN NSException *_RCTNotImplementedException(SEL, Class); \ +method NS_UNAVAILABLE { @throw _RCTNotImplementedException(_cmd, [self class]); } \ +_Pragma("clang diagnostic pop") diff --git a/React/Base/RCTDevMenu.m b/React/Base/RCTDevMenu.m index 8a5f23f9d..bce19e8a9 100644 --- a/React/Base/RCTDevMenu.m +++ b/React/Base/RCTDevMenu.m @@ -9,6 +9,7 @@ #import "RCTDevMenu.h" +#import "RCTAssert.h" #import "RCTBridge.h" #import "RCTDefines.h" #import "RCTEventDispatcher.h" @@ -34,7 +35,7 @@ static NSString *const RCTDevMenuSettingsKey = @"RCTDevMenu"; @implementation UIWindow (RCTDevMenu) -- (void)RCT_motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event +- (void)RCT_motionEnded:(__unused UIEventSubtype)motion withEvent:(UIEvent *)event { if (event.subtype == UIEventSubtypeMotionShake) { [[NSNotificationCenter defaultCenter] postNotificationName:RCTShowDevMenuNotification object:nil]; @@ -48,7 +49,7 @@ static NSString *const RCTDevMenuSettingsKey = @"RCTDevMenu"; @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) dispatch_block_t handler; -- (instancetype)initWithTitle:(NSString *)title handler:(dispatch_block_t)handler; +- (instancetype)initWithTitle:(NSString *)title handler:(dispatch_block_t)handler NS_DESIGNATED_INITIALIZER; @end @@ -56,13 +57,15 @@ static NSString *const RCTDevMenuSettingsKey = @"RCTDevMenu"; - (instancetype)initWithTitle:(NSString *)title handler:(dispatch_block_t)handler { - if (self = [super init]) { - self.title = title; - self.handler = handler; + if ((self = [super init])) { + _title = [title copy]; + _handler = [handler copy]; } return self; } +RCT_NOT_IMPLEMENTED(-init) + @end @interface RCTDevMenu () @@ -131,21 +134,23 @@ RCT_EXPORT_MODULE() // Toggle debug menu [commands registerKeyCommandWithInput:@"d" modifierFlags:UIKeyModifierCommand - action:^(UIKeyCommand *command) { + action:^(__unused UIKeyCommand *command) { [weakSelf toggle]; }]; // Toggle element inspector [commands registerKeyCommandWithInput:@"i" modifierFlags:UIKeyModifierCommand - action:^(UIKeyCommand *command) { - [_bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil]; + action:^(__unused UIKeyCommand *command) { + [_bridge.eventDispatcher + sendDeviceEventWithName:@"toggleElementInspector" + body:nil]; }]; // Reload in normal mode [commands registerKeyCommandWithInput:@"n" modifierFlags:UIKeyModifierCommand - action:^(UIKeyCommand *command) { + action:^(__unused UIKeyCommand *command) { weakSelf.executorClass = Nil; }]; #endif @@ -454,7 +459,8 @@ RCT_EXPORT_METHOD(reload) } __weak RCTDevMenu *weakSelf = self; - _updateTask = [[NSURLSession sharedSession] dataTaskWithURL:_liveReloadURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + _updateTask = [[NSURLSession sharedSession] dataTaskWithURL:_liveReloadURL completionHandler: + ^(__unused NSData *data, NSURLResponse *response, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ __strong RCTDevMenu *strongSelf = weakSelf; diff --git a/React/Base/RCTEventDispatcher.m b/React/Base/RCTEventDispatcher.m index b5b2857f0..ac0d1097b 100644 --- a/React/Base/RCTEventDispatcher.m +++ b/React/Base/RCTEventDispatcher.m @@ -31,6 +31,8 @@ static NSNumber *RCTGetEventID(id event) eventName:(NSString *)eventName body:(NSDictionary *)body { + RCTAssertParam(eventName); + if ((self = [super init])) { _viewTag = viewTag; _eventName = eventName; @@ -39,6 +41,8 @@ static NSNumber *RCTGetEventID(id event) return self; } +RCT_NOT_IMPLEMENTED(-init) + - (uint16_t)coalescingKey { return 0; @@ -85,10 +89,6 @@ RCT_EXPORT_MODULE() return self; } -RCT_IMPORT_METHOD(RCTNativeAppEventEmitter, emit); -RCT_IMPORT_METHOD(RCTDeviceEventEmitter, emit); -RCT_IMPORT_METHOD(RCTEventEmitter, receiveEvent); - - (void)sendAppEventWithName:(NSString *)name body:(id)body { [_bridge enqueueJSCall:@"RCTNativeAppEventEmitter.emit" @@ -175,12 +175,10 @@ RCT_IMPORT_METHOD(RCTEventEmitter, receiveEvent); return RCTJSThread; } -- (void)didUpdateFrame:(RCTFrameUpdate *)update +- (void)didUpdateFrame:(__unused RCTFrameUpdate *)update { - NSDictionary *eventQueue; - [_eventQueueLock lock]; - eventQueue = _eventQueue; + NSDictionary *eventQueue = _eventQueue; _eventQueue = [[NSMutableDictionary alloc] init]; _paused = YES; [_eventQueueLock unlock]; @@ -191,12 +189,3 @@ RCT_IMPORT_METHOD(RCTEventEmitter, receiveEvent); } @end - -@implementation RCTBridge (RCTEventDispatcher) - -- (RCTEventDispatcher *)eventDispatcher -{ - return self.modules[RCTBridgeModuleNameForClass([RCTEventDispatcher class])]; -} - -@end diff --git a/React/Base/RCTFPSGraph.m b/React/Base/RCTFPSGraph.m index 461f17e41..5e9b0d855 100644 --- a/React/Base/RCTFPSGraph.m +++ b/React/Base/RCTFPSGraph.m @@ -9,6 +9,7 @@ #import "RCTFPSGraph.h" +#import "RCTAssert.h" #import "RCTDefines.h" #if RCT_DEV @@ -32,7 +33,7 @@ - (instancetype)initWithFrame:(CGRect)frame graphPosition:(RCTFPSGraphPosition)position name:(NSString *)name color:(UIColor *)color { - if (self = [super initWithFrame:frame]) { + if ((self = [super initWithFrame:frame])) { _margin = 2; _prevTime = -1; _maxFPS = 0; @@ -42,8 +43,10 @@ _frames = malloc(sizeof(float) * _length); memset(_frames, 0, sizeof(float) * _length); - _name = name; - _position = position; + _name = name ?: @"FPS"; + _position = position ?: RCTFPSGraphPositionLeft; + + color = color ?: [UIColor greenColor]; _graph = [self createGraph:color]; _label = [self createLabel:color]; @@ -53,6 +56,9 @@ return self; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)dealloc { free(_frames); diff --git a/React/Base/RCTJavaScriptExecutor.h b/React/Base/RCTJavaScriptExecutor.h index 7a3aa2870..146247009 100644 --- a/React/Base/RCTJavaScriptExecutor.h +++ b/React/Base/RCTJavaScriptExecutor.h @@ -43,7 +43,7 @@ typedef void (^RCTJavaScriptCallback)(id json, NSError *error); * Runs an application script, and notifies of the script load being complete via `onComplete`. */ - (void)executeApplicationScript:(NSString *)script - sourceURL:(NSURL *)url + sourceURL:(NSURL *)sourceURL onComplete:(RCTJavaScriptCompleteBlock)onComplete; - (void)injectJSONText:(NSString *)script diff --git a/React/Base/RCTJavaScriptLoader.m b/React/Base/RCTJavaScriptLoader.m index 0210986dc..44d9e81c1 100755 --- a/React/Base/RCTJavaScriptLoader.m +++ b/React/Base/RCTJavaScriptLoader.m @@ -21,12 +21,16 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge { + RCTAssert(bridge, @"birdge parameter is required"); + if ((self = [super init])) { _bridge = bridge; } return self; } +RCT_NOT_IMPLEMENTED(-init) + - (void)loadBundleAtURL:(NSURL *)scriptURL onComplete:(void (^)(NSError *, NSString *))onComplete { // Sanitize the script URL diff --git a/React/Base/RCTKeyCommands.m b/React/Base/RCTKeyCommands.m index 823acb241..52d8c30dd 100644 --- a/React/Base/RCTKeyCommands.m +++ b/React/Base/RCTKeyCommands.m @@ -77,7 +77,7 @@ static RCTKeyCommands *RKKeyCommandsSharedInstance = nil; // To fix this, we use a linear search, since there won't be many keys anyway [_commandBindings enumerateKeysAndObjectsUsingBlock: - ^(UIKeyCommand *k, void (^block)(UIKeyCommand *), BOOL *stop) { + ^(UIKeyCommand *k, void (^block)(UIKeyCommand *), __unused BOOL *stop) { if ([key.input isEqualToString:k.input] && key.modifierFlags == k.modifierFlags) { block(key); } @@ -105,7 +105,7 @@ static RCTKeyCommands *RKKeyCommandsSharedInstance = nil; modifierFlags:flags action:@selector(RCT_handleKeyCommand:)]; - _commandBindings[command] = block ?: ^(UIKeyCommand *cmd) {}; + _commandBindings[command] = block ?: ^(__unused UIKeyCommand *cmd) {}; } - (void)unregisterKeyCommandWithInput:(NSString *)input diff --git a/React/Base/RCTLog.h b/React/Base/RCTLog.h index 5dead10be..11b957fd3 100644 --- a/React/Base/RCTLog.h +++ b/React/Base/RCTLog.h @@ -90,13 +90,12 @@ RCT_EXTERN void RCTAddLogFunction(RCTLogFunction logFunction); RCT_EXTERN void RCTPerformBlockWithLogPrefix(void (^block)(void), NSString *prefix); /** - * Private logging functions - ignore these. + * Private logging function - ignore this. */ -RCT_EXTERN void _RCTLogFormat(RCTLogLevel, const char *, int, NSString *, ...) NS_FORMAT_FUNCTION(4,5); #define _RCTLog(lvl, ...) do { \ - if (lvl >= RCTLOG_FATAL_LEVEL) { RCTAssert(NO, __VA_ARGS__); } \ - _RCTLogFormat(lvl, __FILE__, __LINE__, __VA_ARGS__); \ -} while (0) +if (lvl >= RCTLOG_FATAL_LEVEL) { RCTAssert(NO, __VA_ARGS__); } \ +_RCTLogFormat(lvl, __FILE__, __LINE__, __VA_ARGS__); } while (0) +RCT_EXTERN void _RCTLogFormat(RCTLogLevel, const char *, int, NSString *, ...) NS_FORMAT_FUNCTION(4,5); /** * Logging macros. Use these to log information, warnings and errors in your diff --git a/React/Base/RCTLog.m b/React/Base/RCTLog.m index 92c255659..e34502f3b 100644 --- a/React/Base/RCTLog.m +++ b/React/Base/RCTLog.m @@ -169,28 +169,28 @@ void _RCTLogFormat( #if RCT_DEBUG // Red box is only available in debug mode - // Log to red box - if (level >= RCTLOG_REDBOX_LEVEL) { - NSArray *stackSymbols = [NSThread callStackSymbols]; - NSMutableArray *stack = [NSMutableArray arrayWithCapacity:(stackSymbols.count - 1)]; - [stackSymbols enumerateObjectsUsingBlock:^(NSString *frameSymbols, NSUInteger idx, BOOL *stop) { - if (idx != 0) { // don't include the current frame - NSString *address = [[frameSymbols componentsSeparatedByString:@"0x"][1] componentsSeparatedByString:@" "][0]; - NSRange addressRange = [frameSymbols rangeOfString:address]; - NSString *methodName = [frameSymbols substringFromIndex:(addressRange.location + addressRange.length + 1)]; - if (idx == 1) { - NSString *file = [[@(fileName) componentsSeparatedByString:@"/"] lastObject]; - stack[0] = @{@"methodName": methodName, @"file": file, @"lineNumber": @(lineNumber)}; - } else { - stack[idx - 1] = @{@"methodName": methodName}; - } + // Log to red box + if (level >= RCTLOG_REDBOX_LEVEL) { + NSArray *stackSymbols = [NSThread callStackSymbols]; + NSMutableArray *stack = [NSMutableArray arrayWithCapacity:(stackSymbols.count - 1)]; + [stackSymbols enumerateObjectsUsingBlock:^(NSString *frameSymbols, NSUInteger idx, __unused BOOL *stop) { + if (idx > 0) { // don't include the current frame + NSString *address = [[frameSymbols componentsSeparatedByString:@"0x"][1] componentsSeparatedByString:@" "][0]; + NSRange addressRange = [frameSymbols rangeOfString:address]; + NSString *methodName = [frameSymbols substringFromIndex:(addressRange.location + addressRange.length + 1)]; + if (idx == 1) { + NSString *file = [[@(fileName) componentsSeparatedByString:@"/"] lastObject]; + [stack addObject:@{@"methodName": methodName, @"file": file, @"lineNumber": @(lineNumber)}]; + } else { + [stack addObject:@{@"methodName": methodName}]; } - }]; - [[RCTRedBox sharedInstance] showErrorMessage:message withStack:stack]; - } + } + }]; + [[RCTRedBox sharedInstance] showErrorMessage:message withStack:stack]; + } - // Log to JS executor - [RCTBridge logMessage:message level:level ? @(RCTLogLevels[level - 1]) : @"info"]; + // Log to JS executor + [RCTBridge logMessage:message level:level ? @(RCTLogLevels[level - 1]) : @"info"]; #endif diff --git a/React/Base/RCTProfile.m b/React/Base/RCTProfile.m index 1269d7594..a2b3d7106 100644 --- a/React/Base/RCTProfile.m +++ b/React/Base/RCTProfile.m @@ -43,7 +43,7 @@ NSDictionary *RCTProfileInfo; NSUInteger RCTProfileEventID = 0; NSMutableDictionary *RCTProfileOngoingEvents; NSTimeInterval RCTProfileStartTime; -NSLock *_RCTProfileLock; +NSRecursiveLock *_RCTProfileLock; #pragma mark - Macros @@ -118,20 +118,22 @@ static SEL RCTProfileProxySelector(SEL selector) } static void RCTProfileForwardInvocation(NSObject *, SEL, NSInvocation *); -static void RCTProfileForwardInvocation(NSObject *self, SEL cmd, NSInvocation *invocation) +static void RCTProfileForwardInvocation(NSObject *self, __unused SEL cmd, NSInvocation *invocation) { NSString *name = [NSString stringWithFormat:@"-[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(invocation.selector)]; SEL newSel = RCTProfileProxySelector(invocation.selector); - if ([object_getClass(self) instancesRespondToSelector:newSel]) { - invocation.selector = newSel; - RCTProfileBeginEvent(); - [invocation invoke]; - RCTProfileEndEvent(name, @"objc_call,modules,auto", nil); - } else { - // Use original selector to don't change error message - [self doesNotRecognizeSelector:invocation.selector]; - } + RCTProfileLock( + if ([object_getClass(self) instancesRespondToSelector:newSel]) { + invocation.selector = newSel; + RCTProfileBeginEvent(); + [invocation invoke]; + RCTProfileEndEvent(name, @"objc_call,modules,auto", nil); + } else { + // Use original selector to don't change error message + [self doesNotRecognizeSelector:invocation.selector]; + } + ); } static IMP RCTProfileMsgForward(NSObject *, SEL); @@ -150,7 +152,7 @@ static IMP RCTProfileMsgForward(NSObject *self, SEL selector) static void RCTProfileHookModules(RCTBridge *); static void RCTProfileHookModules(RCTBridge *bridge) { - [bridge.modules enumerateKeysAndObjectsUsingBlock:^(NSString *className, id module, BOOL *stop) { + for (id module in bridge.modules.allValues) { [bridge dispatchBlock:^{ Class moduleClass = object_getClass(module); Class proxyClass = objc_allocateClassPair(moduleClass, RCTProfileProxyClassName(moduleClass), 0); @@ -183,21 +185,23 @@ static void RCTProfileHookModules(RCTBridge *bridge) objc_registerClassPair(proxyClass); object_setClass(module, proxyClass); } forModule:module]; - }]; + } } void RCTProfileUnhookModules(RCTBridge *); void RCTProfileUnhookModules(RCTBridge *bridge) { - [bridge.modules enumerateKeysAndObjectsUsingBlock:^(NSString *className, id module, BOOL *stop) { + for (id module in bridge.modules.allValues) { [bridge dispatchBlock:^{ + RCTProfileLock( Class proxyClass = object_getClass(module); if (module.class != proxyClass) { object_setClass(module, module.class); objc_disposeClassPair(proxyClass); } + ); } forModule:module]; - }]; + }; } @@ -217,7 +221,7 @@ void RCTProfileInit(RCTBridge *bridge) static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - _RCTProfileLock = [[NSLock alloc] init]; + _RCTProfileLock = [[NSRecursiveLock alloc] init]; }); RCTProfileLock( RCTProfileStartTime = CACurrentMediaTime(); diff --git a/React/Base/RCTRedBox.m b/React/Base/RCTRedBox.m index b293a162d..8e85c0ca2 100644 --- a/React/Base/RCTRedBox.m +++ b/React/Base/RCTRedBox.m @@ -90,6 +90,8 @@ return self; } +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -145,12 +147,12 @@ #pragma mark - TableView -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +- (NSInteger)numberOfSectionsInTableView:(__unused UITableView *)tableView { return 2; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger)tableView:(__unused UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return section == 0 ? 1 : [_lastStackTrace count]; } diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index b12cda4f2..094e88840 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -62,7 +62,7 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat RCTAssert(bridge, @"A bridge instance is required to create an RCTRootView"); RCTAssert(moduleName, @"A moduleName is required to create an RCTRootView"); - if ((self = [super init])) { + if ((self = [super initWithFrame:CGRectZero])) { self.backgroundColor = [UIColor whiteColor]; @@ -100,6 +100,9 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat return [self initWithBridge:bridge moduleName:moduleName]; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)setBackgroundColor:(UIColor *)backgroundColor { super.backgroundColor = backgroundColor; @@ -116,9 +119,6 @@ NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotificat return YES; } -RCT_IMPORT_METHOD(AppRegistry, runApplication) -RCT_IMPORT_METHOD(ReactNative, unmountComponentAtNodeAndRemoveContainer) - - (void)setLoadingView:(UIView *)loadingView { _loadingView = loadingView; @@ -147,7 +147,7 @@ RCT_IMPORT_METHOD(ReactNative, unmountComponentAtNodeAndRemoveContainer) options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ _loadingView.hidden = YES; - } completion:^(BOOL finished) { + } completion:^(__unused BOOL finished) { [_loadingView removeFromSuperview]; }]; }); diff --git a/React/Base/RCTTouchHandler.m b/React/Base/RCTTouchHandler.m index 5c66aa49e..c7c19ed9b 100644 --- a/React/Base/RCTTouchHandler.m +++ b/React/Base/RCTTouchHandler.m @@ -40,12 +40,11 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge { + RCTAssertParam(bridge); + if ((self = [super initWithTarget:nil action:NULL])) { - RCTAssert(bridge != nil, @"Expect an event dispatcher"); - _bridge = bridge; - _nativeTouches = [[NSMutableOrderedSet alloc] init]; _reactTouches = [[NSMutableArray alloc] init]; _touchViews = [[NSMutableArray alloc] init]; @@ -58,6 +57,8 @@ return self; } +RCT_NOT_IMPLEMENTED(-initWithTarget:(id)target action:(SEL)action) + typedef NS_ENUM(NSInteger, RCTTouchEventType) { RCTTouchEventTypeStart, RCTTouchEventTypeMove, @@ -148,8 +149,6 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) { reactTouch[@"timestamp"] = @(nativeTouch.timestamp * 1000); // in ms, for JS } -RCT_IMPORT_METHOD(RCTEventEmitter, receiveTouches); - /** * Constructs information about touch events to send across the serialized * boundary. This data should be compliant with W3C `Touch` objects. This data @@ -163,7 +162,7 @@ RCT_IMPORT_METHOD(RCTEventEmitter, receiveTouches); */ - (void)_updateAndDispatchTouches:(NSSet *)touches eventName:(NSString *)eventName - originatingTime:(CFTimeInterval)originatingTime + originatingTime:(__unused CFTimeInterval)originatingTime { // Update touches NSMutableArray *changedIndexes = [[NSMutableArray alloc] init]; @@ -269,12 +268,12 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches) } } -- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer +- (BOOL)canPreventGestureRecognizer:(__unused UIGestureRecognizer *)preventedGestureRecognizer { return NO; } -- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer +- (BOOL)canBePreventedByGestureRecognizer:(__unused UIGestureRecognizer *)preventingGestureRecognizer { return NO; } diff --git a/React/Base/RCTUtils.h b/React/Base/RCTUtils.h index 5150b5c97..48eb903ae 100644 --- a/React/Base/RCTUtils.h +++ b/React/Base/RCTUtils.h @@ -36,9 +36,6 @@ RCT_EXTERN CGFloat RCTRoundPixelValue(CGFloat value); RCT_EXTERN CGFloat RCTCeilPixelValue(CGFloat value); RCT_EXTERN CGFloat RCTFloorPixelValue(CGFloat value); -// Get current time, for precise performance metrics -RCT_EXTERN NSTimeInterval RCTTGetAbsoluteTime(void); - // Method swizzling RCT_EXTERN void RCTSwapClassMethods(Class cls, SEL original, SEL replacement); RCT_EXTERN void RCTSwapInstanceMethods(Class cls, SEL original, SEL replacement); diff --git a/React/Base/RCTUtils.m b/React/Base/RCTUtils.m index a9522ad8c..15b5f8f7a 100644 --- a/React/Base/RCTUtils.m +++ b/React/Base/RCTUtils.m @@ -70,7 +70,7 @@ id RCTJSONClean(id object) if ([object isKindOfClass:[NSDictionary class]]) { __block BOOL copy = NO; NSMutableDictionary *values = [[NSMutableDictionary alloc] initWithCapacity:[object count]]; - [object enumerateKeysAndObjectsUsingBlock:^(NSString *key, id item, BOOL *stop) { + [object enumerateKeysAndObjectsUsingBlock:^(NSString *key, id item, __unused BOOL *stop) { id value = RCTJSONClean(item); values[key] = value; copy |= value != item; @@ -81,14 +81,14 @@ id RCTJSONClean(id object) if ([object isKindOfClass:[NSArray class]]) { __block BOOL copy = NO; __block NSArray *values = object; - [object enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) { + [object enumerateObjectsUsingBlock:^(id item, NSUInteger idx, __unused BOOL *stop) { id value = RCTJSONClean(item); if (copy) { [(NSMutableArray *)values addObject:value]; } else if (value != item) { // Converted value is different, so we'll need to copy the array values = [[NSMutableArray alloc] initWithCapacity:values.count]; - for (NSInteger i = 0; i < idx; i++) { + for (NSUInteger i = 0; i < idx; i++) { [(NSMutableArray *)values addObject:object[i]]; } [(NSMutableArray *)values addObject:value]; @@ -167,19 +167,6 @@ CGFloat RCTFloorPixelValue(CGFloat value) return floor(value * scale) / scale; } -NSTimeInterval RCTTGetAbsoluteTime(void) -{ - static struct mach_timebase_info tb_info = {0}; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - int ret = mach_timebase_info(&tb_info); - assert(0 == ret); - }); - - uint64_t timeInNanoseconds = (mach_absolute_time() * tb_info.numer) / tb_info.denom; - return ((NSTimeInterval)timeInNanoseconds) / 1000000; -} - void RCTSwapClassMethods(Class cls, SEL original, SEL replacement) { Method originalMethod = class_getClassMethod(cls, original); diff --git a/React/Executors/RCTContextExecutor.m b/React/Executors/RCTContextExecutor.m index 2bd6b7ae5..54736613e 100644 --- a/React/Executors/RCTContextExecutor.m +++ b/React/Executors/RCTContextExecutor.m @@ -80,7 +80,7 @@ RCT_EXPORT_MODULE() * crashes. */ -static JSValueRef RCTNativeLoggingHook(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) +static JSValueRef RCTNativeLoggingHook(JSContextRef context, __unused JSObjectRef object, __unused JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) { if (argumentCount > 0) { JSStringRef messageRef = JSValueToStringCopy(context, arguments[0], exception); @@ -109,7 +109,7 @@ static JSValueRef RCTNativeLoggingHook(JSContextRef context, JSObjectRef object, } // Do-very-little native hook for testing. -static JSValueRef RCTNoop(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) +static JSValueRef RCTNoop(JSContextRef context, __unused JSObjectRef object, __unused JSObjectRef thisObject, __unused size_t argumentCount, __unused const JSValueRef arguments[], __unused JSValueRef *exception) { static int counter = 0; counter++; @@ -120,7 +120,7 @@ static JSValueRef RCTNoop(JSContextRef context, JSObjectRef object, JSObjectRef static NSMutableArray *profiles; -static JSValueRef RCTConsoleProfile(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) +static JSValueRef RCTConsoleProfile(JSContextRef context, __unused JSObjectRef object, __unused JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], __unused JSValueRef *exception) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -147,7 +147,7 @@ static JSValueRef RCTConsoleProfile(JSContextRef context, JSObjectRef object, JS return JSValueMakeUndefined(context); } -static JSValueRef RCTConsoleProfileEnd(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) +static JSValueRef RCTConsoleProfileEnd(JSContextRef context, __unused JSObjectRef object, __unused JSObjectRef thisObject, __unused size_t argumentCount, __unused const JSValueRef arguments[], __unused JSValueRef *exception) { NSString *profileInfo = [profiles lastObject]; [profiles removeLastObject]; @@ -156,6 +156,10 @@ static JSValueRef RCTConsoleProfileEnd(JSContextRef context, JSObjectRef object, NSString *profileName = [profiles lastObject]; [profiles removeLastObject]; + if (argumentCount > 0 && !JSValueIsUndefined(context, arguments[0])) { + profileName = RCTJSValueToNSString(context, arguments[0]); + } + _RCTProfileEndEvent(profileID, profileName, @"console", profileInfo); return JSValueMakeUndefined(context); @@ -311,7 +315,10 @@ static NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError) [[NSNotificationCenter defaultCenter] removeObserver:self]; #endif - [_context performSelector:@selector(invalidate) onThread:_javaScriptThread withObject:nil waitUntilDone:NO]; + [_context performSelector:@selector(invalidate) + onThread:_javaScriptThread + withObject:nil + waitUntilDone:NO]; } - (void)dealloc @@ -358,7 +365,7 @@ static NSError *RCTNSErrorFromJSError(JSContextRef context, JSValueRef jsError) JSValueRef moduleJSRef = JSObjectCallAsFunction(contextJSRef, (JSObjectRef)requireJSRef, NULL, 1, (const JSValueRef *)&moduleNameJSRef, &errorJSRef); JSStringRelease(moduleNameJSStringRef); - if (moduleJSRef != NULL && errorJSRef == NULL) { + if (moduleJSRef != NULL && errorJSRef == NULL && !JSValueIsUndefined(contextJSRef, moduleJSRef)) { // get method JSStringRef methodNameJSStringRef = JSStringCreateWithCFString((__bridge CFStringRef)method); diff --git a/React/Executors/RCTWebViewExecutor.m b/React/Executors/RCTWebViewExecutor.m index 57c8d25db..0d8f0ad0f 100644 --- a/React/Executors/RCTWebViewExecutor.m +++ b/React/Executors/RCTWebViewExecutor.m @@ -153,7 +153,8 @@ RCT_EXPORT_MODULE() if (_objectsToInject.count > 0) { NSMutableString *scriptWithInjections = [[NSMutableString alloc] initWithString:@"/* BEGIN NATIVELY INJECTED OBJECTS */\n"]; - [_objectsToInject enumerateKeysAndObjectsUsingBlock:^(NSString *objectName, NSString *blockScript, BOOL *stop) { + [_objectsToInject enumerateKeysAndObjectsUsingBlock: + ^(NSString *objectName, NSString *blockScript, __unused BOOL *stop) { [scriptWithInjections appendString:objectName]; [scriptWithInjections appendString:@" = ("]; [scriptWithInjections appendString:blockScript]; @@ -200,7 +201,7 @@ RCT_EXPORT_MODULE() /** * `UIWebViewDelegate` methods. Handle application script load. */ -- (void)webViewDidFinishLoad:(UIWebView *)webView +- (void)webViewDidFinishLoad:(__unused UIWebView *)webView { RCTAssertMainThread(); if (_onApplicationScriptLoaded) { diff --git a/React/Modules/RCTAlertManager.m b/React/Modules/RCTAlertManager.m index 3bdb035fc..f93ef812a 100644 --- a/React/Modules/RCTAlertManager.m +++ b/React/Modules/RCTAlertManager.m @@ -101,7 +101,7 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args } [_alerts addObject:alertView]; - [_alertCallbacks addObject:callback ?: ^(id unused) {}]; + [_alertCallbacks addObject:callback ?: ^(__unused id unused) {}]; [_alertButtonKeys addObject:buttonKeys]; [alertView show]; diff --git a/React/Modules/RCTTiming.m b/React/Modules/RCTTiming.m index 2f3f6d40b..d6387d1d6 100644 --- a/React/Modules/RCTTiming.m +++ b/React/Modules/RCTTiming.m @@ -74,8 +74,6 @@ RCT_EXPORT_MODULE() -RCT_IMPORT_METHOD(RCTJSTimers, callTimers) - - (instancetype)init { if ((self = [super init])) { @@ -139,7 +137,7 @@ RCT_IMPORT_METHOD(RCTJSTimers, callTimers) _paused = NO; } -- (void)didUpdateFrame:(RCTFrameUpdate *)update +- (void)didUpdateFrame:(__unused RCTFrameUpdate *)update { NSMutableArray *timersToCall = [[NSMutableArray alloc] init]; for (RCTTimer *timer in _timers.allObjects) { @@ -153,7 +151,7 @@ RCT_IMPORT_METHOD(RCTJSTimers, callTimers) // call timers that need to be called if ([timersToCall count] > 0) { - [_bridge enqueueJSCall:@"RCTJSTimers.callTimers" args:@[timersToCall]]; + [_bridge enqueueJSCall:@"JSTimersExecution.callTimers" args:@[timersToCall]]; } if (_timers.count == 0) { diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index 366087480..0ffbaf0c3 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -225,7 +225,7 @@ static NSString *RCTViewNameForModuleName(NSString *moduleName) } // TODO: only send name once instead of a dictionary of name and type keyed by name -static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewName) +static NSDictionary *RCTViewConfigForModule(Class managerClass) { unsigned int count = 0; Method *methods = class_copyMethodList(object_getClass(managerClass), &count); @@ -308,11 +308,12 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa // Get view managers from bridge NSMutableDictionary *viewManagers = [[NSMutableDictionary alloc] init]; NSMutableDictionary *viewConfigs = [[NSMutableDictionary alloc] init]; - [_bridge.modules enumerateKeysAndObjectsUsingBlock:^(NSString *moduleName, RCTViewManager *manager, BOOL *stop) { + [_bridge.modules enumerateKeysAndObjectsUsingBlock: + ^(NSString *moduleName, RCTViewManager *manager, __unused BOOL *stop) { if ([manager isKindOfClass:[RCTViewManager class]]) { NSString *viewName = RCTViewNameForModuleName(moduleName); viewManagers[viewName] = manager; - viewConfigs[viewName] = RCTViewConfigForModule([manager class], viewName); + viewConfigs[viewName] = RCTViewConfigForModule([manager class]); } }]; @@ -325,7 +326,7 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa return _shadowQueue; } -- (void)registerRootView:(UIView *)rootView; +- (void)registerRootView:(UIView *)rootView { RCTAssertMainThread(); @@ -501,9 +502,9 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa } // Perform layout (possibly animated) - return ^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + return ^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { RCTResponseSenderBlock callback = self->_layoutAnimation.callback; - __block NSInteger completionsCalled = 0; + __block NSUInteger completionsCalled = 0; for (NSUInteger ii = 0; ii < frames.count; ii++) { NSNumber *reactTag = frameReactTags[ii]; UIView *view = viewRegistry[reactTag]; @@ -515,7 +516,7 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa BOOL shouldAnimateCreation = isNew && ![parentsAreNew[ii] boolValue]; RCTAnimation *createAnimation = shouldAnimateCreation ? _layoutAnimation.createAnimation : nil; - void (^completion)(BOOL finished) = ^(BOOL finished) { + void (^completion)(BOOL) = ^(BOOL finished) { completionsCalled++; if (event != (id)kCFNull) { [self.bridge.eventDispatcher sendInputEventWithName:@"topLayout" body:event]; @@ -578,7 +579,7 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa NSMutableSet *applierBlocks = [NSMutableSet setWithCapacity:1]; [topView collectUpdatedProperties:applierBlocks parentProperties:@{}]; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { for (RCTApplierBlock block in applierBlocks) { block(viewRegistry); } @@ -594,9 +595,9 @@ RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(NSNumber *)containerID) id container = _shadowViewRegistry[containerID]; RCTAssert(container != nil, @"container view (for ID %@) not found", containerID); - NSUInteger subviewsCount = [[container reactSubviews] count]; + NSUInteger subviewsCount = [container reactSubviews].count; NSMutableArray *indices = [[NSMutableArray alloc] initWithCapacity:subviewsCount]; - for (NSInteger childIndex = 0; childIndex < subviewsCount; childIndex++) { + for (NSUInteger childIndex = 0; childIndex < subviewsCount; childIndex++) { [indices addObject:@(childIndex)]; } @@ -619,20 +620,21 @@ RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(NSNumber *)containerID) { // If there are no indices to move or the container has no subviews don't bother // We support parents with nil subviews so long as they're all nil so this allows for this behavior - if ([atIndices count] == 0 || [[container reactSubviews] count] == 0) { + if (atIndices.count == 0 || [container reactSubviews].count == 0) { return nil; } // Construction of removed children must be done "up front", before indices are disturbed by removals. NSMutableArray *removedChildren = [NSMutableArray arrayWithCapacity:atIndices.count]; RCTAssert(container != nil, @"container view (for ID %@) not found", container); - for (NSInteger i = 0; i < [atIndices count]; i++) { - NSInteger index = [atIndices[i] integerValue]; - if (index < [[container reactSubviews] count]) { + for (NSNumber *indexNumber in atIndices) { + NSUInteger index = indexNumber.unsignedIntegerValue; + if (index < [container reactSubviews].count) { [removedChildren addObject:[container reactSubviews][index]]; } } if (removedChildren.count != atIndices.count) { - RCTLogMustFix(@"removedChildren count (%tu) was not what we expected (%tu)", removedChildren.count, atIndices.count); + RCTLogMustFix(@"removedChildren count (%tu) was not what we expected (%tu)", + removedChildren.count, atIndices.count); } return removedChildren; } @@ -778,7 +780,7 @@ static BOOL RCTCallPropertySetter(NSString *key, SEL setter, id value, id view, static void RCTSetViewProps(NSDictionary *props, UIView *view, UIView *defaultView, RCTViewManager *manager) { - [props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { + [props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, __unused BOOL *stop) { SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set_%@:forView:withDefaultView:", key]); RCTCallPropertySetter(key, setter, obj, view, defaultView, manager); @@ -789,7 +791,7 @@ static void RCTSetViewProps(NSDictionary *props, UIView *view, static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView, RCTShadowView *defaultView, RCTViewManager *manager) { - [props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { + [props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, __unused BOOL *stop) { SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set_%@:forShadowView:withDefaultView:", key]); RCTCallPropertySetter(key, setter, obj, shadowView, defaultView, manager); @@ -877,7 +879,7 @@ RCT_EXPORT_METHOD(updateView:(NSNumber *)reactTag RCTSetShadowViewProps(props, shadowView, _defaultShadowViews[viewName], viewManager); [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { - UIView *view = uiManager->_viewRegistry[reactTag]; + UIView *view = viewRegistry[reactTag]; RCTSetViewProps(props, view, uiManager->_defaultViews[viewName], viewManager); }]; } @@ -885,7 +887,7 @@ RCT_EXPORT_METHOD(updateView:(NSNumber *)reactTag RCT_EXPORT_METHOD(focus:(NSNumber *)reactTag) { if (!reactTag) return; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { UIView *newResponder = viewRegistry[reactTag]; [newResponder reactWillMakeFirstResponder]; [newResponder becomeFirstResponder]; @@ -896,7 +898,7 @@ RCT_EXPORT_METHOD(focus:(NSNumber *)reactTag) RCT_EXPORT_METHOD(blur:(NSNumber *)reactTag) { if (!reactTag) return; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ UIView *currentResponder = viewRegistry[reactTag]; [currentResponder resignFirstResponder]; }]; @@ -908,7 +910,7 @@ RCT_EXPORT_METHOD(findSubviewIn:(NSNumber *)reactTag atPoint:(CGPoint)point call return; } - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { UIView *view = viewRegistry[reactTag]; UIView *target = [view hitTest:point withEvent:nil]; CGRect frame = [target convertRect:target.bounds toView:view]; @@ -940,7 +942,7 @@ RCT_EXPORT_METHOD(findSubviewIn:(NSNumber *)reactTag atPoint:(CGPoint)point call // Set up next layout animation if (_nextLayoutAnimation) { RCTLayoutAnimation *layoutAnimation = _nextLayoutAnimation; - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self addUIBlock:^(RCTUIManager *uiManager, __unused RCTSparseArray *viewRegistry) { uiManager->_layoutAnimation = layoutAnimation; }]; } @@ -954,7 +956,7 @@ RCT_EXPORT_METHOD(findSubviewIn:(NSNumber *)reactTag atPoint:(CGPoint)point call // Clear layout animations if (_nextLayoutAnimation) { - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self addUIBlock:^(RCTUIManager *uiManager, __unused RCTSparseArray *viewRegistry) { uiManager->_layoutAnimation = nil; }]; _nextLayoutAnimation = nil; @@ -996,7 +998,7 @@ RCT_EXPORT_METHOD(measure:(NSNumber *)reactTag return; } - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { UIView *view = viewRegistry[reactTag]; if (!view) { RCTLogError(@"measure cannot find view with tag #%@", reactTag); @@ -1063,7 +1065,7 @@ static void RCTMeasureLayout(RCTShadowView *view, */ RCT_EXPORT_METHOD(measureLayout:(NSNumber *)reactTag relativeTo:(NSNumber *)ancestorReactTag - errorCallback:(RCTResponseSenderBlock)errorCallback + errorCallback:(__unused RCTResponseSenderBlock)errorCallback callback:(RCTResponseSenderBlock)callback) { RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; @@ -1079,7 +1081,7 @@ RCT_EXPORT_METHOD(measureLayout:(NSNumber *)reactTag * height). */ RCT_EXPORT_METHOD(measureLayoutRelativeToParent:(NSNumber *)reactTag - errorCallback:(RCTResponseSenderBlock)errorCallback + errorCallback:(__unused RCTResponseSenderBlock)errorCallback callback:(RCTResponseSenderBlock)callback) { RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; @@ -1095,7 +1097,7 @@ RCT_EXPORT_METHOD(measureLayoutRelativeToParent:(NSNumber *)reactTag */ RCT_EXPORT_METHOD(measureViewsInRect:(CGRect)rect parentView:(NSNumber *)reactTag - errorCallback:(RCTResponseSenderBlock)errorCallback + errorCallback:(__unused RCTResponseSenderBlock)errorCallback callback:(RCTResponseSenderBlock)callback) { RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; @@ -1107,7 +1109,8 @@ RCT_EXPORT_METHOD(measureViewsInRect:(CGRect)rect NSMutableArray *results = [[NSMutableArray alloc] initWithCapacity:[childShadowViews count]]; - [childShadowViews enumerateObjectsUsingBlock:^(RCTShadowView *childShadowView, NSUInteger idx, BOOL *stop) { + [childShadowViews enumerateObjectsUsingBlock: + ^(RCTShadowView *childShadowView, NSUInteger idx, __unused BOOL *stop) { CGRect childLayout = [childShadowView measureLayoutRelativeToAncestor:shadowView]; if (CGRectIsNull(childLayout)) { RCTLogError(@"View %@ (tag #%@) is not a decendant of %@ (tag #%@)", @@ -1167,7 +1170,7 @@ RCT_EXPORT_METHOD(scrollTo:(NSNumber *)reactTag withOffsetX:(CGFloat)offsetX offsetY:(CGFloat)offsetY) { - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ UIView *view = viewRegistry[reactTag]; if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { [(id)view scrollToOffset:(CGPoint){offsetX, offsetY} animated:YES]; @@ -1182,7 +1185,7 @@ RCT_EXPORT_METHOD(scrollWithoutAnimationTo:(NSNumber *)reactTag offsetX:(CGFloat)offsetX offsetY:(CGFloat)offsetY) { - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ UIView *view = viewRegistry[reactTag]; if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { [(id)view scrollToOffset:(CGPoint){offsetX, offsetY} animated:NO]; @@ -1195,7 +1198,7 @@ RCT_EXPORT_METHOD(scrollWithoutAnimationTo:(NSNumber *)reactTag RCT_EXPORT_METHOD(zoomToRect:(NSNumber *)reactTag withRect:(CGRect)rect) { - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ UIView *view = viewRegistry[reactTag]; if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { [(id)view zoomToRect:rect animated:YES]; @@ -1211,7 +1214,7 @@ RCT_EXPORT_METHOD(zoomToRect:(NSNumber *)reactTag */ RCT_EXPORT_METHOD(setJSResponder:(NSNumber *)reactTag) { - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { _jsResponder = viewRegistry[reactTag]; if (!_jsResponder) { RCTLogError(@"Invalid view set to be the JS responder - tag %zd", reactTag); @@ -1221,7 +1224,7 @@ RCT_EXPORT_METHOD(setJSResponder:(NSNumber *)reactTag) RCT_EXPORT_METHOD(clearJSResponder) { - [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self addUIBlock:^(__unused RCTUIManager *uiManager, __unused RCTSparseArray *viewRegistry) { _jsResponder = nil; }]; } @@ -1326,7 +1329,7 @@ RCT_EXPORT_METHOD(clearJSResponder) }, } mutableCopy]; - [_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, RCTViewManager *manager, BOOL *stop) { + for (RCTViewManager *manager in _viewManagers) { if (RCTClassOverridesInstanceMethod([manager class], @selector(customBubblingEventTypes))) { NSDictionary *eventTypes = [manager customBubblingEventTypes]; for (NSString *eventName in eventTypes) { @@ -1335,7 +1338,7 @@ RCT_EXPORT_METHOD(clearJSResponder) } [customBubblingEventTypesConfigs addEntriesFromDictionary:eventTypes]; } - }]; + }; return customBubblingEventTypesConfigs; } @@ -1387,7 +1390,7 @@ RCT_EXPORT_METHOD(clearJSResponder) }, } mutableCopy]; - [_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, RCTViewManager *manager, BOOL *stop) { + for (RCTViewManager *manager in _viewManagers) { if (RCTClassOverridesInstanceMethod([manager class], @selector(customDirectEventTypes))) { NSDictionary *eventTypes = [manager customDirectEventTypes]; for (NSString *eventName in eventTypes) { @@ -1395,7 +1398,7 @@ RCT_EXPORT_METHOD(clearJSResponder) } [customDirectEventTypes addEntriesFromDictionary:eventTypes]; } - }]; + }; return customDirectEventTypes; } @@ -1418,8 +1421,11 @@ RCT_EXPORT_METHOD(clearJSResponder) }, } mutableCopy]; - [_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, RCTViewManager *manager, BOOL *stop) { - NSMutableDictionary *constantsNamespace = [NSMutableDictionary dictionaryWithDictionary:allJSConstants[name]]; + [_viewManagers enumerateKeysAndObjectsUsingBlock: + ^(NSString *name, RCTViewManager *manager, __unused BOOL *stop) { + + NSMutableDictionary *constantsNamespace = + [NSMutableDictionary dictionaryWithDictionary:allJSConstants[name]]; // Add custom constants // TODO: should these be inherited? @@ -1440,7 +1446,7 @@ RCT_EXPORT_METHOD(clearJSResponder) RCT_EXPORT_METHOD(configureNextLayoutAnimation:(NSDictionary *)config withCallback:(RCTResponseSenderBlock)callback - errorCallback:(RCTResponseSenderBlock)errorCallback) + errorCallback:(__unused RCTResponseSenderBlock)errorCallback) { if (_nextLayoutAnimation) { RCTLogWarn(@"Warning: Overriding previous layout animation with new one before the first began:\n%@ -> %@.", _nextLayoutAnimation, config); diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index 513773b6d..81f65d39a 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -618,6 +618,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -626,6 +627,10 @@ MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = ( + "-Wextra", + "-Wall", + ); }; name = Debug; }; @@ -654,6 +659,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; @@ -662,6 +668,10 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = ( + "-Wextra", + "-Wall", + ); }; name = Release; }; diff --git a/React/Views/RCTMapManager.m b/React/Views/RCTMapManager.m index 7a9401fdd..b1c5c84b8 100644 --- a/React/Views/RCTMapManager.m +++ b/React/Views/RCTMapManager.m @@ -64,7 +64,7 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap) } } -- (void)mapView:(RCTMap *)mapView regionWillChangeAnimated:(BOOL)animated +- (void)mapView:(RCTMap *)mapView regionWillChangeAnimated:(__unused BOOL)animated { [self _regionChanged:mapView]; @@ -77,7 +77,7 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap) [[NSRunLoop mainRunLoop] addTimer:mapView.regionChangeObserveTimer forMode:NSRunLoopCommonModes]; } -- (void)mapView:(RCTMap *)mapView regionDidChangeAnimated:(BOOL)animated +- (void)mapView:(RCTMap *)mapView regionDidChangeAnimated:(__unused BOOL)animated { [mapView.regionChangeObserveTimer invalidate]; mapView.regionChangeObserveTimer = nil; diff --git a/React/Views/RCTNavigator.m b/React/Views/RCTNavigator.m index 381846569..63e3d8023 100644 --- a/React/Views/RCTNavigator.m +++ b/React/Views/RCTNavigator.m @@ -267,8 +267,10 @@ NSInteger kNeverProgressed = -10000; @synthesize paused = _paused; -- (id)initWithBridge:(RCTBridge *)bridge +- (instancetype)initWithBridge:(RCTBridge *)bridge { + RCTAssertParam(bridge); + if ((self = [super initWithFrame:CGRectZero])) { _paused = YES; @@ -291,7 +293,10 @@ NSInteger kNeverProgressed = -10000; return self; } -- (void)didUpdateFrame:(RCTFrameUpdate *)update +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + +- (void)didUpdateFrame:(__unused RCTFrameUpdate *)update { if (_currentlyTransitioningFrom != _currentlyTransitioningTo) { UIView *topView = _dummyView; @@ -328,8 +333,8 @@ NSInteger kNeverProgressed = -10000; * locks aside from the animation complete hook. */ - (void)navigationController:(UINavigationController *)navigationController - willShowViewController:(UIViewController *)viewController - animated:(BOOL)animated + willShowViewController:(__unused UIViewController *)viewController + animated:(__unused BOOL)animated { id tc = navigationController.topViewController.transitionCoordinator; @@ -343,12 +348,12 @@ NSInteger kNeverProgressed = -10000; NSUInteger indexOfFrom = [_currentViews indexOfObject:fromController.navItem]; NSUInteger indexOfTo = [_currentViews indexOfObject:toController.navItem]; CGFloat destination = indexOfFrom < indexOfTo ? 1.0 : -1.0; - _dummyView.frame = (CGRect){{destination}}; + _dummyView.frame = (CGRect){{destination, 0}, CGSizeZero}; _currentlyTransitioningFrom = indexOfFrom; _currentlyTransitioningTo = indexOfTo; _paused = NO; } - completion:^(id context) { + completion:^(__unused id context) { [weakSelf freeLock]; _currentlyTransitioningFrom = 0; _currentlyTransitioningTo = 0; @@ -441,13 +446,13 @@ NSInteger kNeverProgressed = -10000; // hooked up yet, so we do it on demand here [self addControllerToClosestParent:_navigationController]; - NSInteger viewControllerCount = _navigationController.viewControllers.count; + NSUInteger viewControllerCount = _navigationController.viewControllers.count; // The "react count" is the count of views that are visible on the navigation // stack. There may be more beyond this - that aren't visible, and may be // deleted/purged soon. - NSInteger previousReactCount = + NSUInteger previousReactCount = _previousRequestedTopOfStack == kNeverRequested ? 0 : _previousRequestedTopOfStack + 1; - NSInteger currentReactCount = _requestedTopOfStack + 1; + NSUInteger currentReactCount = _requestedTopOfStack + 1; BOOL jsGettingAhead = // ----- previously caught up ------ ------ no longer caught up ------- @@ -465,7 +470,7 @@ NSInteger kNeverProgressed = -10000; BOOL jsGettingtooSlow = // --- previously not caught up -------- ------- no longer caught up ---------- viewControllerCount < previousReactCount && currentReactCount < previousReactCount; - + BOOL reactPushOne = jsGettingAhead && currentReactCount == previousReactCount + 1; BOOL reactPopN = jsGettingAhead && currentReactCount < previousReactCount; @@ -486,7 +491,7 @@ BOOL jsGettingtooSlow = // Views before the previous React count must not have changed. Views greater than previousReactCount // up to currentReactCount may have changed. - for (NSInteger i = 0; i < MIN(_currentViews.count, MIN(_previousViews.count, previousReactCount)); i++) { + for (NSUInteger i = 0; i < MIN(_currentViews.count, MIN(_previousViews.count, previousReactCount)); i++) { if (_currentViews[i] != _previousViews[i]) { RCTLogError(@"current view should equal previous view"); } diff --git a/React/Views/RCTNavigatorManager.m b/React/Views/RCTNavigatorManager.m index 1158f7dcf..7d9a78045 100644 --- a/React/Views/RCTNavigatorManager.m +++ b/React/Views/RCTNavigatorManager.m @@ -37,10 +37,11 @@ RCT_EXPORT_VIEW_PROPERTY(requestedTopOfStack, NSInteger) // TODO: remove error callbacks RCT_EXPORT_METHOD(requestSchedulingJavaScriptNavigation:(NSNumber *)reactTag - errorCallback:(RCTResponseSenderBlock)errorCallback - callback:(__unused RCTResponseSenderBlock)callback) + errorCallback:(__unused RCTResponseSenderBlock)errorCallback + callback:(RCTResponseSenderBlock)callback) { - [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ + [self.bridge.uiManager addUIBlock: + ^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ RCTNavigator *navigator = viewRegistry[reactTag]; if ([navigator isKindOfClass:[RCTNavigator class]]) { BOOL wasAcquired = [navigator requestSchedulingJavaScriptNavigation]; diff --git a/React/Views/RCTPicker.m b/React/Views/RCTPicker.m index dd2bcdb8a..9e1f3bb07 100644 --- a/React/Views/RCTPicker.m +++ b/React/Views/RCTPicker.m @@ -27,9 +27,11 @@ const NSInteger UNINITIALIZED_INDEX = -1; NSInteger _selectedIndex; } -- (id)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher +- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { - if (self = [super initWithFrame:CGRectZero]) { + RCTAssertParam(eventDispatcher); + + if ((self = [super initWithFrame:CGRectZero])) { _eventDispatcher = eventDispatcher; _selectedIndex = UNINITIALIZED_INDEX; self.delegate = self; @@ -37,12 +39,13 @@ const NSInteger UNINITIALIZED_INDEX = -1; return self; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)setItems:(NSArray *)items { - if (_items != items) { - _items = [items copy]; - [self setNeedsLayout]; - } + _items = [items copy]; + [self setNeedsLayout]; } - (void)setSelectedIndex:(NSInteger)selectedIndex @@ -58,12 +61,13 @@ const NSInteger UNINITIALIZED_INDEX = -1; #pragma mark - UIPickerViewDataSource protocol -- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView +- (NSInteger)numberOfComponentsInPickerView:(__unused UIPickerView *)pickerView { return 1; } -- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component +- (NSInteger)pickerView:(__unused UIPickerView *)pickerView +numberOfRowsInComponent:(__unused NSInteger)component { return _items.count; } @@ -80,12 +84,14 @@ const NSInteger UNINITIALIZED_INDEX = -1; return [self itemForRow:row][@"value"]; } -- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component +- (NSString *)pickerView:(__unused UIPickerView *)pickerView + titleForRow:(NSInteger)row forComponent:(__unused NSInteger)component { return [self itemForRow:row][@"label"]; } -- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component +- (void)pickerView:(__unused UIPickerView *)pickerView + didSelectRow:(NSInteger)row inComponent:(__unused NSInteger)component { _selectedIndex = row; NSDictionary *event = @{ @@ -96,4 +102,5 @@ const NSInteger UNINITIALIZED_INDEX = -1; [_eventDispatcher sendInputEventWithName:@"topChange" body:event]; } + @end diff --git a/React/Views/RCTPickerManager.m b/React/Views/RCTPickerManager.m index de6c1f916..8e31e5fe9 100644 --- a/React/Views/RCTPickerManager.m +++ b/React/Views/RCTPickerManager.m @@ -27,7 +27,7 @@ RCT_EXPORT_VIEW_PROPERTY(selectedIndex, NSInteger) - (NSDictionary *)constantsToExport { - RCTPicker *view = [[RCTPicker alloc] init]; + UIPickerView *view = [[UIPickerView alloc] init]; return @{ @"ComponentHeight": @(view.intrinsicContentSize.height), @"ComponentWidth": @(view.intrinsicContentSize.width) diff --git a/React/Views/RCTScrollView.m b/React/Views/RCTScrollView.m index e6fdb83ca..6c3f5d519 100644 --- a/React/Views/RCTScrollView.m +++ b/React/Views/RCTScrollView.m @@ -44,7 +44,9 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; scrollView:(UIScrollView *)scrollView userData:(NSDictionary *)userData { - if (self = [super init]) { + RCTAssertParam(reactTag); + + if ((self = [super init])) { _type = type; _viewTag = reactTag; _scrollView = scrollView; @@ -53,6 +55,8 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; return self; } +RCT_NOT_IMPLEMENTED(-init) + - (uint16_t)coalescingKey { return 0; @@ -166,7 +170,7 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; return NO; } -- (void)handleCustomPan:(UIPanGestureRecognizer *)sender +- (void)handleCustomPan:(__unused UIPanGestureRecognizer *)sender { if ([self _shouldDisableScrollInteraction]) { self.panGestureRecognizer.enabled = NO; @@ -181,7 +185,7 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; } } -- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated +- (void)scrollRectToVisible:(__unused CGRect)rect animated:(__unused BOOL)animated { // noop } @@ -228,7 +232,7 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; * In order to have this called, you must have delaysContentTouches set to NO * (which is the not the `UIKit` default). */ -- (BOOL)touchesShouldCancelInContentView:(UIView *)view +- (BOOL)touchesShouldCancelInContentView:(__unused UIView *)view { //TODO: shouldn't this call super if _shouldDisableScrollInteraction returns NO? return ![self _shouldDisableScrollInteraction]; @@ -265,8 +269,9 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; __block UIView *previousHeader = nil; __block UIView *currentHeader = nil; __block UIView *nextHeader = nil; - NSInteger subviewCount = contentView.reactSubviews.count; - [_stickyHeaderIndices enumerateIndexesWithOptions:0 usingBlock:^(NSUInteger idx, BOOL *stop) { + NSUInteger subviewCount = contentView.reactSubviews.count; + [_stickyHeaderIndices enumerateIndexesWithOptions:0 usingBlock: + ^(NSUInteger idx, __unused BOOL *stop) { if (idx >= subviewCount) { RCTLogError(@"Sticky header index %zd was outside the range {0, %zd}", idx, subviewCount); @@ -358,6 +363,8 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { + RCTAssertParam(eventDispatcher); + if ((self = [super initWithFrame:CGRectZero])) { _eventDispatcher = eventDispatcher; @@ -377,12 +384,15 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; return self; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)setRemoveClippedSubviews:(__unused BOOL)removeClippedSubviews { // Does nothing } -- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex +- (void)insertReactSubview:(UIView *)view atIndex:(__unused NSInteger)atIndex { RCTAssert(_contentView == nil, @"RCTScrollView may only contain a single subview"); _contentView = view; @@ -401,11 +411,21 @@ CGFloat const ZINDEX_STICKY_HEADER = 50; return _contentView ? @[_contentView] : @[]; } +- (BOOL)centerContent +{ + return _scrollView.centerContent; +} + - (void)setCenterContent:(BOOL)centerContent { _scrollView.centerContent = centerContent; } +- (NSIndexSet *)stickyHeaderIndices +{ + return _scrollView.stickyHeaderIndices; +} + - (void)setStickyHeaderIndices:(NSIndexSet *)headerIndices { RCTAssert(_scrollView.contentSize.width <= self.frame.size.width, @@ -506,7 +526,8 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove) // Calculate changed frames NSMutableArray *updatedChildFrames = [[NSMutableArray alloc] init]; - [[_contentView reactSubviews] enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { + [[_contentView reactSubviews] enumerateObjectsUsingBlock: + ^(UIView *subview, NSUInteger idx, __unused BOOL *stop) { // Check if new or changed CGRect newFrame = subview.frame; @@ -560,7 +581,17 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove) - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { - [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeEnd reactTag:self.reactTag scrollView:scrollView userData:nil]; + NSDictionary *userData = @{ + @"velocity": @{ + @"x": @(velocity.x), + @"y": @(velocity.y) + }, + @"targetContentOffset": @{ + @"x": @(targetContentOffset->x), + @"y": @(targetContentOffset->y) + } + }; + [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeEnd reactTag:self.reactTag scrollView:scrollView userData:userData]; RCT_FORWARD_SCROLL_EVENT(scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset); } @@ -589,7 +620,7 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove) return YES; } -- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView +- (UIView *)viewForZoomingInScrollView:(__unused UIScrollView *)scrollView { return _contentView; } diff --git a/React/Views/RCTScrollViewManager.m b/React/Views/RCTScrollViewManager.m index 15803df1e..6e74d1333 100644 --- a/React/Views/RCTScrollViewManager.m +++ b/React/Views/RCTScrollViewManager.m @@ -75,7 +75,7 @@ RCT_DEPRECATED_VIEW_PROPERTY(throttleScrollCallbackMS, scrollEventThrottle) RCT_EXPORT_METHOD(getContentSize:(NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback) { - [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { UIView *view = viewRegistry[reactTag]; if (!view) { diff --git a/React/Views/RCTShadowView.m b/React/Views/RCTShadowView.m index ba70ca34f..9d56bb906 100644 --- a/React/Views/RCTShadowView.m +++ b/React/Views/RCTShadowView.m @@ -213,7 +213,8 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st } } -- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame parentConstraint:(CGSize)parentConstraint +- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame + parentConstraint:(__unused CGSize)parentConstraint { [self fillCSSNode:_cssNode]; layoutNode(_cssNode, CSS_UNDEFINED); @@ -363,6 +364,34 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st return self.reactTag; } +- (NSString *)description +{ + NSString *description = super.description; + description = [[description substringToIndex:description.length - 1] stringByAppendingFormat:@"; viewName: %@; reactTag: %@; frame: %@>", self.viewName, self.reactTag, NSStringFromCGRect(self.frame)]; + return description; +} + +- (void)addRecursiveDescriptionToString:(NSMutableString *)string atLevel:(NSUInteger)level +{ + for (NSUInteger i = 0; i < level; i++) { + [string appendString:@" | "]; + } + + [string appendString:self.description]; + [string appendString:@"\n"]; + + for (RCTShadowView *subview in _reactSubviews) { + [subview addRecursiveDescriptionToString:string atLevel:level + 1]; + } +} + +- (NSString *)recursiveDescription +{ + NSMutableString *description = [NSMutableString string]; + [self addRecursiveDescriptionToString:description atLevel:0]; + return description; +} + // Margin #define RCT_MARGIN_PROPERTY(prop, metaProp) \ diff --git a/React/Views/RCTTabBar.m b/React/Views/RCTTabBar.m index b5b6240a4..06df7bad6 100644 --- a/React/Views/RCTTabBar.m +++ b/React/Views/RCTTabBar.m @@ -30,8 +30,10 @@ NSMutableArray *_tabViews; } -- (id)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher +- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { + RCTAssertParam(eventDispatcher); + if ((self = [super initWithFrame:CGRectZero])) { _eventDispatcher = eventDispatcher; _tabViews = [[NSMutableArray alloc] init]; @@ -42,6 +44,9 @@ return self; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (UIViewController *)backingViewController { return _tabController; @@ -105,7 +110,8 @@ _tabsChanged = NO; } - [[self reactSubviews] enumerateObjectsUsingBlock:^(RCTTabBarItem *tab, NSUInteger index, BOOL *stop) { + [[self reactSubviews] enumerateObjectsUsingBlock: + ^(RCTTabBarItem *tab, NSUInteger index, __unused BOOL *stop) { UIViewController *controller = _tabController.viewControllers[index]; controller.tabBarItem = tab.barItem; if (tab.selected) { @@ -114,11 +120,21 @@ }]; } +- (UIColor *)barTintColor +{ + return _tabController.tabBar.barTintColor; +} + - (void)setBarTintColor:(UIColor *)barTintColor { _tabController.tabBar.barTintColor = barTintColor; } +- (UIColor *)tintColor +{ + return _tabController.tabBar.tintColor; +} + - (void)setTintColor:(UIColor *)tintColor { _tabController.tabBar.tintColor = tintColor; diff --git a/React/Views/RCTTextField.m b/React/Views/RCTTextField.m index 12d52b1b8..46e9cc7a4 100644 --- a/React/Views/RCTTextField.m +++ b/React/Views/RCTTextField.m @@ -24,7 +24,7 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { if ((self = [super initWithFrame:CGRectZero])) { - + RCTAssert(eventDispatcher, @"eventDispatcher is a required parameter"); _eventDispatcher = eventDispatcher; [self addTarget:self action:@selector(_textFieldDidChange) forControlEvents:UIControlEventEditingChanged]; [self addTarget:self action:@selector(_textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin]; @@ -35,6 +35,9 @@ return self; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)setText:(NSString *)text { if (![text isEqualToString:self.text]) { diff --git a/React/Views/RCTTextFieldManager.m b/React/Views/RCTTextFieldManager.m index 7b867bd0d..3d440665a 100644 --- a/React/Views/RCTTextFieldManager.m +++ b/React/Views/RCTTextFieldManager.m @@ -43,11 +43,11 @@ RCT_CUSTOM_VIEW_PROPERTY(fontSize, CGFloat, RCTTextField) { view.font = [RCTConvert UIFont:view.font withSize:json ?: @(defaultView.font.pointSize)]; } -RCT_CUSTOM_VIEW_PROPERTY(fontWeight, NSString, RCTTextField) +RCT_CUSTOM_VIEW_PROPERTY(fontWeight, NSString, __unused RCTTextField) { view.font = [RCTConvert UIFont:view.font withWeight:json]; // defaults to normal } -RCT_CUSTOM_VIEW_PROPERTY(fontStyle, NSString, RCTTextField) +RCT_CUSTOM_VIEW_PROPERTY(fontStyle, NSString, __unused RCTTextField) { view.font = [RCTConvert UIFont:view.font withStyle:json]; // defaults to normal } @@ -60,7 +60,7 @@ RCT_CUSTOM_VIEW_PROPERTY(fontFamily, NSString, RCTTextField) { NSNumber *reactTag = shadowView.reactTag; UIEdgeInsets padding = shadowView.paddingAsInsets; - return ^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + return ^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { ((RCTTextField *)viewRegistry[reactTag]).contentInset = padding; }; } diff --git a/React/Views/RCTView.m b/React/Views/RCTView.m index a584a5798..a151efb5c 100644 --- a/React/Views/RCTView.m +++ b/React/Views/RCTView.m @@ -129,6 +129,8 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view) return self; } +RCT_NOT_IMPLEMENTED(-initWithCoder:unused) + - (NSString *)accessibilityLabel { if (super.accessibilityLabel) { @@ -183,6 +185,14 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view) } } +- (NSString *)description +{ + NSString *superDescription = super.description; + NSRange semicolonRange = [superDescription rangeOfString:@";"]; + NSString *replacement = [NSString stringWithFormat:@"; reactTag: %@;", self.reactTag]; + return [superDescription stringByReplacingCharactersInRange:semicolonRange withString:replacement]; +} + #pragma mark - Statics for dealing with layoutGuides + (void)autoAdjustInsetsForView:(UIView *)parentView @@ -236,10 +246,10 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view) - (void)react_remountAllSubviews { if (_reactSubviews) { - NSInteger index = 0; + NSUInteger index = 0; for (UIView *view in _reactSubviews) { if (view.superview != self) { - if (index < [self subviews].count) { + if (index < self.subviews.count) { [self insertSubview:view atIndex:index]; } else { [self addSubview:view]; diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index d7a93b7e3..ce027bbed 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -79,12 +79,12 @@ RCT_EXPORT_MODULE() return nil; } -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowView:(RCTShadowView *)shadowView +- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowView:(__unused RCTShadowView *)shadowView { return nil; } -- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(RCTSparseArray *)shadowViewRegistry +- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(__unused RCTSparseArray *)shadowViewRegistry { return nil; } @@ -169,11 +169,11 @@ RCT_CUSTOM_VIEW_PROPERTY(borderWidth, CGFloat, RCTView) view.layer.borderWidth = json ? [RCTConvert CGFloat:json] : defaultView.layer.borderWidth; } } -RCT_CUSTOM_VIEW_PROPERTY(onAccessibilityTap, BOOL, RCTView) +RCT_CUSTOM_VIEW_PROPERTY(onAccessibilityTap, BOOL, __unused RCTView) { view.accessibilityTapHandler = [self eventHandlerWithName:@"topAccessibilityTap" json:json]; } -RCT_CUSTOM_VIEW_PROPERTY(onMagicTap, BOOL, RCTView) +RCT_CUSTOM_VIEW_PROPERTY(onMagicTap, BOOL, __unused RCTView) { view.magicTapHandler = [self eventHandlerWithName:@"topMagicTap" json:json]; } @@ -239,7 +239,7 @@ RCT_EXPORT_SHADOW_PROPERTY(borderTopWidth, CGFloat) RCT_EXPORT_SHADOW_PROPERTY(borderRightWidth, CGFloat) RCT_EXPORT_SHADOW_PROPERTY(borderBottomWidth, CGFloat) RCT_EXPORT_SHADOW_PROPERTY(borderLeftWidth, CGFloat) -RCT_CUSTOM_SHADOW_PROPERTY(borderWidth, CGFloat, RCTShadowView) { +RCT_CUSTOM_SHADOW_PROPERTY(borderWidth, CGFloat, __unused RCTShadowView) { [view setBorderWidth:[RCTConvert CGFloat:json]]; } diff --git a/React/Views/RCTWebView.m b/React/Views/RCTWebView.m index 56cda0c88..9e2fd3504 100644 --- a/React/Views/RCTWebView.m +++ b/React/Views/RCTWebView.m @@ -30,6 +30,8 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { + RCTAssertParam(eventDispatcher); + if ((self = [super initWithFrame:CGRectZero])) { super.backgroundColor = [UIColor clearColor]; _automaticallyAdjustContentInsets = YES; @@ -42,6 +44,9 @@ return self; } +RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)goForward { [_webView goForward]; @@ -57,6 +62,11 @@ [_webView reload]; } +- (NSURL *)URL +{ + return _webView.request.URL; +} + - (void)setURL:(NSURL *)URL { // Because of the way React works, as pages redirect, we actually end up @@ -68,7 +78,7 @@ } if (!URL) { // Clear the webview - [_webView loadHTMLString:nil baseURL:nil]; + [_webView loadHTMLString:@"" baseURL:nil]; return; } [_webView loadRequest:[NSURLRequest requestWithURL:URL]]; @@ -128,7 +138,7 @@ static NSString *const RCTJSAJAXScheme = @"react-ajax"; -- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request +- (BOOL)webView:(__unused UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { // We have this check to filter out iframe requests and whatnot @@ -146,7 +156,7 @@ static NSString *const RCTJSAJAXScheme = @"react-ajax"; return ![request.URL.scheme isEqualToString:RCTJSAJAXScheme]; } -- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error +- (void)webView:(__unused UIWebView *)webView didFailLoadWithError:(NSError *)error { if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { // NSURLErrorCancelled is reported when a page has a redirect OR if you load diff --git a/React/Views/RCTWebViewManager.m b/React/Views/RCTWebViewManager.m index 015285871..50659a562 100644 --- a/React/Views/RCTWebViewManager.m +++ b/React/Views/RCTWebViewManager.m @@ -47,7 +47,7 @@ RCT_EXPORT_VIEW_PROPERTY(shouldInjectAJAXHandler, BOOL); RCT_EXPORT_METHOD(goBack:(NSNumber *)reactTag) { - [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { RCTWebView *view = viewRegistry[reactTag]; if (![view isKindOfClass:[RCTWebView class]]) { RCTLogError(@"Invalid view returned from registry, expecting RKWebView, got: %@", view); @@ -58,7 +58,7 @@ RCT_EXPORT_METHOD(goBack:(NSNumber *)reactTag) RCT_EXPORT_METHOD(goForward:(NSNumber *)reactTag) { - [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { id view = viewRegistry[reactTag]; if (![view isKindOfClass:[RCTWebView class]]) { RCTLogError(@"Invalid view returned from registry, expecting RKWebView, got: %@", view); @@ -70,7 +70,7 @@ RCT_EXPORT_METHOD(goForward:(NSNumber *)reactTag) RCT_EXPORT_METHOD(reload:(NSNumber *)reactTag) { - [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { RCTWebView *view = viewRegistry[reactTag]; if (![view isKindOfClass:[RCTWebView class]]) { RCTLogMustFix(@"Invalid view returned from registry, expecting RKWebView, got: %@", view); diff --git a/React/Views/RCTWrapperViewController.m b/React/Views/RCTWrapperViewController.m index 400ce5fab..c8da5e448 100644 --- a/React/Views/RCTWrapperViewController.m +++ b/React/Views/RCTWrapperViewController.m @@ -32,7 +32,10 @@ - (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTEventDispatcher *)eventDispatcher { - if (self = [super initWithNibName:nil bundle:nil]) { + RCTAssertParam(contentView); + RCTAssertParam(eventDispatcher); + + if ((self = [super initWithNibName:nil bundle:nil])) { _contentView = contentView; _eventDispatcher = eventDispatcher; self.automaticallyAdjustsScrollViewInsets = NO; @@ -43,12 +46,15 @@ - (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTEventDispatcher *)eventDispatcher { - if (self = [self initWithContentView:navItem eventDispatcher:eventDispatcher]) { + if ((self = [self initWithContentView:navItem eventDispatcher:eventDispatcher])) { _navItem = navItem; } return self; } +RCT_NOT_IMPLEMENTED(-initWithNibName:(NSString *)nn bundle:(NSBundle *)nb) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) + - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; diff --git a/React/Views/UIView+React.m b/React/Views/UIView+React.m index a448559ca..abde6c1f3 100644 --- a/React/Views/UIView+React.m +++ b/React/Views/UIView+React.m @@ -118,7 +118,7 @@ */ - (void)reactWillMakeFirstResponder {}; - (void)reactDidMakeFirstResponder {}; -- (BOOL)reactRespondsToTouch:(UITouch *)touch +- (BOOL)reactRespondsToTouch:(__unused UITouch *)touch { return YES; } diff --git a/package.json b/package.json index 08db6d6c1..606c9bf59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native", - "version": "0.4.4", + "version": "0.6.0", "description": "A framework for building native apps using React", "license": "BSD-3-Clause", "repository": {