diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js index 69a59a45389..101b9137c3e 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js @@ -121,7 +121,28 @@ class StructCollector { case 'MixedTypeAnnotation': throw new Error('Mixed types are unsupported in structs'); case 'UnionTypeAnnotation': - throw new Error('Union types are unsupported in structs'); + switch (typeAnnotation.memberType) { + case 'StringTypeAnnotation': + return wrapNullable(nullable, { + type: 'StringTypeAnnotation', + }); + case 'NumberTypeAnnotation': + return wrapNullable(nullable, { + type: 'NumberTypeAnnotation', + }); + case 'ObjectTypeAnnotation': + // This isn't smart enough to actually know how to generate the + // options on the native side. So we just treat it as an unknown object type + return wrapNullable(nullable, { + type: 'GenericObjectTypeAnnotation', + }); + default: + (typeAnnotation.memberType: empty); + throw new Error( + 'Union types are unsupported in structs' + + JSON.stringify(typeAnnotation), + ); + } default: { return wrapNullable(nullable, typeAnnotation); } diff --git a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js index ac9cf2189c7..409ff9cca7b 100644 --- a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js @@ -2575,6 +2575,67 @@ const SAMPLE_WITH_UPPERCASE_NAME: SchemaType = { }, }; +const UNION_MODULE: SchemaType = { + modules: { + NativeSampleTurboModule: { + type: 'NativeModule', + aliasMap: {}, + enumMap: {}, + spec: { + eventEmitters: [], + methods: [ + { + name: 'getUnion', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'UnionTypeAnnotation', + memberType: 'ObjectTypeAnnotation', + }, + params: [ + { + name: 'chooseInt', + optional: false, + typeAnnotation: { + type: 'UnionTypeAnnotation', + memberType: 'NumberTypeAnnotation', + }, + }, + { + name: 'chooseFloat', + optional: false, + typeAnnotation: { + type: 'UnionTypeAnnotation', + memberType: 'NumberTypeAnnotation', + }, + }, + { + name: 'chooseObject', + optional: false, + typeAnnotation: { + type: 'UnionTypeAnnotation', + memberType: 'ObjectTypeAnnotation', + }, + }, + { + name: 'chooseString', + optional: false, + typeAnnotation: { + type: 'UnionTypeAnnotation', + memberType: 'StringTypeAnnotation', + }, + }, + ], + }, + }, + ], + }, + moduleName: 'SampleTurboModule', + }, + }, +}; + module.exports = { complex_objects: COMPLEX_OBJECTS, two_modules_different_files: TWO_MODULES_DIFFERENT_FILES, @@ -2585,4 +2646,5 @@ module.exports = { real_module_example: REAL_MODULE_EXAMPLE, cxx_only_native_modules: CXX_ONLY_NATIVE_MODULES, SampleWithUppercaseName: SAMPLE_WITH_UPPERCASE_NAME, + union_module: UNION_MODULE, }; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap index 8e0045608a7..cefc9c3956a 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap @@ -705,6 +705,42 @@ NativeSampleTurboModule2CxxSpecJSI::NativeSampleTurboModule2CxxSpecJSI(std::shar } +} // namespace facebook::react +", +} +`; + +exports[`GenerateModuleCpp can generate fixture union_module 1`] = ` +Map { + "union_moduleJSI-generated.cpp" => "/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleCpp.js + */ + +#include \\"union_moduleJSI.h\\" + +namespace facebook::react { + +static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getUnion( + rt, + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asNumber(), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt), + count <= 3 ? throw jsi::JSError(rt, \\"Expected argument in position 3 to be passed\\") : args[3].asString(rt) + ); +} + +NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) + : TurboModule(\\"SampleTurboModule\\", jsInvoker) { + methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion}; +} + + } // namespace facebook::react ", } diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index c297d405592..3c559f125a5 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -2412,3 +2412,80 @@ private: ", } `; + +exports[`GenerateModuleH can generate fixture union_module 1`] = ` +Map { + "union_moduleJSI.h" => "/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleH.js + */ + +#pragma once + +#include +#include + +namespace facebook::react { + + + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { +protected: + NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); + +public: + virtual jsi::Object getUnion(jsi::Runtime &rt, double chooseInt, double chooseFloat, jsi::Object chooseObject, jsi::String chooseString) = 0; + +}; + +template +class JSI_EXPORT NativeSampleTurboModuleCxxSpec : public TurboModule { +public: + jsi::Value create(jsi::Runtime &rt, const jsi::PropNameID &propName) override { + return delegate_.create(rt, propName); + } + + std::vector getPropertyNames(jsi::Runtime& runtime) override { + return delegate_.getPropertyNames(runtime); + } + + static constexpr std::string_view kModuleName = \\"SampleTurboModule\\"; + +protected: + NativeSampleTurboModuleCxxSpec(std::shared_ptr jsInvoker) + : TurboModule(std::string{NativeSampleTurboModuleCxxSpec::kModuleName}, jsInvoker), + delegate_(reinterpret_cast(this), jsInvoker) {} + + +private: + class Delegate : public NativeSampleTurboModuleCxxSpecJSI { + public: + Delegate(T *instance, std::shared_ptr jsInvoker) : + NativeSampleTurboModuleCxxSpecJSI(std::move(jsInvoker)), instance_(instance) { + + } + + jsi::Object getUnion(jsi::Runtime &rt, double chooseInt, double chooseFloat, jsi::Object chooseObject, jsi::String chooseString) override { + static_assert( + bridging::getParameterCount(&T::getUnion) == 5, + \\"Expected getUnion(...) to have 5 parameters\\"); + + return bridging::callFromJs( + rt, &T::getUnion, jsInvoker_, instance_, std::move(chooseInt), std::move(chooseFloat), std::move(chooseObject), std::move(chooseString)); + } + + private: + friend class NativeSampleTurboModuleCxxSpec; + T *instance_; + }; + + Delegate delegate_; +}; + +} // namespace facebook::react +", +} +`; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap index 3fafff6f52f..2b68008dc63 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap @@ -1186,3 +1186,71 @@ namespace facebook::react { ", } `; + +exports[`GenerateModuleHObjCpp can generate fixture union_module 1`] = ` +Map { + "union_module.h" => "/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#ifndef __cplusplus +#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm. +#endif + +// Avoid multiple includes of union_module symbols +#ifndef union_module_H +#define union_module_H + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + + +@protocol NativeSampleTurboModuleSpec + +- (NSDictionary *)getUnion:(double)chooseInt + chooseFloat:(double)chooseFloat + chooseObject:(NSDictionary *)chooseObject + chooseString:(NSString *)chooseString; + +@end + +@interface NativeSampleTurboModuleSpecBase : NSObject { +@protected +facebook::react::EventEmitterCallback _eventEmitterCallback; +} +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; + + +@end + +namespace facebook::react { + /** + * ObjC++ class for module 'NativeSampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; +} // namespace facebook::react + +#endif // union_module_H +", +} +`; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap index 4da79695dad..e90a1b00f8f 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap @@ -591,3 +591,48 @@ public abstract class NativeSampleTurboModule2Spec extends ReactContextBaseJavaM ", } `; + +exports[`GenerateModuleJavaSpec can generate fixture union_module 1`] = ` +Map { + "java/com/facebook/fbreact/specs/NativeSampleTurboModuleSpec.java" => " +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJavaSpec.js + * + * @nolint + */ + +package com.facebook.fbreact.specs; + +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import javax.annotation.Nonnull; + +public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule { + public static final String NAME = \\"SampleTurboModule\\"; + + public NativeSampleTurboModuleSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public @Nonnull String getName() { + return NAME; + } + + @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip + public abstract WritableMap getUnion(double chooseInt, double chooseFloat, ReadableMap chooseObject, String chooseString); +} +", +} +`; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap index c929bfd55c5..7990033c5ca 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap @@ -512,3 +512,41 @@ std::shared_ptr two_modules_different_files_ModuleProvider(const st ", } `; + +exports[`GenerateModuleJniCpp can generate fixture union_module 1`] = ` +Map { + "jni/union_module-generated.cpp" => " +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJniCpp.js + */ + +#include \\"union_module.h\\" + +namespace facebook::react { + +static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static jmethodID cachedMethodId = nullptr; + return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, \\"getUnion\\", \\"(DDLcom/facebook/react/bridge/ReadableMap;Ljava/lang/String;)Lcom/facebook/react/bridge/WritableMap;\\", args, count, cachedMethodId); +} + +NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms) + : JavaTurboModule(params) { + methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion}; +} + +std::shared_ptr union_module_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms) { + if (moduleName == \\"SampleTurboModule\\") { + return std::make_shared(params); + } + return nullptr; +} + +} // namespace facebook::react +", +} +`; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap index f656df76b87..9126401fbeb 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniH-test.js.snap @@ -674,3 +674,77 @@ target_compile_options( ", } `; + +exports[`GenerateModuleJniH can generate fixture union_module 1`] = ` +Map { + "jni/union_module.h" => " +/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleJniH.js + */ + +#pragma once + +#include +#include +#include + +namespace facebook::react { + +/** + * JNI C++ class for module 'NativeSampleTurboModule' + */ +class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { +public: + NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); +}; + + +JSI_EXPORT +std::shared_ptr union_module_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms); + +} // namespace facebook::react +", + "jni/CMakeLists.txt" => "# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +file(GLOB react_codegen_SRCS CONFIGURE_DEPENDS *.cpp react/renderer/components/union_module/*.cpp) + +add_library( + react_codegen_union_module + OBJECT + \${react_codegen_SRCS} +) + +target_include_directories(react_codegen_union_module PUBLIC . react/renderer/components/union_module) + +target_link_libraries( + react_codegen_union_module + fbjni + jsi + # We need to link different libraries based on whether we are building rncore or not, that's necessary + # because we want to break a circular dependency between react_codegen_rncore and reactnative + reactnative +) + +target_compile_options( + react_codegen_union_module + PRIVATE + -DLOG_TAG=\\\\\\"ReactNative\\\\\\" + -fexceptions + -frtti + -std=c++20 + -Wall +) +", +} +`; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap index 13be394c79d..656296fd539 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap @@ -700,3 +700,48 @@ namespace facebook::react { ", } `; + +exports[`GenerateModuleMm can generate fixture union_module 1`] = ` +Map { + "union_module-generated.mm" => "/** + * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). + * + * Do not edit this file as changes may cause incorrect behavior and will be lost + * once the code is regenerated. + * + * @generated by codegen project: GenerateModuleObjCpp + * + * We create an umbrella header (and corresponding implementation) here since + * Cxx compilation in BUCK has a limitation: source-code producing genrule()s + * must have a single output. More files => more genrule()s => slower builds. + */ + +#import \\"union_module.h\\" + + +@implementation NativeSampleTurboModuleSpecBase + + +- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper +{ + _eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback); +} +@end + + +namespace facebook::react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getUnion\\", @selector(getUnion:chooseFloat:chooseObject:chooseString:), args, count); + } + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleSpecJSI_getUnion}; + + } +} // namespace facebook::react +", +} +`; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js index 9544c8999ce..8a0b3934810 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/__test_fixtures__/fixtures.js @@ -619,7 +619,35 @@ export interface Spec extends TurboModule { } export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); +`; +const NATIVE_MODULE_WITH_UNION_RETURN_TYPES = ` +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; + +import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +getStringUnion: () => 'light' | 'dark'; + +setStringUnion: (strings: 'light' | 'dark') => void; + + +getNumberUnion: () => 1 | 2; + +setNumberUnion: (numbers: 1 | 2) => void; + + +getObjectUnion: () => {a: 1} | {b: 2}; + +setObjectUnion: (objects: {a: 1} | {b: 2}) => void; +} + +export default (TurboModuleRegistry.get('SampleTurboModule'): ?Spec); `; const NATIVE_MODULE_WITH_EVENT_EMITTERS = ` @@ -854,6 +882,7 @@ module.exports = { NATIVE_MODULE_WITH_BASIC_PARAM_TYPES, NATIVE_MODULE_WITH_CALLBACK, NATIVE_MODULE_WITH_UNION, + NATIVE_MODULE_WITH_UNION_RETURN_TYPES, NATIVE_MODULE_WITH_EVENT_EMITTERS, EMPTY_NATIVE_MODULE, ANDROID_ONLY_NATIVE_MODULE, diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap index be6a7997ced..6580851a5af 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap @@ -2281,6 +2281,120 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNION 1` }" `; +exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNION_RETURN_TYPES 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliasMap': {}, + 'enumMap': {}, + 'spec': { + 'eventEmitters': [], + 'methods': [ + { + 'name': 'getStringUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'StringTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'setStringUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'strings', + 'optional': false, + 'typeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'getNumberUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'NumberTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'setNumberUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'numbers', + 'optional': false, + 'typeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'NumberTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'getObjectUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'ObjectTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'setObjectUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'objects', + 'optional': false, + 'typeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'ObjectTypeAnnotation' + } + } + ] + } + } + ] + }, + 'moduleName': 'SampleTurboModule' + } + } +}" +`; + exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_UNSAFE_OBJECT 1`] = ` "{ 'modules': { diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js index 41495d6dc54..5c28d3955d4 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__test_fixtures__/fixtures.js @@ -725,6 +725,33 @@ export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; +const NATIVE_MODULE_WITH_UNION_RETURN_TYPES = ` +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + readonly getStringUnion: () => 'light' | 'dark'; + readonly setStringUnion: (strings: 'light' | 'dark') => void; + + readonly getNumberUnion: () => 1 | 2; + readonly setNumberUnion: (numbers: 1 | 2) => void; + + readonly getObjectUnion: () => {a: 1} | {b: 2}; + readonly setObjectUnion: (objects: {a: 1} | {b: 2}) => void; +} + +export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); +`; + const NATIVE_MODULE_WITH_EVENT_EMITTERS = ` /** * Copyright (c) Meta Platforms, Inc. and affiliates. @@ -912,6 +939,7 @@ module.exports = { NATIVE_MODULE_WITH_BASIC_PARAM_TYPES, NATIVE_MODULE_WITH_CALLBACK, NATIVE_MODULE_WITH_UNION, + NATIVE_MODULE_WITH_UNION_RETURN_TYPES, NATIVE_MODULE_WITH_EVENT_EMITTERS, EMPTY_NATIVE_MODULE, ANDROID_ONLY_NATIVE_MODULE, diff --git a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap index 8e99438fd9e..0f3cd82c2e5 100644 --- a/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap +++ b/packages/react-native-codegen/src/parsers/typescript/modules/__tests__/__snapshots__/typescript-module-parser-snapshot-test.js.snap @@ -2759,6 +2759,120 @@ exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_UN }" `; +exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_UNION_RETURN_TYPES 1`] = ` +"{ + 'modules': { + 'NativeSampleTurboModule': { + 'type': 'NativeModule', + 'aliasMap': {}, + 'enumMap': {}, + 'spec': { + 'eventEmitters': [], + 'methods': [ + { + 'name': 'getStringUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'StringTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'setStringUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'strings', + 'optional': false, + 'typeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'StringTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'getNumberUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'NumberTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'setNumberUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'numbers', + 'optional': false, + 'typeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'NumberTypeAnnotation' + } + } + ] + } + }, + { + 'name': 'getObjectUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'ObjectTypeAnnotation' + }, + 'params': [] + } + }, + { + 'name': 'setObjectUnion', + 'optional': false, + 'typeAnnotation': { + 'type': 'FunctionTypeAnnotation', + 'returnTypeAnnotation': { + 'type': 'VoidTypeAnnotation' + }, + 'params': [ + { + 'name': 'objects', + 'optional': false, + 'typeAnnotation': { + 'type': 'UnionTypeAnnotation', + 'memberType': 'ObjectTypeAnnotation' + } + } + ] + } + } + ] + }, + 'moduleName': 'SampleTurboModule' + } + } +}" +`; + exports[`RN Codegen TypeScript Parser can generate fixture NATIVE_MODULE_WITH_UNSAFE_OBJECT 1`] = ` "{ 'modules': {