mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Refactor: Separate arg conversion from invocation creation
Summary: The old and the new native module system perform method argument conversion very differently: - The TurboModule system converts from JSI Value -> ObjC value. It tries to minimize reliance on RCTConvert. - The legacy NativeModule system is practically built on top of RCTConvert. It relies on runtime type checking to convert between JSI value -> ObjC value. So, this diff pulls arg conversion into its own method. That way we can implement argument conversion differently in the TurboModule interop layer. Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D44850618 fbshipit-source-id: 811d42ed5a78493df9969c546431a4efdf374c0e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
425592399f
commit
d487fdf81b
+8
@@ -90,6 +90,14 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule {
|
||||
const jsi::Value *args,
|
||||
size_t count,
|
||||
NSMutableArray *retainedObjectsForInvocation);
|
||||
void setInvocationArg(
|
||||
jsi::Runtime &runtime,
|
||||
const char *methodName,
|
||||
const std::string &objCArgType,
|
||||
const jsi::Value &arg,
|
||||
size_t i,
|
||||
NSInvocation *inv,
|
||||
NSMutableArray *retainedObjectsForInvocation);
|
||||
id performMethodInvocation(
|
||||
jsi::Runtime &runtime,
|
||||
bool isSync,
|
||||
|
||||
+102
-90
@@ -541,6 +541,106 @@ NSString *ObjCTurboModule::getArgumentTypeName(NSString *methodName, int argInde
|
||||
return nil;
|
||||
}
|
||||
|
||||
void ObjCTurboModule::setInvocationArg(
|
||||
jsi::Runtime &runtime,
|
||||
const char *methodName,
|
||||
const std::string &objCArgType,
|
||||
const jsi::Value &arg,
|
||||
size_t i,
|
||||
NSInvocation *inv,
|
||||
NSMutableArray *retainedObjectsForInvocation)
|
||||
{
|
||||
if (arg.isBool()) {
|
||||
bool v = arg.getBool();
|
||||
|
||||
/**
|
||||
* JS type checking ensures the Objective C argument here is either a BOOL or NSNumber*.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
id objCArg = [NSNumber numberWithBool:v];
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
} else {
|
||||
[inv setArgument:(void *)&v atIndex:i + 2];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg.isNumber()) {
|
||||
double v = arg.getNumber();
|
||||
|
||||
/**
|
||||
* JS type checking ensures the Objective C argument here is either a double or NSNumber*.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
id objCArg = [NSNumber numberWithDouble:v];
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
} else {
|
||||
[inv setArgument:(void *)&v atIndex:i + 2];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert arg to ObjC objects.
|
||||
*/
|
||||
id objCArg = convertJSIValueToObjCObject(runtime, arg, jsInvoker_);
|
||||
if (objCArg) {
|
||||
NSString *methodNameNSString = @(methodName);
|
||||
|
||||
/**
|
||||
* Convert objects using RCTConvert.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
NSString *argumentType = getArgumentTypeName(methodNameNSString, i);
|
||||
if (argumentType != nil) {
|
||||
NSString *rctConvertMethodName = [NSString stringWithFormat:@"%@:", argumentType];
|
||||
SEL rctConvertSelector = NSSelectorFromString(rctConvertMethodName);
|
||||
|
||||
if ([RCTConvert respondsToSelector:rctConvertSelector]) {
|
||||
// Message dispatch logic from old infra
|
||||
id (*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
||||
id convertedObjCArg = convert([RCTConvert class], rctConvertSelector, objCArg);
|
||||
|
||||
[inv setArgument:(void *)&convertedObjCArg atIndex:i + 2];
|
||||
if (convertedObjCArg) {
|
||||
[retainedObjectsForInvocation addObject:convertedObjCArg];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert objects using RCTCxxConvert to structs.
|
||||
*/
|
||||
if ([objCArg isKindOfClass:[NSDictionary class]] && hasMethodArgConversionSelector(methodNameNSString, i)) {
|
||||
SEL methodArgConversionSelector = getMethodArgConversionSelector(methodNameNSString, i);
|
||||
|
||||
// Message dispatch logic from old infra (link:
|
||||
// https://github.com/facebook/react-native/commit/6783694158057662fd7b11fc123c339b2b21bfe6#diff-263fc157dfce55895cdc16495b55d190R350)
|
||||
RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
||||
RCTManagedPointer *box = convert([RCTCxxConvert class], methodArgConversionSelector, objCArg);
|
||||
|
||||
void *pointer = box.voidPointer;
|
||||
[inv setArgument:&pointer atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:box];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert converted args unmodified.
|
||||
*/
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
if (objCArg) {
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
}
|
||||
}
|
||||
|
||||
NSInvocation *ObjCTurboModule::createMethodInvocation(
|
||||
jsi::Runtime &runtime,
|
||||
bool isSync,
|
||||
@@ -566,98 +666,10 @@ NSInvocation *ObjCTurboModule::createMethodInvocation(
|
||||
NSMethodSignature *methodSignature = [[module class] instanceMethodSignatureForSelector:selector];
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const jsi::Value *arg = &args[i];
|
||||
const jsi::Value &arg = args[i];
|
||||
const std::string objCArgType = [methodSignature getArgumentTypeAtIndex:i + 2];
|
||||
|
||||
if (arg->isBool()) {
|
||||
bool v = arg->getBool();
|
||||
|
||||
/**
|
||||
* JS type checking ensures the Objective C argument here is either a BOOL or NSNumber*.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
id objCArg = [NSNumber numberWithBool:v];
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
} else {
|
||||
[inv setArgument:(void *)&v atIndex:i + 2];
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg->isNumber()) {
|
||||
double v = arg->getNumber();
|
||||
|
||||
/**
|
||||
* JS type checking ensures the Objective C argument here is either a double or NSNumber*.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
id objCArg = [NSNumber numberWithDouble:v];
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
} else {
|
||||
[inv setArgument:(void *)&v atIndex:i + 2];
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert arg to ObjC objects.
|
||||
*/
|
||||
id objCArg = convertJSIValueToObjCObject(runtime, *arg, jsInvoker_);
|
||||
if (objCArg) {
|
||||
NSString *methodNameNSString = @(methodName);
|
||||
|
||||
/**
|
||||
* Convert objects using RCTConvert.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
NSString *argumentType = getArgumentTypeName(methodNameNSString, i);
|
||||
if (argumentType != nil) {
|
||||
NSString *rctConvertMethodName = [NSString stringWithFormat:@"%@:", argumentType];
|
||||
SEL rctConvertSelector = NSSelectorFromString(rctConvertMethodName);
|
||||
|
||||
if ([RCTConvert respondsToSelector:rctConvertSelector]) {
|
||||
// Message dispatch logic from old infra
|
||||
id (*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
||||
id convertedObjCArg = convert([RCTConvert class], rctConvertSelector, objCArg);
|
||||
|
||||
[inv setArgument:(void *)&convertedObjCArg atIndex:i + 2];
|
||||
if (convertedObjCArg) {
|
||||
[retainedObjectsForInvocation addObject:convertedObjCArg];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert objects using RCTCxxConvert to structs.
|
||||
*/
|
||||
if ([objCArg isKindOfClass:[NSDictionary class]] && hasMethodArgConversionSelector(methodNameNSString, i)) {
|
||||
SEL methodArgConversionSelector = getMethodArgConversionSelector(methodNameNSString, i);
|
||||
|
||||
// Message dispatch logic from old infra (link:
|
||||
// https://github.com/facebook/react-native/commit/6783694158057662fd7b11fc123c339b2b21bfe6#diff-263fc157dfce55895cdc16495b55d190R350)
|
||||
RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
||||
RCTManagedPointer *box = convert([RCTCxxConvert class], methodArgConversionSelector, objCArg);
|
||||
|
||||
void *pointer = box.voidPointer;
|
||||
[inv setArgument:&pointer atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:box];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert converted args unmodified.
|
||||
*/
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
if (objCArg) {
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
}
|
||||
setInvocationArg(runtime, methodName, objCArgType, arg, i, inv, retainedObjectsForInvocation);
|
||||
}
|
||||
|
||||
if (isSync) {
|
||||
|
||||
Reference in New Issue
Block a user