Replace exported method registration with statically allocated struct
Reviewed By: fromcelticpark Differential Revision: D5389383 fbshipit-source-id: 9eb29b254b616574966b43ad24aa880d44589652
This commit is contained in:
Родитель
d94f3e4b98
Коммит
cb12080179
|
@ -15,16 +15,17 @@
|
|||
#define FB_REFERENCE_IMAGE_DIR ""
|
||||
#endif
|
||||
|
||||
#define RCT_RUN_RUNLOOP_WHILE(CONDITION) \
|
||||
{ \
|
||||
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:5]; \
|
||||
while ((CONDITION)) { \
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; \
|
||||
if ([timeout timeIntervalSinceNow] <= 0) { \
|
||||
XCTFail(@"Runloop timed out before condition was met"); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
#define RCT_RUN_RUNLOOP_WHILE(CONDITION) \
|
||||
{ \
|
||||
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:5]; \
|
||||
NSRunLoop *runloop = [NSRunLoop mainRunLoop]; \
|
||||
while ((CONDITION)) { \
|
||||
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; \
|
||||
if ([timeout timeIntervalSinceNow] <= 0) { \
|
||||
XCTFail(@"Runloop timed out before condition was met"); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -112,9 +112,7 @@ RCT_EXPORT_METHOD(test:(__unused NSString *)a
|
|||
AllocationTestModule *module = [AllocationTestModule new];
|
||||
@autoreleasepool {
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:_bundleURL
|
||||
moduleProvider:^{
|
||||
return @[module];
|
||||
}
|
||||
moduleProvider:^{ return @[module]; }
|
||||
launchOptions:nil];
|
||||
XCTAssertTrue(module.isValid, @"AllocationTestModule should be valid");
|
||||
(void)bridge;
|
||||
|
@ -130,12 +128,10 @@ RCT_EXPORT_METHOD(test:(__unused NSString *)a
|
|||
@autoreleasepool {
|
||||
AllocationTestModule *module = [AllocationTestModule new];
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:_bundleURL
|
||||
moduleProvider:^{
|
||||
return @[module];
|
||||
}
|
||||
moduleProvider:^{ return @[module]; }
|
||||
launchOptions:nil];
|
||||
XCTAssertNotNil(module, @"AllocationTestModule should have been created");
|
||||
weakModule = module;
|
||||
XCTAssertNotNil(weakModule, @"AllocationTestModule should have been created");
|
||||
(void)bridge;
|
||||
}
|
||||
|
||||
|
@ -145,11 +141,18 @@ RCT_EXPORT_METHOD(test:(__unused NSString *)a
|
|||
|
||||
- (void)testModuleMethodsAreDeallocated
|
||||
{
|
||||
static RCTMethodInfo methodInfo = {
|
||||
.objcName = "test:(NSString *)a :(nonnull NSNumber *)b :(RCTResponseSenderBlock)c :(RCTResponseErrorBlock)d",
|
||||
.jsName = "",
|
||||
.isSync = false
|
||||
};
|
||||
|
||||
__weak RCTModuleMethod *weakMethod;
|
||||
@autoreleasepool {
|
||||
__autoreleasing RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithMethodSignature:@"test:(NSString *)a :(nonnull NSNumber *)b :(RCTResponseSenderBlock)c :(RCTResponseErrorBlock)d" JSMethodName:@"" isSync:NO moduleClass:[AllocationTestModule class]];
|
||||
weakMethod = method;
|
||||
__autoreleasing RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithExportedMethod:&methodInfo
|
||||
moduleClass:[AllocationTestModule class]];
|
||||
XCTAssertNotNil(method, @"RCTModuleMethod should have been created");
|
||||
weakMethod = method;
|
||||
}
|
||||
|
||||
RCT_RUN_RUNLOOP_WHILE(weakMethod)
|
||||
|
@ -172,7 +175,6 @@ RCT_EXPORT_METHOD(test:(__unused NSString *)a
|
|||
#if !TARGET_OS_TV // userInteractionEnabled is true for Apple TV views
|
||||
XCTAssertFalse(rootContentView.userInteractionEnabled, @"RCTContentView should have been invalidated");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
- (void)testUnderlyingBridgeIsDeallocated
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
@implementation RCTMethodArgumentTests
|
||||
|
||||
extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes);
|
||||
extern SEL RCTParseMethodSignature(const char *methodSignature, NSArray **argTypes);
|
||||
|
||||
- (void)testOneArgument
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSInteger)foo";
|
||||
const char *methodSignature = "foo:(NSInteger)foo";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
|
@ -34,7 +34,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testTwoArguments
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSInteger)foo bar:(BOOL)bar";
|
||||
const char *methodSignature = "foo:(NSInteger)foo bar:(BOOL)bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
|
@ -45,7 +45,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testSpaces
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo : (NSInteger)foo bar : (BOOL) bar";
|
||||
const char *methodSignature = "foo : (NSInteger)foo bar : (BOOL) bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
|
@ -56,7 +56,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testNewlines
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo : (NSInteger)foo\nbar : (BOOL) bar";
|
||||
const char *methodSignature = "foo : (NSInteger)foo\nbar : (BOOL) bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
|
@ -67,7 +67,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testUnnamedArgs
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSInteger)foo:(BOOL)bar";
|
||||
const char *methodSignature = "foo:(NSInteger)foo:(BOOL)bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo::");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
|
@ -78,7 +78,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testUntypedUnnamedArgs
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:foo:bar:bar";
|
||||
const char *methodSignature = "foo:foo:bar:bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:::");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)3);
|
||||
|
@ -90,7 +90,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testAttributes
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(__attribute__((unused)) NSString *)foo bar:(__unused BOOL)bar";
|
||||
const char *methodSignature = "foo:(__attribute__((unused)) NSString *)foo bar:(__unused BOOL)bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
|
@ -101,7 +101,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testNullability
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(nullable NSString *)foo bar:(nonnull NSNumber *)bar baz:(id)baz";
|
||||
const char *methodSignature = "foo:(nullable NSString *)foo bar:(nonnull NSNumber *)bar baz:(id)baz";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:baz:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)3);
|
||||
|
@ -116,7 +116,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testSemicolonStripping
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSString *)foo bar:(BOOL)bar;";
|
||||
const char *methodSignature = "foo:(NSString *)foo bar:(BOOL)bar;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
|
@ -127,7 +127,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testUnused
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(__unused NSString *)foo bar:(NSNumber *)bar";
|
||||
const char *methodSignature = "foo:(__unused NSString *)foo bar:(NSNumber *)bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
|
@ -140,7 +140,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testGenericArray
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSArray<NSString *> *)foo;";
|
||||
const char *methodSignature = "foo:(NSArray<NSString *> *)foo;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
|
@ -150,7 +150,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testNestedGenericArray
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSArray<NSArray<NSString *> *> *)foo;";
|
||||
const char *methodSignature = "foo:(NSArray<NSArray<NSString *> *> *)foo;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
|
@ -160,7 +160,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testGenericSet
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSSet<NSNumber *> *)foo;";
|
||||
const char *methodSignature = "foo:(NSSet<NSNumber *> *)foo;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
|
@ -170,7 +170,7 @@ extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes
|
|||
- (void)testGenericDictionary
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSDictionary<NSString *, NSNumber *> *)foo;";
|
||||
const char *methodSignature = "foo:(NSDictionary<NSString *, NSNumber *> *)foo;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
|
|
|
@ -37,18 +37,18 @@ static BOOL RCTLogsError(void (^block)(void))
|
|||
CGRect _s;
|
||||
}
|
||||
|
||||
static RCTModuleMethod *buildDefaultMethodWithMethodSignature(NSString *methodSignature) {
|
||||
return [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
isSync:NO
|
||||
moduleClass:[RCTModuleMethodTests class]];
|
||||
static RCTModuleMethod *buildDefaultMethodWithMethodSignature(const char *methodSignature)
|
||||
{
|
||||
// This leaks a RCTMethodInfo, but it's a test, so...
|
||||
RCTMethodInfo *methodInfo = new RCTMethodInfo {.objcName = methodSignature, .isSync = NO};
|
||||
return [[RCTModuleMethod alloc] initWithExportedMethod:methodInfo moduleClass:[RCTModuleMethodTests class]];
|
||||
}
|
||||
|
||||
static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSignature) {
|
||||
return [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
isSync:YES
|
||||
moduleClass:[RCTModuleMethodTests class]];
|
||||
static RCTModuleMethod *buildSyncMethodWithMethodSignature(const char *methodSignature)
|
||||
{
|
||||
// This leaks a RCTMethodInfo, but it's a test, so...
|
||||
RCTMethodInfo *methodInfo = new RCTMethodInfo {.objcName = methodSignature, .isSync = YES};
|
||||
return [[RCTModuleMethod alloc] initWithExportedMethod:methodInfo moduleClass:[RCTModuleMethodTests class]];
|
||||
}
|
||||
|
||||
+ (NSString *)moduleName { return nil; }
|
||||
|
@ -62,7 +62,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
|
||||
- (void)testNonnull
|
||||
{
|
||||
NSString *methodSignature = @"doFooWithBar:(nonnull NSString *)bar";
|
||||
const char *methodSignature = "doFooWithBar:(nonnull NSString *)bar";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertFalse(RCTLogsError(^{
|
||||
[method invokeWithBridge:nil module:self arguments:@[@"Hello World"]];
|
||||
|
@ -85,7 +85,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
{
|
||||
// Specifying an NSNumber param without nonnull isn't allowed
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
NSString *methodSignature = @"doFooWithNumber:(NSNumber *)n";
|
||||
const char *methodSignature = "doFooWithNumber:(NSNumber *)n";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
// Invoke method to trigger parsing
|
||||
[method invokeWithBridge:nil module:self arguments:@[@1]];
|
||||
|
@ -93,7 +93,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
}
|
||||
|
||||
{
|
||||
NSString *methodSignature = @"doFooWithNumber:(nonnull NSNumber *)n";
|
||||
const char *methodSignature = "doFooWithNumber:(nonnull NSNumber *)n";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
[method invokeWithBridge:nil module:self arguments:@[[NSNull null]]];
|
||||
|
@ -101,7 +101,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
}
|
||||
|
||||
{
|
||||
NSString *methodSignature = @"doFooWithDouble:(double)n";
|
||||
const char *methodSignature = "doFooWithDouble:(double)n";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
[method invokeWithBridge:nil module:self arguments:@[[NSNull null]]];
|
||||
|
@ -109,7 +109,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
}
|
||||
|
||||
{
|
||||
NSString *methodSignature = @"doFooWithInteger:(NSInteger)n";
|
||||
const char *methodSignature = "doFooWithInteger:(NSInteger)n";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
[method invokeWithBridge:nil module:self arguments:@[[NSNull null]]];
|
||||
|
@ -119,7 +119,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
|
||||
- (void)testStructArgument
|
||||
{
|
||||
NSString *methodSignature = @"doFooWithCGRect:(CGRect)s";
|
||||
const char *methodSignature = "doFooWithCGRect:(CGRect)s";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
|
||||
CGRect r = CGRectMake(10, 20, 30, 40);
|
||||
|
@ -129,7 +129,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
|
||||
- (void)testWhitespaceTolerance
|
||||
{
|
||||
NSString *methodSignature = @"doFoo : \t (NSString *)foo";
|
||||
const char *methodSignature = "doFoo : \t (NSString *)foo";
|
||||
|
||||
__block RCTModuleMethod *method;
|
||||
XCTAssertFalse(RCTLogsError(^{
|
||||
|
@ -146,19 +146,19 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
- (void)testFunctionType
|
||||
{
|
||||
{
|
||||
NSString *methodSignature = @"doFoo";
|
||||
const char *methodSignature = "doFoo";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertTrue(method.functionType == RCTFunctionTypeNormal);
|
||||
}
|
||||
|
||||
{
|
||||
NSString *methodSignature = @"openURL:(NSURL *)URL resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject";
|
||||
const char *methodSignature = "openURL:(NSURL *)URL resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertTrue(method.functionType == RCTFunctionTypePromise);
|
||||
}
|
||||
|
||||
{
|
||||
NSString *methodSignature = @"echoString:(NSString *)input";
|
||||
const char *methodSignature = "echoString:(NSString *)input";
|
||||
RCTModuleMethod *method = buildSyncMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertTrue(method.functionType == RCTFunctionTypeSync);
|
||||
}
|
||||
|
@ -167,14 +167,14 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
- (void)testReturnsValueForSyncFunction
|
||||
{
|
||||
{
|
||||
NSString *methodSignature = @"echoString:(NSString *)input";
|
||||
const char *methodSignature = "echoString:(NSString *)input";
|
||||
RCTModuleMethod *method = buildSyncMethodWithMethodSignature(methodSignature);
|
||||
id result = [method invokeWithBridge:nil module:self arguments:@[@"Test String Value"]];
|
||||
XCTAssertEqualObjects(result, @"Test String Value");
|
||||
}
|
||||
|
||||
{
|
||||
NSString *methodSignature = @"methodThatReturnsNil";
|
||||
const char *methodSignature = "methodThatReturnsNil";
|
||||
RCTModuleMethod *method = buildSyncMethodWithMethodSignature(methodSignature);
|
||||
id result = [method invokeWithBridge:nil module:self arguments:@[]];
|
||||
XCTAssertNil(result);
|
||||
|
@ -183,7 +183,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
|
||||
- (void)testReturnsNilForDefaultFunction
|
||||
{
|
||||
NSString *methodSignature = @"doFoo";
|
||||
const char *methodSignature = "doFoo";
|
||||
RCTModuleMethod *method = buildDefaultMethodWithMethodSignature(methodSignature);
|
||||
id result = [method invokeWithBridge:nil module:self arguments:@[]];
|
||||
XCTAssertNil(result);
|
||||
|
@ -192,7 +192,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
- (void)testReturnTypeForSyncFunction
|
||||
{
|
||||
{
|
||||
NSString *methodSignature = @"methodThatReturnsNil";
|
||||
const char *methodSignature = "methodThatReturnsNil";
|
||||
RCTModuleMethod *method = buildSyncMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertFalse(RCTLogsError(^{
|
||||
// Invoke method to trigger parsing
|
||||
|
@ -201,7 +201,7 @@ static RCTModuleMethod *buildSyncMethodWithMethodSignature(NSString *methodSigna
|
|||
}
|
||||
|
||||
{
|
||||
NSString *methodSignature = @"doFoo";
|
||||
const char *methodSignature = "doFoo";
|
||||
RCTModuleMethod *method = buildSyncMethodWithMethodSignature(methodSignature);
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
// Invoke method to trigger parsing
|
|
@ -1067,7 +1067,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
|||
}
|
||||
|
||||
NSString *message = [NSString stringWithFormat:
|
||||
@"Exception '%@' was thrown while invoking %@ on target %@ with params %@",
|
||||
@"Exception '%@' was thrown while invoking %s on target %@ with params %@",
|
||||
exception, method.JSMethodName, moduleData.name, params];
|
||||
RCTFatal(RCTErrorWithMessage(message));
|
||||
return nil;
|
||||
|
|
|
@ -30,7 +30,7 @@ static inline const char *RCTFunctionDescriptorFromType(RCTFunctionType type) {
|
|||
|
||||
@protocol RCTBridgeMethod <NSObject>
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *JSMethodName;
|
||||
@property (nonatomic, readonly) const char *JSMethodName;
|
||||
@property (nonatomic, readonly) RCTFunctionType functionType;
|
||||
|
||||
- (id)invokeWithBridge:(RCTBridge *)bridge
|
||||
|
|
|
@ -47,7 +47,17 @@ typedef void (^RCTPromiseRejectBlock)(NSString *code, NSString *message, NSError
|
|||
*
|
||||
* NOTE: RCTJSThread is not a real libdispatch queue
|
||||
*/
|
||||
extern dispatch_queue_t RCTJSThread;
|
||||
RCT_EXTERN dispatch_queue_t RCTJSThread;
|
||||
|
||||
RCT_EXTERN_C_BEGIN
|
||||
|
||||
typedef struct RCTMethodInfo {
|
||||
const char *const jsName;
|
||||
const char *const objcName;
|
||||
const BOOL isSync;
|
||||
} RCTMethodInfo;
|
||||
|
||||
RCT_EXTERN_C_END
|
||||
|
||||
/**
|
||||
* Provides the interface needed to register a bridge module.
|
||||
|
@ -248,9 +258,9 @@ RCT_EXTERN void RCTRegisterModule(Class); \
|
|||
* and also whether this method is synchronous.
|
||||
*/
|
||||
#define _RCT_EXTERN_REMAP_METHOD(js_name, method, is_blocking_synchronous_method) \
|
||||
+ (NSArray *)RCT_CONCAT(__rct_export__, \
|
||||
RCT_CONCAT(js_name, RCT_CONCAT(__LINE__, __COUNTER__))) { \
|
||||
return @[@#js_name, @#method, @is_blocking_synchronous_method]; \
|
||||
+ (const RCTMethodInfo *)RCT_CONCAT(__rct_export__, RCT_CONCAT(js_name, RCT_CONCAT(__LINE__, __COUNTER__))) { \
|
||||
static RCTMethodInfo config = {#js_name, #method, is_blocking_synchronous_method}; \
|
||||
return &config; \
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
*/
|
||||
#if defined(__cplusplus)
|
||||
#define RCT_EXTERN extern "C" __attribute__((visibility("default")))
|
||||
#define RCT_EXTERN_C_BEGIN extern "C" {
|
||||
#define RCT_EXTERN_C_END }
|
||||
#else
|
||||
#define RCT_EXTERN extern __attribute__((visibility("default")))
|
||||
#define RCT_EXTERN_C_BEGIN
|
||||
#define RCT_EXTERN_C_END
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -270,14 +270,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
|||
SEL selector = method_getName(method);
|
||||
if ([NSStringFromSelector(selector) hasPrefix:@"__rct_export__"]) {
|
||||
IMP imp = method_getImplementation(method);
|
||||
NSArray *entries =
|
||||
((NSArray *(*)(id, SEL))imp)(_moduleClass, selector);
|
||||
id<RCTBridgeMethod> moduleMethod =
|
||||
[[RCTModuleMethod alloc] initWithMethodSignature:entries[1]
|
||||
JSMethodName:entries[0]
|
||||
isSync:((NSNumber *)entries[2]).boolValue
|
||||
moduleClass:_moduleClass];
|
||||
|
||||
auto exportedMethod = ((const RCTMethodInfo *(*)(id, SEL))imp)(_moduleClass, selector);
|
||||
id<RCTBridgeMethod> moduleMethod = [[RCTModuleMethod alloc] initWithExportedMethod:exportedMethod
|
||||
moduleClass:_moduleClass];
|
||||
[moduleMethods addObject:moduleMethod];
|
||||
}
|
||||
}
|
||||
|
@ -345,7 +340,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
|||
}
|
||||
[syncMethods addObject:@(methods.count)];
|
||||
}
|
||||
[methods addObject:method.JSMethodName];
|
||||
[methods addObject:@(method.JSMethodName)];
|
||||
}
|
||||
|
||||
NSArray *config = @[
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeMethod.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTNullability.h>
|
||||
|
||||
@class RCTBridge;
|
||||
|
@ -27,9 +28,7 @@
|
|||
@property (nonatomic, readonly) Class moduleClass;
|
||||
@property (nonatomic, readonly) SEL selector;
|
||||
|
||||
- (instancetype)initWithMethodSignature:(NSString *)objCMethodName
|
||||
JSMethodName:(NSString *)JSMethodName
|
||||
isSync:(BOOL)isSync
|
||||
- (instancetype)initWithExportedMethod:(const RCTMethodInfo *)exportMethod
|
||||
moduleClass:(Class)moduleClass NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
|
|
@ -41,21 +41,20 @@ typedef BOOL (^RCTArgumentBlock)(RCTBridge *, NSUInteger, id);
|
|||
@implementation RCTModuleMethod
|
||||
{
|
||||
Class _moduleClass;
|
||||
const RCTMethodInfo *_methodInfo;
|
||||
NSString *_JSMethodName;
|
||||
|
||||
SEL _selector;
|
||||
NSInvocation *_invocation;
|
||||
NSArray<RCTArgumentBlock> *_argumentBlocks;
|
||||
NSString *_methodSignature;
|
||||
SEL _selector;
|
||||
BOOL _isSync;
|
||||
}
|
||||
|
||||
@synthesize JSMethodName = _JSMethodName;
|
||||
|
||||
static void RCTLogArgumentError(RCTModuleMethod *method, NSUInteger index,
|
||||
id valueOrType, const char *issue)
|
||||
{
|
||||
RCTLogError(@"Argument %tu (%@) of %@.%@ %s", index, valueOrType,
|
||||
RCTLogError(@"Argument %tu (%@) of %@.%s %s", index, valueOrType,
|
||||
RCTBridgeModuleNameForClass(method->_moduleClass),
|
||||
method->_JSMethodName, issue);
|
||||
method.JSMethodName, issue);
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
|
@ -114,10 +113,9 @@ static BOOL RCTCheckCallbackMultipleInvocations(BOOL *didInvoke) {
|
|||
}
|
||||
}
|
||||
|
||||
SEL RCTParseMethodSignature(NSString *, NSArray<RCTMethodArgument *> **);
|
||||
SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument *> **arguments)
|
||||
SEL RCTParseMethodSignature(const char *, NSArray<RCTMethodArgument *> **);
|
||||
SEL RCTParseMethodSignature(const char *input, NSArray<RCTMethodArgument *> **arguments)
|
||||
{
|
||||
const char *input = methodSignature.UTF8String;
|
||||
RCTSkipWhitespace(&input);
|
||||
|
||||
NSMutableArray *args;
|
||||
|
@ -164,30 +162,25 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
|||
return NSSelectorFromString(selector);
|
||||
}
|
||||
|
||||
- (instancetype)initWithMethodSignature:(NSString *)methodSignature
|
||||
JSMethodName:(NSString *)JSMethodName
|
||||
isSync:(BOOL)isSync
|
||||
moduleClass:(Class)moduleClass
|
||||
- (instancetype)initWithExportedMethod:(const RCTMethodInfo *)exportedMethod
|
||||
moduleClass:(Class)moduleClass
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_moduleClass = moduleClass;
|
||||
_methodSignature = [methodSignature copy];
|
||||
_JSMethodName = [JSMethodName copy];
|
||||
_isSync = isSync;
|
||||
_methodInfo = exportedMethod;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)processMethodSignature
|
||||
{
|
||||
NSArray<RCTMethodArgument *> *arguments;
|
||||
_selector = RCTParseMethodSignature(_methodSignature, &arguments);
|
||||
RCTAssert(_selector, @"%@ is not a valid selector", _methodSignature);
|
||||
_selector = RCTParseMethodSignature(_methodInfo->objcName, &arguments);
|
||||
RCTAssert(_selector, @"%s is not a valid selector", _methodInfo->objcName);
|
||||
|
||||
// Create method invocation
|
||||
NSMethodSignature *methodSignature = [_moduleClass instanceMethodSignatureForSelector:_selector];
|
||||
RCTAssert(methodSignature, @"%@ is not a recognized Objective-C method.", _methodSignature);
|
||||
RCTAssert(methodSignature, @"%s is not a recognized Objective-C method.", sel_getName(_selector));
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
|
||||
invocation.selector = _selector;
|
||||
_invocation = invocation;
|
||||
|
@ -328,8 +321,8 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
|||
)
|
||||
} else if ([typeName isEqualToString:@"RCTPromiseResolveBlock"]) {
|
||||
RCTAssert(i == numberOfArguments - 2,
|
||||
@"The RCTPromiseResolveBlock must be the second to last parameter in -[%@ %@]",
|
||||
_moduleClass, _methodSignature);
|
||||
@"The RCTPromiseResolveBlock must be the second to last parameter in %@",
|
||||
[self methodName]);
|
||||
RCT_ARG_BLOCK(
|
||||
if (RCT_DEBUG && ![json isKindOfClass:[NSNumber class]]) {
|
||||
RCTLogArgumentError(weakSelf, index, json, "should be a promise resolver function");
|
||||
|
@ -345,8 +338,8 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
|||
)
|
||||
} else if ([typeName isEqualToString:@"RCTPromiseRejectBlock"]) {
|
||||
RCTAssert(i == numberOfArguments - 1,
|
||||
@"The RCTPromiseRejectBlock must be the last parameter in -[%@ %@]",
|
||||
_moduleClass, _methodSignature);
|
||||
@"The RCTPromiseRejectBlock must be the last parameter in %@",
|
||||
[self methodName]);
|
||||
RCT_ARG_BLOCK(
|
||||
if (RCT_DEBUG && ![json isKindOfClass:[NSNumber class]]) {
|
||||
RCTLogArgumentError(weakSelf, index, json, "should be a promise rejecter function");
|
||||
|
@ -422,9 +415,9 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
|||
|
||||
if (RCT_DEBUG) {
|
||||
const char *objcType = _invocation.methodSignature.methodReturnType;
|
||||
if (_isSync && objcType[0] != _C_ID)
|
||||
RCTLogError(@"Return type of %@.%@ should be (id) as the method is \"sync\"",
|
||||
RCTBridgeModuleNameForClass(_moduleClass), _JSMethodName);
|
||||
if (_methodInfo->isSync && objcType[0] != _C_ID)
|
||||
RCTLogError(@"Return type of %@.%s should be (id) as the method is \"sync\"",
|
||||
RCTBridgeModuleNameForClass(_moduleClass), self.JSMethodName);
|
||||
}
|
||||
|
||||
_argumentBlocks = [argumentBlocks copy];
|
||||
|
@ -434,36 +427,41 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
|||
{
|
||||
if (_selector == NULL) {
|
||||
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"", (@{ @"module": NSStringFromClass(_moduleClass),
|
||||
@"method": _methodSignature }));
|
||||
@"method": @(_methodInfo->objcName) }));
|
||||
[self processMethodSignature];
|
||||
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
|
||||
}
|
||||
return _selector;
|
||||
}
|
||||
|
||||
- (NSString *)JSMethodName
|
||||
- (const char *)JSMethodName
|
||||
{
|
||||
NSString *methodName = _JSMethodName;
|
||||
if (methodName.length == 0) {
|
||||
methodName = _methodSignature;
|
||||
NSRange colonRange = [methodName rangeOfString:@":"];
|
||||
if (colonRange.location != NSNotFound) {
|
||||
methodName = [methodName substringToIndex:colonRange.location];
|
||||
if (!methodName) {
|
||||
const char *jsName = _methodInfo->jsName;
|
||||
if (jsName && strlen(jsName) > 0) {
|
||||
methodName = @(jsName);
|
||||
} else {
|
||||
methodName = @(_methodInfo->objcName);
|
||||
NSRange colonRange = [methodName rangeOfString:@":"];
|
||||
if (colonRange.location != NSNotFound) {
|
||||
methodName = [methodName substringToIndex:colonRange.location];
|
||||
}
|
||||
methodName = [methodName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
RCTAssert(methodName.length, @"%s is not a valid JS function name, please"
|
||||
" supply an alternative using RCT_REMAP_METHOD()", _methodInfo->objcName);
|
||||
}
|
||||
methodName = [methodName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
RCTAssert(methodName.length, @"%@ is not a valid JS function name, please"
|
||||
" supply an alternative using RCT_REMAP_METHOD()", _methodSignature);
|
||||
_JSMethodName = methodName;
|
||||
}
|
||||
return methodName;
|
||||
return methodName.UTF8String;
|
||||
}
|
||||
|
||||
- (RCTFunctionType)functionType
|
||||
{
|
||||
if ([_methodSignature rangeOfString:@"RCTPromise"].length) {
|
||||
RCTAssert(!_isSync, @"Promises cannot be used in sync functions");
|
||||
|
||||
if (strstr(_methodInfo->objcName, "RCTPromise") != NULL) {
|
||||
RCTAssert(!_methodInfo->isSync, @"Promises cannot be used in sync functions");
|
||||
return RCTFunctionTypePromise;
|
||||
} else if (_isSync) {
|
||||
} else if (_methodInfo->isSync) {
|
||||
return RCTFunctionTypeSync;
|
||||
} else {
|
||||
return RCTFunctionTypeNormal;
|
||||
|
@ -494,11 +492,11 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
|||
expectedCount -= 2;
|
||||
}
|
||||
|
||||
RCTLogError(@"%@.%@ was called with %zd arguments but expects %zd arguments. "
|
||||
RCTLogError(@"%@.%s was called with %zd arguments but expects %zd arguments. "
|
||||
@"If you haven\'t changed this method yourself, this usually means that "
|
||||
@"your versions of the native code and JavaScript code are out of sync. "
|
||||
@"Updating both should make this error go away.",
|
||||
RCTBridgeModuleNameForClass(_moduleClass), _JSMethodName,
|
||||
RCTBridgeModuleNameForClass(_moduleClass), self.JSMethodName,
|
||||
actualCount, expectedCount);
|
||||
return nil;
|
||||
}
|
||||
|
@ -540,7 +538,7 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
|||
}
|
||||
|
||||
id result = nil;
|
||||
if (_isSync) {
|
||||
if (_methodInfo->isSync) {
|
||||
void *pointer;
|
||||
[_invocation getReturnValue:&pointer];
|
||||
result = (__bridge id)pointer;
|
||||
|
@ -554,13 +552,12 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
|||
if (_selector == NULL) {
|
||||
[self processMethodSignature];
|
||||
}
|
||||
return [NSString stringWithFormat:@"-[%@ %@]", _moduleClass,
|
||||
NSStringFromSelector(_selector)];
|
||||
return [NSString stringWithFormat:@"-[%@ %s]", _moduleClass, sel_getName(_selector)];
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: %p; exports %@ as %@(); type: %s>",
|
||||
return [NSString stringWithFormat:@"<%@: %p; exports %@ as %s(); type: %s>",
|
||||
[self class], self, [self methodName], self.JSMethodName, RCTFunctionDescriptorFromType(self.functionType)];
|
||||
}
|
||||
|
||||
|
|
|
@ -26,17 +26,31 @@ using namespace facebook::react;
|
|||
std::unique_ptr<CxxModule::Method> _method;
|
||||
}
|
||||
|
||||
@synthesize JSMethodName = _JSMethodName;
|
||||
|
||||
- (instancetype)initWithCxxMethod:(const CxxModule::Method &)method
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_JSMethodName = @(method.name.c_str());
|
||||
_method = folly::make_unique<CxxModule::Method>(method);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (const char *)JSMethodName
|
||||
{
|
||||
return _method->name.c_str();
|
||||
}
|
||||
|
||||
- (RCTFunctionType)functionType
|
||||
{
|
||||
std::string type(_method->getType());
|
||||
if (type == "sync") {
|
||||
return RCTFunctionTypeSync;
|
||||
} else if (type == "async") {
|
||||
return RCTFunctionTypeNormal;
|
||||
} else {
|
||||
return RCTFunctionTypePromise;
|
||||
}
|
||||
}
|
||||
|
||||
- (id)invokeWithBridge:(RCTBridge *)bridge
|
||||
module:(id)module
|
||||
arguments:(NSArray *)arguments
|
||||
|
@ -110,16 +124,9 @@ using namespace facebook::react;
|
|||
}
|
||||
}
|
||||
|
||||
- (RCTFunctionType)functionType
|
||||
{
|
||||
// TODO: support promise-style APIs
|
||||
return _method->syncFunc ? RCTFunctionTypeSync : RCTFunctionTypeNormal;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: %p; name = %@>",
|
||||
[self class], self, self.JSMethodName];
|
||||
return [NSString stringWithFormat:@"<%@: %p; name = %s>", [self class], self, self.JSMethodName];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -38,7 +38,7 @@ std::vector<MethodDescriptor> RCTNativeModule::getMethods() {
|
|||
|
||||
for (id<RCTBridgeMethod> method in m_moduleData.methods) {
|
||||
descs.emplace_back(
|
||||
method.JSMethodName.UTF8String,
|
||||
method.JSMethodName,
|
||||
RCTFunctionDescriptorFromType(method.functionType)
|
||||
);
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ MethodCallResult RCTNativeModule::invokeInner(unsigned int methodId, const folly
|
|||
}
|
||||
|
||||
NSString *message = [NSString stringWithFormat:
|
||||
@"Exception '%@' was thrown while invoking %@ on target %@ with params %@",
|
||||
@"Exception '%@' was thrown while invoking %s on target %@ with params %@",
|
||||
exception, method.JSMethodName, m_moduleData.name, objcParams];
|
||||
RCTFatal(RCTErrorWithMessage(message));
|
||||
}
|
||||
|
|
|
@ -68,6 +68,11 @@ public:
|
|||
|
||||
std::function<folly::dynamic(folly::dynamic)> syncFunc;
|
||||
|
||||
const char *getType() {
|
||||
assert(func || syncFunc);
|
||||
return func ? (callbacks == 2 ? "promise" : "async") : "sync";
|
||||
}
|
||||
|
||||
// std::function/lambda ctors
|
||||
|
||||
Method(std::string aname,
|
||||
|
|
|
@ -57,9 +57,7 @@ std::vector<MethodDescriptor> CxxNativeModule::getMethods() {
|
|||
|
||||
std::vector<MethodDescriptor> descs;
|
||||
for (auto& method : methods_) {
|
||||
assert(method.func || method.syncFunc);
|
||||
auto methodType = method.func ? (method.callbacks == 2 ? "promise" : "async") : "sync";
|
||||
descs.emplace_back(method.name, methodType);
|
||||
descs.emplace_back(method.name, method.getType());
|
||||
}
|
||||
return descs;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче