[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 ;
2017-07-24 13:46:01 +00:00
const RCTMethodInfo * _methodInfo ;
NSString * _JSMethodName ;
SEL _selector ;
2015-08-06 22:44:15 +00:00
NSInvocation * _invocation ;
2015-11-03 22:45:46 +00:00
NSArray < RCTArgumentBlock > * _argumentBlocks ;
[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-03 11:37:47 +00:00
static void RCTLogArgumentError ( RCTModuleMethod * method , NSUInteger index ,
id valueOrType , const char * issue )
{
2017-07-24 13:46:01 +00:00
RCTLogError ( @ "Argument %tu (%@) of %@.%s %s" , index , valueOrType ,
2015-08-03 11:37:47 +00:00
RCTBridgeModuleNameForClass ( method -> _moduleClass ) ,
2017-07-24 13:46:01 +00:00
method . JSMethodName , issue ) ;
2015-08-03 11:37:47 +00:00
}
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
2017-07-24 13:46:03 +00:00
# if RCT_DEBUG
static BOOL checkCallbackMultipleInvocations ( 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
}
2017-07-24 13:46:03 +00:00
# endif
2016-12-08 21:31:52 +00:00
2017-07-24 13:46:01 +00:00
SEL RCTParseMethodSignature ( const char * , NSArray < RCTMethodArgument * > * * ) ;
SEL RCTParseMethodSignature ( const char * input , NSArray < RCTMethodArgument * > * * arguments )
2015-12-10 18:09:04 +00:00
{
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
}
2017-07-24 13:46:01 +00:00
- ( instancetype ) initWithExportedMethod : ( const RCTMethodInfo * ) exportedMethod
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 ;
2017-07-24 13:46:01 +00:00
_methodInfo = exportedMethod ;
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 ;
2017-07-24 13:46:01 +00:00
_selector = RCTParseMethodSignature ( _methodInfo -> objcName , & arguments ) ;
RCTAssert ( _selector , @ "%s is not a valid selector" , _methodInfo -> objcName ) ;
[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 ] ;
2017-07-24 13:46:01 +00:00
RCTAssert ( methodSignature , @ "%s is not a recognized Objective-C method." , sel_getName ( _selector ) ) ;
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
2017-07-24 13:46:03 +00:00
# if RCT_DEBUG
__weak RCTModuleMethod * weakSelf = self ;
# endif
2015-08-11 15:33:28 +00:00
# define RCT_ARG _BLOCK ( _logic ) \
[ argumentBlocks addObject : ^ ( __unused RCTBridge * bridge , NSUInteger index , id json ) { \
2017-07-24 13:46:03 +00:00
_logic \
[ invocation setArgument : & value atIndex : ( index ) + 2 ] ; \
return YES ; \
} ]
# define __PRIMITIVE _CASE ( _type , _nullable ) { \
isNullableType = _nullable ; \
_type ( * convert ) ( id , SEL , id ) = ( typeof ( convert ) ) objc_msgSend ; \
RCT_ARG _BLOCK ( _type value = convert ( [ RCTConvert class ] , selector , json ) ; ) ; \
break ; \
}
2015-08-11 15:33:28 +00:00
2017-07-24 13:46:03 +00:00
# define PRIMITIVE_CASE ( _type ) __PRIMITIVE _CASE ( _type , NO )
# define NULLABLE_PRIMITIVE _CASE ( _type ) __PRIMITIVE _CASE ( _type , YES )
2015-10-22 11:02:51 +00:00
2017-07-24 13:46:03 +00:00
// Explicitly copy the block and retain it , since NSInvocation doesn ' t retain them
# define __COPY _BLOCK ( block . . . ) \
id value = [ block copy ] ; \
CFBridgingRetain ( value )
2015-08-11 15:33:28 +00:00
2017-07-24 13:46:03 +00:00
# if RCT_DEBUG
# define BLOCK_CASE ( _block _args , _block ) RCT_ARG _BLOCK ( \
if ( json && ! [ json isKindOfClass : [ NSNumber class ] ] ) { \
RCTLogArgumentError ( weakSelf , index , json , "should be a function" ) ; \
return NO ; \
} \
__block BOOL didInvoke = NO ; \
__COPY _BLOCK ( ^ _block _args { \
if ( checkCallbackMultipleInvocations ( & didInvoke ) ) _block \
} ) ; \
)
# else
# define BLOCK_CASE ( _block _args , _block ) \
RCT_ARG _BLOCK ( __COPY _BLOCK ( ^ _block _args { _block } ) ; )
# endif
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 ] ) {
2017-07-24 13:46:03 +00:00
// Primitives
case _C _CHR : PRIMITIVE_CASE ( char )
case _C _UCHR : PRIMITIVE_CASE ( unsigned char )
case _C _SHT : PRIMITIVE_CASE ( short )
case _C _USHT : PRIMITIVE_CASE ( unsigned short )
case _C _INT : PRIMITIVE_CASE ( int )
case _C _UINT : PRIMITIVE_CASE ( unsigned int )
case _C _LNG : PRIMITIVE_CASE ( long )
case _C _ULNG : PRIMITIVE_CASE ( unsigned long )
case _C _LNG _LNG : PRIMITIVE_CASE ( long long )
case _C _ULNG _LNG : PRIMITIVE_CASE ( unsigned long long )
case _C _FLT : PRIMITIVE_CASE ( float )
case _C _DBL : PRIMITIVE_CASE ( double )
case _C _BOOL : PRIMITIVE_CASE ( BOOL )
case _C _SEL : NULLABLE_PRIMITIVE _CASE ( SEL )
case _C _CHARPTR : NULLABLE_PRIMITIVE _CASE ( const char * )
case _C _PTR : NULLABLE_PRIMITIVE _CASE ( 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 ) ;
2017-07-24 13:46:03 +00:00
) ;
2015-10-22 11:02:51 +00:00
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 : {
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 ) ) {
2017-07-24 13:46:03 +00:00
BLOCK_CASE ( ( NSArray * args ) , {
[ bridge enqueueCallback : json args : args ] ;
} ) ;
2015-08-11 15:33:28 +00:00
} 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" ] ) {
2017-07-24 13:46:03 +00:00
BLOCK_CASE ( ( NSArray * args ) , {
[ bridge enqueueCallback : json args : args ] ;
} ) ;
2015-08-11 15:33:28 +00:00
} else if ( [ typeName isEqualToString : @ "RCTResponseErrorBlock" ] ) {
2017-07-24 13:46:03 +00:00
BLOCK_CASE ( ( NSError * error ) , {
[ bridge enqueueCallback : json args : @ [ RCTJSErrorFromNSError ( error ) ] ] ;
} ) ;
2015-08-11 15:33:28 +00:00
} else if ( [ typeName isEqualToString : @ "RCTPromiseResolveBlock" ] ) {
RCTAssert ( i = = numberOfArguments - 2 ,
2017-07-24 13:46:01 +00:00
@ "The RCTPromiseResolveBlock must be the second to last parameter in %@" ,
[ self methodName ] ) ;
2017-07-24 13:46:03 +00:00
BLOCK_CASE ( ( id result ) , {
[ bridge enqueueCallback : json args : result ? @ [ result ] : @ [ ] ] ;
} ) ;
2015-08-11 15:33:28 +00:00
} else if ( [ typeName isEqualToString : @ "RCTPromiseRejectBlock" ] ) {
RCTAssert ( i = = numberOfArguments - 1 ,
2017-07-24 13:46:01 +00:00
@ "The RCTPromiseRejectBlock must be the last parameter in %@" ,
[ self methodName ] ) ;
2017-07-24 13:46:03 +00:00
BLOCK_CASE ( ( NSString * code , NSString * message , NSError * error ) , {
NSDictionary * errorJSON = RCTJSErrorFromCodeMessageAndNSError ( code , message , error ) ;
[ bridge enqueueCallback : json args : @ [ errorJSON ] ] ;
} ) ;
2015-08-11 15:33:28 +00:00
} else {
// Unknown argument type
2017-07-24 13:46:03 +00:00
RCTLogError ( @ "Unknown argument type '%@' in method %@. Extend RCTConvert to support this type." ,
typeName , [ self methodName ] ) ;
2015-08-11 15:33:28 +00:00
}
2015-07-31 13:55:47 +00:00
2017-07-24 13:46:03 +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-08-11 15:33:28 +00:00
}
2017-07-24 13:46:03 +00:00
nullability = RCTNonnullable ;
}
2015-07-31 13:55:47 +00:00
2017-07-24 13:46:03 +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 ) ;
2015-07-29 12:54:59 +00:00
}
2017-07-24 13:46:03 +00:00
nullability = RCTNonnullable ;
}
[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-07-24 13:46:03 +00:00
if ( nullability = = RCTNonnullable ) {
RCTArgumentBlock oldBlock = argumentBlocks [ i - 2 ] ;
argumentBlocks [ i - 2 ] = ^ ( RCTBridge * bridge , NSUInteger index , id json ) {
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 ) {
2015-10-29 12:13:58 +00:00
return NO ;
}
2015-08-11 15:33:28 +00:00
}
2017-07-24 13:46:03 +00:00
return YES ;
}
RCTLogArgumentError ( weakSelf , index , typeName , "must not be null" ) ;
return NO ;
} ;
2015-08-11 15:33:28 +00:00
}
2017-07-24 13:46:03 +00:00
# endif
[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-07-24 13:46:03 +00:00
# if RCT_DEBUG
const char * objcType = _invocation . methodSignature . methodReturnType ;
if ( _methodInfo -> isSync && objcType [ 0 ] ! = _C _ID ) {
RCTLogError ( @ "Return type of %@.%s should be (id) as the method is \" sync \ "" ,
RCTBridgeModuleNameForClass ( _moduleClass ) , self . JSMethodName ) ;
2017-04-27 18:49:49 +00:00
}
2017-07-24 13:46:03 +00:00
# endif
2017-04-27 18:49:49 +00:00
2017-07-24 13:46:03 +00:00
_argumentBlocks = argumentBlocks ;
2015-08-11 15:33:28 +00:00
}
- ( SEL ) selector
{
if ( _selector = = NULL ) {
2016-09-05 18:11:37 +00:00
RCT_PROFILE _BEGIN _EVENT ( RCTProfileTagAlways , @ "" , ( @ { @ "module" : NSStringFromClass ( _moduleClass ) ,
2017-07-24 13:46:01 +00:00
@ "method" : @ ( _methodInfo -> objcName ) } ) ) ;
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
}
2017-07-24 13:46:01 +00:00
- ( const char * ) JSMethodName
2015-09-18 22:01:21 +00:00
{
2016-09-05 14:32:19 +00:00
NSString * methodName = _JSMethodName ;
2017-07-24 13:46:01 +00:00
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 ) ;
2016-09-05 14:32:19 +00:00
}
2017-07-24 13:46:01 +00:00
_JSMethodName = methodName ;
2016-09-05 14:32:19 +00:00
}
2017-07-24 13:46:01 +00:00
return methodName . UTF8String ;
2016-09-05 14:32:19 +00:00
}
- ( RCTFunctionType ) functionType
{
2017-07-24 13:46:01 +00:00
if ( strstr ( _methodInfo -> objcName , "RCTPromise" ) ! = NULL ) {
RCTAssert ( ! _methodInfo -> isSync , @ "Promises cannot be used in sync functions" ) ;
2016-09-05 14:32:19 +00:00
return RCTFunctionTypePromise ;
2017-07-24 13:46:01 +00:00
} else if ( _methodInfo -> isSync ) {
2017-04-27 18:49:49 +00:00
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 ] ;
}
2017-07-24 13:46:03 +00:00
# if RCT_DEBUG
// Sanity check
RCTAssert ( [ module class ] = = _moduleClass , @ " Attempted to invoke method \
% @ on a module of class % @ " , [ self methodName ] , [ module class ] ) ;
[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-07-24 13:46:03 +00:00
// Safety check
if ( arguments . count ! = _argumentBlocks . count ) {
NSInteger actualCount = arguments . count ;
NSInteger expectedCount = _argumentBlocks . count ;
[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-07-24 13:46:03 +00:00
// Subtract the implicit Promise resolver and rejecter functions for implementations of async functions
if ( self . functionType = = RCTFunctionTypePromise ) {
actualCount - = 2 ;
expectedCount - = 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
}
2017-07-24 13:46:03 +00:00
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 ) , self . JSMethodName ,
actualCount , expectedCount ) ;
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
}
2017-07-24 13:46:03 +00:00
# endif
[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
2017-07-24 13:46:03 +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-07-24 13:46:01 +00:00
if ( _methodInfo -> isSync ) {
2017-07-24 13:46:03 +00:00
void * returnValue ;
[ _invocation getReturnValue : & returnValue ] ;
return ( __bridge id ) returnValue ;
2017-04-27 18:49:49 +00:00
}
2017-07-24 13:46:03 +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
}
- ( NSString * ) methodName
{
2017-07-24 13:46:03 +00:00
if ( ! _selector ) {
2015-08-11 15:33:28 +00:00
[ self processMethodSignature ] ;
}
2017-07-24 13:46:01 +00:00
return [ NSString stringWithFormat : @ "-[%@ %s]" , _moduleClass , sel_getName ( _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
}
- ( NSString * ) description
{
2017-07-24 13:46:01 +00:00
return [ NSString stringWithFormat : @ "<%@: %p; exports %@ as %s(); type: %s>" ,
2017-04-28 12:32:13 +00:00
[ 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