diff --git a/Examples/Movies/MoviesApp.js b/Examples/Movies/MoviesApp.js index 983fb2087..768ad895a 100644 --- a/Examples/Movies/MoviesApp.js +++ b/Examples/Movies/MoviesApp.js @@ -8,7 +8,7 @@ var React = require('react-native/addons'); var { - Bundler, + AppRegistry, NavigatorIOS, StyleSheet, } = React; @@ -36,6 +36,6 @@ var styles = StyleSheet.create({ }, }); -Bundler.registerComponent('MoviesApp', () => MoviesApp); +AppRegistry.registerComponent('MoviesApp', () => MoviesApp); module.exports = MoviesApp; diff --git a/Examples/TicTacToe/TicTacToeApp.js b/Examples/TicTacToe/TicTacToeApp.js index b91b090c0..913123c45 100755 --- a/Examples/TicTacToe/TicTacToeApp.js +++ b/Examples/TicTacToe/TicTacToeApp.js @@ -8,7 +8,7 @@ var React = require('react-native'); var { - Bundler, + AppRegistry, Image, StyleSheet, Text, @@ -317,6 +317,6 @@ var styles = StyleSheet.create({ }, }); -Bundler.registerComponent('TicTacToeApp', () => TicTacToeApp); +AppRegistry.registerComponent('TicTacToeApp', () => TicTacToeApp); module.exports = TicTacToeApp; diff --git a/Examples/UIExplorer/UIExplorerApp.js b/Examples/UIExplorer/UIExplorerApp.js index 5458dde98..7c73d4ee3 100644 --- a/Examples/UIExplorer/UIExplorerApp.js +++ b/Examples/UIExplorer/UIExplorerApp.js @@ -9,7 +9,7 @@ var React = require('react-native/addons'); var UIExplorerList = require('./UIExplorerList'); var { - Bundler, + AppRegistry, NavigatorIOS, StyleSheet, } = React; @@ -39,6 +39,6 @@ var styles = StyleSheet.create({ }, }); -Bundler.registerComponent('UIExplorerApp', () => UIExplorerApp); +AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp); module.exports = UIExplorerApp; diff --git a/Libraries/Bundler/Bundler.js b/Libraries/AppRegistry/AppRegistry.js similarity index 51% rename from Libraries/Bundler/Bundler.js rename to Libraries/AppRegistry/AppRegistry.js index 9b3651bc6..a11f5d494 100644 --- a/Libraries/Bundler/Bundler.js +++ b/Libraries/AppRegistry/AppRegistry.js @@ -1,7 +1,7 @@ /** * Copyright 2004-present Facebook. All Rights Reserved. * - * @providesModule Bundler + * @providesModule AppRegistry */ 'use strict'; @@ -16,31 +16,42 @@ if (__DEV__) { var runnables = {}; -class Bundler { - static registerConfig(config) { +/** + * `AppRegistry` is the JS entry point to running all React Native apps. App + * root components should register themselves with + * `AppRegistry.registerComponent`, then the native system can load the bundle + * for the app and then actually run the app when it's ready by invoking + * `AppRegistry.runApplication`. + * + * `AppRegistry` should be `require`d early in the `require` sequence to make + * sure the JS execution environment is setup before other modules are + * `require`d. + */ +var AppRegistry = { + registerConfig: function(config) { for (var i = 0; i < config.length; ++i) { if (config[i].run) { - Bundler.registerRunnable(config[i].appKey, config[i].run); + AppRegistry.registerRunnable(config[i].appKey, config[i].run); } else { - Bundler.registerComponent(config[i].appKey, config[i].component); + AppRegistry.registerComponent(config[i].appKey, config[i].component); } } - } + }, - static registerComponent(appKey, getComponentFunc) { + registerComponent: function(appKey, getComponentFunc) { runnables[appKey] = { run: (appParameters) => renderApplication(getComponentFunc(), appParameters.initialProps, appParameters.rootTag) }; return appKey; - } + }, - static registerRunnable(appKey, func) { + registerRunnable: function(appKey, func) { runnables[appKey] = {run: func}; return appKey; - } + }, - static runApplication(appKey, appParameters) { + runApplication: function(appKey, appParameters) { console.log( 'Running application "' + appKey + '" with appParams: ', appParameters @@ -51,7 +62,7 @@ class Bundler { 'Application ' + appKey + ' has not been registered.' ); runnables[appKey].run(appParameters); - } -} + }, +}; -module.exports = Bundler; +module.exports = AppRegistry; diff --git a/Libraries/react-native/react-native-interface.js b/Libraries/react-native/react-native-interface.js index 8a99d1188..c37bbe685 100644 --- a/Libraries/react-native/react-native-interface.js +++ b/Libraries/react-native/react-native-interface.js @@ -3,7 +3,7 @@ declare module "react-native" { constructor(params: Object): void; } - declare var Bundler: ReactClass; + declare var AppRegistry: ReactClass; declare var ExpandingText: ReactClass; declare var Image: ReactClass; declare var ListView: ReactClass; diff --git a/Libraries/react-native/react-native.js b/Libraries/react-native/react-native.js index 55b0d95d2..78c93960b 100644 --- a/Libraries/react-native/react-native.js +++ b/Libraries/react-native/react-native.js @@ -7,7 +7,7 @@ var ReactNative = { ...require('React'), - Bundler: require('Bundler'), + AppRegistry: require('AppRegistry'), ExpandingText: require('ExpandingText'), Image: require('Image'), LayoutAnimation: require('LayoutAnimation'), diff --git a/README.md b/README.md index 689b6ba25..07e34b563 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ well :) A. Copy the entire `Examples/TicTacToe` folder, rename stuff in Xcode, and replace the `TicTacToeApp.js` with your own. Then, in `AppDelegate.m`, update `moduleName` to match your call to -`Bundler.registerComponent(, )` at the bottom of your +`AppRegistry.registerComponent(, )` at the bottom of your JS file, and update `jsCodeLocation` to match your JS file name and location. ##### Q. Can I submit my own React Native app to the App Store? diff --git a/ReactKit/Base/RCTBridge.m b/ReactKit/Base/RCTBridge.m index cdd6af842..5ae7000da 100644 --- a/ReactKit/Base/RCTBridge.m +++ b/ReactKit/Base/RCTBridge.m @@ -64,7 +64,7 @@ typedef NS_ENUM(NSUInteger, RCTBridgeFields) { }]; blocks = [NSString stringWithFormat:@"block args at %@", [indexString substringFromIndex:2]]; } - + return [NSString stringWithFormat:@"<%@: %p; exports -%@ as %@; %@>", NSStringFromClass(self.class), self, NSStringFromSelector(self.selector), self.JSMethodName, blocks]; } @@ -90,45 +90,45 @@ static NSDictionary *RCTExportedMethodsByModule(void) static NSMutableDictionary *methodsByModule; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - + Dl_info info; dladdr(&RCTExportedMethodsByModule, &info); - + const RCTExportValue mach_header = (RCTExportValue)info.dli_fbase; const RCTExportSection *section = RCTGetSectByNameFromHeader((void *)mach_header, "__DATA", "RCTExport"); - + if (section == NULL) { return; } - + methodsByModule = [NSMutableDictionary dictionary]; NSCharacterSet *plusMinusCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"+-"]; - + for (RCTExportValue addr = section->offset; addr < section->offset + section->size; addr += sizeof(id) * 2) { - + const char **entry = (const char **)(mach_header + addr); NSScanner *scanner = [NSScanner scannerWithString:@(entry[0])]; - + NSString *plusMinus; if (![scanner scanCharactersFromSet:plusMinusCharacterSet intoString:&plusMinus]) continue; if (![scanner scanString:@"[" intoString:NULL]) continue; - + NSString *className; if (![scanner scanUpToString:@" " intoString:&className]) continue; [scanner scanString:@" " intoString:NULL]; - + NSString *selectorName; if (![scanner scanUpToString:@"]" intoString:&selectorName]) continue; - + Class class = NSClassFromString(className); if (class == Nil) continue; - + SEL selector = NSSelectorFromString(selectorName); Method method = ([plusMinus characterAtIndex:0] == '+' ? class_getClassMethod : class_getInstanceMethod)(class, selector); if (method == nil) continue; - + unsigned int argumentCount = method_getNumberOfArguments(method); NSMutableIndexSet *blockArgumentIndexes = [NSMutableIndexSet indexSet]; static const char *blockType = @encode(typeof(^{})); @@ -139,21 +139,21 @@ static NSDictionary *RCTExportedMethodsByModule(void) } free(type); } - + NSString *JSMethodName = strlen(entry[1]) ? @(entry[1]) : [NSStringFromSelector(selector) componentsSeparatedByString:@":"][0]; RCTModuleMethod *moduleMethod = [[RCTModuleMethod alloc] initWithSelector:selector JSMethodName:JSMethodName arity:method_getNumberOfArguments(method) - 2 blockArgumentIndexes:blockArgumentIndexes]; - + NSString *moduleName = [class respondsToSelector:@selector(moduleName)] ? [class moduleName] : className; NSArray *moduleMap = methodsByModule[moduleName]; methodsByModule[moduleName] = (moduleMap != nil) ? [moduleMap arrayByAddingObject:moduleMethod] : @[moduleMethod]; } - + }); - + return methodsByModule; } @@ -167,35 +167,35 @@ static NSDictionary *RCTBridgeModuleClasses(void) static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ modules = [NSMutableDictionary dictionary]; - + unsigned int classCount; Class *classes = objc_copyClassList(&classCount); for (unsigned int i = 0; i < classCount; i++) { - + Class cls = classes[i]; - + if (!class_getSuperclass(cls)) { // Class has no superclass - it's probably something weird continue; } - + if (![cls conformsToProtocol:@protocol(RCTBridgeModule)]) { // Not an RCTBridgeModule continue; } - + // Get module name NSString *moduleName = [cls respondsToSelector:@selector(moduleName)] ? [cls moduleName] : NSStringFromClass(cls); - + // Check module name is unique id existingClass = modules[moduleName]; RCTCAssert(existingClass == Nil, @"Attempted to register RCTBridgeModule class %@ for the name '%@', but name was already registered by class %@", cls, moduleName, existingClass); modules[moduleName] = cls; } - + free(classes); }); - + return modules; } @@ -231,9 +231,9 @@ static NSDictionary *RCTRemoteModulesConfig() static NSMutableDictionary *remoteModules; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - + RCTRemoteModulesByID = [[NSMutableDictionary alloc] init]; - + remoteModules = [[NSMutableDictionary alloc] init]; [RCTBridgeModuleClasses() enumerateKeysAndObjectsUsingBlock:^(NSString *moduleName, Class moduleClass, BOOL *stop) { @@ -245,7 +245,7 @@ static NSDictionary *RCTRemoteModulesConfig() @"type": @"remote", }; }]; - + NSDictionary *module = @{ @"moduleID": @(remoteModules.count), @"methods": methods @@ -259,13 +259,13 @@ static NSDictionary *RCTRemoteModulesConfig() } } remoteModules[moduleName] = [module copy]; - + // Add module lookup RCTRemoteModulesByID[module[@"moduleID"]] = moduleName; - + }]; }); - + return remoteModules; } @@ -297,38 +297,38 @@ static NSDictionary *RCTLocalModulesConfig() static NSMutableDictionary *localModules; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - + RCTLocalModuleIDs = [[NSMutableDictionary alloc] init]; RCTLocalMethodIDs = [[NSMutableDictionary alloc] init]; - + NSMutableArray *JSMethods = [[NSMutableArray alloc] init]; - + // Add globally used methods [JSMethods addObjectsFromArray:@[ - @"Bundler.runApplication", + @"AppRegistry.runApplication", @"RCTDeviceEventEmitter.emit", @"RCTEventEmitter.receiveEvent", @"RCTEventEmitter.receiveTouches", ]]; - + // NOTE: these methods are currently unused in the OSS project // @"Dimensions.set", // @"RCTNativeAppEventEmitter.emit", // @"ReactIOS.unmountComponentAtNodeAndRemoveContainer", - + // Register individual methods from modules for (Class cls in RCTBridgeModuleClasses().allValues) { if (RCTClassOverridesClassMethod(cls, @selector(JSMethods))) { [JSMethods addObjectsFromArray:[cls JSMethods]]; } } - + localModules = [[NSMutableDictionary alloc] init]; for (NSString *moduleDotMethod in JSMethods) { - + NSArray *parts = [moduleDotMethod componentsSeparatedByString:@"."]; RCTCAssert(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]; @@ -339,7 +339,7 @@ static NSDictionary *RCTLocalModulesConfig() }; localModules[moduleName] = module; } - + // Add method if it doesn't already exist NSString *methodName = parts[1]; NSMutableDictionary *methods = module[@"methods"]; @@ -349,13 +349,13 @@ static NSDictionary *RCTLocalModulesConfig() @"type": @"local" }; } - + // Add module and method lookup RCTLocalModuleIDs[moduleDotMethod] = module[@"moduleID"]; RCTLocalMethodIDs[moduleDotMethod] = methods[methodName][@"methodID"]; } }); - + return localModules; } @@ -374,7 +374,7 @@ static id _latestJSExecutor; _latestJSExecutor = _javaScriptExecutor; _eventDispatcher = [[RCTEventDispatcher alloc] initWithBridge:self]; _shadowQueue = dispatch_queue_create("com.facebook.ReactKit.ShadowQueue", DISPATCH_QUEUE_SERIAL); - + // Instantiate modules _moduleInstances = [[NSMutableDictionary alloc] init]; [RCTBridgeModuleClasses() enumerateKeysAndObjectsUsingBlock:^(NSString *moduleName, Class moduleClass, BOOL *stop) { @@ -391,7 +391,7 @@ static id _latestJSExecutor; } } }]; - + // Inject module data into JS context NSString *configJSON = RCTJSONStringify(@{ @"remoteModuleConfig": RCTRemoteModulesConfig(), @@ -401,12 +401,12 @@ static id _latestJSExecutor; [_javaScriptExecutor injectJSONText:configJSON asGlobalObjectNamed:@"__fbBatchedBridgeConfig" callback:^(id err) { dispatch_semaphore_signal(semaphore); }]; - + if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC)) != 0) { RCTLogMustFix(@"JavaScriptExecutor took too long to inject JSON object"); } } - + return self; } @@ -428,12 +428,12 @@ static id _latestJSExecutor; _latestJSExecutor = nil; } _javaScriptExecutor = nil; - + dispatch_sync(_shadowQueue, ^{ // Make sure all dispatchers have been executed before continuing // TODO: is this still needed? }); - + for (id target in _moduleInstances.objectEnumerator) { if ([target respondsToSelector:@selector(invalidate)]) { [(id)target invalidate]; @@ -459,10 +459,10 @@ static id _latestJSExecutor; NSNumber *moduleID = RCTLocalModuleIDs[moduleDotMethod]; RCTAssert(moduleID, @"Module '%@' not registered.", [[moduleDotMethod componentsSeparatedByString:@"."] firstObject]); - + NSNumber *methodID = RCTLocalMethodIDs[moduleDotMethod]; RCTAssert(methodID, @"Method '%@' not registered.", moduleDotMethod); - + [self _invokeAndProcessModule:@"BatchedBridge" method:@"callFunctionReturnFlushedQueue" arguments:@[moduleID, methodID, args]]; @@ -476,7 +476,7 @@ static id _latestJSExecutor; onComplete(scriptLoadError); return; } - + [_javaScriptExecutor executeJSCall:@"BatchedBridge" method:@"flushedQueue" arguments:@[] @@ -492,19 +492,19 @@ static id _latestJSExecutor; - (void)_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args { NSTimeInterval startJS = RCTTGetAbsoluteTime(); - + RCTJavaScriptCallback processResponse = ^(id objcValue, NSError *error) { NSTimeInterval startNative = RCTTGetAbsoluteTime(); [self _handleBuffer:objcValue]; - + NSTimeInterval end = RCTTGetAbsoluteTime(); NSTimeInterval timeJS = startNative - startJS; NSTimeInterval timeNative = end - startNative; - + // TODO: surface this performance information somewhere [[NSNotificationCenter defaultCenter] postNotificationName:@"PERF" object:nil userInfo:@{@"JS": @(timeJS * 1000000), @"Native": @(timeNative * 1000000)}]; }; - + [_javaScriptExecutor executeJSCall:module method:method arguments:args @@ -528,12 +528,12 @@ static id _latestJSExecutor; if (buffer == nil || buffer == (id)kCFNull) { return; } - + if (![buffer isKindOfClass:[NSArray class]]) { RCTLogError(@"Buffer must be an instance of NSArray, got %@", NSStringFromClass([buffer class])); return; } - + NSArray *requestsArray = (NSArray *)buffer; NSUInteger bufferRowCount = [requestsArray count]; NSUInteger expectedFieldsCount = RCTBridgeFieldResponseReturnValues + 1; @@ -541,7 +541,7 @@ static id _latestJSExecutor; RCTLogError(@"Must pass all fields to buffer - expected %zd, saw %zd", expectedFieldsCount, bufferRowCount); return; } - + for (NSUInteger fieldIndex = RCTBridgeFieldRequestModuleIDs; fieldIndex <= RCTBridgeFieldParamss; fieldIndex++) { id field = [requestsArray objectAtIndex:fieldIndex]; if (![field isKindOfClass:[NSArray class]]) { @@ -549,18 +549,18 @@ static id _latestJSExecutor; return; } } - + NSArray *moduleIDs = requestsArray[RCTBridgeFieldRequestModuleIDs]; NSArray *methodIDs = requestsArray[RCTBridgeFieldMethodIDs]; NSArray *paramsArrays = requestsArray[RCTBridgeFieldParamss]; - + NSUInteger numRequests = [moduleIDs count]; BOOL allSame = numRequests == [methodIDs count] && numRequests == [paramsArrays count]; if (!allSame) { RCTLogError(@"Invalid data message - all must be length: %zd", numRequests); return; } - + for (NSUInteger i = 0; i < numRequests; i++) { @autoreleasepool { [self _handleRequestNumber:i @@ -569,7 +569,7 @@ static id _latestJSExecutor; params:paramsArrays[i]]; } } - + // TODO: only used by RCTUIManager - can we eliminate this special case? dispatch_async(_shadowQueue, ^{ for (id target in _moduleInstances.objectEnumerator) { @@ -589,19 +589,19 @@ static id _latestJSExecutor; RCTLogError(@"Invalid module/method/params tuple for request #%zd", i); return NO; } - + NSString *moduleName = RCTRemoteModulesByID[moduleID]; if (!moduleName) { RCTLogError(@"Unknown moduleID: %@", moduleID); return NO; } - + NSArray *methods = RCTExportedMethodsByModule()[moduleName]; if (methodID >= methods.count) { RCTLogError(@"Unknown methodID: %zd for module: %@", methodID, moduleName); return NO; } - + RCTModuleMethod *method = methods[methodID]; NSUInteger methodArity = method.arity; if (params.count != methodArity) { @@ -612,30 +612,30 @@ static id _latestJSExecutor; method.JSMethodName); return NO; } - + __weak RCTBridge *weakSelf = self; dispatch_async(_shadowQueue, ^{ __strong RCTBridge *strongSelf = weakSelf; - + if (!strongSelf.isValid) { // strongSelf has been invalidated since the dispatch_async call and this // invocation should not continue. return; } - + // TODO: we should just store module instances by index, since that's how we look them up anyway id target = strongSelf->_moduleInstances[moduleName]; RCTAssert(target != nil, @"No module found for name '%@'", moduleName); - + SEL selector = method.selector; NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [invocation setArgument:&target atIndex:0]; [invocation setArgument:&selector atIndex:1]; - + // Retain used blocks until after invocation completes. NS_VALID_UNTIL_END_OF_SCOPE NSMutableArray *blocks = [NSMutableArray array]; - + [params enumerateObjectsUsingBlock:^(id param, NSUInteger idx, BOOL *stop) { if ([param isEqual:[NSNull null]]) { param = nil; @@ -644,9 +644,9 @@ static id _latestJSExecutor; [blocks addObject:block]; param = block; } - + NSUInteger argIdx = idx + 2; - + // TODO: can we do this lookup in advance and cache the logic instead of // recalculating it every time for every parameter? BOOL shouldSet = YES; @@ -659,7 +659,7 @@ static id _latestJSExecutor; shouldSet = NO; } break; - + case '*': if ([param isKindOfClass:[NSString class]]) { const char *string = [param UTF8String]; @@ -667,7 +667,7 @@ static id _latestJSExecutor; shouldSet = NO; } break; - + // TODO: it seems like an error if the param doesn't respond // so we should probably surface that error rather than failing silently #define CASE(_value, _type, _selector) \ @@ -678,7 +678,7 @@ static id _latestJSExecutor; shouldSet = NO; \ } \ break; - + CASE('c', char, charValue) CASE('C', unsigned char, unsignedCharValue) CASE('s', short, shortValue) @@ -692,16 +692,16 @@ static id _latestJSExecutor; CASE('f', float, floatValue) CASE('d', double, doubleValue) CASE('B', BOOL, boolValue) - + default: break; } - + if (shouldSet) { [invocation setArgument:¶m atIndex:argIdx]; } }]; - + @try { [invocation invoke]; } @@ -709,7 +709,7 @@ static id _latestJSExecutor; RCTLogError(@"Exception thrown while invoking %@ on target %@ with params %@: %@", method.JSMethodName, target, params, exception); } }); - + return YES; } @@ -724,7 +724,7 @@ static id _latestJSExecutor; if (!cbID) { return nil; } - + return ^(NSArray *args) { [self _sendResponseToJavaScriptCallbackID:cbID args:args]; }; @@ -737,7 +737,7 @@ static id _latestJSExecutor; dispatch_once(&onceToken, ^{ invocations = [NSMutableDictionary dictionary]; }); - + id key = @(argCount); NSInvocation *invocation = invocations[key]; if (invocation == nil) { @@ -746,7 +746,7 @@ static id _latestJSExecutor; invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; invocations[key] = invocation; } - + return invocation; } @@ -772,7 +772,7 @@ static id _latestJSExecutor; return; } NSMutableArray *args = [NSMutableArray arrayWithObject:level]; - + // TODO (#5906496): Find out and document why we skip the first object for (id ob in [objects subarrayWithRange:(NSRange){1, [objects count] - 1}]) { if ([NSJSONSerialization isValidJSONObject:@[ob]]) { diff --git a/ReactKit/Base/RCTRootView.m b/ReactKit/Base/RCTRootView.m index f5227ffe3..2985e4a7e 100644 --- a/ReactKit/Base/RCTRootView.m +++ b/ReactKit/Base/RCTRootView.m @@ -36,7 +36,7 @@ static Class _globalExecutorClass; action:^(UIKeyCommand *command) { [self reloadAll]; }]; - + // Cmd-D reloads using the web view executor, allows attaching from Safari dev tools. [[RCTKeyCommands sharedInstance] registerKeyCommandWithInput:@"d" modifierFlags:UIKeyModifierCommand @@ -46,7 +46,7 @@ static Class _globalExecutorClass; }]; #endif - + } - (id)initWithCoder:(NSCoder *)aDecoder @@ -96,7 +96,7 @@ static Class _globalExecutorClass; [[RCTRedBox sharedInstance] showErrorMessage:[error localizedDescription] withDetails:[error localizedFailureReason]]; } } else { - + [_bridge registerRootView:self]; NSString *moduleName = _moduleName ?: @""; @@ -104,7 +104,7 @@ static Class _globalExecutorClass; @"rootTag": self.reactTag, @"initialProps": self.initialProperties ?: @{}, }; - [_bridge enqueueJSCall:@"Bundler.runApplication" + [_bridge enqueueJSCall:@"AppRegistry.runApplication" args:@[moduleName, appParameters]]; } } @@ -113,11 +113,11 @@ static Class _globalExecutorClass; { // Clear view [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; - + if (!_scriptURL) { return; } - + // Clean up [self removeGestureRecognizer:_touchHandler]; [_executor invalidate]; @@ -132,7 +132,7 @@ static Class _globalExecutorClass; // Load the bundle NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:_scriptURL completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { - + // Handle general request errors if (error) { if ([[error domain] isEqualToString:NSURLErrorDomain]) { @@ -148,7 +148,7 @@ static Class _globalExecutorClass; [self bundleFinishedLoading:error]; return; } - + // Parse response as text NSStringEncoding encoding = NSUTF8StringEncoding; if (response.textEncodingName != nil) { @@ -158,7 +158,7 @@ static Class _globalExecutorClass; } } NSString *rawText = [[NSString alloc] initWithData:data encoding:encoding]; - + // Handle HTTP errors if ([response isKindOfClass:[NSHTTPURLResponse class]] && [(NSHTTPURLResponse *)response statusCode] != 200) { NSDictionary *userInfo; @@ -178,7 +178,7 @@ static Class _globalExecutorClass; error = [NSError errorWithDomain:@"JSServer" code:[(NSHTTPURLResponse *)response statusCode] userInfo:userInfo]; - + [self bundleFinishedLoading:error]; return; } @@ -189,9 +189,9 @@ static Class _globalExecutorClass; [self bundleFinishedLoading:error]; }); }]; - + }]; - + [task resume]; } diff --git a/ReactKit/Executors/RCTContextExecutor.m b/ReactKit/Executors/RCTContextExecutor.m index 4f1f6fae7..e3eabc16f 100644 --- a/ReactKit/Executors/RCTContextExecutor.m +++ b/ReactKit/Executors/RCTContextExecutor.m @@ -35,7 +35,7 @@ static JSValueRef RCTNativeLoggingHook(JSContextRef context, JSObjectRef object, NSString *str = (__bridge_transfer NSString *)JSStringCopyCFString(kCFAllocatorDefault, string); NSError *error = nil; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: - @"( stack: )?([_a-z0-9]*)@?(http://|file:///)[a-z.0-9:/_-]+/MainBundle/([a-z0-9_]+).includeRequire.runModule.bundle(:[0-9]+:[0-9]+)" + @"( stack: )?([_a-z0-9]*)@?(http://|file:///)[a-z.0-9:/_-]+/([a-z0-9_]+).includeRequire.runModule.bundle(:[0-9]+:[0-9]+)" options:NSRegularExpressionCaseInsensitive error:&error]; NSString *modifiedString = [regex stringByReplacingMatchesInString:str options:0 range:NSMakeRange(0, [str length]) withTemplate:@"[$4$5] \t$2"];