Support optional return types
Summary: This fixes an issue in the C++ TurboModule codegen where optional return types would result in a compiler error because they were not being defaulted to `null` when converting to `jsi::Value`. Changelog: Internal Reviewed By: javache Differential Revision: D36989312 fbshipit-source-id: 525f9ce7a5638ba5a655fa69ba9647978030ab0b
This commit is contained in:
Родитель
47bd78f64f
Коммит
68e4e91bd4
|
@ -50,6 +50,27 @@ T callFromJs(
|
|||
rt, fromJs<Args>(rt, std::forward<JSArgs>(args), jsInvoker)...),
|
||||
jsInvoker);
|
||||
|
||||
} else if constexpr (is_optional_v<T>) {
|
||||
static_assert(
|
||||
is_optional_v<R>
|
||||
? supportsToJs<typename R::value_type, typename T::value_type>
|
||||
: supportsToJs<R, typename T::value_type>,
|
||||
"Incompatible return type");
|
||||
|
||||
auto result = toJs(
|
||||
rt,
|
||||
(instance->*method)(
|
||||
rt, fromJs<Args>(rt, std::forward<JSArgs>(args), jsInvoker)...),
|
||||
jsInvoker);
|
||||
|
||||
if constexpr (std::is_same_v<decltype(result), jsi::Value>) {
|
||||
if (result.isNull() || result.isUndefined()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return convert(rt, std::move(result));
|
||||
|
||||
} else {
|
||||
static_assert(std::is_convertible_v<R, T>, "Incompatible return type");
|
||||
|
||||
|
|
|
@ -24,6 +24,15 @@ inline constexpr bool is_jsi_v =
|
|||
std::is_same_v<jsi::String, remove_cvref_t<T>> ||
|
||||
std::is_base_of_v<jsi::Object, remove_cvref_t<T>>;
|
||||
|
||||
template <typename>
|
||||
struct is_optional : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_optional<std::optional<T>> : std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_optional_v = is_optional<T>::value;
|
||||
|
||||
template <typename T>
|
||||
struct Converter;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import type {
|
|||
NativeModulePropertyShape,
|
||||
NativeModuleFunctionTypeAnnotation,
|
||||
NativeModuleParamTypeAnnotation,
|
||||
NativeModuleTypeAnnotation,
|
||||
} from '../../CodegenSchema';
|
||||
|
||||
import type {AliasResolver} from './Utils';
|
||||
|
@ -28,21 +29,33 @@ type FilesOutput = Map<string, string>;
|
|||
const HostFunctionTemplate = ({
|
||||
hasteModuleName,
|
||||
methodName,
|
||||
isVoid,
|
||||
returnTypeAnnotation,
|
||||
args,
|
||||
}: $ReadOnly<{
|
||||
hasteModuleName: string,
|
||||
methodName: string,
|
||||
isVoid: boolean,
|
||||
returnTypeAnnotation: Nullable<NativeModuleTypeAnnotation>,
|
||||
args: Array<string>,
|
||||
}>) => {
|
||||
const isNullable = returnTypeAnnotation.type === 'NullableTypeAnnotation';
|
||||
const isVoid = returnTypeAnnotation.type === 'VoidTypeAnnotation';
|
||||
const methodCallArgs = ['rt', ...args].join(', ');
|
||||
const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs});`;
|
||||
const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs})`;
|
||||
|
||||
return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${
|
||||
isVoid ? `\n ${methodCall}` : ''
|
||||
isVoid
|
||||
? `\n ${methodCall};`
|
||||
: isNullable
|
||||
? `\n auto result = ${methodCall};`
|
||||
: ''
|
||||
}
|
||||
return ${isVoid ? 'jsi::Value::undefined();' : methodCall}
|
||||
return ${
|
||||
isVoid
|
||||
? 'jsi::Value::undefined()'
|
||||
: isNullable
|
||||
? 'result ? jsi::Value(std::move(*result)) : jsi::Value::null()'
|
||||
: methodCall
|
||||
};
|
||||
}`;
|
||||
};
|
||||
|
||||
|
@ -173,13 +186,11 @@ function serializePropertyIntoHostFunction(
|
|||
): string {
|
||||
const [propertyTypeAnnotation] =
|
||||
unwrapNullable<NativeModuleFunctionTypeAnnotation>(property.typeAnnotation);
|
||||
const isVoid =
|
||||
propertyTypeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation';
|
||||
|
||||
return HostFunctionTemplate({
|
||||
hasteModuleName,
|
||||
methodName: property.name,
|
||||
isVoid,
|
||||
returnTypeAnnotation: propertyTypeAnnotation.returnTypeAnnotation,
|
||||
args: propertyTypeAnnotation.params.map((p, i) =>
|
||||
serializeArg(p, i, resolveAlias),
|
||||
),
|
||||
|
|
|
@ -62,13 +62,16 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArrays(jsi
|
|||
return jsi::Value::undefined();
|
||||
}
|
||||
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
||||
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableObject(rt);
|
||||
auto result = static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableObject(rt);
|
||||
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
|
||||
}
|
||||
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableGenericObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
||||
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableGenericObject(rt);
|
||||
auto result = static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableGenericObject(rt);
|
||||
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
|
||||
}
|
||||
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
||||
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableArray(rt);
|
||||
auto result = static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableArray(rt);
|
||||
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
|
||||
}
|
||||
|
||||
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
|
@ -109,7 +112,8 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getMixed(jsi:
|
|||
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getMixed(rt, jsi::Value(rt, args[0]));
|
||||
}
|
||||
static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableNumberFromNullableAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
||||
return static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableNumberFromNullableAlias(rt, args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)));
|
||||
auto result = static_cast<NativeSampleTurboModuleCxxSpecJSI *>(&turboModule)->getNullableNumberFromNullableAlias(rt, args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)));
|
||||
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
|
||||
}
|
||||
|
||||
NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
|
||||
|
|
Загрузка…
Ссылка в новой задаче