Implemented lazy parsing of method signatures to improve TTI

This commit is contained in:
Nick Lockwood 2015-08-11 08:33:28 -07:00
parent 57a6a02dff
commit a5e9f83a0a
5 changed files with 240 additions and 213 deletions

View File

@ -162,8 +162,8 @@
- (void)testFamilyStyleAndWeight
{
{
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-UltraLightItalic" size:14];
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontStyle": @"italic", @"fontWeight": @"100"}];
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-LightItalic" size:14];
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontStyle": @"italic", @"fontWeight": @"300"}];
RCTAssertEqualFonts(expected, result);
}
{

View File

@ -63,9 +63,11 @@ static BOOL RCTLogsError(void (^block)(void))
// Specifying an NSNumber param without nonnull isn't allowed
XCTAssertTrue(RCTLogsError(^{
NSString *methodName = @"doFooWithNumber:(NSNumber *)n";
(void)[[RCTModuleMethod alloc] initWithObjCMethodName:methodName
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
JSMethodName:nil
moduleClass:[self class]];
// Invoke method to trigger parsing
[method invokeWithBridge:nil module:self arguments:@[@1]];
}));
}

View File

@ -88,7 +88,7 @@ RCT_NOT_IMPLEMENTED(-init);
[self.methods enumerateObjectsUsingBlock:^(RCTModuleMethod *method, NSUInteger idx, __unused BOOL *stop) {
methodconfig[method.JSMethodName] = @{
@"methodID": @(idx),
@"type": method.functionKind == RCTJavaScriptFunctionKindAsync ? @"remoteAsync" : @"remote",
@"type": method.functionType == RCTFunctionTypePromise ? @"remoteAsync" : @"remote",
};
}];
config[@"methods"] = [methodconfig copy];

View File

@ -11,9 +11,9 @@
@class RCTBridge;
typedef NS_ENUM(NSUInteger, RCTJavaScriptFunctionKind) {
RCTJavaScriptFunctionKindNormal,
RCTJavaScriptFunctionKindAsync,
typedef NS_ENUM(NSUInteger, RCTFunctionType) {
RCTFunctionTypeNormal,
RCTFunctionTypePromise,
};
typedef NS_ENUM(NSUInteger, RCTNullability) {
@ -35,7 +35,7 @@ typedef NS_ENUM(NSUInteger, RCTNullability) {
@property (nonatomic, copy, readonly) NSString *JSMethodName;
@property (nonatomic, readonly) Class moduleClass;
@property (nonatomic, readonly) SEL selector;
@property (nonatomic, readonly) RCTJavaScriptFunctionKind functionKind;
@property (nonatomic, readonly) RCTFunctionType functionType;
- (instancetype)initWithObjCMethodName:(NSString *)objCMethodName
JSMethodName:(NSString *)JSMethodName

View File

@ -46,9 +46,10 @@ typedef void (^RCTArgumentBlock)(RCTBridge *, NSUInteger, id);
@implementation RCTModuleMethod
{
Class _moduleClass;
SEL _selector;
NSInvocation *_invocation;
NSArray *_argumentBlocks;
NSString *_objCMethodName;
SEL _selector;
}
static void RCTLogArgumentError(RCTModuleMethod *method, NSUInteger index,
@ -117,13 +118,8 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
{
if ((self = [super init])) {
NSArray *arguments;
RCTParseObjCMethodName(&objCMethodName, &arguments);
_moduleClass = moduleClass;
_selector = NSSelectorFromString(objCMethodName);
RCTAssert(_selector, @"%@ is not a valid selector", objCMethodName);
_objCMethodName = [objCMethodName copy];
_JSMethodName = JSMethodName.length > 0 ? JSMethodName : ({
NSString *methodName = objCMethodName;
NSRange colonRange = [methodName rangeOfString:@":"];
@ -135,6 +131,25 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
methodName;
});
if ([_objCMethodName rangeOfString:@"RCTPromise"].length) {
_functionType = RCTFunctionTypePromise;
} else {
_functionType = RCTFunctionTypeNormal;
}
}
return self;
}
- (void)processMethodSignature
{
NSArray *arguments;
NSString *objCMethodName = _objCMethodName;
RCTParseObjCMethodName(&objCMethodName, &arguments);
_selector = NSSelectorFromString(objCMethodName);
RCTAssert(_selector, @"%@ is not a valid selector", objCMethodName);
// Create method invocation
NSMethodSignature *methodSignature = [_moduleClass instanceMethodSignatureForSelector:_selector];
RCTAssert(methodSignature, @"%@ is not a recognized Objective-C method.", objCMethodName);
@ -148,10 +163,10 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
NSMutableArray *argumentBlocks = [[NSMutableArray alloc] initWithCapacity:numberOfArguments - 2];
#define RCT_ARG_BLOCK(_logic) \
[argumentBlocks addObject:^(__unused RCTBridge *bridge, NSUInteger index, id json) { \
[argumentBlocks addObject:^(__unused RCTBridge *bridge, NSUInteger index, id json) { \
_logic \
[invocation setArgument:&value atIndex:(index) + 2]; \
}];
}];
__weak RCTModuleMethod *weakSelf = self;
void (^addBlockArgument)(void) = ^{
@ -280,7 +295,6 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
arguments:@[json, result ? @[result] : @[]]];
});
)
_functionKind = RCTJavaScriptFunctionKindAsync;
} else if ([typeName isEqualToString:@"RCTPromiseRejectBlock"]) {
RCTAssert(i == numberOfArguments - 1,
@"The RCTPromiseRejectBlock must be the last parameter in -[%@ %@]",
@ -299,7 +313,6 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
arguments:@[json, @[errorJSON]]];
});
)
_functionKind = RCTJavaScriptFunctionKindAsync;
} else {
// Unknown argument type
@ -350,15 +363,24 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
}
_argumentBlocks = [argumentBlocks copy];
}
}
return self;
- (SEL)selector
{
if (_selector == NULL) {
[self processMethodSignature];
}
return _selector;
}
- (void)invokeWithBridge:(RCTBridge *)bridge
module:(id)module
arguments:(NSArray *)arguments
{
if (_argumentBlocks == nil) {
[self processMethodSignature];
}
if (RCT_DEBUG) {
// Sanity check
@ -371,7 +393,7 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
NSInteger expectedCount = _argumentBlocks.count;
// Subtract the implicit Promise resolver and rejecter functions for implementations of async functions
if (_functionKind == RCTJavaScriptFunctionKindAsync) {
if (_functionType == RCTFunctionTypePromise) {
actualCount -= 2;
expectedCount -= 2;
}
@ -398,6 +420,9 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
- (NSString *)methodName
{
if (_selector == NULL) {
[self processMethodSignature];
}
return [NSString stringWithFormat:@"-[%@ %@]", _moduleClass,
NSStringFromSelector(_selector)];
}