diff --git a/.gitignore b/.gitignore
index 37060d99a..392c6ee02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,10 @@
# Xcode
#
+!**/*.xcodeproj
+!**/*.pbxproj
+!**/*.xcworkspacedata
+!**/*.xcsettings
+!**/*.xcscheme
build/
*.pbxuser
!default.pbxuser
diff --git a/Examples/Movies/Movies.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Movies/Movies.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 3071f8f00..000000000
--- a/Examples/Movies/Movies.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/Examples/Movies/Movies.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Examples/Movies/Movies.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index 08de0be8d..000000000
--- a/Examples/Movies/Movies.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
-
-
-
diff --git a/Examples/TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index e5f301dcc..000000000
--- a/Examples/TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/Examples/TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Examples/TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index 08de0be8d..000000000
--- a/Examples/TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
-
-
-
diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index e668abba3..000000000
--- a/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index 08de0be8d..000000000
--- a/Examples/UIExplorer/UIExplorer.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
-
-
-
diff --git a/ReactKit/Base/RCTBridge.h b/ReactKit/Base/RCTBridge.h
index 1e1f4f5da..9a890a07a 100644
--- a/ReactKit/Base/RCTBridge.h
+++ b/ReactKit/Base/RCTBridge.h
@@ -4,6 +4,7 @@
#import "RCTInvalidating.h"
#import "RCTJavaScriptExecutor.h"
+@class RCTBridge;
@class RCTEventDispatcher;
@class RCTRootView;
@@ -26,6 +27,12 @@ static inline NSDictionary *RCTAPIErrorObject(NSString *msg)
return @{@"apiError": msg ?: @""};
}
+/**
+ * This block can be used to instantiate modules that require additional
+ * init parameters, or additional configuration prior to being used.
+ */
+typedef NSArray *(^RCTBridgeModuleProviderBlock)(RCTBridge *bridge);
+
/**
* Async batched bridge used to communicate with the JavaScript application.
*/
@@ -34,11 +41,13 @@ static inline NSDictionary *RCTAPIErrorObject(NSString *msg)
/**
* The designated initializer. This creates a new bridge on top of the specified
* executor. The bridge should then be used for all subsequent communication
- * with the JavaScript code running in the executor. You can optionally pass in
- * a list of module instances to be used instead of the auto-instantiated versions.
+ * with the JavaScript code running in the executor. Modules will be automatically
+ * instantiated using the default contructor, but you can optionally pass in a
+ * module provider block to manually instantiate modules that require additional
+ * init parameters or configuration.
*/
- (instancetype)initWithJavaScriptExecutor:(id)javaScriptExecutor
- moduleInstances:(NSArray *)moduleInstances NS_DESIGNATED_INITIALIZER;
+ moduleProvider:(RCTBridgeModuleProviderBlock)block NS_DESIGNATED_INITIALIZER;
/**
* This method is used to call functions in the JavaScript application context.
@@ -60,6 +69,11 @@ static inline NSDictionary *RCTAPIErrorObject(NSString *msg)
*/
@property (nonatomic, readonly) RCTEventDispatcher *eventDispatcher;
+/**
+ * A dictionary of all registered RCTBridgeModule instances, keyed by moduleName.
+ */
+@property (nonatomic, copy, readonly) NSDictionary *modules;
+
/**
* The shadow queue is used to execute callbacks from the JavaScript code. All
* native hooks (e.g. exported module methods) will be executed on the shadow
diff --git a/ReactKit/Base/RCTBridge.m b/ReactKit/Base/RCTBridge.m
index b8acc322d..97a5dc12e 100644
--- a/ReactKit/Base/RCTBridge.m
+++ b/ReactKit/Base/RCTBridge.m
@@ -9,7 +9,6 @@
#import
#import "RCTConvert.h"
-#import "RCTInvalidating.h"
#import "RCTEventDispatcher.h"
#import "RCTLog.h"
#import "RCTSparseArray.h"
@@ -101,6 +100,40 @@ static id RCTCreateModuleInstance(Class cls, RCTBridge *bridge)
}
}
+/**
+ * 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];
+
+ 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 (RCTClassOverridesClassMethod(cls, @selector(JSMethods))) {
+ [uniqueMethods addObjectsFromArray:[cls JSMethods]];
+ }
+ }
+ free(classes);
+
+ JSMethods = [uniqueMethods allObjects];
+ });
+
+ return JSMethods;
+}
+
/**
* This function scans all classes available at runtime and returns an array
* of all classes that implement the RTCBridgeModule protocol.
@@ -264,7 +297,7 @@ static NSDictionary *RCTRemoteModulesConfig(NSDictionary *modulesByName)
NSArray *methods = RCTExportedMethodsByModuleID()[moduleID];
NSMutableDictionary *methodsByName = [NSMutableDictionary dictionaryWithCapacity:methods.count];
- [methods enumerateObjectsUsingBlock:^(RCTModuleMethod *method, NSUInteger methodID, BOOL *stop) {
+ [methods enumerateObjectsUsingBlock:^(RCTModuleMethod *method, NSUInteger methodID, BOOL *_stop) {
methodsByName[method.JSMethodName] = @{
@"methodID": @(methodID),
@"type": @"remote",
@@ -335,38 +368,16 @@ 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:@[
- @"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 RCTBridgeModuleClassesByModuleID()) {
- if (RCTClassOverridesClassMethod(cls, @selector(JSMethods))) {
- [JSMethods addObjectsFromArray:[cls JSMethods]];
- }
- }
-
+
localModules = [[NSMutableDictionary alloc] init];
- for (NSString *moduleDotMethod in JSMethods) {
-
+ for (NSString *moduleDotMethod in RCTJSMethods()) {
+
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];
@@ -377,7 +388,7 @@ static NSDictionary *RCTLocalModulesConfig()
};
localModules[moduleName] = module;
}
-
+
// Add method if it doesn't already exist
NSString *methodName = parts[1];
NSMutableDictionary *methods = module[@"methods"];
@@ -387,27 +398,27 @@ static NSDictionary *RCTLocalModulesConfig()
@"type": @"local"
};
}
-
+
// Add module and method lookup
RCTLocalModuleIDs[moduleDotMethod] = module[@"moduleID"];
RCTLocalMethodIDs[moduleDotMethod] = methods[methodName][@"methodID"];
}
});
-
+
return localModules;
}
@implementation RCTBridge
{
RCTSparseArray *_modulesByID;
- NSMutableDictionary *_modulesByName;
+ NSDictionary *_modulesByName;
id _javaScriptExecutor;
}
static id _latestJSExecutor;
- (instancetype)initWithJavaScriptExecutor:(id)javaScriptExecutor
- moduleInstances:(NSArray *)moduleInstances
+ moduleProvider:(RCTBridgeModuleProviderBlock)block
{
if ((self = [super init])) {
_javaScriptExecutor = javaScriptExecutor;
@@ -417,31 +428,39 @@ static id _latestJSExecutor;
// Register passed-in module instances
NSMutableDictionary *preregisteredModules = [[NSMutableDictionary alloc] init];
- for (id module in moduleInstances) {
- preregisteredModules[RCTModuleNameForClass([module class])] = module;
+ if (block) {
+ for (id module in block(self)) {
+ preregisteredModules[RCTModuleNameForClass([module class])] = module;
+ }
}
// Instantiate modules
_modulesByID = [[RCTSparseArray alloc] init];
- _modulesByName = [[NSMutableDictionary alloc] initWithDictionary:preregisteredModules];
+ NSMutableDictionary *modulesByName = [preregisteredModules mutableCopy];
[RCTBridgeModuleClassesByModuleID() enumerateObjectsUsingBlock:^(Class moduleClass, NSUInteger moduleID, BOOL *stop) {
NSString *moduleName = RCTModuleNamesByID[moduleID];
// Check if module instance has already been registered for this name
- if (_modulesByName[moduleName] != nil) {
+ if ((_modulesByID[moduleID] = modulesByName[moduleName])) {
// Preregistered instances takes precedence, no questions asked
if (!preregisteredModules[moduleName]) {
// It's OK to have a name collision as long as the second instance is nil
RCTAssert(RCTCreateModuleInstance(moduleClass, self) == nil,
@"Attempted to register RCTBridgeModule class %@ for the name '%@', \
but name was already registered by class %@", moduleClass,
- moduleName, [_modulesByName[moduleName] class]);
+ moduleName, [modulesByName[moduleName] class]);
}
} else {
// Module name hasn't been used before, so go ahead and instantiate
- _modulesByID[moduleID] = _modulesByName[moduleName] = RCTCreateModuleInstance(moduleClass, self);
+ id module = RCTCreateModuleInstance(moduleClass, self);
+ if (module) {
+ _modulesByID[moduleID] = modulesByName[moduleName] = module;
+ }
}
}];
-
+
+ // Store modules
+ _modulesByName = [modulesByName copy];
+
// Inject module data into JS context
NSString *configJSON = RCTJSONStringify(@{
@"remoteModuleConfig": RCTRemoteModulesConfig(_modulesByName),
@@ -460,6 +479,14 @@ static id _latestJSExecutor;
return self;
}
+- (NSDictionary *)modules
+{
+ RCTAssert(_modulesByName != nil, @"Bridge modules have not yet been initialized. \
+ You may be trying to access a module too early in the startup procedure.");
+
+ return _modulesByName;
+}
+
- (void)dealloc
{
RCTAssert(!self.valid, @"must call -invalidate before -dealloc");
@@ -516,7 +543,7 @@ static id _latestJSExecutor;
[self _invokeAndProcessModule:@"BatchedBridge"
method:@"callFunctionReturnFlushedQueue"
- arguments:@[moduleID, methodID, args]];
+ arguments:@[moduleID, methodID, args ?: @[]]];
}
- (void)enqueueApplicationScript:(NSString *)script url:(NSURL *)url onComplete:(RCTJavaScriptCompleteBlock)onComplete
@@ -699,8 +726,8 @@ static id _latestJSExecutor;
switch (argumentType[0]) {
case ':':
if ([param isKindOfClass:[NSString class]]) {
- SEL selector = NSSelectorFromString(param);
- [invocation setArgument:&selector atIndex:argIdx];
+ SEL sel = NSSelectorFromString(param);
+ [invocation setArgument:&sel atIndex:argIdx];
shouldSet = NO;
}
break;
@@ -813,7 +840,7 @@ static id _latestJSExecutor;
+ (void)log:(NSArray *)objects level:(NSString *)level
{
if (!_latestJSExecutor || ![_latestJSExecutor isValid]) {
- RCTLogError(@"%@", RCTLogFormatString(@"ERROR: No valid JS executor to log %@.", objects));
+ RCTLogError(@"ERROR: No valid JS executor to log %@.", objects);
return;
}
NSMutableArray *args = [NSMutableArray arrayWithObject:level];
diff --git a/ReactKit/Base/RCTBridgeModule.h b/ReactKit/Base/RCTBridgeModule.h
index 1f95960b1..d9df70a22 100644
--- a/ReactKit/Base/RCTBridgeModule.h
+++ b/ReactKit/Base/RCTBridgeModule.h
@@ -2,6 +2,8 @@
#import
+#import "RCTJSMethodRegistrar.h"
+
@class RCTBridge;
/**
@@ -11,9 +13,9 @@
typedef void (^RCTResponseSenderBlock)(NSArray *response);
/**
- * Provides minimal interface needed to register a bridge module
+ * Provides the interface needed to register a bridge module.
*/
-@protocol RCTBridgeModule
+@protocol RCTBridgeModule
@optional
/**
@@ -47,15 +49,12 @@ typedef void (^RCTResponseSenderBlock)(NSArray *response);
+ (NSDictionary *)constantsToExport;
/**
- * An array of JavaScript methods that the module will call via the
- * -[RCTBridge enqueueJSCall:args:] method. Each method should be specified
- * as a string of the form "JSModuleName.jsMethodName". Attempting to call a
- * method that has not been registered will result in an error. If a method
- * has already been regsistered by another module, it is not necessary to
- * register it again, but it is good pratice. Registering the same method
- * more than once is silently ignored and will not result in an error.
+ * Some "constants" are not really constant, and need to be re-generated
+ * each time the bridge module is created. Support for this feature is
+ * deprecated and may be going away or changing, but for now you can use
+ * the -constantsToExport instance method to register these "pseudo-constants".
*/
-+ (NSArray *)JSMethods;
+- (NSDictionary *)constantsToExport;
/**
* Notifies the module that a batch of JS method invocations has just completed.
diff --git a/ReactKit/Base/RCTEventDispatcher.h b/ReactKit/Base/RCTEventDispatcher.h
index fba5e7668..5c97c8de6 100644
--- a/ReactKit/Base/RCTEventDispatcher.h
+++ b/ReactKit/Base/RCTEventDispatcher.h
@@ -30,10 +30,16 @@ typedef NS_ENUM(NSInteger, RCTScrollEventType) {
- (instancetype)initWithBridge:(RCTBridge *)bridge;
/**
- * Send a device or application event that does not relate to a specific
- * view, e.g. rotation, location, keyboard show/hide, background/awake, etc.
+ * Send an application-specific event that does not relate to a specific
+ * view, e.g. a navigation or data update notification.
*/
-- (void)sendDeviceEventWithName:(NSString *)name body:(NSDictionary *)body;
+- (void)sendAppEventWithName:(NSString *)name body:(id)body;
+
+/**
+ * Send a device or iOS event that does not relate to a specific view,
+ * e.g.rotation, location, keyboard show/hide, background/awake, etc.
+ */
+- (void)sendDeviceEventWithName:(NSString *)name body:(id)body;
/**
* Send a user input event. The body dictionary must contain a "target"
diff --git a/ReactKit/Base/RCTEventDispatcher.m b/ReactKit/Base/RCTEventDispatcher.m
index 2805cf6e5..fe791d674 100644
--- a/ReactKit/Base/RCTEventDispatcher.m
+++ b/ReactKit/Base/RCTEventDispatcher.m
@@ -7,7 +7,7 @@
@implementation RCTEventDispatcher
{
- RCTBridge *_bridge;
+ RCTBridge __weak *_bridge;
}
- (instancetype)initWithBridge:(RCTBridge *)bridge
@@ -18,20 +18,34 @@
return self;
}
-- (void)sendDeviceEventWithName:(NSString *)name body:(NSDictionary *)body
++ (NSArray *)JSMethods
+{
+ return @[
+ @"RCTNativeAppEventEmitter.emit",
+ @"RCTDeviceEventEmitter.emit",
+ @"RCTEventEmitter.receiveEvent",
+ ];
+}
+
+- (void)sendAppEventWithName:(NSString *)name body:(id)body
+{
+ [_bridge enqueueJSCall:@"RCTNativeAppEventEmitter.emit"
+ args:body ? @[name, body] : @[name]];
+}
+
+- (void)sendDeviceEventWithName:(NSString *)name body:(id)body
{
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit"
args:body ? @[name, body] : @[name]];
}
-
- (void)sendInputEventWithName:(NSString *)name body:(NSDictionary *)body
{
RCTAssert([body[@"target"] isKindOfClass:[NSNumber class]],
- @"Event body dictionary must include a 'target' property containing a react tag");
+ @"Event body dictionary must include a 'target' property containing a react tag");
[_bridge enqueueJSCall:@"RCTEventEmitter.receiveEvent"
- args:@[body[@"target"], name, body]];
+ args:body ? @[body[@"target"], name, body] : @[body[@"target"], name]];
}
- (void)sendTextEventWithType:(RCTTextEventType)type
@@ -46,9 +60,11 @@
@"topEndEditing",
};
- [self sendInputEventWithName:events[type] body:@{
+ [self sendInputEventWithName:events[type] body:text ? @{
@"text": text,
@"target": reactTag
+ } : @{
+ @"target": reactTag
}];
}
diff --git a/ReactKit/Base/RCTJSMethodRegistrar.h b/ReactKit/Base/RCTJSMethodRegistrar.h
new file mode 100644
index 000000000..20a35a96b
--- /dev/null
+++ b/ReactKit/Base/RCTJSMethodRegistrar.h
@@ -0,0 +1,24 @@
+// Copyright 2004-present Facebook. All Rights Reserved.
+
+#import
+
+@class RCTBridge;
+
+/**
+ * Provides an interface to register JS methods to be called via the bridge.
+ */
+@protocol RCTJSMethodRegistrar
+@optional
+
+/**
+ * An array of JavaScript methods that the class will call via the
+ * -[RCTBridge enqueueJSCall:args:] method. Each method should be specified
+ * as a string of the form "JSModuleName.jsMethodName". Attempting to call a
+ * method that has not been registered will result in an error. 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 is silently ignored and will not result in an error.
+ */
++ (NSArray *)JSMethods;
+
+@end
diff --git a/ReactKit/Base/RCTRootView.m b/ReactKit/Base/RCTRootView.m
index 4b9cca59f..5968357a9 100644
--- a/ReactKit/Base/RCTRootView.m
+++ b/ReactKit/Base/RCTRootView.m
@@ -81,9 +81,20 @@ static Class _globalExecutorClass;
object:nil];
}
++ (NSArray *)JSMethods
+{
+ return @[
+ @"AppRegistry.runApplication",
+ @"ReactIOS.unmountComponentAtNodeAndRemoveContainer"
+ ];
+}
+
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ [_bridge enqueueJSCall:@"ReactIOS.unmountComponentAtNodeAndRemoveContainer"
+ args:@[self.reactTag]];
}
- (void)bundleFinishedLoading:(NSError *)error
@@ -125,7 +136,7 @@ static Class _globalExecutorClass;
// Choose local executor if specified, followed by global, followed by default
_executor = [[_executorClass ?: _globalExecutorClass ?: [RCTContextExecutor class] alloc] init];
- _bridge = [[RCTBridge alloc] initWithJavaScriptExecutor:_executor moduleInstances:nil];
+ _bridge = [[RCTBridge alloc] initWithJavaScriptExecutor:_executor moduleProvider:nil];
_touchHandler = [[RCTTouchHandler alloc] initWithBridge:_bridge];
[self addGestureRecognizer:_touchHandler];
diff --git a/ReactKit/Base/RCTSparseArray.m b/ReactKit/Base/RCTSparseArray.m
index 0e71f32e6..4611c1b56 100644
--- a/ReactKit/Base/RCTSparseArray.m
+++ b/ReactKit/Base/RCTSparseArray.m
@@ -108,4 +108,9 @@
return [[[self class] allocWithZone:zone] initWithSparseArray:self];
}
+- (NSString *)description
+{
+ return [[super description] stringByAppendingString:[_storage description]];
+}
+
@end
diff --git a/ReactKit/Base/RCTTouchHandler.m b/ReactKit/Base/RCTTouchHandler.m
index 0bca6680b..c56f996cc 100644
--- a/ReactKit/Base/RCTTouchHandler.m
+++ b/ReactKit/Base/RCTTouchHandler.m
@@ -137,6 +137,11 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
reactTouch[@"timestamp"] = @(nativeTouch.timestamp * 1000); // in ms, for JS
}
++ (NSArray *)JSMethods
+{
+ return @[@"RCTEventEmitter.receiveTouches"];
+}
+
/**
* Constructs information about touch events to send across the serialized
* boundary. This data should be compliant with W3C `Touch` objects. This data
diff --git a/ReactKit/Modules/RCTTiming.m b/ReactKit/Modules/RCTTiming.m
index d01b07509..e833f3d5f 100644
--- a/ReactKit/Modules/RCTTiming.m
+++ b/ReactKit/Modules/RCTTiming.m
@@ -2,6 +2,7 @@
#import "RCTTiming.h"
+#import "RCTAssert.h"
#import "RCTBridge.h"
#import "RCTLog.h"
#import "RCTSparseArray.h"
@@ -11,7 +12,7 @@
@property (nonatomic, strong, readonly) NSDate *target;
@property (nonatomic, assign, readonly) BOOL repeats;
-@property (nonatomic, strong, readonly) NSNumber *callbackID;
+@property (nonatomic, copy, readonly) NSNumber *callbackID;
@property (nonatomic, assign, readonly) NSTimeInterval interval;
@end
@@ -172,12 +173,12 @@
if (jsSchedulingOverhead < 0) {
RCTLogWarn(@"jsSchedulingOverhead (%ims) should be positive", (int)(jsSchedulingOverhead * 1000));
}
-
+
NSTimeInterval targetTime = interval - jsSchedulingOverhead;
if (interval < 0.018) { // Make sure short intervals run each frame
interval = 0;
}
-
+
RCTTimer *timer = [[RCTTimer alloc] initWithCallbackID:callbackID
interval:interval
targetTime:targetTime
diff --git a/ReactKit/ReactKit.xcodeproj/project.pbxproj b/ReactKit/ReactKit.xcodeproj/project.pbxproj
index 3be8f807c..e342d22a3 100644
--- a/ReactKit/ReactKit.xcodeproj/project.pbxproj
+++ b/ReactKit/ReactKit.xcodeproj/project.pbxproj
@@ -137,6 +137,7 @@
13E067531A70F44B002CDEE1 /* UIView+ReactKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+ReactKit.h"; sourceTree = ""; };
13E067541A70F44B002CDEE1 /* UIView+ReactKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+ReactKit.m"; sourceTree = ""; };
13ED13891A80C9D40050A8F9 /* RCTPointerEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPointerEvents.h; sourceTree = ""; };
+ 13EFFCCF1A98E6FE002607DC /* RCTJSMethodRegistrar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJSMethodRegistrar.h; sourceTree = ""; };
830213F31A654E0800B993E6 /* RCTBridgeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeModule.h; sourceTree = ""; };
830A229C1A66C68A008503DA /* RCTRootView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootView.h; sourceTree = ""; };
830A229D1A66C68A008503DA /* RCTRootView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootView.m; sourceTree = ""; };
@@ -320,6 +321,7 @@
137029521A69923600575408 /* RCTImageDownloader.m */,
83CBBA4C1A601E3B00E9B192 /* RCTInvalidating.h */,
83CBBA631A601ECA00E9B192 /* RCTJavaScriptExecutor.h */,
+ 13EFFCCF1A98E6FE002607DC /* RCTJSMethodRegistrar.h */,
13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */,
13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */,
83CBBA4D1A601E3B00E9B192 /* RCTLog.h */,
diff --git a/ReactKit/ReactKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ReactKit/ReactKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index fd0bcb8a2..000000000
--- a/ReactKit/ReactKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/ReactKit/ReactKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ReactKit/ReactKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index 08de0be8d..000000000
--- a/ReactKit/ReactKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
-
-
-
diff --git a/package.json b/package.json
index c377c5d9e..93a723ff5 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,9 @@
"/node_modules/",
"/packager/"
],
- "testFileExtensions": ["js"]
+ "testFileExtensions": [
+ "js"
+ ]
},
"scripts": {
"test": "jest",
@@ -45,7 +47,8 @@
"underscore": "1.7.0",
"wordwrap": "0.0.2",
"worker-farm": "1.1.0",
- "yargs": "1.3.2"
+ "yargs": "1.3.2",
+ "joi": "~5.1.0"
},
"devDependencies": {
"jest-cli": "0.2.1",
diff --git a/packager/react-packager/package.json b/packager/react-packager/package.json
index ad7b76029..0ac47c257 100644
--- a/packager/react-packager/package.json
+++ b/packager/react-packager/package.json
@@ -4,7 +4,11 @@
"description": "",
"main": "index.js",
"jest": {
- "unmockedModulePathPatterns": ["source-map"],
- "testPathIgnorePatterns": ["JSAppServer/node_modules"]
+ "unmockedModulePathPatterns": [
+ "source-map"
+ ],
+ "testPathIgnorePatterns": [
+ "JSAppServer/node_modules"
+ ]
}
}
diff --git a/packager/transformer.js b/packager/transformer.js
index df5e7143d..ffcb80e2d 100644
--- a/packager/transformer.js
+++ b/packager/transformer.js
@@ -16,18 +16,26 @@ var staticTypeSyntax =
var visitorList = reactVisitors;
-function transform(transformSets, srcTxt, options) {
- options = options || {};
+function transform(transformSets, srcTxt) {
+ var options = {
+ es3: true,
+ sourceType: 'nonStrictModule'
+ };
// These tranforms mostly just erase type annotations and static typing
// related statements, but they were conflicting with other tranforms.
// Running them first solves that problem
var staticTypeSyntaxResult = jstransform(
staticTypeSyntax,
- srcTxt
+ srcTxt,
+ options
);
- return jstransform(visitorList, staticTypeSyntaxResult.code);
+ return jstransform(
+ visitorList,
+ staticTypeSyntaxResult.code,
+ options
+ );
}
module.exports = function(data, callback) {
@@ -35,8 +43,7 @@ module.exports = function(data, callback) {
try {
result = transform(
data.transformSets,
- data.sourceCode,
- data.options
+ data.sourceCode
);
} catch (e) {
return callback(null, {