[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
/ * *
* 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 "RCTModuleMethod.h"
# import < objc / message . h >
2015-07-28 20:09:22 +00:00
# import "RCTAssert.h"
2015-12-15 13:39:30 +00:00
# import "RCTBridge+Private.h"
2016-11-23 15:47:52 +00:00
# import "RCTBridge.h"
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
# import "RCTConvert.h"
# import "RCTLog.h"
2015-12-10 18:09:04 +00:00
# import "RCTParserUtils.h"
2016-09-05 18:11:37 +00:00
# import "RCTProfile.h"
2016-11-23 15:47:52 +00:00
# import "RCTUtils.h"
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-11 20:18:08 +00:00
typedef BOOL ( ^ RCTArgumentBlock ) ( RCTBridge * , NSUInteger , id ) ;
2015-07-29 12:54:59 +00:00
@ implementation RCTMethodArgument
- ( instancetype ) initWithType : ( NSString * ) type
nullability : ( RCTNullability ) nullability
2015-07-31 13:55:47 +00:00
unused : ( BOOL ) unused
2015-07-29 12:54:59 +00:00
{
2016-09-05 14:32:19 +00:00
if ( self = [ super init ] ) {
2015-07-29 12:54:59 +00:00
_type = [ type copy ] ;
_nullability = nullability ;
2015-07-31 13:55:47 +00:00
_unused = unused ;
2015-07-29 12:54:59 +00:00
}
return self ;
}
@ end
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
@ implementation RCTModuleMethod
{
Class _moduleClass ;
2015-08-06 22:44:15 +00:00
NSInvocation * _invocation ;
2015-11-03 22:45:46 +00:00
NSArray < RCTArgumentBlock > * _argumentBlocks ;
2015-12-10 18:09:04 +00:00
NSString * _methodSignature ;
2015-08-11 15:33:28 +00:00
SEL _selector ;
2017-04-27 18:49:49 +00:00
BOOL _isSync ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
}
2015-09-18 22:01:21 +00:00
@ synthesize JSMethodName = _JSMethodName ;
2015-08-03 11:37:47 +00:00
static void RCTLogArgumentError ( RCTModuleMethod * method , NSUInteger index ,
id valueOrType , const char * issue )
{
RCTLogError ( @ "Argument %tu (%@) of %@.%@ %s" , index , valueOrType ,
RCTBridgeModuleNameForClass ( method -> _moduleClass ) ,
method -> _JSMethodName , issue ) ;
}
2015-08-24 10:14:33 +00:00
RCT_NOT _IMPLEMENTED ( - ( instancetype ) init )
2015-07-09 23:45:48 +00:00
2015-12-10 18:09:04 +00:00
// 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 )
2015-07-28 20:09:22 +00:00
{
2015-12-10 18:09:04 +00:00
NSString * selectorPart ;
if ( RCTParseIdentifier ( input , & selectorPart ) ) {
[ selector appendString : selectorPart ] ;
}
RCTSkipWhitespace ( input ) ;
if ( RCTReadChar ( input , ' : ' ) ) {
[ selector appendString : @ ":" ] ;
RCTSkipWhitespace ( input ) ;
return YES ;
}
return NO ;
}
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 ;
}
2016-04-13 00:44:31 +00:00
static RCTNullability RCTParseNullabilityPostfix ( const char * * input )
{
if ( RCTReadString ( input , "_Nullable" ) ) {
return RCTNullable ;
} else if ( RCTReadString ( input , "_Nonnull" ) ) {
return RCTNonnullable ;
}
return RCTNullabilityUnspecified ;
}
2016-12-08 21:31:52 +00:00
// returns YES if execution is safe to proceed ( enqueue callback invocation ) , NO if callback has already been invoked
static BOOL RCTCheckCallbackMultipleInvocations ( BOOL * didInvoke ) {
2017-03-31 12:21:17 +00:00
if ( * didInvoke ) {
RCTFatal ( RCTErrorWithMessage ( @ "Illegal callback invocation from native module. This callback type only permits a single invocation from native code." ) ) ;
return NO ;
} else {
* didInvoke = YES ;
return YES ;
}
2016-12-08 21:31:52 +00:00
}
2015-12-10 18:09:04 +00:00
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 ) ;
2015-07-28 20:09:22 +00:00
2015-12-10 18:09:04 +00:00
BOOL unused = RCTParseUnused ( & input ) ;
RCTSkipWhitespace ( & input ) ;
2015-07-28 20:09:22 +00:00
2015-12-10 18:09:04 +00:00
RCTNullability nullability = RCTParseNullability ( & input ) ;
RCTSkipWhitespace ( & input ) ;
2015-07-28 20:09:22 +00:00
2015-12-10 18:09:04 +00:00
NSString * type = RCTParseType ( & input ) ;
2016-04-13 00:44:31 +00:00
RCTSkipWhitespace ( & input ) ;
if ( nullability = = RCTNullabilityUnspecified ) {
nullability = RCTParseNullabilityPostfix ( & input ) ;
}
2015-12-10 18:09:04 +00:00
[ 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 ) ;
2015-07-28 20:09:22 +00:00
}
2015-12-10 18:09:04 +00:00
* arguments = [ args copy ] ;
return NSSelectorFromString ( selector ) ;
2015-07-28 20:09:22 +00:00
}
2015-12-10 18:09:04 +00:00
- ( instancetype ) initWithMethodSignature : ( NSString * ) methodSignature
JSMethodName : ( NSString * ) JSMethodName
2017-04-27 18:49:49 +00:00
isSync : ( BOOL ) isSync
2015-12-10 18:09:04 +00:00
moduleClass : ( Class ) moduleClass
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
{
2016-09-05 14:32:19 +00:00
if ( self = [ super init ] ) {
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
_moduleClass = moduleClass ;
2015-12-10 18:09:04 +00:00
_methodSignature = [ methodSignature copy ] ;
2016-09-05 14:32:19 +00:00
_JSMethodName = [ JSMethodName copy ] ;
2017-04-27 18:49:49 +00:00
_isSync = isSync ;
2015-08-11 15:33:28 +00:00
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-11 15:33:28 +00:00
return self ;
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-11 15:33:28 +00:00
- ( void ) processMethodSignature
{
2015-11-03 22:45:46 +00:00
NSArray < RCTMethodArgument * > * arguments ;
2015-12-10 18:09:04 +00:00
_selector = RCTParseMethodSignature ( _methodSignature , & arguments ) ;
RCTAssert ( _selector , @ "%@ is not a valid selector" , _methodSignature ) ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-11 15:33:28 +00:00
// Create method invocation
NSMethodSignature * methodSignature = [ _moduleClass instanceMethodSignatureForSelector : _selector ] ;
2015-12-10 18:09:04 +00:00
RCTAssert ( methodSignature , @ "%@ is not a recognized Objective-C method." , _methodSignature ) ;
2015-08-11 15:33:28 +00:00
NSInvocation * invocation = [ NSInvocation invocationWithMethodSignature : methodSignature ] ;
2015-08-24 10:14:33 +00:00
invocation . selector = _selector ;
2015-08-11 15:33:28 +00:00
_invocation = invocation ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-11 15:33:28 +00:00
// Process arguments
NSUInteger numberOfArguments = methodSignature . numberOfArguments ;
2015-11-03 22:45:46 +00:00
NSMutableArray < RCTArgumentBlock > * argumentBlocks =
[ [ NSMutableArray alloc ] initWithCapacity : numberOfArguments - 2 ] ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-11 15:33:28 +00:00
# define RCT_ARG _BLOCK ( _logic ) \
[ argumentBlocks addObject : ^ ( __unused RCTBridge * bridge , NSUInteger index , id json ) { \
_logic \
[ invocation setArgument : & value atIndex : ( index ) + 2 ] ; \
2015-08-11 20:18:08 +00:00
return YES ; \
2015-08-11 15:33:28 +00:00
} ] ;
2015-10-22 11:02:51 +00:00
/ * *
* Explicitly copy the block and retain it , since NSInvocation doesn ' t retain them .
* /
# define RCT_BLOCK _ARGUMENT ( block . . . ) \
id value = json ? [ block copy ] : ( id ) ^ ( __unused NSArray * _ ) { } ; \
CFBridgingRetain ( value )
2015-08-11 15:33:28 +00:00
__weak RCTModuleMethod * weakSelf = self ;
void ( ^ addBlockArgument ) ( void ) = ^ {
RCT_ARG _BLOCK (
if ( RCT_DEBUG && json && ! [ json isKindOfClass : [ NSNumber class ] ] ) {
RCTLogArgumentError ( weakSelf , index , json , "should be a function" ) ;
2015-08-11 20:18:08 +00:00
return NO ;
2015-08-11 15:33:28 +00:00
}
2016-12-08 21:31:52 +00:00
__block BOOL didInvoke = NO ;
2015-10-22 11:02:51 +00:00
RCT_BLOCK _ARGUMENT ( ^ ( NSArray * args ) {
2016-12-08 21:31:52 +00:00
if ( RCTCheckCallbackMultipleInvocations ( & didInvoke ) ) {
[ bridge enqueueCallback : json args : args ] ;
}
2015-10-22 11:02:51 +00:00
} ) ;
2015-08-11 15:33:28 +00:00
)
} ;
for ( NSUInteger i = 2 ; i < numberOfArguments ; i + + ) {
const char * objcType = [ methodSignature getArgumentTypeAtIndex : i ] ;
BOOL isNullableType = NO ;
RCTMethodArgument * argument = arguments [ i - 2 ] ;
NSString * typeName = argument . type ;
2015-12-10 18:09:04 +00:00
SEL selector = RCTConvertSelectorForType ( typeName ) ;
2015-08-11 15:33:28 +00:00
if ( [ RCTConvert respondsToSelector : selector ] ) {
switch ( objcType [ 0 ] ) {
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-06 22:44:15 +00:00
# define RCT_CASE ( _value , _type ) \
2015-08-11 15:33:28 +00:00
case _value : { \
_type ( * convert ) ( id , SEL , id ) = ( typeof ( convert ) ) objc_msgSend ; \
RCT_ARG _BLOCK ( _type value = convert ( [ RCTConvert class ] , selector , json ) ; ) \
break ; \
}
2015-08-06 22:44:15 +00:00
2015-08-11 15:33:28 +00:00
RCT_CASE ( _C _CHR , char )
RCT_CASE ( _C _UCHR , unsigned char )
RCT_CASE ( _C _SHT , short )
RCT_CASE ( _C _USHT , unsigned short )
RCT_CASE ( _C _INT , int )
RCT_CASE ( _C _UINT , unsigned int )
RCT_CASE ( _C _LNG , long )
RCT_CASE ( _C _ULNG , unsigned long )
RCT_CASE ( _C _LNG _LNG , long long )
RCT_CASE ( _C _ULNG _LNG , unsigned long long )
RCT_CASE ( _C _FLT , float )
RCT_CASE ( _C _DBL , double )
RCT_CASE ( _C _BOOL , BOOL )
2015-08-06 22:44:15 +00:00
# define RCT_NULLABLE _CASE ( _value , _type ) \
2015-08-11 15:33:28 +00:00
case _value : { \
isNullableType = YES ; \
_type ( * convert ) ( id , SEL , id ) = ( typeof ( convert ) ) objc_msgSend ; \
RCT_ARG _BLOCK ( _type value = convert ( [ RCTConvert class ] , selector , json ) ; ) \
break ; \
}
2015-08-06 22:44:15 +00:00
2015-08-11 15:33:28 +00:00
RCT_NULLABLE _CASE ( _C _SEL , SEL )
RCT_NULLABLE _CASE ( _C _CHARPTR , const char * )
RCT_NULLABLE _CASE ( _C _PTR , void * )
2015-10-22 11:02:51 +00:00
case _C _ID : {
isNullableType = YES ;
id ( * convert ) ( id , SEL , id ) = ( typeof ( convert ) ) objc_msgSend ;
RCT_ARG _BLOCK (
id value = convert ( [ RCTConvert class ] , selector , json ) ;
CFBridgingRetain ( value ) ;
)
break ;
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-11 15:33:28 +00:00
case _C _STRUCT _B : {
2015-08-06 22:44:15 +00:00
2015-08-11 15:33:28 +00:00
NSMethodSignature * typeSignature = [ RCTConvert methodSignatureForSelector : selector ] ;
NSInvocation * typeInvocation = [ NSInvocation invocationWithMethodSignature : typeSignature ] ;
2015-08-24 10:14:33 +00:00
typeInvocation . selector = selector ;
typeInvocation . target = [ RCTConvert class ] ;
2015-08-06 22:44:15 +00:00
2015-08-18 13:55:25 +00:00
[ argumentBlocks addObject : ^ ( __unused RCTBridge * bridge , NSUInteger index , id json ) {
2015-08-11 15:33:28 +00:00
void * returnValue = malloc ( typeSignature . methodReturnLength ) ;
[ typeInvocation setArgument : & json atIndex : 2 ] ;
[ typeInvocation invoke ] ;
[ typeInvocation getReturnValue : returnValue ] ;
[ invocation setArgument : returnValue atIndex : index + 2 ] ;
free ( returnValue ) ;
2015-08-18 13:55:25 +00:00
return YES ;
2015-08-11 15:33:28 +00:00
} ] ;
break ;
}
2015-07-07 15:47:23 +00:00
2015-08-11 15:33:28 +00:00
default : {
static const char * blockType = @ encode ( typeof ( ^ { } ) ) ;
if ( ! strcmp ( objcType , blockType ) ) {
addBlockArgument ( ) ;
} else {
RCTLogError ( @ "Unsupported argument type '%@' in method %@." ,
typeName , [ self methodName ] ) ;
2015-07-31 13:55:47 +00:00
}
2015-07-29 12:54:59 +00:00
}
2015-08-11 15:33:28 +00:00
}
} else if ( [ typeName isEqualToString : @ "RCTResponseSenderBlock" ] ) {
addBlockArgument ( ) ;
} else if ( [ typeName isEqualToString : @ "RCTResponseErrorBlock" ] ) {
RCT_ARG _BLOCK (
2015-07-29 12:54:59 +00:00
2015-08-11 15:33:28 +00:00
if ( RCT_DEBUG && json && ! [ json isKindOfClass : [ NSNumber class ] ] ) {
RCTLogArgumentError ( weakSelf , index , json , "should be a function" ) ;
2015-08-11 20:18:08 +00:00
return NO ;
2015-08-11 15:33:28 +00:00
}
2015-07-29 12:54:59 +00:00
2016-12-08 21:31:52 +00:00
__block BOOL didInvoke = NO ;
2015-10-22 11:02:51 +00:00
RCT_BLOCK _ARGUMENT ( ^ ( NSError * error ) {
2016-12-08 21:31:52 +00:00
if ( RCTCheckCallbackMultipleInvocations ( & didInvoke ) ) {
[ bridge enqueueCallback : json args : @ [ RCTJSErrorFromNSError ( error ) ] ] ;
}
2015-10-22 11:02:51 +00:00
} ) ;
2015-08-11 15:33:28 +00:00
)
} else if ( [ typeName isEqualToString : @ "RCTPromiseResolveBlock" ] ) {
RCTAssert ( i = = numberOfArguments - 2 ,
@ "The RCTPromiseResolveBlock must be the second to last parameter in -[%@ %@]" ,
2015-12-10 18:09:04 +00:00
_moduleClass , _methodSignature ) ;
2015-08-11 15:33:28 +00:00
RCT_ARG _BLOCK (
if ( RCT_DEBUG && ! [ json isKindOfClass : [ NSNumber class ] ] ) {
RCTLogArgumentError ( weakSelf , index , json , "should be a promise resolver function" ) ;
2015-08-11 20:18:08 +00:00
return NO ;
2015-08-11 15:33:28 +00:00
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2016-12-08 21:31:52 +00:00
__block BOOL didInvoke = NO ;
2015-10-22 11:02:51 +00:00
RCT_BLOCK _ARGUMENT ( ^ ( id result ) {
2016-12-08 21:31:52 +00:00
if ( RCTCheckCallbackMultipleInvocations ( & didInvoke ) ) {
[ bridge enqueueCallback : json args : result ? @ [ result ] : @ [ ] ] ;
}
2015-08-11 15:33:28 +00:00
} ) ;
)
} else if ( [ typeName isEqualToString : @ "RCTPromiseRejectBlock" ] ) {
RCTAssert ( i = = numberOfArguments - 1 ,
@ "The RCTPromiseRejectBlock must be the last parameter in -[%@ %@]" ,
2015-12-10 18:09:04 +00:00
_moduleClass , _methodSignature ) ;
2015-08-11 15:33:28 +00:00
RCT_ARG _BLOCK (
if ( RCT_DEBUG && ! [ json isKindOfClass : [ NSNumber class ] ] ) {
RCTLogArgumentError ( weakSelf , index , json , "should be a promise rejecter function" ) ;
2015-08-11 20:18:08 +00:00
return NO ;
2015-08-11 15:33:28 +00:00
}
2015-07-29 12:54:59 +00:00
2016-12-08 21:31:52 +00:00
__block BOOL didInvoke = NO ;
2016-01-19 20:19:47 +00:00
RCT_BLOCK _ARGUMENT ( ^ ( NSString * code , NSString * message , NSError * error ) {
2016-12-08 21:31:52 +00:00
if ( RCTCheckCallbackMultipleInvocations ( & didInvoke ) ) {
NSDictionary * errorJSON = RCTJSErrorFromCodeMessageAndNSError ( code , message , error ) ;
[ bridge enqueueCallback : json args : @ [ errorJSON ] ] ;
}
2015-08-11 15:33:28 +00:00
} ) ;
)
} else {
2015-07-31 13:55:47 +00:00
2015-08-11 15:33:28 +00:00
// Unknown argument type
RCTLogError ( @ "Unknown argument type '%@' in method %@. Extend RCTConvert"
" to support this type." , typeName , [ self methodName ] ) ;
}
2015-07-31 13:55:47 +00:00
2015-08-11 15:33:28 +00:00
if ( RCT_DEBUG ) {
RCTNullability nullability = argument . nullability ;
if ( ! isNullableType ) {
if ( nullability = = RCTNullable ) {
RCTLogArgumentError ( weakSelf , i - 2 , typeName , "is marked as "
"nullable, but is not a nullable type." ) ;
2015-07-31 13:55:47 +00:00
}
2015-08-11 15:33:28 +00:00
nullability = RCTNonnullable ;
}
2015-07-31 13:55:47 +00:00
2015-08-11 15:33:28 +00:00
/ * *
* Special case - Numbers are not nullable in Android , so we
* don ' t support this for now . In future we may allow it .
* /
if ( [ typeName isEqualToString : @ "NSNumber" ] ) {
BOOL unspecified = ( nullability = = RCTNullabilityUnspecified ) ;
if ( ! argument . unused && ( nullability = = RCTNullable || unspecified ) ) {
RCTLogArgumentError ( weakSelf , i - 2 , typeName ,
[ unspecified ? @ "has unspecified nullability" : @ "is marked as nullable"
stringByAppendingString : @ " but React requires that all NSNumber "
"arguments are explicitly marked as `nonnull` to ensure "
"compatibility with Android." ] . UTF8String ) ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
}
2015-08-11 15:33:28 +00:00
nullability = RCTNonnullable ;
2015-07-29 12:54:59 +00:00
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
2015-08-11 15:33:28 +00:00
if ( nullability = = RCTNonnullable ) {
RCTArgumentBlock oldBlock = argumentBlocks [ i - 2 ] ;
argumentBlocks [ i - 2 ] = ^ ( RCTBridge * bridge , NSUInteger index , id json ) {
2015-10-29 12:13:58 +00:00
if ( json ! = nil ) {
if ( ! oldBlock ( bridge , index , json ) ) {
return NO ;
}
if ( isNullableType ) {
// Check converted value wasn ' t null either , as method probably
// won ' t gracefully handle a nil vallue for a nonull argument
void * value ;
[ invocation getArgument : & value atIndex : index + 2 ] ;
if ( value = = NULL ) {
return NO ;
}
}
return YES ;
2015-08-11 15:33:28 +00:00
}
2015-10-29 12:13:58 +00:00
RCTLogArgumentError ( weakSelf , index , typeName , "must not be null" ) ;
return NO ;
2015-08-11 15:33:28 +00:00
} ;
}
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
}
2017-04-27 18:49:49 +00:00
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 ) ;
}
2015-08-11 15:33:28 +00:00
_argumentBlocks = [ argumentBlocks copy ] ;
}
- ( SEL ) selector
{
if ( _selector = = NULL ) {
2016-09-05 18:11:37 +00:00
RCT_PROFILE _BEGIN _EVENT ( RCTProfileTagAlways , @ "" , ( @ { @ "module" : NSStringFromClass ( _moduleClass ) ,
@ "method" : _methodSignature } ) ) ;
2015-08-11 15:33:28 +00:00
[ self processMethodSignature ] ;
2016-09-05 18:11:37 +00:00
RCT_PROFILE _END _EVENT ( RCTProfileTagAlways , @ "" ) ;
2015-08-11 15:33:28 +00:00
}
return _selector ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
}
2016-09-05 14:32:19 +00:00
- ( NSString * ) JSMethodName
2015-09-18 22:01:21 +00:00
{
2016-09-05 14:32:19 +00:00
NSString * methodName = _JSMethodName ;
if ( methodName . length = = 0 ) {
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()" , _methodSignature ) ;
}
return methodName ;
}
- ( RCTFunctionType ) functionType
{
if ( [ _methodSignature rangeOfString : @ "RCTPromise" ] . length ) {
2017-04-28 12:32:13 +00:00
RCTAssert ( ! _isSync , @ "Promises cannot be used in sync functions" ) ;
2017-04-27 18:49:49 +00:00
2016-09-05 14:32:19 +00:00
return RCTFunctionTypePromise ;
2017-04-27 18:49:49 +00:00
} else if ( _isSync ) {
return RCTFunctionTypeSync ;
2016-09-05 14:32:19 +00:00
} else {
return RCTFunctionTypeNormal ;
2015-09-18 22:01:21 +00:00
}
}
2016-09-05 14:32:20 +00:00
- ( id ) invokeWithBridge : ( RCTBridge * ) bridge
module : ( id ) module
arguments : ( NSArray * ) arguments
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
{
2015-08-11 15:33:28 +00:00
if ( _argumentBlocks = = nil ) {
[ self processMethodSignature ] ;
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
if ( RCT_DEBUG ) {
// Sanity check
RCTAssert ( [ module class ] = = _moduleClass , @ " Attempted to invoke method \
% @ on a module of class % @ " , [ self methodName ] , [ module class ] ) ;
// Safety check
if ( arguments . count ! = _argumentBlocks . count ) {
NSInteger actualCount = arguments . count ;
NSInteger expectedCount = _argumentBlocks . count ;
// Subtract the implicit Promise resolver and rejecter functions for implementations of async functions
2016-09-05 14:32:19 +00:00
if ( self . functionType = = RCTFunctionTypePromise ) {
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
actualCount - = 2 ;
expectedCount - = 2 ;
}
2017-01-27 18:09:20 +00:00
RCTLogError ( @ "%@.%@ 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." ,
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
RCTBridgeModuleNameForClass ( _moduleClass ) , _JSMethodName ,
actualCount , expectedCount ) ;
2016-09-05 14:32:20 +00:00
return nil ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
}
}
// Set arguments
NSUInteger index = 0 ;
for ( id json in arguments ) {
2015-07-29 12:54:59 +00:00
RCTArgumentBlock block = _argumentBlocks [ index ] ;
2015-08-11 20:18:08 +00:00
if ( ! block ( bridge , index , RCTNilIfNull ( json ) ) ) {
// Invalid argument , abort
2015-08-18 13:55:25 +00:00
RCTLogArgumentError ( self , index , json ,
"could not be processed. Aborting method call." ) ;
2016-09-05 14:32:20 +00:00
return nil ;
2015-08-11 20:18:08 +00:00
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
index + + ;
}
// Invoke method
2015-08-06 22:44:15 +00:00
[ _invocation invokeWithTarget : module ] ;
2015-10-22 11:02:51 +00:00
RCTAssert (
@ encode ( RCTArgumentBlock ) [ 0 ] = = _C _ID ,
@ "Block type encoding has changed, it won't be released. A check for the block"
"type encoding (%s) has to be added below." ,
@ encode ( RCTArgumentBlock )
) ;
index = 2 ;
for ( NSUInteger length = _invocation . methodSignature . numberOfArguments ; index < length ; index + + ) {
if ( [ _invocation . methodSignature getArgumentTypeAtIndex : index ] [ 0 ] = = _C _ID ) {
__unsafe _unretained id value ;
[ _invocation getArgument : & value atIndex : index ] ;
if ( value ) {
CFRelease ( ( __bridge CFTypeRef ) value ) ;
}
}
}
2016-09-05 14:32:20 +00:00
2017-04-27 18:49:49 +00:00
id result = nil ;
if ( _isSync ) {
void * pointer ;
[ _invocation getReturnValue : & pointer ] ;
result = ( __bridge id ) pointer ;
}
return result ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
}
- ( NSString * ) methodName
{
2015-08-11 15:33:28 +00:00
if ( _selector = = NULL ) {
[ self processMethodSignature ] ;
}
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
return [ NSString stringWithFormat : @ "-[%@ %@]" , _moduleClass ,
NSStringFromSelector ( _selector ) ] ;
}
- ( NSString * ) description
{
2017-04-28 12:32:13 +00:00
return [ NSString stringWithFormat : @ "<%@: %p; exports %@ as %@(); type: %s>" ,
[ self class ] , self , [ self methodName ] , self . JSMethodName , RCTFunctionDescriptorFromType ( self . functionType ) ] ;
[ReactNative] Move module info from bridge to RCTModuleData
Summary:
@public
The info about bridge modules (such as id, name, queue, methods...) was spread
across arrays & dictionaries on the bridge, move it into a specific class.
It also removes a lot of information that was statically cached, and now have
the same lifecycle of the bridge.
Also moved RCTModuleMethod, RCTFrameUpdate and RCTBatchedBridge into it's own
files, for organization sake.
NOTE: This diff seems huge, but most of it was just moving code :)
Test Plan:
Tested UIExplorer & UIExplorer tests, Catalyst, MAdMan and Groups. Everything
looks fine.
2015-06-24 23:34:56 +00:00
}
@ end