Replaced RegExp method parser with recursive descent
Summary: public This diff replaces the RegEx module method parser with a handwritten recursive descent parser that's faster and easier to maintain. The new parser is ~8 times faster when tested on the UIManager.managerChildren() method, and uses ~1/10 as much RAM. The new parser also supports lightweight generics, and is more tolerant of white space. (This means that you now can – and should – use types like `NSArray<NSString *> *` for your exported properties and method arguments, instead of `NSStringArray`). Reviewed By: jspahrsummers Differential Revision: D2736636 fb-gh-sync-id: f6a11431935fa8acc8ac36f3471032ec9a1c8490
This commit is contained in:
parent
ce7c0b735f
commit
88ac40666c
|
@ -132,7 +132,7 @@ RCT_EXPORT_METHOD(test:(__unused NSString *)a
|
|||
{
|
||||
__weak RCTModuleMethod *weakMethod;
|
||||
@autoreleasepool {
|
||||
__autoreleasing RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:@"test:(NSString *)a :(nonnull NSNumber *)b :(RCTResponseSenderBlock)c :(RCTResponseErrorBlock)d" JSMethodName:@"" moduleClass:[AllocationTestModule class]];
|
||||
__autoreleasing RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithMethodSignature:@"test:(NSString *)a :(nonnull NSNumber *)b :(RCTResponseSenderBlock)c :(RCTResponseErrorBlock)d" JSMethodName:@"" moduleClass:[AllocationTestModule class]];
|
||||
weakMethod = method;
|
||||
XCTAssertNotNil(method, @"RCTModuleMethod should have been created");
|
||||
}
|
||||
|
|
|
@ -23,14 +23,14 @@
|
|||
|
||||
@implementation RCTMethodArgumentTests
|
||||
|
||||
extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes);
|
||||
extern SEL RCTParseMethodSignature(NSString *methodSignature, NSArray **argTypes);
|
||||
|
||||
- (void)testOneArgument
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo:(NSInteger)foo";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:");
|
||||
NSString *methodSignature = @"foo:(NSInteger)foo";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testTwoArguments
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo:(NSInteger)foo bar:(BOOL)bar";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:bar:");
|
||||
NSString *methodSignature = @"foo:(NSInteger)foo bar:(BOOL)bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
|
||||
|
@ -49,9 +49,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testSpaces
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo : (NSInteger)foo bar : (BOOL) bar";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:bar:");
|
||||
NSString *methodSignature = @"foo : (NSInteger)foo bar : (BOOL) bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
|
||||
|
@ -60,9 +60,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testNewlines
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo : (NSInteger)foo\nbar : (BOOL) bar";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:bar:");
|
||||
NSString *methodSignature = @"foo : (NSInteger)foo\nbar : (BOOL) bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
|
||||
|
@ -71,9 +71,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testUnnamedArgs
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo:(NSInteger)foo:(BOOL)bar";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo::");
|
||||
NSString *methodSignature = @"foo:(NSInteger)foo:(BOOL)bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo::");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
|
||||
|
@ -82,9 +82,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testUntypedUnnamedArgs
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo:foo:bar:bar";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:::");
|
||||
NSString *methodSignature = @"foo:foo:bar:bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:::");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)3);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"id");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"id");
|
||||
|
@ -94,9 +94,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testAttributes
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo:(__attribute__((nonnull)) NSString *)foo bar:(__unused BOOL)bar";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:bar:");
|
||||
NSString *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);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSString");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
|
||||
|
@ -105,9 +105,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testNullability
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo:(nullable NSString *)foo bar:(nonnull NSNumber *)bar baz:(id)baz";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:bar:baz:");
|
||||
NSString *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);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSString");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"NSNumber");
|
||||
|
@ -120,9 +120,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testSemicolonStripping
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo:(NSString *)foo bar:(BOOL)bar;";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:bar:");
|
||||
NSString *methodSignature = @"foo:(NSString *)foo bar:(BOOL)bar;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSString");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
|
||||
|
@ -131,9 +131,9 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
- (void)testUnused
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodName = @"foo:(__unused NSString *)foo bar:(NSNumber *)bar";
|
||||
RCTParseObjCMethodName(&methodName, &arguments);
|
||||
XCTAssertEqualObjects(methodName, @"foo:bar:");
|
||||
NSString *methodSignature = @"foo:(__unused NSString *)foo bar:(NSNumber *)bar";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:bar:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)2);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSString");
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"NSNumber");
|
||||
|
@ -141,4 +141,44 @@ extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes
|
|||
XCTAssertFalse(((RCTMethodArgument *)arguments[1]).unused);
|
||||
}
|
||||
|
||||
- (void)testGenericArray
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSArray<NSString *> *)foo;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSStringArray");
|
||||
}
|
||||
|
||||
- (void)testNestedGenericArray
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSArray<NSArray<NSString *> *> *)foo;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSStringArrayArray");
|
||||
}
|
||||
|
||||
- (void)testGenericSet
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSSet<NSNumber *> *)foo;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSNumberSet");
|
||||
}
|
||||
|
||||
- (void)testGenericDictionary
|
||||
{
|
||||
NSArray *arguments;
|
||||
NSString *methodSignature = @"foo:(NSDictionary<NSString *, NSNumber *> *)foo;";
|
||||
SEL selector = RCTParseMethodSignature(methodSignature, &arguments);
|
||||
XCTAssertEqualObjects(NSStringFromSelector(selector), @"foo:");
|
||||
XCTAssertEqual(arguments.count, (NSUInteger)1);
|
||||
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSNumberDictionary");
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -47,8 +47,8 @@ static BOOL RCTLogsError(void (^block)(void))
|
|||
|
||||
- (void)testNonnull
|
||||
{
|
||||
NSString *methodName = @"doFooWithBar:(nonnull NSString *)bar";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
|
||||
NSString *methodSignature = @"doFooWithBar:(nonnull NSString *)bar";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
moduleClass:[self class]];
|
||||
XCTAssertFalse(RCTLogsError(^{
|
||||
|
@ -72,8 +72,8 @@ static BOOL RCTLogsError(void (^block)(void))
|
|||
{
|
||||
// Specifying an NSNumber param without nonnull isn't allowed
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
NSString *methodName = @"doFooWithNumber:(NSNumber *)n";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
|
||||
NSString *methodSignature = @"doFooWithNumber:(NSNumber *)n";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
moduleClass:[self class]];
|
||||
// Invoke method to trigger parsing
|
||||
|
@ -82,8 +82,8 @@ static BOOL RCTLogsError(void (^block)(void))
|
|||
}
|
||||
|
||||
{
|
||||
NSString *methodName = @"doFooWithNumber:(nonnull NSNumber *)n";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
|
||||
NSString *methodSignature = @"doFooWithNumber:(nonnull NSNumber *)n";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
moduleClass:[self class]];
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
|
@ -92,8 +92,8 @@ static BOOL RCTLogsError(void (^block)(void))
|
|||
}
|
||||
|
||||
{
|
||||
NSString *methodName = @"doFooWithDouble:(double)n";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
|
||||
NSString *methodSignature = @"doFooWithDouble:(double)n";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
moduleClass:[self class]];
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
|
@ -102,8 +102,8 @@ static BOOL RCTLogsError(void (^block)(void))
|
|||
}
|
||||
|
||||
{
|
||||
NSString *methodName = @"doFooWithInteger:(NSInteger)n";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
|
||||
NSString *methodSignature = @"doFooWithInteger:(NSInteger)n";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
moduleClass:[self class]];
|
||||
XCTAssertTrue(RCTLogsError(^{
|
||||
|
@ -114,8 +114,8 @@ static BOOL RCTLogsError(void (^block)(void))
|
|||
|
||||
- (void)testStructArgument
|
||||
{
|
||||
NSString *methodName = @"doFooWithCGRect:(CGRect)s";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
|
||||
NSString *methodSignature = @"doFooWithCGRect:(CGRect)s";
|
||||
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
moduleClass:[self class]];
|
||||
|
||||
|
@ -126,11 +126,11 @@ static BOOL RCTLogsError(void (^block)(void))
|
|||
|
||||
- (void)testWhitespaceTolerance
|
||||
{
|
||||
NSString *methodName = @"doFoo : \t (NSString *)foo";
|
||||
NSString *methodSignature = @"doFoo : \t (NSString *)foo";
|
||||
|
||||
__block RCTModuleMethod *method;
|
||||
XCTAssertFalse(RCTLogsError(^{
|
||||
method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
|
||||
method = [[RCTModuleMethod alloc] initWithMethodSignature:methodSignature
|
||||
JSMethodName:nil
|
||||
moduleClass:[self class]];
|
||||
}));
|
||||
|
|
|
@ -56,7 +56,7 @@ static NSString *RCTGenerateFormBoundary()
|
|||
return [[NSString alloc] initWithBytesNoCopy:bytes length:boundaryLength encoding:NSUTF8StringEncoding freeWhenDone:YES];
|
||||
}
|
||||
|
||||
- (RCTURLRequestCancellationBlock)process:(NSDictionaryArray *)formData
|
||||
- (RCTURLRequestCancellationBlock)process:(NSArray<NSDictionary *> *)formData
|
||||
callback:(RCTHTTPQueryResult)callback
|
||||
{
|
||||
RCTAssertThread(_networker.methodQueue, @"process: must be called on method queue");
|
||||
|
@ -289,7 +289,7 @@ RCT_EXPORT_MODULE()
|
|||
}
|
||||
};
|
||||
}
|
||||
NSDictionaryArray *formData = [RCTConvert NSDictionaryArray:query[@"formData"]];
|
||||
NSArray<NSDictionary *> *formData = [RCTConvert NSDictionaryArray:query[@"formData"]];
|
||||
if (formData) {
|
||||
RCTHTTPFormDataHelper *formDataHelper = [RCTHTTPFormDataHelper new];
|
||||
formDataHelper.networker = self;
|
||||
|
|
|
@ -90,7 +90,7 @@ RCT_EXPORT_METHOD(setValues:(NSDictionary *)values)
|
|||
/**
|
||||
* Remove some values from the settings.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(deleteValues:(NSStringArray *)keys)
|
||||
RCT_EXPORT_METHOD(deleteValues:(NSArray<NSString *> *)keys)
|
||||
{
|
||||
_ignoringUpdates = YES;
|
||||
for (NSString *key in keys) {
|
||||
|
|
|
@ -94,28 +94,13 @@ typedef NSURL RCTFileURL;
|
|||
size:(id)size weight:(id)weight style:(id)style
|
||||
scaleMultiplier:(CGFloat)scaleMultiplier;
|
||||
|
||||
typedef NSArray NSArrayArray;
|
||||
+ (NSArray<NSArray *> *)NSArrayArray:(id)json;
|
||||
|
||||
typedef NSArray NSStringArray;
|
||||
+ (NSArray<NSString *> *)NSStringArray:(id)json;
|
||||
|
||||
typedef NSArray NSStringArrayArray;
|
||||
+ (NSArray<NSArray<NSString *> *> *)NSStringArrayArray:(id)json;
|
||||
|
||||
typedef NSArray NSDictionaryArray;
|
||||
+ (NSArray<NSDictionary *> *)NSDictionaryArray:(id)json;
|
||||
|
||||
typedef NSArray NSURLArray;
|
||||
+ (NSArray<NSURL *> *)NSURLArray:(id)json;
|
||||
|
||||
typedef NSArray RCTFileURLArray;
|
||||
+ (NSArray<NSURL *> *)RCTFileURLArray:(id)json;
|
||||
|
||||
typedef NSArray NSNumberArray;
|
||||
+ (NSArray<RCTFileURL *> *)RCTFileURLArray:(id)json;
|
||||
+ (NSArray<NSNumber *> *)NSNumberArray:(id)json;
|
||||
|
||||
typedef NSArray UIColorArray;
|
||||
+ (NSArray<UIColor *> *)UIColorArray:(id)json;
|
||||
|
||||
typedef NSArray CGColorArray;
|
||||
|
@ -145,6 +130,18 @@ typedef BOOL css_clip_t, css_backface_visibility_t;
|
|||
|
||||
@interface RCTConvert (Deprecated)
|
||||
|
||||
/**
|
||||
* Use lightweight generics syntax instead, e.g. NSArray<NSString *>
|
||||
*/
|
||||
typedef NSArray NSArrayArray __deprecated_msg("Use NSArray<NSArray *>");
|
||||
typedef NSArray NSStringArray __deprecated_msg("Use NSArray<NSString *>");
|
||||
typedef NSArray NSStringArrayArray __deprecated_msg("Use NSArray<NSArray<NSString *> *>");
|
||||
typedef NSArray NSDictionaryArray __deprecated_msg("Use NSArray<NSDictionary *>");
|
||||
typedef NSArray NSURLArray __deprecated_msg("Use NSArray<NSURL *>");
|
||||
typedef NSArray RCTFileURLArray __deprecated_msg("Use NSArray<RCTFileURL *>");
|
||||
typedef NSArray NSNumberArray __deprecated_msg("Use NSArray<NSNumber *>");
|
||||
typedef NSArray UIColorArray __deprecated_msg("Use NSArray<UIColor *>");
|
||||
|
||||
/**
|
||||
* Synchronous image loading is generally a bad idea for performance reasons.
|
||||
* If you need to pass image references, try to use `RCTImageSource` and then
|
||||
|
@ -162,6 +159,11 @@ RCT_EXTERN NSNumber *RCTConvertEnumValue(const char *, NSDictionary *, NSNumber
|
|||
RCT_EXTERN NSNumber *RCTConvertMultiEnumValue(const char *, NSDictionary *, NSNumber *, id);
|
||||
RCT_EXTERN NSArray *RCTConvertArrayValue(SEL, id);
|
||||
|
||||
/**
|
||||
* Get the converter function for the specified type
|
||||
*/
|
||||
RCT_EXTERN SEL RCTConvertSelectorForType(NSString *type);
|
||||
|
||||
/**
|
||||
* This macro is used for logging conversion errors. This is just used to
|
||||
* avoid repeating the same boilerplate for every error message.
|
||||
|
@ -238,7 +240,7 @@ RCT_CUSTOM_CONVERTER(type, type, [RCT_DEBUG ? [self NSNumber:json] : json getter
|
|||
* This macro is used for creating converter functions for typed arrays.
|
||||
*/
|
||||
#define RCT_ARRAY_CONVERTER(type) \
|
||||
+ (NSArray<type *> *)type##Array:(id)json \
|
||||
+ (NSArray<id> *)type##Array:(id)json \
|
||||
{ \
|
||||
return RCTConvertArrayValue(@selector(type:), json); \
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#import "RCTDefines.h"
|
||||
#import "RCTImageSource.h"
|
||||
#import "RCTParserUtils.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@implementation RCTConvert
|
||||
|
@ -649,6 +650,12 @@ NSArray *RCTConvertArrayValue(SEL type, id json)
|
|||
return values;
|
||||
}
|
||||
|
||||
SEL RCTConvertSelectorForType(NSString *type)
|
||||
{
|
||||
const char *input = type.UTF8String;
|
||||
return NSSelectorFromString([RCTParseType(&input) stringByAppendingString:@":"]);
|
||||
}
|
||||
|
||||
RCT_ARRAY_CONVERTER(NSURL)
|
||||
RCT_ARRAY_CONVERTER(RCTFileURL)
|
||||
RCT_ARRAY_CONVERTER(UIColor)
|
||||
|
|
|
@ -122,7 +122,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
|
|||
NSArray<NSString *> *entries =
|
||||
((NSArray<NSString *> *(*)(id, SEL))imp)(_moduleClass, selector);
|
||||
id<RCTBridgeMethod> moduleMethod =
|
||||
[[RCTModuleMethod alloc] initWithObjCMethodName:entries[1]
|
||||
[[RCTModuleMethod alloc] initWithMethodSignature:entries[1]
|
||||
JSMethodName:entries[0]
|
||||
moduleClass:_moduleClass];
|
||||
|
||||
|
|
|
@ -10,15 +10,10 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTBridgeMethod.h"
|
||||
#import "RCTNullability.h"
|
||||
|
||||
@class RCTBridge;
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTNullability) {
|
||||
RCTNullabilityUnspecified,
|
||||
RCTNullable,
|
||||
RCTNonnullable,
|
||||
};
|
||||
|
||||
@interface RCTMethodArgument : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *type;
|
||||
|
@ -32,7 +27,7 @@ typedef NS_ENUM(NSUInteger, RCTNullability) {
|
|||
@property (nonatomic, readonly) Class moduleClass;
|
||||
@property (nonatomic, readonly) SEL selector;
|
||||
|
||||
- (instancetype)initWithObjCMethodName:(NSString *)objCMethodName
|
||||
- (instancetype)initWithMethodSignature:(NSString *)objCMethodName
|
||||
JSMethodName:(NSString *)JSMethodName
|
||||
moduleClass:(Class)moduleClass NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#import "RCTBridge.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTParserUtils.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
typedef BOOL (^RCTArgumentBlock)(RCTBridge *, NSUInteger, id);
|
||||
|
@ -50,7 +51,7 @@ typedef BOOL (^RCTArgumentBlock)(RCTBridge *, NSUInteger, id);
|
|||
Class _moduleClass;
|
||||
NSInvocation *_invocation;
|
||||
NSArray<RCTArgumentBlock> *_argumentBlocks;
|
||||
NSString *_objCMethodName;
|
||||
NSString *_methodSignature;
|
||||
SEL _selector;
|
||||
NSDictionary *_profileArgs;
|
||||
}
|
||||
|
@ -68,77 +69,106 @@ static void RCTLogArgumentError(RCTModuleMethod *method, NSUInteger index,
|
|||
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
|
||||
void RCTParseObjCMethodName(NSString **, NSArray<RCTMethodArgument *> **);
|
||||
void RCTParseObjCMethodName(NSString **objCMethodName, NSArray<RCTMethodArgument *> **arguments)
|
||||
// returns YES if the selector ends in a colon (indicating that there is at
|
||||
// least one argument, and maybe more selector parts) or NO if it doesn't.
|
||||
static BOOL RCTParseSelectorPart(const char **input, NSMutableString *selector)
|
||||
{
|
||||
static NSRegularExpression *typeNameRegex;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *unusedPattern = @"(?:__unused|__attribute__\\(\\(unused\\)\\))";
|
||||
NSString *constPattern = @"(?:const)";
|
||||
NSString *nullablePattern = @"(?:__nullable|nullable|__attribute__\\(\\(nullable\\)\\))";
|
||||
NSString *nonnullPattern = @"(?:__nonnull|nonnull|__attribute__\\(\\(nonnull\\)\\))";
|
||||
NSString *annotationPattern = [NSString stringWithFormat:@"(?:(?:(%@)|%@|(%@)|(%@))\\s*)",
|
||||
unusedPattern, constPattern, nullablePattern, nonnullPattern];
|
||||
NSString *pattern = [NSString stringWithFormat:@"(?<=:)(\\s*\\(%1$@?(\\w+?)(?:\\s*\\*)?%1$@?\\))?\\s*\\w+",
|
||||
annotationPattern];
|
||||
typeNameRegex = [[NSRegularExpression alloc] initWithPattern:pattern options:0 error:NULL];
|
||||
});
|
||||
NSString *selectorPart;
|
||||
if (RCTParseIdentifier(input, &selectorPart)) {
|
||||
[selector appendString:selectorPart];
|
||||
}
|
||||
RCTSkipWhitespace(input);
|
||||
if (RCTReadChar(input, ':')) {
|
||||
[selector appendString:@":"];
|
||||
RCTSkipWhitespace(input);
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Extract argument types
|
||||
NSString *methodName = *objCMethodName;
|
||||
NSRange methodRange = {0, methodName.length};
|
||||
NSMutableArray *args = [NSMutableArray array];
|
||||
[typeNameRegex enumerateMatchesInString:methodName options:0 range:methodRange usingBlock:^(NSTextCheckingResult *result, __unused NSMatchingFlags flags, __unused BOOL *stop) {
|
||||
NSRange typeRange = [result rangeAtIndex:5];
|
||||
NSString *type = typeRange.length ? [methodName substringWithRange:typeRange] : @"id";
|
||||
BOOL unused = ([result rangeAtIndex:2].length > 0);
|
||||
RCTNullability nullability = [result rangeAtIndex:3].length ? RCTNullable :
|
||||
[result rangeAtIndex:4].length ? RCTNonnullable : RCTNullabilityUnspecified;
|
||||
static BOOL RCTParseUnused(const char **input)
|
||||
{
|
||||
return RCTReadString(input, "__unused") ||
|
||||
RCTReadString(input, "__attribute__((unused))");
|
||||
}
|
||||
|
||||
static RCTNullability RCTParseNullability(const char **input)
|
||||
{
|
||||
if (RCTReadString(input, "nullable")) {
|
||||
return RCTNullable;
|
||||
} else if (RCTReadString(input, "nonnull")) {
|
||||
return RCTNonnullable;
|
||||
}
|
||||
return RCTNullabilityUnspecified;
|
||||
}
|
||||
|
||||
SEL RCTParseMethodSignature(NSString *, NSArray<RCTMethodArgument *> **);
|
||||
SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument *> **arguments)
|
||||
{
|
||||
const char *input = methodSignature.UTF8String;
|
||||
RCTSkipWhitespace(&input);
|
||||
|
||||
NSMutableArray *args;
|
||||
NSMutableString *selector = [NSMutableString new];
|
||||
while (RCTParseSelectorPart(&input, selector)) {
|
||||
if (!args) {
|
||||
args = [NSMutableArray new];
|
||||
}
|
||||
|
||||
// Parse type
|
||||
if (RCTReadChar(&input, '(')) {
|
||||
RCTSkipWhitespace(&input);
|
||||
|
||||
BOOL unused = RCTParseUnused(&input);
|
||||
RCTSkipWhitespace(&input);
|
||||
|
||||
RCTNullability nullability = RCTParseNullability(&input);
|
||||
RCTSkipWhitespace(&input);
|
||||
|
||||
NSString *type = RCTParseType(&input);
|
||||
[args addObject:[[RCTMethodArgument alloc] initWithType:type
|
||||
nullability:nullability
|
||||
unused:unused]];
|
||||
}];
|
||||
RCTSkipWhitespace(&input);
|
||||
RCTReadChar(&input, ')');
|
||||
RCTSkipWhitespace(&input);
|
||||
} else {
|
||||
// Type defaults to id if unspecified
|
||||
[args addObject:[[RCTMethodArgument alloc] initWithType:@"id"
|
||||
nullability:RCTNullable
|
||||
unused:NO]];
|
||||
}
|
||||
|
||||
// Argument name
|
||||
RCTParseIdentifier(&input, NULL);
|
||||
RCTSkipWhitespace(&input);
|
||||
}
|
||||
|
||||
*arguments = [args copy];
|
||||
|
||||
// Remove the parameter types and names
|
||||
methodName = [typeNameRegex stringByReplacingMatchesInString:methodName options:0
|
||||
range:methodRange
|
||||
withTemplate:@""];
|
||||
|
||||
// Remove whitespace
|
||||
methodName = [methodName stringByReplacingOccurrencesOfString:@"\n" withString:@""];
|
||||
methodName = [methodName stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||
|
||||
// Strip trailing semicolon
|
||||
if ([methodName hasSuffix:@";"]) {
|
||||
methodName = [methodName substringToIndex:methodName.length - 1];
|
||||
return NSSelectorFromString(selector);
|
||||
}
|
||||
|
||||
*objCMethodName = methodName;
|
||||
}
|
||||
|
||||
- (instancetype)initWithObjCMethodName:(NSString *)objCMethodName
|
||||
- (instancetype)initWithMethodSignature:(NSString *)methodSignature
|
||||
JSMethodName:(NSString *)JSMethodName
|
||||
moduleClass:(Class)moduleClass
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
|
||||
_moduleClass = moduleClass;
|
||||
_objCMethodName = [objCMethodName copy];
|
||||
_methodSignature = [methodSignature copy];
|
||||
_JSMethodName = JSMethodName.length > 0 ? JSMethodName : ({
|
||||
NSString *methodName = objCMethodName;
|
||||
NSString *methodName = methodSignature;
|
||||
NSRange colonRange = [methodName rangeOfString:@":"];
|
||||
if (colonRange.location != NSNotFound) {
|
||||
methodName = [methodName substringToIndex:colonRange.location];
|
||||
}
|
||||
methodName = [methodName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
RCTAssert(methodName.length, @"%@ is not a valid JS function name, please"
|
||||
" supply an alternative using RCT_REMAP_METHOD()", objCMethodName);
|
||||
" supply an alternative using RCT_REMAP_METHOD()", methodSignature);
|
||||
methodName;
|
||||
});
|
||||
|
||||
if ([_objCMethodName rangeOfString:@"RCTPromise"].length) {
|
||||
if ([_methodSignature rangeOfString:@"RCTPromise"].length) {
|
||||
_functionType = RCTFunctionTypePromise;
|
||||
} else {
|
||||
_functionType = RCTFunctionTypeNormal;
|
||||
|
@ -151,15 +181,12 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray<RCTMethodArgument
|
|||
- (void)processMethodSignature
|
||||
{
|
||||
NSArray<RCTMethodArgument *> *arguments;
|
||||
NSString *objCMethodName = _objCMethodName;
|
||||
RCTParseObjCMethodName(&objCMethodName, &arguments);
|
||||
|
||||
_selector = NSSelectorFromString(objCMethodName);
|
||||
RCTAssert(_selector, @"%@ is not a valid selector", objCMethodName);
|
||||
_selector = RCTParseMethodSignature(_methodSignature, &arguments);
|
||||
RCTAssert(_selector, @"%@ is not a valid selector", _methodSignature);
|
||||
|
||||
// Create method invocation
|
||||
NSMethodSignature *methodSignature = [_moduleClass instanceMethodSignatureForSelector:_selector];
|
||||
RCTAssert(methodSignature, @"%@ is not a recognized Objective-C method.", objCMethodName);
|
||||
RCTAssert(methodSignature, @"%@ is not a recognized Objective-C method.", _methodSignature);
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
|
||||
invocation.selector = _selector;
|
||||
_invocation = invocation;
|
||||
|
@ -203,7 +230,7 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray<RCTMethodArgument
|
|||
BOOL isNullableType = NO;
|
||||
RCTMethodArgument *argument = arguments[i - 2];
|
||||
NSString *typeName = argument.type;
|
||||
SEL selector = NSSelectorFromString([typeName stringByAppendingString:@":"]);
|
||||
SEL selector = RCTConvertSelectorForType(typeName);
|
||||
if ([RCTConvert respondsToSelector:selector]) {
|
||||
switch (objcType[0]) {
|
||||
|
||||
|
@ -296,7 +323,7 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray<RCTMethodArgument
|
|||
} else if ([typeName isEqualToString:@"RCTPromiseResolveBlock"]) {
|
||||
RCTAssert(i == numberOfArguments - 2,
|
||||
@"The RCTPromiseResolveBlock must be the second to last parameter in -[%@ %@]",
|
||||
_moduleClass, objCMethodName);
|
||||
_moduleClass, _methodSignature);
|
||||
RCT_ARG_BLOCK(
|
||||
if (RCT_DEBUG && ![json isKindOfClass:[NSNumber class]]) {
|
||||
RCTLogArgumentError(weakSelf, index, json, "should be a promise resolver function");
|
||||
|
@ -310,7 +337,7 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray<RCTMethodArgument
|
|||
} else if ([typeName isEqualToString:@"RCTPromiseRejectBlock"]) {
|
||||
RCTAssert(i == numberOfArguments - 1,
|
||||
@"The RCTPromiseRejectBlock must be the last parameter in -[%@ %@]",
|
||||
_moduleClass, objCMethodName);
|
||||
_moduleClass, _methodSignature);
|
||||
RCT_ARG_BLOCK(
|
||||
if (RCT_DEBUG && ![json isKindOfClass:[NSNumber class]]) {
|
||||
RCTLogArgumentError(weakSelf, index, json, "should be a promise rejecter function");
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTNullability) {
|
||||
RCTNullabilityUnspecified,
|
||||
RCTNullable,
|
||||
RCTNonnullable,
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTDefines.h"
|
||||
|
||||
@interface RCTParserUtils : NSObject
|
||||
|
||||
/**
|
||||
* Generic utility functions for parsing Objective-C source code.
|
||||
*/
|
||||
RCT_EXTERN BOOL RCTReadChar(const char **input, char c);
|
||||
RCT_EXTERN BOOL RCTReadString(const char **input, const char *string);
|
||||
RCT_EXTERN void RCTSkipWhitespace(const char **input);
|
||||
RCT_EXTERN BOOL RCTParseIdentifier(const char **input, NSString **string);
|
||||
|
||||
/**
|
||||
* Parse an Objective-C type into a form that can be used by RCTConvert.
|
||||
* This doesn't really belong here, but it's used by both RCTConvert and
|
||||
* RCTModuleMethod, which makes it difficult to find a better home for it.
|
||||
*/
|
||||
RCT_EXTERN NSString *RCTParseType(const char **input);
|
||||
|
||||
@end
|
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTParserUtils.h"
|
||||
|
||||
#import "RCTLog.h"
|
||||
|
||||
@implementation RCTParserUtils
|
||||
|
||||
BOOL RCTReadChar(const char **input, char c)
|
||||
{
|
||||
if (**input == c) {
|
||||
(*input)++;
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL RCTReadString(const char **input, const char *string)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; string[i] != 0; i++) {
|
||||
if (string[i] != (*input)[i]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
*input += i;
|
||||
return YES;
|
||||
}
|
||||
|
||||
void RCTSkipWhitespace(const char **input)
|
||||
{
|
||||
while (isspace(**input)) {
|
||||
(*input)++;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL RCTIsIdentifierHead(const char c)
|
||||
{
|
||||
return isalpha(c) || c == '_';
|
||||
}
|
||||
|
||||
static BOOL RCTIsIdentifierTail(const char c)
|
||||
{
|
||||
return isalnum(c) || c == '_';
|
||||
}
|
||||
|
||||
BOOL RCTParseIdentifier(const char **input, NSString **string)
|
||||
{
|
||||
const char *start = *input;
|
||||
if (!RCTIsIdentifierHead(**input)) {
|
||||
return NO;
|
||||
}
|
||||
(*input)++;
|
||||
while (RCTIsIdentifierTail(**input)) {
|
||||
(*input)++;
|
||||
}
|
||||
if (string) {
|
||||
*string = [[NSString alloc] initWithBytes:start
|
||||
length:(NSInteger)(*input - start)
|
||||
encoding:NSASCIIStringEncoding];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
static BOOL RCTIsCollectionType(NSString *type)
|
||||
{
|
||||
static NSSet *collectionTypes;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
collectionTypes = [[NSSet alloc] initWithObjects:
|
||||
@"NSArray", @"NSSet", @"NSDictionary", nil];
|
||||
});
|
||||
return [collectionTypes containsObject:type];
|
||||
}
|
||||
|
||||
NSString *RCTParseType(const char **input)
|
||||
{
|
||||
NSString *type;
|
||||
RCTParseIdentifier(input, &type);
|
||||
RCTSkipWhitespace(input);
|
||||
if (RCTReadChar(input, '<')) {
|
||||
RCTSkipWhitespace(input);
|
||||
NSString *subtype = RCTParseType(input);
|
||||
if (RCTIsCollectionType(type)) {
|
||||
if ([type isEqualToString:@"NSDictionary"]) {
|
||||
// Dictionaries have both a key *and* value type, but the key type has
|
||||
// to be a string for JSON, so we only care about the value type
|
||||
if (RCT_DEBUG && ![subtype isEqualToString:@"NSString"]) {
|
||||
RCTLogError(@"%@ is not a valid key type for a JSON dictionary", subtype);
|
||||
}
|
||||
RCTSkipWhitespace(input);
|
||||
RCTReadChar(input, ',');
|
||||
RCTSkipWhitespace(input);
|
||||
subtype = RCTParseType(input);
|
||||
}
|
||||
if (![subtype isEqualToString:@"id"]) {
|
||||
type = [type stringByReplacingCharactersInRange:(NSRange){0, 2 /* "NS" */}
|
||||
withString:subtype];
|
||||
}
|
||||
} else {
|
||||
// It's a protocol rather than a generic collection - ignore it
|
||||
}
|
||||
RCTSkipWhitespace(input);
|
||||
RCTReadChar(input, '>');
|
||||
}
|
||||
RCTSkipWhitespace(input);
|
||||
RCTReadChar(input, '*');
|
||||
return type;
|
||||
}
|
||||
|
||||
@end
|
|
@ -319,7 +319,7 @@ RCT_EXPORT_MODULE()
|
|||
|
||||
#pragma mark - Exported JS Functions
|
||||
|
||||
RCT_EXPORT_METHOD(multiGet:(NSStringArray *)keys
|
||||
RCT_EXPORT_METHOD(multiGet:(NSArray<NSString *> *)keys
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
|
@ -338,7 +338,7 @@ RCT_EXPORT_METHOD(multiGet:(NSStringArray *)keys
|
|||
callback(@[RCTNullIfNil(errors), result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(multiSet:(NSStringArrayArray *)kvPairs
|
||||
RCT_EXPORT_METHOD(multiSet:(NSArray<NSArray<NSString *> *> *)kvPairs
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
|
@ -358,7 +358,7 @@ RCT_EXPORT_METHOD(multiSet:(NSStringArrayArray *)kvPairs
|
|||
callback(@[RCTNullIfNil(errors)]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(multiMerge:(NSStringArrayArray *)kvPairs
|
||||
RCT_EXPORT_METHOD(multiMerge:(NSArray<NSArray<NSString *> *> *)kvPairs
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
|
@ -394,7 +394,7 @@ RCT_EXPORT_METHOD(multiMerge:(NSStringArrayArray *)kvPairs
|
|||
callback(@[RCTNullIfNil(errors)]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(multiRemove:(NSStringArray *)keys
|
||||
RCT_EXPORT_METHOD(multiRemove:(NSArray<NSString *> *)keys
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
NSDictionary *errorOut = [self _ensureSetup];
|
||||
|
|
|
@ -34,7 +34,7 @@ RCT_EXPORT_MODULE()
|
|||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reportSoftException:(NSString *)message
|
||||
stack:(NSDictionaryArray *)stack
|
||||
stack:(NSArray<NSDictionary *> *)stack
|
||||
exceptionId:(nonnull NSNumber *)exceptionId)
|
||||
{
|
||||
[_bridge.redBox showErrorMessage:message withStack:stack];
|
||||
|
@ -45,7 +45,7 @@ RCT_EXPORT_METHOD(reportSoftException:(NSString *)message
|
|||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reportFatalException:(NSString *)message
|
||||
stack:(NSDictionaryArray *)stack
|
||||
stack:(NSArray<NSDictionary *> *)stack
|
||||
exceptionId:(nonnull NSNumber *)exceptionId)
|
||||
{
|
||||
[_bridge.redBox showErrorMessage:message withStack:stack];
|
||||
|
@ -66,7 +66,7 @@ RCT_EXPORT_METHOD(reportFatalException:(NSString *)message
|
|||
}
|
||||
|
||||
RCT_EXPORT_METHOD(updateExceptionMessage:(NSString *)message
|
||||
stack:(NSDictionaryArray *)stack
|
||||
stack:(NSArray<NSDictionary *> *)stack
|
||||
exceptionId:(nonnull NSNumber *)exceptionId)
|
||||
{
|
||||
[_bridge.redBox updateErrorMessage:message withStack:stack];
|
||||
|
@ -78,7 +78,7 @@ RCT_EXPORT_METHOD(updateExceptionMessage:(NSString *)message
|
|||
|
||||
// Deprecated. Use reportFatalException directly instead.
|
||||
RCT_EXPORT_METHOD(reportUnhandledException:(NSString *)message
|
||||
stack:(NSDictionaryArray *)stack)
|
||||
stack:(NSArray<NSDictionary *> *)stack)
|
||||
{
|
||||
[self reportFatalException:message stack:stack exceptionId:@-1];
|
||||
}
|
||||
|
|
|
@ -721,11 +721,11 @@ RCT_EXPORT_METHOD(replaceExistingNonRootView:(nonnull NSNumber *)reactTag
|
|||
}
|
||||
|
||||
RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerReactTag
|
||||
moveFromIndices:(NSNumberArray *)moveFromIndices
|
||||
moveToIndices:(NSNumberArray *)moveToIndices
|
||||
addChildReactTags:(NSNumberArray *)addChildReactTags
|
||||
addAtIndices:(NSNumberArray *)addAtIndices
|
||||
removeAtIndices:(NSNumberArray *)removeAtIndices)
|
||||
moveFromIndices:(NSArray<NSNumber *> *)moveFromIndices
|
||||
moveToIndices:(NSArray<NSNumber *> *)moveToIndices
|
||||
addChildReactTags:(NSArray<NSNumber *> *)addChildReactTags
|
||||
addAtIndices:(NSArray<NSNumber *> *)addAtIndices
|
||||
removeAtIndices:(NSArray<NSNumber *> *)removeAtIndices)
|
||||
{
|
||||
[self _manageChildren:containerReactTag
|
||||
moveFromIndices:moveFromIndices
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
13A0C2891B74F71200B29F6F /* RCTDevLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2861B74F71200B29F6F /* RCTDevLoadingView.m */; };
|
||||
13A0C28A1B74F71200B29F6F /* RCTDevMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A0C2881B74F71200B29F6F /* RCTDevMenu.m */; };
|
||||
13A1F71E1A75392D00D3D453 /* RCTKeyCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */; };
|
||||
13A6E20E1C19AA0C00845B82 /* RCTParserUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 13A6E20D1C19AA0C00845B82 /* RCTParserUtils.m */; };
|
||||
13AB90C11B6FA36700713B4F /* RCTComponentData.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AB90C01B6FA36700713B4F /* RCTComponentData.m */; };
|
||||
13AF20451AE707F9005F5298 /* RCTSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AF20441AE707F9005F5298 /* RCTSlider.m */; };
|
||||
13AFBCA01C07247D00BBAEAA /* RCTMapOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 13AFBC9F1C07247D00BBAEAA /* RCTMapOverlay.m */; };
|
||||
|
@ -141,6 +142,9 @@
|
|||
13A0C2881B74F71200B29F6F /* RCTDevMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDevMenu.m; sourceTree = "<group>"; };
|
||||
13A1F71C1A75392D00D3D453 /* RCTKeyCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTKeyCommands.h; sourceTree = "<group>"; };
|
||||
13A1F71D1A75392D00D3D453 /* RCTKeyCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTKeyCommands.m; sourceTree = "<group>"; };
|
||||
13A6E20C1C19AA0C00845B82 /* RCTParserUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTParserUtils.h; sourceTree = "<group>"; };
|
||||
13A6E20D1C19AA0C00845B82 /* RCTParserUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTParserUtils.m; sourceTree = "<group>"; };
|
||||
13A6E20F1C19ABC700845B82 /* RCTNullability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTNullability.h; sourceTree = "<group>"; };
|
||||
13AB90BF1B6FA36700713B4F /* RCTComponentData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTComponentData.h; sourceTree = "<group>"; };
|
||||
13AB90C01B6FA36700713B4F /* RCTComponentData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTComponentData.m; sourceTree = "<group>"; };
|
||||
13AF1F851AE6E777005F5298 /* RCTDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDefines.h; sourceTree = "<group>"; };
|
||||
|
@ -518,6 +522,9 @@
|
|||
14C2CA731B3AC64300E6CBB2 /* RCTModuleData.m */,
|
||||
14C2CA6F1B3AC63800E6CBB2 /* RCTModuleMethod.h */,
|
||||
14C2CA701B3AC63800E6CBB2 /* RCTModuleMethod.m */,
|
||||
13A6E20F1C19ABC700845B82 /* RCTNullability.h */,
|
||||
13A6E20C1C19AA0C00845B82 /* RCTParserUtils.h */,
|
||||
13A6E20D1C19AA0C00845B82 /* RCTParserUtils.m */,
|
||||
142014181B32094000CC17BA /* RCTPerformanceLogger.h */,
|
||||
142014171B32094000CC17BA /* RCTPerformanceLogger.m */,
|
||||
830A229C1A66C68A008503DA /* RCTRootView.h */,
|
||||
|
@ -674,6 +681,7 @@
|
|||
83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */,
|
||||
83CBBA521A601E3B00E9B192 /* RCTLog.m in Sources */,
|
||||
13B0801D1A69489C00A75B9A /* RCTNavItemManager.m in Sources */,
|
||||
13A6E20E1C19AA0C00845B82 /* RCTParserUtils.m in Sources */,
|
||||
13E067571A70F44B002CDEE1 /* RCTView.m in Sources */,
|
||||
13AFBCA01C07247D00BBAEAA /* RCTMapOverlay.m in Sources */,
|
||||
13456E931ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m in Sources */,
|
||||
|
|
|
@ -114,7 +114,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||
if ([managerClass respondsToSelector:selector]) {
|
||||
NSArray<NSString *> *typeAndKeyPath =
|
||||
((NSArray<NSString *> *(*)(id, SEL))objc_msgSend)(managerClass, selector);
|
||||
type = NSSelectorFromString([typeAndKeyPath[0] stringByAppendingString:@":"]);
|
||||
type = RCTConvertSelectorForType(typeAndKeyPath[0]);
|
||||
keyPath = typeAndKeyPath.count > 1 ? typeAndKeyPath[1] : nil;
|
||||
} else {
|
||||
propBlock = ^(__unused id view, __unused id json) {};
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#import "RCTPickerManager.h"
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTPicker.h"
|
||||
|
||||
@implementation RCTPickerManager
|
||||
|
@ -22,7 +21,7 @@ RCT_EXPORT_MODULE()
|
|||
return [RCTPicker new];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(items, NSDictionaryArray)
|
||||
RCT_EXPORT_VIEW_PROPERTY(items, NSArray<NSDictionary *>)
|
||||
RCT_EXPORT_VIEW_PROPERTY(selectedIndex, NSInteger)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(color, UIColor)
|
||||
|
|
|
@ -22,7 +22,7 @@ RCT_EXPORT_MODULE()
|
|||
return [RCTSegmentedControl new];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(values, NSStringArray)
|
||||
RCT_EXPORT_VIEW_PROPERTY(values, NSArray<NSString *>)
|
||||
RCT_EXPORT_VIEW_PROPERTY(selectedIndex, NSInteger)
|
||||
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
|
||||
RCT_EXPORT_VIEW_PROPERTY(momentary, BOOL)
|
||||
|
|
Loading…
Reference in New Issue