diff --git a/.flowconfig b/.flowconfig index edd3fc461862b4..c8b28fb8c86800 100644 --- a/.flowconfig +++ b/.flowconfig @@ -75,4 +75,4 @@ untyped-import untyped-type-import [version] -^0.134.0 +^0.135.0 diff --git a/.flowconfig.android b/.flowconfig.android index 63d4ec5bcecaaa..8008aacbad5243 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -75,4 +75,4 @@ untyped-import untyped-type-import [version] -^0.134.0 +^0.135.0 diff --git a/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js b/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js index bac74826a1fb11..d01757865909fc 100644 --- a/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js +++ b/Libraries/Components/Picker/AndroidDialogPickerNativeComponent.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow strict-local + * @flow */ 'use strict'; @@ -14,6 +14,8 @@ import * as React from 'react'; import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; import requireNativeComponent from '../../ReactNative/requireNativeComponent'; +import registerGeneratedViewConfig from '../../Utilities/registerGeneratedViewConfig'; +import AndroidDialogPickerViewConfig from './AndroidDialogPickerViewConfig'; import type { DirectEventHandler, @@ -64,6 +66,17 @@ export const Commands: NativeCommands = codegenNativeCommands({ supportedCommands: ['setNativeSelectedPosition'], }); -export default (requireNativeComponent( - 'AndroidDialogPicker', -): NativeType); +let AndroidDialogPickerNativeComponent; +if (global.RN$Bridgeless) { + registerGeneratedViewConfig( + 'AndroidDialogPicker', + AndroidDialogPickerViewConfig, + ); + AndroidDialogPickerNativeComponent = 'AndroidDialogPicker'; +} else { + AndroidDialogPickerNativeComponent = requireNativeComponent( + 'AndroidDialogPicker', + ); +} + +export default ((AndroidDialogPickerNativeComponent: any): NativeType); diff --git a/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js b/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js new file mode 100644 index 00000000000000..1108b8105e37e1 --- /dev/null +++ b/Libraries/Components/Picker/AndroidDialogPickerViewConfig.js @@ -0,0 +1,30 @@ +/** + * Copyright (c) Facebook, Inc. and its 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-local + * @format + */ + +'use strict'; + +import type {GeneratedViewConfig} from '../../Utilities/registerGeneratedViewConfig'; + +const AndroidDialogPickerViewConfig = { + uiViewClassName: 'AndroidDialogPicker', + bubblingEventTypes: {}, + directEventTypes: {}, + validAttributes: { + color: {process: require('../../StyleSheet/processColor')}, + backgroundColor: {process: require('../../StyleSheet/processColor')}, + enabled: true, + items: true, + prompt: true, + selected: true, + onSelect: true, + }, +}; + +module.exports = (AndroidDialogPickerViewConfig: GeneratedViewConfig); diff --git a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm index 1f7227f478f872..5ca05feb84cd38 100644 --- a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm +++ b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm @@ -1610,46 +1610,72 @@ + (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenSelectDialogConfig:(id)js } // namespace react } // namespace facebook -@implementation RCTCxxConvert (NativeImageStore_SpecAddImageFromBase64ErrorCallbackError) -+ (RCTManagedPointer *)JS_NativeImageStore_SpecAddImageFromBase64ErrorCallbackError:(id)json +namespace facebook { + namespace react { + + + static facebook::jsi::Value __hostFunction_NativeImageStoreAndroidSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getBase64ForTag", @selector(getBase64ForTag:successCallback:errorCallback:), args, count); + } + + + NativeImageStoreAndroidSpecJSI::NativeImageStoreAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreAndroidSpecJSI_getBase64ForTag}; + + + + } + + } // namespace react +} // namespace facebook +@implementation RCTCxxConvert (NativeImageStoreIOS_SpecGetBase64ForTagErrorCallbackError) ++ (RCTManagedPointer *)JS_NativeImageStoreIOS_SpecGetBase64ForTagErrorCallbackError:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +@implementation RCTCxxConvert (NativeImageStoreIOS_SpecAddImageFromBase64ErrorCallbackError) ++ (RCTManagedPointer *)JS_NativeImageStoreIOS_SpecAddImageFromBase64ErrorCallbackError:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end namespace facebook { namespace react { - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static facebook::jsi::Value __hostFunction_NativeImageStoreIOSSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "getBase64ForTag", @selector(getBase64ForTag:successCallback:errorCallback:), args, count); } - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_hasImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static facebook::jsi::Value __hostFunction_NativeImageStoreIOSSpecJSI_hasImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "hasImageForTag", @selector(hasImageForTag:callback:), args, count); } - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_removeImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static facebook::jsi::Value __hostFunction_NativeImageStoreIOSSpecJSI_removeImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "removeImageForTag", @selector(removeImageForTag:), args, count); } - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static facebook::jsi::Value __hostFunction_NativeImageStoreIOSSpecJSI_addImageFromBase64(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, "addImageFromBase64", @selector(addImageFromBase64:successCallback:errorCallback:), args, count); } - NativeImageStoreSpecJSI::NativeImageStoreSpecJSI(const ObjCTurboModule::InitParams ¶ms) + NativeImageStoreIOSSpecJSI::NativeImageStoreIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag}; + methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreIOSSpecJSI_getBase64ForTag}; - methodMap_["hasImageForTag"] = MethodMetadata {2, __hostFunction_NativeImageStoreSpecJSI_hasImageForTag}; + methodMap_["hasImageForTag"] = MethodMetadata {2, __hostFunction_NativeImageStoreIOSSpecJSI_hasImageForTag}; - methodMap_["removeImageForTag"] = MethodMetadata {1, __hostFunction_NativeImageStoreSpecJSI_removeImageForTag}; + methodMap_["removeImageForTag"] = MethodMetadata {1, __hostFunction_NativeImageStoreIOSSpecJSI_removeImageForTag}; - methodMap_["addImageFromBase64"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64}; + methodMap_["addImageFromBase64"] = MethodMetadata {3, __hostFunction_NativeImageStoreIOSSpecJSI_addImageFromBase64}; diff --git a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h index 6a2b084f362e9c..91f0c7ebbf56cf 100644 --- a/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h +++ b/Libraries/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h @@ -1525,9 +1525,45 @@ namespace facebook { }; } // namespace react } // namespace facebook +@protocol NativeImageStoreAndroidSpec + +- (void)getBase64ForTag:(NSString *)uri + successCallback:(RCTResponseSenderBlock)successCallback + errorCallback:(RCTResponseSenderBlock)errorCallback; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'ImageStoreAndroid' + */ + + class JSI_EXPORT NativeImageStoreAndroidSpecJSI : public ObjCTurboModule { + public: + NativeImageStoreAndroidSpecJSI(const ObjCTurboModule::InitParams ¶ms); + + }; + } // namespace react +} // namespace facebook namespace JS { - namespace NativeImageStore { + namespace NativeImageStoreIOS { + struct SpecGetBase64ForTagErrorCallbackError { + NSString *message() const; + + SpecGetBase64ForTagErrorCallbackError(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeImageStoreIOS_SpecGetBase64ForTagErrorCallbackError) ++ (RCTManagedPointer *)JS_NativeImageStoreIOS_SpecGetBase64ForTagErrorCallbackError:(id)json; +@end + +namespace JS { + namespace NativeImageStoreIOS { struct SpecAddImageFromBase64ErrorCallbackError { NSString *message() const; @@ -1538,10 +1574,10 @@ namespace JS { } } -@interface RCTCxxConvert (NativeImageStore_SpecAddImageFromBase64ErrorCallbackError) -+ (RCTManagedPointer *)JS_NativeImageStore_SpecAddImageFromBase64ErrorCallbackError:(id)json; +@interface RCTCxxConvert (NativeImageStoreIOS_SpecAddImageFromBase64ErrorCallbackError) ++ (RCTManagedPointer *)JS_NativeImageStoreIOS_SpecAddImageFromBase64ErrorCallbackError:(id)json; @end -@protocol NativeImageStoreSpec +@protocol NativeImageStoreIOSSpec - (void)getBase64ForTag:(NSString *)uri successCallback:(RCTResponseSenderBlock)successCallback @@ -1557,12 +1593,12 @@ namespace JS { namespace facebook { namespace react { /** - * ObjC++ class for module 'ImageStore' + * ObjC++ class for module 'ImageStoreIOS' */ - class JSI_EXPORT NativeImageStoreSpecJSI : public ObjCTurboModule { + class JSI_EXPORT NativeImageStoreIOSSpecJSI : public ObjCTurboModule { public: - NativeImageStoreSpecJSI(const ObjCTurboModule::InitParams ¶ms); + NativeImageStoreIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; } // namespace react @@ -3298,7 +3334,12 @@ inline bool JS::NativeImagePickerIOS::SpecOpenSelectDialogConfig::showVideos() c id const p = _v[@"showVideos"]; return RCTBridgingToBool(p); } -inline NSString *JS::NativeImageStore::SpecAddImageFromBase64ErrorCallbackError::message() const +inline NSString *JS::NativeImageStoreIOS::SpecGetBase64ForTagErrorCallbackError::message() const +{ + id const p = _v[@"message"]; + return RCTBridgingToString(p); +} +inline NSString *JS::NativeImageStoreIOS::SpecAddImageFromBase64ErrorCallbackError::message() const { id const p = _v[@"message"]; return RCTBridgingToString(p); diff --git a/Libraries/Image/NativeImageStoreAndroid.js b/Libraries/Image/NativeImageStoreAndroid.js new file mode 100644 index 00000000000000..8ab6dc7c1a2315 --- /dev/null +++ b/Libraries/Image/NativeImageStoreAndroid.js @@ -0,0 +1,27 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +import type {TurboModule} from '../TurboModule/RCTExport'; +import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +getConstants: () => {||}; + +getBase64ForTag: ( + uri: string, + successCallback: (base64ImageData: string) => void, + errorCallback: (error: string) => void, + ) => void; +} + +export default (TurboModuleRegistry.getEnforcing( + 'ImageStoreManager', +): Spec); diff --git a/Libraries/Image/NativeImageStore.js b/Libraries/Image/NativeImageStoreIOS.js similarity index 75% rename from Libraries/Image/NativeImageStore.js rename to Libraries/Image/NativeImageStoreIOS.js index 38603b6aaab2cf..d94f1ef4f35095 100644 --- a/Libraries/Image/NativeImageStore.js +++ b/Libraries/Image/NativeImageStoreIOS.js @@ -15,21 +15,11 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; export interface Spec extends TurboModule { +getConstants: () => {||}; - // Common +getBase64ForTag: ( uri: string, successCallback: (base64ImageData: string) => void, - - /** - * On Android, the failure callback is called with a string. - * On iOS, the failure callback is called with an error object. - * - * TODO(T47527939) Unify this inconsistency - */ - errorCallback: (error: {|message: string|} | string) => void, + errorCallback: (error: {|message: string|}) => void, ) => void; - - // iOS-only +hasImageForTag: (uri: string, callback: (hasImage: boolean) => void) => void; +removeImageForTag: (uri: string) => void; +addImageFromBase64: ( diff --git a/Libraries/Image/RCTImageLoader.mm b/Libraries/Image/RCTImageLoader.mm index 0ea5a4a0c988f9..723b64dbe6184b 100644 --- a/Libraries/Image/RCTImageLoader.mm +++ b/Libraries/Image/RCTImageLoader.mm @@ -831,19 +831,6 @@ - (NSString *)loaderModuleNameForRequestUrl:(NSURL *)url { return nil; } -- (void)trackURLImageContentDidSetForRequest:(RCTImageURLLoaderRequest *)loaderRequest -{ - if (!loaderRequest) { - return; - } - - // This delegate method is Fabric-only - id loadHandler = [self imageURLLoaderForURL:loaderRequest.imageURL]; - if ([loadHandler respondsToSelector:@selector(trackURLImageContentDidSetForRequest:)]) { - [(id)loadHandler trackURLImageContentDidSetForRequest:loaderRequest]; - } -} - - (void)trackURLImageVisibilityForRequest:(RCTImageURLLoaderRequest *)loaderRequest imageView:(UIView *)imageView { if (!loaderRequest || !imageView) { diff --git a/Libraries/Image/RCTImageLoaderWithAttributionProtocol.h b/Libraries/Image/RCTImageLoaderWithAttributionProtocol.h index bd26221531b8a4..44f4ee849a4a75 100644 --- a/Libraries/Image/RCTImageLoaderWithAttributionProtocol.h +++ b/Libraries/Image/RCTImageLoaderWithAttributionProtocol.h @@ -36,11 +36,6 @@ RCT_EXTERN void RCTEnableImageLoadingPerfInstrumentation(BOOL enabled); completionBlock:(RCTImageLoaderCompletionBlockWithMetadata)completionBlock; #endif -/** - * Image instrumentation - notify that the image content (UIImage) has been set on the native view. - */ -- (void)trackURLImageContentDidSetForRequest:(RCTImageURLLoaderRequest *)loaderRequest; - /** * Image instrumentation - start tracking the on-screen visibility of the native image view. */ diff --git a/Libraries/Image/RCTImageStoreManager.mm b/Libraries/Image/RCTImageStoreManager.mm index 907ecbbb6b0871..7eb3b1e91cc3d5 100644 --- a/Libraries/Image/RCTImageStoreManager.mm +++ b/Libraries/Image/RCTImageStoreManager.mm @@ -22,7 +22,7 @@ static NSString *const RCTImageStoreURLScheme = @"rct-image-store"; -@interface RCTImageStoreManager() +@interface RCTImageStoreManager() @end @implementation RCTImageStoreManager @@ -236,7 +236,7 @@ - (void)getImageForTag:(NSString *)imageTag withBlock:(void (^)(UIImage *image)) - (std::shared_ptr)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params { - return std::make_shared(params); + return std::make_shared(params); } @end diff --git a/Libraries/Image/RCTImageURLLoaderWithAttribution.h b/Libraries/Image/RCTImageURLLoaderWithAttribution.h index b05ebfba8adfdf..4013367b4d3c63 100644 --- a/Libraries/Image/RCTImageURLLoaderWithAttribution.h +++ b/Libraries/Image/RCTImageURLLoaderWithAttribution.h @@ -59,11 +59,6 @@ struct ImageURLLoaderAttribution { completionHandler:(RCTImageLoaderCompletionBlockWithMetadata)completionHandler; #endif -/** - * Image instrumentation - notify that the image content (UIImage) has been set on the native view. - */ -- (void)trackURLImageContentDidSetForRequest:(RCTImageURLLoaderRequest *)loaderRequest; - /** * Image instrumentation - start tracking the on-screen visibility of the native image view. */ diff --git a/Libraries/Interaction/PanResponder.js b/Libraries/Interaction/PanResponder.js index 1aaf9fce9ecaee..4106597cb6d40c 100644 --- a/Libraries/Interaction/PanResponder.js +++ b/Libraries/Interaction/PanResponder.js @@ -121,7 +121,7 @@ const currentCentroidY = TouchHistoryMath.currentCentroidY; * ### Working Example * * To see it in action, try the - * [PanResponder example in RNTester](https://github.com/facebook/react-native/blob/master/RNTester/js/PanResponderExample.js) + * [PanResponder example in RNTester](https://github.com/facebook/react-native/blob/master/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js) */ export type GestureState = {| diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.m b/Libraries/Text/TextInput/RCTBaseTextInputView.m index 01ab7f19d12267..e8b87f333ddcec 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -365,11 +365,13 @@ - (BOOL)textInputShouldReturn // `onSubmitEditing` is called when "Submit" button // (the blue key on onscreen keyboard) did pressed // (no connection to any specific "submitting" process). - [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit - reactTag:self.reactTag - text:[self.backedTextInputView.attributedText.string copy] - key:nil - eventCount:_nativeEventCount]; + if (_blurOnSubmit) { + [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit + reactTag:self.reactTag + text:[self.backedTextInputView.attributedText.string copy] + key:nil + eventCount:_nativeEventCount]; + } return _blurOnSubmit; } diff --git a/Libraries/TypeSafety/RCTConvertHelpers.h b/Libraries/TypeSafety/RCTConvertHelpers.h index 1b6bf9341e7a86..0b7144b9c8ea2d 100644 --- a/Libraries/TypeSafety/RCTConvertHelpers.h +++ b/Libraries/TypeSafety/RCTConvertHelpers.h @@ -49,6 +49,7 @@ NSArray *RCTConvertOptionalVecToArray(const folly::Optional &vec) bool RCTBridgingToBool(id value); folly::Optional RCTBridgingToOptionalBool(id value); NSString *RCTBridgingToString(id value); +NSString *RCTBridgingToOptionalString(id value); folly::Optional RCTBridgingToOptionalDouble(id value); double RCTBridgingToDouble(id value); NSArray *RCTBridgingToArray(id value); diff --git a/Libraries/TypeSafety/RCTConvertHelpers.mm b/Libraries/TypeSafety/RCTConvertHelpers.mm index 69fb3e4a3de4f4..cd79c41f6fece4 100644 --- a/Libraries/TypeSafety/RCTConvertHelpers.mm +++ b/Libraries/TypeSafety/RCTConvertHelpers.mm @@ -27,6 +27,12 @@ bool RCTBridgingToBool(id value) return [RCTConvert NSString:RCTNilIfNull(value)]; } +NSString *RCTBridgingToOptionalString(id value) +{ + return RCTBridgingToString(value); +} + + folly::Optional RCTBridgingToOptionalDouble(id value) { if (!RCTNilIfNull(value)) { diff --git a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index ce8e55c0229fb6..09dd599650f026 100644 --- a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -13,9 +13,7 @@ #import #import #import -#import #import -#import #import using namespace facebook::react; @@ -160,11 +158,6 @@ - (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(voi if (!data.hasValue()) { return; } - auto instrumentation = std::static_pointer_cast( - data.value().getImageRequest().getSharedImageInstrumentation()); - if (instrumentation) { - instrumentation->didSetImage(); - } }; if (imageProps.blurRadius > __FLT_EPSILON__) { diff --git a/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm b/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm index 54061f535d79ee..dc852ff001da6d 100644 --- a/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm +++ b/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm @@ -56,20 +56,6 @@ - (BOOL)prefersStatusBarHidden return [RCTSharedApplication() isStatusBarHidden]; } -- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)())completion -{ - UIView *snapshot = [self.view snapshotViewAfterScreenUpdates:NO]; - [self.view addSubview:snapshot]; - - [super dismissViewControllerAnimated:flag - completion:^{ - [snapshot removeFromSuperview]; - if (completion) { - completion(); - } - }]; -} - #if RCT_DEV - (UIInterfaceOrientationMask)supportedInterfaceOrientations { diff --git a/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h b/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h index 16fbdfb9624ab7..b61196c4c57b0a 100644 --- a/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h +++ b/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.h @@ -5,12 +5,13 @@ * LICENSE file in the root directory of this source tree. */ +#import #import /** * UIView class for root component. */ -@interface RCTModalHostViewComponentView : RCTViewComponentView +@interface RCTModalHostViewComponentView : RCTViewComponentView /** * Subclasses may override this method and present the modal on different view controller. diff --git a/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm index 65f2f6ce266300..01648dd2f423d9 100644 --- a/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm @@ -101,6 +101,7 @@ @implementation RCTModalHostViewComponentView { ModalHostViewShadowNode::ConcreteStateTeller _stateTeller; BOOL _shouldAnimatePresentation; BOOL _isPresented; + UIView *_modalContentsSnapshot; } - (instancetype)initWithFrame:(CGRect)frame @@ -161,10 +162,22 @@ - (void)ensurePresentedOnlyIfNeeded BOOL shouldBeHidden = _isPresented && !self.superview; if (shouldBeHidden) { _isPresented = NO; + // To animate dismissal of view controller, snapshot of + // view hierarchy needs to be added to the UIViewController. + [self.viewController.view addSubview:_modalContentsSnapshot]; [self dismissViewController:self.viewController animated:_shouldAnimatePresentation]; } } +#pragma mark - RCTMountingTransactionObserving + +- (void)mountingTransactionWillMountWithMetadata:(MountingTransactionMetadata const &)metadata +{ + _modalContentsSnapshot = [self.viewController.view snapshotViewAfterScreenUpdates:NO]; +} + +#pragma mark - UIView methods + - (void)didMoveToWindow { [super didMoveToWindow]; diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 859b4582980e8a..848e26d2678584 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -498,16 +498,15 @@ - (void)_remountChildren visibleFrame.size.width *= scale; visibleFrame.size.height *= scale; +#ifndef NDEBUG + NSMutableArray *> *expectedSubviews = [NSMutableArray new]; +#endif + NSInteger mountedIndex = 0; for (UIView *componentView in _childComponentViews) { BOOL shouldBeMounted = YES; BOOL isMounted = componentView.superview != nil; - // If a view is mounted, it must be mounted exactly at `mountedIndex` position. - RCTAssert( - !isMounted || [_containerView.subviews objectAtIndex:mountedIndex] == componentView, - @"Attempt to unmount improperly mounted component view."); - // It's simpler and faster to not mess with views that are not `RCTViewComponentView` subclasses. if ([componentView isKindOfClass:[RCTViewComponentView class]]) { RCTViewComponentView *viewComponentView = (RCTViewComponentView *)componentView; @@ -529,7 +528,24 @@ - (void)_remountChildren if (shouldBeMounted) { mountedIndex++; } + +#ifndef NDEBUG + if (shouldBeMounted) { + [expectedSubviews addObject:componentView]; + } +#endif + } + +#ifndef NDEBUG + RCTAssert( + _containerView.subviews.count == expectedSubviews.count, + @"-[RCTScrollViewComponentView _remountChildren]: Inconsistency detected."); + for (NSInteger i = 0; i < expectedSubviews.count; i++) { + RCTAssert( + [_containerView.subviews objectAtIndex:i] == [expectedSubviews objectAtIndex:i], + @"-[RCTScrollViewComponentView _remountChildren]: Inconsistency detected."); } +#endif } #pragma mark - RCTScrollableProtocol diff --git a/React/Views/RCTDatePicker.m b/React/Views/RCTDatePicker.m index 9fee82b3cfffc2..064191b3e8aa1c 100644 --- a/React/Views/RCTDatePicker.m +++ b/React/Views/RCTDatePicker.m @@ -14,11 +14,11 @@ #import "UIView+React.h" #ifndef __IPHONE_14_0 - #define __IPHONE_14_0 140000 +#define __IPHONE_14_0 140000 #endif // __IPHONE_14_0 #ifndef RCT_IOS_14_0_SDK_OR_LATER - #define RCT_IOS_14_0_SDK_OR_LATER (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0) +#define RCT_IOS_14_0_SDK_OR_LATER (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0) #endif // RCT_IOS_14_0_SDK_OR_LATER @interface RCTDatePicker () diff --git a/ReactAndroid/Android-prebuilt.mk b/ReactAndroid/Android-prebuilt.mk index 4a4fb45ee1ff5b..394032a524ab95 100644 --- a/ReactAndroid/Android-prebuilt.mk +++ b/ReactAndroid/Android-prebuilt.mk @@ -24,7 +24,7 @@ REACT_ANDROID_SRC_DIR := $(REACT_ANDROID_DIR)/src/main REACT_COMMON_DIR := $(REACT_ANDROID_DIR)/../ReactCommon REACT_GENERATED_SRC_DIR := $(REACT_ANDROID_BUILD_DIR)/generated/source # Note: this only have .so, not .a -REACT_NDK_EXPORT_DIR := $(REACT_ANDROID_BUILD_DIR)/react-ndk/exported +REACT_NDK_EXPORT_DIR := $(PROJECT_BUILD_DIR)/react-ndk/exported # fb include $(CLEAR_VARS) diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 04ef27362cf6fc..766e22770f7b6c 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -7,7 +7,7 @@ POM_PACKAGING=aar MOCKITO_CORE_VERSION=2.26.0 POWERMOCK_VERSION=2.0.2 -ROBOLECTRIC_VERSION=4.3.1 +ROBOLECTRIC_VERSION=4.4 JUNIT_VERSION=4.12 FEST_ASSERT_CORE_VERSION=2.0M10 diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreAndroidSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreAndroidSpec.java new file mode 100644 index 00000000000000..f3c53ac8544ac5 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreAndroidSpec.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + * + *

Generated by an internal genrule from Flow types. + * + * @generated + * @nolint + */ + +package com.facebook.fbreact.specs; + +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReactModuleWithSpec; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; + +public abstract class NativeImageStoreAndroidSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { + public NativeImageStoreAndroidSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @ReactMethod + public abstract void getBase64ForTag(String uri, Callback successCallback, + Callback errorCallback); +} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreIOSSpec.java b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreIOSSpec.java new file mode 100644 index 00000000000000..10455469ccec72 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/NativeImageStoreIOSSpec.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + * + *

Generated by an internal genrule from Flow types. + * + * @generated + * @nolint + */ + +package com.facebook.fbreact.specs; + +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReactModuleWithSpec; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; + +public abstract class NativeImageStoreIOSSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { + public NativeImageStoreIOSSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @ReactMethod + public abstract void addImageFromBase64(String base64ImageData, Callback successCallback, + Callback errorCallback); + + @ReactMethod + public abstract void getBase64ForTag(String uri, Callback successCallback, + Callback errorCallback); + + @ReactMethod + public abstract void hasImageForTag(String uri, Callback callback); + + @ReactMethod + public abstract void removeImageForTag(String uri); +} diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec-generated.cpp b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec-generated.cpp index 85c52d7e79592a..e8fdde414ba7d9 100644 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec-generated.cpp +++ b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec-generated.cpp @@ -1416,36 +1416,56 @@ namespace facebook { namespace react { - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static facebook::jsi::Value __hostFunction_NativeImageStoreAndroidSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getBase64ForTag", "(Ljava/lang/String;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); } - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_hasImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + + NativeImageStoreAndroidSpecJSI::NativeImageStoreAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms) + : JavaTurboModule(params) { + + methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreAndroidSpecJSI_getBase64ForTag}; + + + + } + + } // namespace react +} // namespace facebook +namespace facebook { + namespace react { + + + static facebook::jsi::Value __hostFunction_NativeImageStoreIOSSpecJSI_getBase64ForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "getBase64ForTag", "(Ljava/lang/String;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); + } + + static facebook::jsi::Value __hostFunction_NativeImageStoreIOSSpecJSI_hasImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "hasImageForTag", "(Ljava/lang/String;Lcom/facebook/react/bridge/Callback;)V", args, count); } - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_removeImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static facebook::jsi::Value __hostFunction_NativeImageStoreIOSSpecJSI_removeImageForTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "removeImageForTag", "(Ljava/lang/String;)V", args, count); } - static facebook::jsi::Value __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static facebook::jsi::Value __hostFunction_NativeImageStoreIOSSpecJSI_addImageFromBase64(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, "addImageFromBase64", "(Ljava/lang/String;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V", args, count); } - NativeImageStoreSpecJSI::NativeImageStoreSpecJSI(const JavaTurboModule::InitParams ¶ms) + NativeImageStoreIOSSpecJSI::NativeImageStoreIOSSpecJSI(const JavaTurboModule::InitParams ¶ms) : JavaTurboModule(params) { - methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_getBase64ForTag}; + methodMap_["getBase64ForTag"] = MethodMetadata {3, __hostFunction_NativeImageStoreIOSSpecJSI_getBase64ForTag}; - methodMap_["hasImageForTag"] = MethodMetadata {2, __hostFunction_NativeImageStoreSpecJSI_hasImageForTag}; + methodMap_["hasImageForTag"] = MethodMetadata {2, __hostFunction_NativeImageStoreIOSSpecJSI_hasImageForTag}; - methodMap_["removeImageForTag"] = MethodMetadata {1, __hostFunction_NativeImageStoreSpecJSI_removeImageForTag}; + methodMap_["removeImageForTag"] = MethodMetadata {1, __hostFunction_NativeImageStoreIOSSpecJSI_removeImageForTag}; - methodMap_["addImageFromBase64"] = MethodMetadata {3, __hostFunction_NativeImageStoreSpecJSI_addImageFromBase64}; + methodMap_["addImageFromBase64"] = MethodMetadata {3, __hostFunction_NativeImageStoreIOSSpecJSI_addImageFromBase64}; diff --git a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec.h b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec.h index 940c22e2f62c94..49f97cc402c4d2 100644 --- a/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec.h +++ b/ReactAndroid/src/main/java/com/facebook/fbreact/specs/jni/FBReactNativeSpec.h @@ -440,12 +440,26 @@ namespace facebook { namespace facebook { namespace react { /** - * C++ class for module 'ImageStore' + * C++ class for module 'ImageStoreAndroid' */ - class JSI_EXPORT NativeImageStoreSpecJSI : public JavaTurboModule { + class JSI_EXPORT NativeImageStoreAndroidSpecJSI : public JavaTurboModule { public: - NativeImageStoreSpecJSI(const JavaTurboModule::InitParams ¶ms); + NativeImageStoreAndroidSpecJSI(const JavaTurboModule::InitParams ¶ms); + + }; + } // namespace react +} // namespace facebook + +namespace facebook { + namespace react { + /** + * C++ class for module 'ImageStoreIOS' + */ + + class JSI_EXPORT NativeImageStoreIOSSpecJSI : public JavaTurboModule { + public: + NativeImageStoreIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); }; } // namespace react diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java index 6ff40bda0ffb18..632f57af48fa38 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java @@ -63,9 +63,9 @@ public MountingManager(@NonNull ViewManagerRegistry viewManagerRegistry) { mViewManagerRegistry = viewManagerRegistry; } - private static void logViewHierarchy(ViewGroup parent) { + private static void logViewHierarchy(ViewGroup parent, boolean recurse) { int parentTag = parent.getId(); - FLog.e(TAG, " "); + FLog.e(TAG, " "); for (int i = 0; i < parent.getChildCount(); i++) { FLog.e( TAG, @@ -73,11 +73,24 @@ private static void logViewHierarchy(ViewGroup parent) { + i + " tag=" + parent.getChildAt(i).getId() - + " toString=" - + parent.getChildAt(i).toString() + + " class=" + + parent.getChildAt(i).getClass().toString() + ">"); } FLog.e(TAG, " "); + + if (recurse) { + FLog.e(TAG, "Displaying Ancestors:"); + ViewParent ancestor = parent.getParent(); + while (ancestor != null) { + ViewGroup ancestorViewGroup = (ancestor instanceof ViewGroup ? (ViewGroup) ancestor : null); + int ancestorId = ancestorViewGroup == null ? View.NO_ID : ancestorViewGroup.getId(); + FLog.e( + TAG, + ""); + ancestor = ancestor.getParent(); + } + } } /** @@ -218,7 +231,7 @@ public void addViewAt(final int parentTag, final int tag, final int index) { // Display children before inserting if (SHOW_CHANGED_VIEW_HIERARCHIES) { FLog.e(TAG, "addViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " BEFORE"); - logViewHierarchy(parentView); + logViewHierarchy(parentView, false); } try { @@ -243,7 +256,7 @@ public void addViewAt(final int parentTag, final int tag, final int index) { public void run() { FLog.e( TAG, "addViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " AFTER"); - logViewHierarchy(parentView); + logViewHierarchy(parentView, false); } }); } @@ -359,7 +372,7 @@ public void removeViewAt(final int tag, final int parentTag, final int index) { if (SHOW_CHANGED_VIEW_HIERARCHIES) { // Display children before deleting any FLog.e(TAG, "removeViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " BEFORE"); - logViewHierarchy(parentView); + logViewHierarchy(parentView, false); } ViewGroupManager viewGroupManager = getViewGroupManager(viewState); @@ -398,6 +411,7 @@ public void removeViewAt(final int tag, final int parentTag, final int index) { return; } + logViewHierarchy(parentView, true); throw new IllegalStateException( "Tried to remove view [" + tag @@ -431,6 +445,8 @@ public void removeViewAt(final int tag, final int parentTag, final int index) { // enough that we shouldn't try to change this invariant, without a lot of thought. int childCount = viewGroupManager.getChildCount(parentView); + logViewHierarchy(parentView, true); + throw new IllegalStateException( "Cannot remove child at index " + index @@ -451,7 +467,7 @@ public void run() { FLog.e( TAG, "removeViewAt: [" + tag + "] -> [" + parentTag + "] idx: " + index + " AFTER"); - logViewHierarchy(parentView); + logViewHierarchy(parentView, false); } }); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/ImageStoreManager.java b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/ImageStoreManager.java index 8bf377cfb4cc13..0752be6e554cae 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/camera/ImageStoreManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/camera/ImageStoreManager.java @@ -12,7 +12,7 @@ import android.os.AsyncTask; import android.util.Base64; import android.util.Base64OutputStream; -import com.facebook.fbreact.specs.NativeImageStoreSpec; +import com.facebook.fbreact.specs.NativeImageStoreAndroidSpec; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.GuardedAsyncTask; import com.facebook.react.bridge.ReactApplicationContext; @@ -25,7 +25,7 @@ import java.io.InputStream; @ReactModule(name = ImageStoreManager.NAME) -public class ImageStoreManager extends NativeImageStoreSpec { +public class ImageStoreManager extends NativeImageStoreAndroidSpec { public static final String NAME = "ImageStoreManager"; private static final int BUFFER_SIZE = 8192; @@ -105,20 +105,4 @@ private static void closeQuietly(Closeable closeable) { // shhh } } - - @Override - public void hasImageForTag(String uri, Callback callback) { - // iOS only - } - - @Override - public void removeImageForTag(String uri) { - // iOS only - } - - @Override - public void addImageFromBase64( - String base64ImageData, Callback successCallback, Callback errorCallback) { - // iOS only - } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java index e5c42e059905e6..ffc46232aa9994 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/picker/ReactPickerManager.java @@ -13,7 +13,7 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.EventDispatcher; @@ -62,13 +62,9 @@ protected void onAfterUpdateTransaction(ReactPicker view) { @Override protected void addEventEmitters(final ThemedReactContext reactContext, final ReactPicker picker) { - UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class); - - if (uiManager == null) { - return; - } - - picker.setOnSelectListener(new PickerEventEmitter(picker, uiManager.getEventDispatcher())); + picker.setOnSelectListener( + new PickerEventEmitter( + picker, UIManagerHelper.getEventDispatcherForReactTag(reactContext, picker.getId()))); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 61b1a712332a5d..b632671b712b6c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -266,6 +266,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { int scrollToY = pendingContentOffsetY != UNSET_CONTENT_OFFSET ? pendingContentOffsetY : getScrollY(); reactScrollTo(scrollToX, scrollToY); + ReactScrollViewHelper.emitLayoutEvent(this); } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 6497c6bce989b2..118579c886f109 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -223,6 +223,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { int scrollToY = pendingContentOffsetY != UNSET_CONTENT_OFFSET ? pendingContentOffsetY : getScrollY(); reactScrollTo(scrollToX, scrollToY); + ReactScrollViewHelper.emitLayoutEvent(this); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java index 5183f24c44bd80..c10a38ebdb02aa 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java @@ -14,6 +14,8 @@ import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReactContext; import com.facebook.react.uimanager.UIManagerHelper; +import java.util.ArrayList; +import java.util.List; /** Helper class that deals with emitting Scroll Events. */ public class ReactScrollViewHelper { @@ -23,6 +25,16 @@ public class ReactScrollViewHelper { public static final String AUTO = "auto"; public static final String OVER_SCROLL_NEVER = "never"; + public interface ScrollListener { + void onScroll( + ViewGroup scrollView, ScrollEventType scrollEventType, float xVelocity, float yVelocity); + + void onLayout(ViewGroup scrollView); + } + + // Support global native listeners for scroll events + private static List sScrollListeners = new ArrayList<>(); + // If all else fails, this is the hardcoded value in OverScroller.java, in AOSP. // The default is defined here (as of this diff): // https://android.googlesource.com/platform/frameworks/base/+/ae5bcf23b5f0875e455790d6af387184dbd009c1/core/java/android/widget/OverScroller.java#44 @@ -64,6 +76,10 @@ private static void emitScrollEvent( return; } + for (ScrollListener scrollListener : sScrollListeners) { + scrollListener.onScroll(scrollView, scrollEventType, xVelocity, yVelocity); + } + ReactContext reactContext = (ReactContext) scrollView.getContext(); UIManagerHelper.getEventDispatcherForReactTag(reactContext, scrollView.getId()) .dispatchEvent( @@ -80,6 +96,13 @@ private static void emitScrollEvent( scrollView.getHeight())); } + /** This is only for Java listeners. onLayout events emitted to JS are handled elsewhere. */ + public static void emitLayoutEvent(ViewGroup scrollView) { + for (ScrollListener scrollListener : sScrollListeners) { + scrollListener.onLayout(scrollView); + } + } + public static int parseOverScrollMode(String jsOverScrollMode) { if (jsOverScrollMode == null || jsOverScrollMode.equals(AUTO)) { return View.OVER_SCROLL_IF_CONTENT_SCROLLS; @@ -130,4 +153,12 @@ public void startScroll(int startX, int startY, int dx, int dy, int duration) { mScrollAnimationDuration = duration; } } + + public static void addScrollListener(ScrollListener listener) { + sScrollListeners.add(listener); + } + + public static void removeScrollListener(ScrollListener listener) { + sScrollListeners.remove(listener); + } } diff --git a/ReactAndroid/src/main/third-party/java/robolectric/4.3.1/BUCK b/ReactAndroid/src/main/third-party/java/robolectric/4.4/BUCK similarity index 80% rename from ReactAndroid/src/main/third-party/java/robolectric/4.3.1/BUCK rename to ReactAndroid/src/main/third-party/java/robolectric/4.4/BUCK index aeca8ed4f5bd3a..9033f5b0ce9705 100644 --- a/ReactAndroid/src/main/third-party/java/robolectric/4.3.1/BUCK +++ b/ReactAndroid/src/main/third-party/java/robolectric/4.4/BUCK @@ -56,8 +56,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "bouncycastle-binary.jar", - sha1 = "2507204241ab450456bdb8e8c0a8f986e418bd99", - url = "mvn:org.bouncycastle:bcprov-jdk15on:jar:1.59", + sha1 = "320b989112f00a63a3bcfa5a98f31a4f865a20fa", + url = "mvn:org.bouncycastle:bcprov-jdk15on:jar:1.65", ) rn_prebuilt_jar( @@ -79,8 +79,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4.jar", - sha1 = "66e4550b96285eadcb5a45a21ad6fbe8842fa960", - url = "mvn:org.robolectric:robolectric:jar:4.3", + sha1 = "418c5bfae392fdbf71cd463a42a3e8c3b839a924", + url = "mvn:org.robolectric:robolectric:jar:4.4", ) rn_prebuilt_jar( @@ -90,8 +90,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-annotations.jar", - sha1 = "3db63d633be908a18db18615b594f824c034ae6d", - url = "mvn:org.robolectric:annotations:jar:4.3", + sha1 = "70fc5b1699467dfd7de606fc6c02ff9fc1816d9f", + url = "mvn:org.robolectric:annotations:jar:4.4", ) rn_prebuilt_jar( @@ -101,8 +101,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-junit.jar", - sha1 = "fcafc9942e8748c8bab832b022672ca21808c492", - url = "mvn:org.robolectric:junit:jar:4.3", + sha1 = "fbcda51d8e6f3a3897ae5cedc7aa481815745290", + url = "mvn:org.robolectric:junit:jar:4.4", ) rn_prebuilt_jar( @@ -112,8 +112,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-pluginapi.jar", - sha1 = "128acea3aed3bbe36f8fde865f3a26b920237718", - url = "mvn:org.robolectric:pluginapi:jar:4.3", + sha1 = "1ee94260f8c51620a35eac33fc1efc01350c751f", + url = "mvn:org.robolectric:pluginapi:jar:4.4", ) rn_prebuilt_jar( @@ -123,8 +123,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-plugins-maven-dependency-resolver.jar", - sha1 = "b1ea126cb80dbba0c2947be9234bbe2877ce2a09", - url = "mvn:org.robolectric:plugins-maven-dependency-resolver:jar:4.3", + sha1 = "9241a3c4bd01627447c76d9b67614808c78ffdd9", + url = "mvn:org.robolectric:plugins-maven-dependency-resolver:jar:4.4", ) rn_prebuilt_jar( @@ -134,8 +134,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-resources.jar", - sha1 = "e40030b0f6808ca378bd2c803713157ee4287ea0", - url = "mvn:org.robolectric:resources:jar:4.3", + sha1 = "a2ee1324bcb62724e6cbfa655bdb5683948a554c", + url = "mvn:org.robolectric:resources:jar:4.4", ) rn_prebuilt_jar( @@ -145,8 +145,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-sandbox.jar", - sha1 = "2302e406aebab5f6843dbf6c2f21952fa86ec26f", - url = "mvn:org.robolectric:sandbox:jar:4.3", + sha1 = "03cedd73c5aedaf79fb9a593552816c9fb3282f2", + url = "mvn:org.robolectric:sandbox:jar:4.4", ) rn_prebuilt_jar( @@ -156,8 +156,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-shadowapi.jar", - sha1 = "81dfcf4a45b623b7744e46358d01c7ce054d0fff", - url = "mvn:org.robolectric:shadowapi:jar:4.3", + sha1 = "529649474b53cf8f6f4a483044ade43aebed8a4c", + url = "mvn:org.robolectric:shadowapi:jar:4.4", ) rn_prebuilt_jar( @@ -167,8 +167,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-shadows-framework.jar", - sha1 = "150103d5732c432906f6130b734e7452855dd67b", - url = "mvn:org.robolectric:shadows-framework:jar:4.3", + sha1 = "90028766e71353ad6f57d7bcb56ac0d861da18c3", + url = "mvn:org.robolectric:shadows-framework:jar:4.4", ) rn_prebuilt_jar( @@ -178,8 +178,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-utils.jar", - sha1 = "97b0331b67d0e1dc8bf50e570b6feb017f62aed1", - url = "mvn:org.robolectric:utils:jar:4.3", + sha1 = "c54b2638d64e7bd4e1e45c4fe8038305402bd711", + url = "mvn:org.robolectric:utils:jar:4.4", ) rn_prebuilt_jar( @@ -189,8 +189,8 @@ rn_prebuilt_jar( fb_native.remote_file( name = "robolectric4-utils-reflector.jar", - sha1 = "3428887d068b66e33026ac533ae4647355167658", - url = "mvn:org.robolectric:utils-reflector:jar:4.3", + sha1 = "44c40ac0d2ef1e7c8b0f6c4e224ef26d356170f1", + url = "mvn:org.robolectric:utils-reflector:jar:4.4", ) rn_prebuilt_jar( diff --git a/ReactAndroid/src/test/java/com/facebook/react/bridge/BUCK b/ReactAndroid/src/test/java/com/facebook/react/bridge/BUCK index 2721f9cb923f4a..c774e197673e51 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/bridge/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/bridge/BUCK @@ -15,7 +15,7 @@ rn_android_library( ], deps = [ react_native_android_toplevel_dep("third-party/java/mockito2:mockito2"), - react_native_dep("third-party/java/robolectric/4.3.1:robolectric"), + react_native_dep("third-party/java/robolectric/4.4:robolectric"), react_native_target("java/com/facebook/react/bridge:bridge"), react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_tests_target("java/org/mockito/configuration:configuration"), diff --git a/ReactCommon/ReactCommon.podspec b/ReactCommon/ReactCommon.podspec index 0c083cf2d5b133..c49fbd8c2c5459 100644 --- a/ReactCommon/ReactCommon.podspec +++ b/ReactCommon/ReactCommon.podspec @@ -54,7 +54,7 @@ Pod::Spec.new do |s| end ss.subspec "samples" do |sss| - sss.source_files = "react/nativemodule/samples/*.{cpp,h}", + sss.source_files = "react/nativemodule/samples/ReactCommon/**/*.{cpp,h}", "react/nativemodule/samples/platform/ios/**/*.{mm,cpp,h}" sss.dependency "ReactCommon/turbomodule/core", version end diff --git a/ReactCommon/hermes/inspector/tools/msggen/.babelrc b/ReactCommon/hermes/inspector/tools/msggen/.babelrc index b96eb4c692e218..8ad6d5109ddf39 100644 --- a/ReactCommon/hermes/inspector/tools/msggen/.babelrc +++ b/ReactCommon/hermes/inspector/tools/msggen/.babelrc @@ -5,5 +5,4 @@ } }] ], - "plugins": ["idx"] } diff --git a/ReactCommon/hermes/inspector/tools/msggen/package.json b/ReactCommon/hermes/inspector/tools/msggen/package.json index 8ee113ea68d624..bcd465c61e42eb 100644 --- a/ReactCommon/hermes/inspector/tools/msggen/package.json +++ b/ReactCommon/hermes/inspector/tools/msggen/package.json @@ -33,7 +33,6 @@ }, "dependencies": { "devtools-protocol": "0.0.730699", - "idx": "^2.1.0", "yargs": "^14.2.0" } } diff --git a/ReactCommon/hermes/inspector/tools/msggen/yarn.lock b/ReactCommon/hermes/inspector/tools/msggen/yarn.lock index cf4d9eaa94aa58..47b1dacda9373d 100644 --- a/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +++ b/ReactCommon/hermes/inspector/tools/msggen/yarn.lock @@ -2519,11 +2519,6 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -idx@^2.1.0: - version "2.5.6" - resolved "https://registry.yarnpkg.com/idx/-/idx-2.5.6.tgz#1f824595070100ae9ad585c86db08dc74f83a59d" - integrity sha512-WFXLF7JgPytbMgelpRY46nHz5tyDcedJ76pLV+RJWdb8h33bxFq4bdZau38DhNSzk5eVniBf1K3jwfK+Lb5nYA== - ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" diff --git a/ReactCommon/react/nativemodule/samples/BUCK b/ReactCommon/react/nativemodule/samples/BUCK index c760c2f06218ab..b6b0fe3b974e52 100644 --- a/ReactCommon/react/nativemodule/samples/BUCK +++ b/ReactCommon/react/nativemodule/samples/BUCK @@ -1,13 +1,15 @@ load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags") -load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob") +load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "FBJNI_TARGET", "react_native_dep", "react_native_target", "react_native_xplat_target", "rn_android_library", "rn_xplat_cxx_library", "subdir_glob") rn_xplat_cxx_library( name = "samples", - srcs = glob(["*.cpp"]), + srcs = glob( + ["ReactCommon/**/*.cpp"], + ), header_namespace = "", exported_headers = subdir_glob( [ - ("", "*.h"), + ("ReactCommon", "*.h"), ], prefix = "ReactCommon", ), @@ -19,10 +21,11 @@ rn_xplat_cxx_library( ], fbandroid_deps = [ react_native_target("jni/react/jni:jni"), + FBJNI_TARGET, ], fbandroid_exported_headers = subdir_glob( [ - ("platform/android", "*.h"), + ("platform/android/ReactCommon", "*.h"), ], prefix = "ReactCommon", ), @@ -78,3 +81,24 @@ rn_xplat_cxx_library( react_native_xplat_target("react/nativemodule/core:core"), ], ) + +rn_android_library( + name = "impl", + srcs = glob(["platform/android/*.java"]), + required_for_source_only_abi = True, + visibility = [ + "PUBLIC", + ], + deps = [ + "//fbandroid/java/com/facebook/debug/log:log", + react_native_dep("third-party/java/jsr-305:jsr-305"), + react_native_dep("third-party/java/jsr-330:jsr-330"), + react_native_target("java/com/facebook/react/bridge:bridge"), + react_native_target("java/com/facebook/react/common:common"), + react_native_target("java/com/facebook/react/module/annotations:annotations"), + ":samples", + ], + exported_deps = [ + react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), + ], +) diff --git a/ReactCommon/react/nativemodule/samples/NativeSampleTurboCxxModuleSpecJSI.cpp b/ReactCommon/react/nativemodule/samples/ReactCommon/NativeSampleTurboCxxModuleSpecJSI.cpp similarity index 100% rename from ReactCommon/react/nativemodule/samples/NativeSampleTurboCxxModuleSpecJSI.cpp rename to ReactCommon/react/nativemodule/samples/ReactCommon/NativeSampleTurboCxxModuleSpecJSI.cpp diff --git a/ReactCommon/react/nativemodule/samples/NativeSampleTurboCxxModuleSpecJSI.h b/ReactCommon/react/nativemodule/samples/ReactCommon/NativeSampleTurboCxxModuleSpecJSI.h similarity index 100% rename from ReactCommon/react/nativemodule/samples/NativeSampleTurboCxxModuleSpecJSI.h rename to ReactCommon/react/nativemodule/samples/ReactCommon/NativeSampleTurboCxxModuleSpecJSI.h diff --git a/ReactCommon/react/nativemodule/samples/SampleTurboCxxModule.cpp b/ReactCommon/react/nativemodule/samples/ReactCommon/SampleTurboCxxModule.cpp similarity index 100% rename from ReactCommon/react/nativemodule/samples/SampleTurboCxxModule.cpp rename to ReactCommon/react/nativemodule/samples/ReactCommon/SampleTurboCxxModule.cpp diff --git a/ReactCommon/react/nativemodule/samples/SampleTurboCxxModule.h b/ReactCommon/react/nativemodule/samples/ReactCommon/SampleTurboCxxModule.h similarity index 100% rename from ReactCommon/react/nativemodule/samples/SampleTurboCxxModule.h rename to ReactCommon/react/nativemodule/samples/ReactCommon/SampleTurboCxxModule.h diff --git a/ReactCommon/react/nativemodule/samples/platform/android/Android.mk b/ReactCommon/react/nativemodule/samples/platform/android/Android.mk new file mode 100644 index 00000000000000..46dfd7623ae029 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/Android.mk @@ -0,0 +1,18 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := sampleturbomodule +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/ReactCommon/*.cpp) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) +LOCAL_SHARED_LIBRARIES := libfbjni libreact_nativemodule_core +LOCAL_CFLAGS := \ + -DLOG_TAG=\"ReactNative\" +LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall + +include $(BUILD_STATIC_LIBRARY) diff --git a/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java b/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java new file mode 100644 index 00000000000000..8475fbc4711299 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// NOTE: This entire file should be codegen'ed. + +package com.facebook.fbreact.specs; + +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReactModuleWithSpec; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.common.build.ReactBuildConfig; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule + implements ReactModuleWithSpec, TurboModule { + public NativeSampleTurboModuleSpec(ReactApplicationContext reactContext) { + super(reactContext); + } + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract double getNumber(double arg); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract WritableMap getValue(double x, String y, ReadableMap z); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract WritableMap getObject(ReadableMap arg); + + @ReactMethod + public abstract void voidFunc(); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract WritableArray getArray(ReadableArray arg); + + @ReactMethod + public abstract void getValueWithPromise(boolean error, Promise promise); + + @ReactMethod + public abstract void getValueWithCallback(Callback callback); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract String getString(String arg); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract double getRootTag(double arg); + + @ReactMethod(isBlockingSynchronousMethod = true) + public abstract boolean getBool(boolean arg); + + protected abstract Map getTypedExportedConstants(); + + @Override + public final @Nullable Map getConstants() { + Map constants = getTypedExportedConstants(); + if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) { + Set obligatoryFlowConstants = + new HashSet<>(Arrays.asList("const2", "const1", "const3")); + Set optionalFlowConstants = new HashSet<>(); + Set undeclaredConstants = new HashSet<>(constants.keySet()); + undeclaredConstants.removeAll(obligatoryFlowConstants); + undeclaredConstants.removeAll(optionalFlowConstants); + if (!undeclaredConstants.isEmpty()) { + throw new IllegalStateException( + String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants)); + } + undeclaredConstants = obligatoryFlowConstants; + undeclaredConstants.removeAll(constants.keySet()); + if (!undeclaredConstants.isEmpty()) { + throw new IllegalStateException( + String.format("Native Module doesn't fill in constants: %s", undeclaredConstants)); + } + } + return constants; + } +} diff --git a/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp b/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp new file mode 100644 index 00000000000000..676a79ee5e76c0 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// NOTE: This entire file should be codegen'ed. + +#include + +namespace facebook { +namespace react { + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod(rt, VoidKind, "voidFunc", "()V", args, count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getBool( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod(rt, BooleanKind, "getBool", "(Z)Z", args, count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getNumber( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod(rt, NumberKind, "getNumber", "(D)D", args, count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getString( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + StringKind, + "getString", + "(Ljava/lang/String;)Ljava/lang/String;", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getArray( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + ArrayKind, + "getArray", + "(Lcom/facebook/react/bridge/ReadableArray;)Lcom/facebook/react/bridge/WritableArray;", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getObject( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + ObjectKind, + "getObject", + "(Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod(rt, NumberKind, "getRootTag", "(D)D", args, count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getValue( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + ObjectKind, + "getValue", + "(DLjava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + VoidKind, + "getValueWithCallback", + "(Lcom/facebook/react/bridge/Callback;)V", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, + PromiseKind, + "getValueWithPromise", + "(ZLcom/facebook/react/bridge/Promise;)V", + args, + count); +} + +static facebook::jsi::Value +__hostFunction_NativeSampleTurboModuleSpecJSI_getConstants( + facebook::jsi::Runtime &rt, + TurboModule &turboModule, + const facebook::jsi::Value *args, + size_t count) { + return static_cast(turboModule) + .invokeJavaMethod( + rt, ObjectKind, "getConstants", "()Ljava/util/Map;", args, count); +} + +NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI( + const JavaTurboModule::InitParams ¶ms) + : JavaTurboModule(params) { + methodMap_["voidFunc"] = + MethodMetadata{0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + methodMap_["getBool"] = + MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; + + methodMap_["getNumber"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; + + methodMap_["getString"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; + + methodMap_["getArray"] = + MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; + + methodMap_["getObject"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; + + methodMap_["getRootTag"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; + + methodMap_["getValue"] = + MethodMetadata{3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + + methodMap_["getValueWithCallback"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; + + methodMap_["getValueWithPromise"] = MethodMetadata{ + 1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + + methodMap_["getConstants"] = MethodMetadata{ + 0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; +} + +std::shared_ptr SampleTurboModuleSpec_ModuleProvider( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms) { + if (moduleName == "SampleTurboModule") { + return std::make_shared(params); + } + return nullptr; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.h b/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.h new file mode 100644 index 00000000000000..6baefae6d890d9 --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/ReactCommon/SampleTurboModuleSpec.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// NOTE: This entire file should be codegen'ed. + +#pragma once + +#include +#include +#include + +namespace facebook { +namespace react { + +/** + * C++ class for module 'SampleTurboModule' + */ +class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public JavaTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const JavaTurboModule::InitParams ¶ms); +}; + +std::shared_ptr SampleTurboModuleSpec_ModuleProvider( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms); + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java b/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java new file mode 100644 index 00000000000000..bc357d2baa3d9b --- /dev/null +++ b/ReactCommon/react/nativemodule/samples/platform/android/SampleTurboModule.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.fbreact.specs; + +import android.app.Activity; +import android.util.DisplayMetrics; +import android.widget.Toast; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Callback; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeArray; +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.common.MapBuilder; +import com.facebook.react.module.annotations.ReactModule; +import java.util.HashMap; +import java.util.Map; + +@ReactModule(name = SampleTurboModule.NAME) +public class SampleTurboModule extends NativeSampleTurboModuleSpec { + + public static final String NAME = "SampleTurboModule"; + + private static final String TAG = SampleTurboModule.class.getName(); + private final ReactApplicationContext mContext; + private Toast mToast; + + public SampleTurboModule(ReactApplicationContext context) { + super(context); + mContext = context; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public boolean getBool(boolean arg) { + log("getBool", arg, arg); + return arg; + } + + @Override + protected Map getTypedExportedConstants() { + Map result = new HashMap<>(); + DisplayMetrics displayMetrics = new DisplayMetrics(); + Activity activity = mContext.getCurrentActivity(); + if (activity != null) { + activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + result.put("const2", displayMetrics.widthPixels); + } + result.put("const1", true); + result.put("const3", "something"); + log("constantsToExport", "", result); + return result; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public double getNumber(double arg) { + log("getNumber", arg, arg); + return arg; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public String getString(String arg) { + log("getString", arg, arg); + return arg; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public double getRootTag(double arg) { + log("getRootTag", arg, arg); + return arg; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public void voidFunc() { + log("voidFunc", "", ""); + return; + } + + // This function returns {@link WritableMap} instead of {@link Map} for backward compat with + // existing native modules that use this Writable* as return types or in events. {@link + // WritableMap} is modified in the Java side, and read (or consumed) on the C++ side. + // In the future, all native modules should ideally return an immutable Map + @DoNotStrip + @Override + @SuppressWarnings("unused") + public WritableMap getObject(ReadableMap arg) { + WritableNativeMap map = new WritableNativeMap(); + map.merge(arg); + log("getObject", arg, map); + return map; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public WritableMap getValue(double numberArg, String stringArg, ReadableMap mapArg) { + WritableMap map = new WritableNativeMap(); + map.putDouble("x", numberArg); + map.putString("y", stringArg); + WritableMap zMap = new WritableNativeMap(); + zMap.merge(mapArg); + map.putMap("z", zMap); + log( + "getValue", + MapBuilder.of("1-numberArg", numberArg, "2-stringArg", stringArg, "3-mapArg", mapArg), + map); + return map; + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public void getValueWithCallback(final Callback callback) { + String result = "Value From Callback"; + log("Callback", "Return Time", result); + callback.invoke(result); + } + + @DoNotStrip + @SuppressWarnings("unused") + @Override + public WritableArray getArray(ReadableArray arg) { + if (arg == null || Arguments.toList(arg) == null) { + // Returning an empty array, since the super class always returns non-null + return new WritableNativeArray(); + } + WritableArray result = Arguments.makeNativeArray(Arguments.toList(arg)); + log("getArray", arg, result); + return result; + } + + @Override + @DoNotStrip + @SuppressWarnings("unused") + public void getValueWithPromise(boolean error, Promise promise) { + if (error) { + promise.reject( + "code 1", + "intentional promise rejection", + new Throwable("promise intentionally rejected")); + } else { + promise.resolve("result"); + } + } + + private void log(String method, Object input, Object output) { + if (mToast != null) { + mToast.cancel(); + } + StringBuilder message = new StringBuilder("Method :"); + message + .append(method) + .append("\nInputs: ") + .append(input.toString()) + .append("\nOutputs: ") + .append(output.toString()); + mToast = Toast.makeText(mContext, message.toString(), Toast.LENGTH_LONG); + mToast.show(); + } + + public void invalidate() {} + + @Override + public String getName() { + return NAME; + } +} diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h index e6aba6e3c07bcd..891d25d46d11ea 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h @@ -308,6 +308,14 @@ static inline bool shouldFirstComeBeforeSecondMutation( return true; } + // Update comes last, before deletes + if (rhs.type == ShadowViewMutation::Type::Update) { + return true; + } + if (lhs.type == ShadowViewMutation::Type::Update) { + return false; + } + // Remove comes before insert if (lhs.type == ShadowViewMutation::Type::Remove && rhs.type == ShadowViewMutation::Type::Insert) { @@ -317,6 +325,16 @@ static inline bool shouldFirstComeBeforeSecondMutation( lhs.type == ShadowViewMutation::Type::Insert) { return false; } + + // Create comes before insert + if (lhs.type == ShadowViewMutation::Type::Create && + rhs.type == ShadowViewMutation::Type::Insert) { + return true; + } + if (rhs.type == ShadowViewMutation::Type::Create && + lhs.type == ShadowViewMutation::Type::Insert) { + return false; + } } else { // Make sure that removes on the same level are sorted - highest indices // must come first. diff --git a/ReactCommon/react/renderer/components/image/ImageShadowNode.h b/ReactCommon/react/renderer/components/image/ImageShadowNode.h index 12490840b611bd..0e60f78deef2dd 100644 --- a/ReactCommon/react/renderer/components/image/ImageShadowNode.h +++ b/ReactCommon/react/renderer/components/image/ImageShadowNode.h @@ -46,7 +46,7 @@ class ImageShadowNode final : public ConcreteViewShadowNode< ShadowNodeFamilyFragment const &familyFragment, ComponentDescriptor const &componentDescriptor) { auto imageSource = ImageSource{ImageSource::Type::Invalid}; - return {imageSource, {imageSource, nullptr, nullptr}, 0}; + return {imageSource, {imageSource, nullptr}, 0}; } #pragma mark - LayoutableShadowNode diff --git a/ReactCommon/react/renderer/components/slider/SliderShadowNode.h b/ReactCommon/react/renderer/components/slider/SliderShadowNode.h index c012ff45a517fa..82ab4d0b1dc6c2 100644 --- a/ReactCommon/react/renderer/components/slider/SliderShadowNode.h +++ b/ReactCommon/react/renderer/components/slider/SliderShadowNode.h @@ -44,13 +44,13 @@ class SliderShadowNode final : public ConcreteViewShadowNode< ComponentDescriptor const &componentDescriptor) { auto imageSource = ImageSource{ImageSource::Type::Invalid}; return {imageSource, - {imageSource, nullptr, nullptr}, + {imageSource, nullptr}, imageSource, - {imageSource, nullptr, nullptr}, + {imageSource, nullptr}, imageSource, - {imageSource, nullptr, nullptr}, + {imageSource, nullptr}, imageSource, - {imageSource, nullptr, nullptr}}; + {imageSource, nullptr}}; } #pragma mark - LayoutableShadowNode diff --git a/ReactCommon/react/renderer/core/EventQueue.cpp b/ReactCommon/react/renderer/core/EventQueue.cpp index 2861d7a14f05ec..2db952292ff9ea 100644 --- a/ReactCommon/react/renderer/core/EventQueue.cpp +++ b/ReactCommon/react/renderer/core/EventQueue.cpp @@ -8,6 +8,7 @@ #include "EventQueue.h" #include "EventEmitter.h" +#include "ShadowNodeFamily.h" namespace facebook { namespace react { @@ -35,6 +36,12 @@ void EventQueue::enqueueEvent(const RawEvent &rawEvent) const { void EventQueue::enqueueStateUpdate(const StateUpdate &stateUpdate) const { { std::lock_guard lock(queueMutex_); + if (!stateUpdateQueue_.empty()) { + auto const position = stateUpdateQueue_.back(); + if (stateUpdate.family == position.family) { + stateUpdateQueue_.pop_back(); + } + } stateUpdateQueue_.push_back(stateUpdate); } diff --git a/ReactCommon/react/renderer/imagemanager/BUCK b/ReactCommon/react/renderer/imagemanager/BUCK index a9797d2884b068..52f99b3fec6fc0 100644 --- a/ReactCommon/react/renderer/imagemanager/BUCK +++ b/ReactCommon/react/renderer/imagemanager/BUCK @@ -70,7 +70,6 @@ rn_xplat_cxx_library( ios_exported_headers = subdir_glob( [ ("", "*.h"), - ("platform/ios", "RCTImageInstrumentationProxy.h"), ("platform/ios", "RCTImagePrimitivesConversions.h"), ], prefix = "react/renderer/imagemanager", diff --git a/ReactCommon/react/renderer/imagemanager/ImageInstrumentation.h b/ReactCommon/react/renderer/imagemanager/ImageInstrumentation.h deleted file mode 100644 index c1671cb6790376..00000000000000 --- a/ReactCommon/react/renderer/imagemanager/ImageInstrumentation.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -namespace facebook { -namespace react { - -/* - * A base class for performing image loading instrumentation. - * The actual instrumentation is app, platform, and image loader-specific. - */ -class ImageInstrumentation { - public: - virtual ~ImageInstrumentation() noexcept = default; - - /** - * Mark that the image content is set on the native image component on screen. - */ - virtual void didSetImage() const = 0; - - /** - * Mark that the image view starts to be visible on screen. - */ - virtual void didEnterVisibilityRange() const = 0; - - /** - * Mark that the image view is no longer visible on screen. - */ - virtual void didExitVisibilityRange() const = 0; -}; - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/ImageRequest.h b/ReactCommon/react/renderer/imagemanager/ImageRequest.h index a77c1f76c794dd..e3f3047566429a 100644 --- a/ReactCommon/react/renderer/imagemanager/ImageRequest.h +++ b/ReactCommon/react/renderer/imagemanager/ImageRequest.h @@ -7,7 +7,6 @@ #pragma once -#include #include #include #include @@ -31,8 +30,7 @@ class ImageRequest final { */ ImageRequest( const ImageSource &imageSource, - std::shared_ptr telemetry, - std::shared_ptr instrumentation); + std::shared_ptr telemetry); /* * The move constructor. @@ -78,20 +76,6 @@ class ImageRequest final { */ const std::shared_ptr &getSharedTelemetry() const; - /* - * Returns stored image instrumentation object as a shared pointer. - * Retain this *or* `ImageRequest` to ensure a correct lifetime of the object. - */ - const std::shared_ptr - &getSharedImageInstrumentation() const; - - /* - * Returns the image instrumentation object specific to this request. - * Use this if a correct lifetime of the object is ensured in some other way - * (e.g. by retaining an `ImageRequest`). - */ - const ImageInstrumentation &getImageInstrumentation() const; - private: /* * Image source associated with the request. @@ -108,11 +92,6 @@ class ImageRequest final { */ std::shared_ptr coordinator_{}; - /* - * Image instrumentation specific to the request. - */ - std::shared_ptr instrumentation_; - /* * Function we can call to cancel image request (see destructor). */ diff --git a/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageManager.cpp b/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageManager.cpp index c1d4d1ac63e7b4..245c3b5e7a783b 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageManager.cpp +++ b/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageManager.cpp @@ -24,7 +24,7 @@ ImageRequest ImageManager::requestImage( const ImageSource &imageSource, SurfaceId surfaceId) const { // Not implemented. - return ImageRequest(imageSource, nullptr, nullptr); + return ImageRequest(imageSource, nullptr); } } // namespace react diff --git a/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp b/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp index 9cdbc7fdd0dda0..9f811bc4d4a3d2 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp +++ b/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp @@ -12,19 +12,15 @@ namespace react { ImageRequest::ImageRequest( const ImageSource &imageSource, - std::shared_ptr telemetry, - std::shared_ptr instrumentation) - : imageSource_(imageSource), - telemetry_(telemetry), - instrumentation_(instrumentation) { + std::shared_ptr telemetry) + : imageSource_(imageSource), telemetry_(telemetry) { // Not implemented. } ImageRequest::ImageRequest(ImageRequest &&other) noexcept : imageSource_(std::move(other.imageSource_)), telemetry_(std::move(other.telemetry_)), - coordinator_(std::move(other.coordinator_)), - instrumentation_(std::move(other.instrumentation_)) { + coordinator_(std::move(other.coordinator_)) { // Not implemented. } @@ -44,16 +40,5 @@ const std::shared_ptr abort(); } -const std::shared_ptr - &ImageRequest::getSharedImageInstrumentation() const { - // Not implemented - abort(); -} - -const ImageInstrumentation &ImageRequest::getImageInstrumentation() const { - // Not implemented - abort(); -} - } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp b/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp index 216e1ffdfd986d..ce7f9b2d04549f 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp @@ -12,24 +12,19 @@ namespace react { ImageRequest::ImageRequest( const ImageSource &imageSource, - std::shared_ptr telemetry, - std::shared_ptr instrumentation) - : imageSource_(imageSource), - telemetry_(telemetry), - instrumentation_(instrumentation) { + std::shared_ptr telemetry) + : imageSource_(imageSource), telemetry_(telemetry) { coordinator_ = std::make_shared(); } ImageRequest::ImageRequest(ImageRequest &&other) noexcept : imageSource_(std::move(other.imageSource_)), telemetry_(std::move(other.telemetry_)), - coordinator_(std::move(other.coordinator_)), - instrumentation_(std::move(other.instrumentation_)) { + coordinator_(std::move(other.coordinator_)) { other.moved_ = true; other.coordinator_ = nullptr; other.cancelRequest_ = nullptr; other.telemetry_ = nullptr; - other.instrumentation_ = nullptr; } ImageRequest::~ImageRequest() { @@ -58,14 +53,5 @@ const std::shared_ptr return coordinator_; } -const std::shared_ptr - &ImageRequest::getSharedImageInstrumentation() const { - return instrumentation_; -} - -const ImageInstrumentation &ImageRequest::getImageInstrumentation() const { - return *instrumentation_; -} - } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.h b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.h deleted file mode 100644 index 95726a5ff0cccf..00000000000000 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -#include -#include - -NS_ASSUME_NONNULL_BEGIN - -namespace facebook { -namespace react { - -class RCTImageInstrumentationProxy final : public ImageInstrumentation { - public: - RCTImageInstrumentationProxy(id imageLoader); - ~RCTImageInstrumentationProxy(); - - void didSetImage() const override; - void didEnterVisibilityRange() const override; - void didExitVisibilityRange() const override; - - void trackNativeImageView(UIView *imageView) const; - void setImageURLLoaderRequest(RCTImageURLLoaderRequest *request); - - private: - __weak id imageLoader_; - RCTImageURLLoaderRequest *imageURLLoaderRequest_; -}; - -} // namespace react -} // namespace facebook - -NS_ASSUME_NONNULL_END diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.mm deleted file mode 100644 index 1ed24f9faacda3..00000000000000 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageInstrumentationProxy.mm +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTImageInstrumentationProxy.h" - -namespace facebook { -namespace react { - -RCTImageInstrumentationProxy::RCTImageInstrumentationProxy(id imageLoader) - : imageLoader_(imageLoader) -{ -} - -RCTImageInstrumentationProxy::~RCTImageInstrumentationProxy() -{ - if (!imageURLLoaderRequest_) { - return; - } - [imageLoader_ trackURLImageDidDestroy:imageURLLoaderRequest_]; -} - -void RCTImageInstrumentationProxy::didSetImage() const -{ - if (!RCTImageLoadingPerfInstrumentationEnabled()) { - return; - } - - if (!imageURLLoaderRequest_) { - return; - } - - [imageLoader_ trackURLImageContentDidSetForRequest:imageURLLoaderRequest_]; -} - -void RCTImageInstrumentationProxy::didEnterVisibilityRange() const -{ - if (!RCTImageLoadingPerfInstrumentationEnabled()) { - return; - } - - // TODO (T58941612): Not yet supported. - if (!imageURLLoaderRequest_) { - return; - } -} - -void RCTImageInstrumentationProxy::didExitVisibilityRange() const -{ - if (!RCTImageLoadingPerfInstrumentationEnabled()) { - return; - } - - // TODO (T58941612): Not yet supported. - if (!imageURLLoaderRequest_) { - return; - } -} - -void RCTImageInstrumentationProxy::trackNativeImageView(UIView *imageView) const -{ - if (!RCTImageLoadingPerfInstrumentationEnabled()) { - return; - } - - if (!imageURLLoaderRequest_) { - return; - } - [imageLoader_ trackURLImageVisibilityForRequest:imageURLLoaderRequest_ imageView:imageView]; -} - -void RCTImageInstrumentationProxy::setImageURLLoaderRequest(RCTImageURLLoaderRequest *request) -{ - imageURLLoaderRequest_ = request; -} - -} // namespace react -} // namespace facebook diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm index b719be1158fbb8..08e0c255885d3f 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm @@ -16,7 +16,6 @@ #import #import -#import "RCTImageInstrumentationProxy.h" #import "RCTImagePrimitivesConversions.h" using namespace facebook::react; @@ -41,10 +40,9 @@ - (ImageRequest)requestImage:(ImageSource)imageSource surfaceId:(SurfaceId)surfa { SystraceSection s("RCTImageManager::requestImage"); - auto imageInstrumentation = std::make_shared(_imageLoader); auto telemetry = std::make_shared(surfaceId); telemetry->willRequestUrl(); - auto imageRequest = ImageRequest(imageSource, telemetry, imageInstrumentation); + auto imageRequest = ImageRequest(imageSource, telemetry); auto weakObserverCoordinator = (std::weak_ptr)imageRequest.getSharedObserverCoordinator(); @@ -108,10 +106,6 @@ - (ImageRequest)requestImage:(ImageSource)imageSource surfaceId:(SurfaceId)surfa completionBlock:completionBlock]; RCTImageLoaderCancellationBlock cancelationBlock = loaderRequest.cancellationBlock; sharedCancelationFunction.assign([cancelationBlock]() { cancelationBlock(); }); - - if (imageInstrumentation) { - imageInstrumentation->setImageURLLoaderRequest(loaderRequest); - } }); return imageRequest; diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm index df89da51cecf31..7a36d42ea4a283 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm @@ -37,7 +37,7 @@ - (instancetype)initWithImageLoader:(id)i - (ImageRequest)requestImage:(ImageSource)imageSource surfaceId:(SurfaceId)surfaceId { auto telemetry = std::make_shared(surfaceId); - auto imageRequest = ImageRequest(imageSource, telemetry, nullptr); + auto imageRequest = ImageRequest(imageSource, telemetry); auto weakObserverCoordinator = (std::weak_ptr)imageRequest.getSharedObserverCoordinator(); diff --git a/build.gradle.kts b/build.gradle.kts index 571f2db36b6c0f..a55cebbc57e9d2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ buildscript { jcenter() } dependencies { - classpath("com.android.tools.build:gradle:3.6.4") + classpath("com.android.tools.build:gradle:4.0.1") classpath("de.undercouch:gradle-download-task:4.0.2") // NOTE: Do not place your application dependencies here; they belong diff --git a/package.json b/package.json index 433b4c90a32c7b..9dad79fee24983 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "ws": "^6.1.4" }, "devDependencies": { - "flow-bin": "^0.134.0", + "flow-bin": "^0.135.0", "react": "16.13.1" }, "detox": { diff --git a/packages/react-native-codegen/.babelrc b/packages/react-native-codegen/.babelrc index b8ac81899b77e0..7a6194fbaa55d8 100644 --- a/packages/react-native-codegen/.babelrc +++ b/packages/react-native-codegen/.babelrc @@ -5,6 +5,7 @@ "@babel/plugin-transform-destructuring", "@babel/plugin-transform-flow-strip-types", "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-optional-chaining" ] diff --git a/packages/react-native-codegen/DEFS.bzl b/packages/react-native-codegen/DEFS.bzl index 33abd24eeaffe5..4da9f3c420c39e 100644 --- a/packages/react-native-codegen/DEFS.bzl +++ b/packages/react-native-codegen/DEFS.bzl @@ -50,7 +50,7 @@ def rn_codegen_modules( rn_xplat_cxx_library( name = "generated_objcpp_modules-{}".format(name), - header_namespace = native_module_spec_name, + header_namespace = "", apple_sdks = (IOS), compiler_flags = [ "-fexceptions", @@ -61,8 +61,7 @@ def rn_codegen_modules( fbobjc_compiler_flags = get_apple_compiler_flags(), fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), ios_exported_headers = { - "{}.h".format(native_module_spec_name): ":{}".format(generate_module_hobjcpp_name), - "{}-generated.mm".format(native_module_spec_name): ":{}".format(generate_module_mm_name), + "{}/{}.h".format(native_module_spec_name, native_module_spec_name): ":{}".format(generate_module_hobjcpp_name), }, ios_headers = [ ":{}".format(generate_module_hobjcpp_name), diff --git a/packages/react-native-codegen/android/build.gradle b/packages/react-native-codegen/android/build.gradle index 69934710e3bdca..e0cc63d645bbcf 100644 --- a/packages/react-native-codegen/android/build.gradle +++ b/packages/react-native-codegen/android/build.gradle @@ -12,7 +12,7 @@ buildscript { jcenter() } dependencies { - classpath("com.android.tools.build:gradle:3.6.4") + classpath("com.android.tools.build:gradle:4.0.1") } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle index 616590c65c97b6..dd269383ec1416 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle @@ -19,7 +19,7 @@ gradlePlugin { } dependencies { - implementation 'com.android.tools.build:gradle:3.6.4' + implementation 'com.android.tools.build:gradle:4.0.1' // Use the same Gson version that `com.android.tools.build:gradle` depends on. implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.google.guava:guava:29.0-jre' diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java index b4051ac81d7f61..c243cae7d73a1e 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java @@ -8,7 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class PromiseType extends Type { - public static final String TYPE_NAME = "GenericPromiseTypeAnnotation"; + public static final String TYPE_NAME = "PromiseTypeAnnotation"; public PromiseType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js index b697ab954dd573..02784457c3bdfb 100644 --- a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeOptionalObjectTurboModule.js @@ -17,7 +17,6 @@ export interface Spec extends TurboModule { +getConstants: () => {| D?: ?boolean, A?: Array, - G?: any, E?: ?{| D?: ?boolean, E?: ?{| diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModule.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModule.js index ee6c0983afb75f..c950ed9e288972 100644 --- a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModule.js +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModule.js @@ -10,9 +10,16 @@ 'use strict'; -import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; +type Animal = {| + name: string, +|}; + export interface Spec extends TurboModule { // Exported methods. +getConstants: () => {| @@ -26,7 +33,14 @@ export interface Spec extends TurboModule { +getString: (arg: string) => string; +getArray: (arg: Array) => Array; +getObject: (arg: Object) => Object; - +getValue: (x: number, y: string, z: Object) => Object; + +getObjectShape: (arg: {|prop: number|}) => {|prop: number|}; + +getAlias: (arg: Animal) => Animal; + +getRootTag: (arg: RootTag) => RootTag; + +getValue: ( + x: number, + getValuegetValuegetValuegetValuegetValuey: string, + z: Object, + ) => Object; +getValueWithCallback: (callback: (value: string) => void) => void; +getValueWithPromise: (error: boolean) => Promise; } diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleArrays.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleArrays.js new file mode 100644 index 00000000000000..fce6f7c0f0fb6a --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleArrays.js @@ -0,0 +1,51 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +type Animal = {| + name: string, +|}; + +export interface Spec extends TurboModule { + // Exported methods. + +getConstants: () => {| + const1: Array, + const2: Array, + const3: Array, + id?: Array, + |}; + +voidFunc: () => void; + +getBool: (id: Array) => Array; + +getNumber: (arg: Array) => Array; + +getString: (arg: Array) => Array; + +getArray: (arg: Array>) => Array>; + +getObject: (arg: Array) => Array; + +getObjectShape: (arg: Array<{|prop: number|}>) => Array<{|prop: number|}>; + +getAlias: (arg: Array) => Array; + +getRootTag: (arg: Array) => Array; + +getValue: ( + x: Array, + y: Array, + z: Array, + ) => Array; + +getValueWithCallback: (callback: (value: Array) => void) => void; + +getValueWithPromise: (error: Array) => Promise>; +} + +export default (TurboModuleRegistry.getEnforcing( + 'SampleTurboModuleArrays', +): Spec); diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullable.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullable.js new file mode 100644 index 00000000000000..ac7b57e386a2d0 --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullable.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +type Animal = ?{| + name: ?string, +|}; + +export interface Spec extends TurboModule { + // Exported methods. + +getConstants: () => {| + const1: ?boolean, + const2: ?number, + const3: ?string, + |}; + +voidFunc: () => void; + +getBool: (arg: ?boolean) => ?boolean; + +getNumber: (arg: ?number) => ?number; + +getString: (arg: ?string) => ?string; + +getArray: (arg: ?Array) => ?Array; + +getObject: (arg: ?Object) => ?Object; + +getObjectShape: (arg: ?{|prop: ?number|}) => ?{|prop: ?number|}; + +getAlias: (arg: ?Animal) => ?Animal; + +getRootTag: (arg: ?RootTag) => ?RootTag; + +getValue: (x: ?number, y: ?string, z: ?Object) => ?Object; + +getValueWithCallback: (callback: (value: ?string) => void) => void; + +getValueWithPromise: (error: ?boolean) => ?Promise; +} + +export default (TurboModuleRegistry.getEnforcing( + 'SampleTurboModuleNullable', +): Spec); diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullableAndOptional.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullableAndOptional.js new file mode 100644 index 00000000000000..29e54d8a5c3693 --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleNullableAndOptional.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +type Animal = ?{| + name?: ?string, +|}; + +export interface Spec extends TurboModule { + // Exported methods. + +getConstants?: () => {| + const1?: ?boolean, + const2?: ?number, + const3?: ?string, + |}; + +voidFunc?: () => void; + +getBool?: (arg?: ?boolean) => ?boolean; + +getNumber?: (arg?: ?number) => ?number; + +getString?: (arg?: ?string) => ?string; + +getArray?: (arg?: ?Array) => ?Array; + +getObject?: (arg?: ?Object) => ?Object; + +getObjectShape?: (arg?: {|prop?: ?number|}) => {|prop?: ?number|}; + +getAlias?: (arg?: ?Animal) => ?Animal; + +getRootTag?: (arg?: ?RootTag) => ?RootTag; + +getValue?: (x?: ?number, y?: ?string, z?: ?Object) => ?Object; + +getValueWithCallback?: (callback?: ?(value?: ?string) => void) => void; + +getValueWithPromise?: (error?: ?boolean) => ?Promise; +} + +export default (TurboModuleRegistry.getEnforcing( + 'SampleTurboModuleNullableAndOptional', +): Spec); diff --git a/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleOptional.js b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleOptional.js new file mode 100644 index 00000000000000..9f12225a2d883b --- /dev/null +++ b/packages/react-native-codegen/e2e/__test_fixtures__/modules/NativeSampleTurboModuleOptional.js @@ -0,0 +1,46 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + */ + +'use strict'; + +import type { + RootTag, + TurboModule, +} from 'react-native/Libraries/TurboModule/RCTExport'; +import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; + +type Animal = {| + name?: string, +|}; + +export interface Spec extends TurboModule { + // Exported methods. + +getConstants?: () => {| + const1?: boolean, + const2?: number, + const3?: string, + |}; + +voidFunc?: () => void; + +getBool?: (arg?: boolean) => boolean; + +getNumber?: (arg?: number) => number; + +getString?: (arg?: string) => string; + +getArray?: (arg?: Array) => Array; + +getObject?: (arg?: Object) => Object; + +getObjectShape?: (arg?: {|prop?: number|}) => {|prop?: number|}; + +getAlias?: (arg?: Animal) => Animal; + +getRootTag?: (arg?: RootTag) => RootTag; + +getValue?: (x?: number, y?: string, z?: Object) => Object; + +getValueWithCallback?: (callback?: (value?: string) => void) => void; + +getValueWithPromise?: (error?: boolean) => Promise; +} + +export default (TurboModuleRegistry.getEnforcing( + 'SampleTurboModuleOptional', +): Spec); diff --git a/packages/react-native-codegen/e2e/__tests__/modules/BUCK b/packages/react-native-codegen/e2e/__tests__/modules/BUCK new file mode 100644 index 00000000000000..29df252313e6ea --- /dev/null +++ b/packages/react-native-codegen/e2e/__tests__/modules/BUCK @@ -0,0 +1,11 @@ +load("@fbsource//xplat/js/RKJSModules/Libraries/NativeModules:defs.bzl", "react_native_module_flow_types_library") + +react_native_module_flow_types_library( + name = "RNCodegenModuleFixtures", + android_package_name = "com.facebook.fbreact.specs", + js_srcs = glob( + [ + "../../__test_fixtures__/modules/*.js", + ], + ), +) diff --git a/packages/react-native-codegen/e2e/__tests__/modules/GenerateModuleObjCpp-test.js b/packages/react-native-codegen/e2e/__tests__/modules/GenerateModuleObjCpp-test.js new file mode 100644 index 00000000000000..2b2deec0b0fe33 --- /dev/null +++ b/packages/react-native-codegen/e2e/__tests__/modules/GenerateModuleObjCpp-test.js @@ -0,0 +1,50 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails oncall+react_native + * @flow strict-local + * @format + */ + +'use strict'; + +const parser = require('../../../src/parsers/flow'); +const generator = require('../../../src/generators/modules/GenerateModuleObjCpp'); +const fs = require('fs'); + +import type {SchemaType} from '../../../src/CodegenSchema'; + +const FIXTURE_DIR = `${__dirname}/../../__test_fixtures__/modules`; + +function getModules(): SchemaType { + const filenames: Array = fs.readdirSync(FIXTURE_DIR); + return filenames.reduce( + (accumulator, file) => { + const schema = parser.parseFile(`${FIXTURE_DIR}/${file}`); + return { + modules: { + ...accumulator.modules, + ...schema.modules, + }, + }; + }, + {modules: {}}, + ); +} + +describe('GenerateModuleObjCpp', () => { + it('can generate a header file NativeModule specs', () => { + const libName = 'RNCodegenModuleFixtures'; + const output = generator.generate(libName, getModules(), libName); + expect(output.get(libName + '.h')).toMatchSnapshot(); + }); + + it('can generate an implementation file NativeModule specs', () => { + const libName = 'RNCodegenModuleFixtures'; + const output = generator.generate(libName, getModules(), libName); + expect(output.get(libName + '-generated.mm')).toMatchSnapshot(); + }); +}); diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap new file mode 100644 index 00000000000000..c0df45acc209bc --- /dev/null +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleObjCpp-test.js.snap @@ -0,0 +1,2358 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GenerateModuleObjCpp can generate a header file NativeModule specs 1`] = ` +" +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated by codegen project: GenerateModuleHObjCpp.js + */ + +#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 + +#import + +#import + +#import + +#import +#import +#import + +#import +#import +#import + +#import + + + +@protocol NativeArrayTurboModuleSpec + +- (NSArray *)getArray:(NSArray *)a; +- (NSArray *)getReadOnlyArray:(NSArray *)a; +- (NSArray *)getArrayWithAlias:(NSArray *)a + b:(NSArray *)b; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'ArrayTurboModule' + */ + class JSI_EXPORT NativeArrayTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeArrayTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +@protocol NativeBooleanTurboModuleSpec + +- (NSNumber *)getBoolean:(BOOL)arg; +- (NSNumber *)getBooleanWithAlias:(BOOL)arg; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'BooleanTurboModule' + */ + class JSI_EXPORT NativeBooleanTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeBooleanTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +@protocol NativeCallbackTurboModuleSpec + +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithCallbackWithAlias:(RCTResponseSenderBlock)c; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'CallbackTurboModule' + */ + class JSI_EXPORT NativeCallbackTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeCallbackTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +@protocol NativeNullableTurboModuleSpec + +- (NSNumber * _Nullable)getBool:(NSNumber *)a; +- (NSNumber * _Nullable)getNumber:(NSNumber *)a; +- (NSString * _Nullable)getString:(NSNumber *)a; +- (NSArray> * _Nullable)getArray:(NSArray * _Nullable)a; +- (NSDictionary * _Nullable)getObject:(NSDictionary * _Nullable)a; +- (void)getValueWithPromise:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NullableTurboModule' + */ + class JSI_EXPORT NativeNullableTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeNullableTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +@protocol NativeNumberTurboModuleSpec + +- (NSNumber *)getNumber:(double)arg; +- (NSNumber *)getNumberWithAlias:(double)arg; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'NumberTurboModule' + */ + class JSI_EXPORT NativeNumberTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeNumberTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +namespace JS { + namespace NativeObjectTurboModule { + struct SpecDifficultObjectAE { + bool D() const; + double E() const; + NSString *F() const; + + SpecDifficultObjectAE(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectAE) ++ (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectAE:(id)json; +@end + + +namespace JS { + namespace NativeObjectTurboModule { + struct SpecDifficultObjectA { + bool D() const; + JS::NativeObjectTurboModule::SpecDifficultObjectAE E() const; + NSString *F() const; + + SpecDifficultObjectA(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectA) ++ (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectA:(id)json; +@end + + +namespace JS { + namespace NativeObjectTurboModule { + struct ConstantsEEE { + + struct Builder { + struct Input { + RCTRequired D; + RCTRequired E; + RCTRequired F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsEEE */ + Builder(ConstantsEEE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsEEE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsEEE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} + +namespace JS { + namespace NativeObjectTurboModule { + struct ConstantsEE { + + struct Builder { + struct Input { + RCTRequired D; + RCTRequired E; + RCTRequired F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsEE */ + Builder(ConstantsEE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsEE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsEE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} + +namespace JS { + namespace NativeObjectTurboModule { + struct ConstantsE { + + struct Builder { + struct Input { + RCTRequired D; + RCTRequired E; + RCTRequired F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsE */ + Builder(ConstantsE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} + +namespace JS { + namespace NativeObjectTurboModule { + struct Constants { + + struct Builder { + struct Input { + RCTRequired D; + RCTRequired E; + RCTRequired F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeObjectTurboModuleSpec + +- (NSDictionary *)getGenericObject:(NSDictionary *)arg; +- (NSDictionary *)getGenericObjectReadOnly:(NSDictionary *)arg; +- (NSDictionary *)getGenericObjectWithAlias:(NSDictionary *)arg; +- (NSDictionary *)difficultObject:(JS::NativeObjectTurboModule::SpecDifficultObjectA &)A; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'ObjectTurboModule' + */ + class JSI_EXPORT NativeObjectTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeObjectTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +namespace JS { + namespace NativeOptionalObjectTurboModule { + struct ConstantsEEE { + + struct Builder { + struct Input { + folly::Optional D; + folly::Optional E; + NSString *F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsEEE */ + Builder(ConstantsEEE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsEEE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsEEE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} + +namespace JS { + namespace NativeOptionalObjectTurboModule { + struct ConstantsEE { + + struct Builder { + struct Input { + folly::Optional D; + folly::Optional E; + NSString *F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsEE */ + Builder(ConstantsEE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsEE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsEE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} + +namespace JS { + namespace NativeOptionalObjectTurboModule { + struct ConstantsE { + + struct Builder { + struct Input { + folly::Optional D; + folly::Optional E; + NSString *F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsE */ + Builder(ConstantsE i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsE fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsE(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} + +namespace JS { + namespace NativeOptionalObjectTurboModule { + struct Constants { + + struct Builder { + struct Input { + folly::Optional D; + id _Nullable A; + folly::Optional E; + NSString *F; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeOptionalObjectTurboModuleSpec + +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'OptionalObjectTurboModule' + */ + class JSI_EXPORT NativeOptionalObjectTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeOptionalObjectTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +@protocol NativePromiseTurboModuleSpec + +- (void)getValueWithPromise:(BOOL)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (void)getValueWithPromiseWithAlias:(NSString *)arg + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'PromiseTurboModule' + */ + class JSI_EXPORT NativePromiseTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativePromiseTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +namespace JS { + namespace NativeSampleTurboModule { + struct SpecGetObjectShapeArg { + double prop() const; + + SpecGetObjectShapeArg(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetObjectShapeArg:(id)json; +@end + + +namespace JS { + namespace NativeSampleTurboModule { + struct Animal { + NSString *name() const; + + Animal(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModule_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_Animal:(id)json; +@end + + +namespace JS { + namespace NativeSampleTurboModule { + struct Constants { + + struct Builder { + struct Input { + RCTRequired const1; + RCTRequired const2; + RCTRequired const3; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleSpec + +- (void)voidFunc; +- (NSNumber *)getBool:(BOOL)arg; +- (NSNumber *)getNumber:(double)arg; +- (NSString *)getString:(NSString *)arg; +- (NSArray> *)getArray:(NSArray *)arg; +- (NSDictionary *)getObject:(NSDictionary *)arg; +- (NSDictionary *)getObjectShape:(JS::NativeSampleTurboModule::SpecGetObjectShapeArg &)arg; +- (NSDictionary *)getAlias:(JS::NativeSampleTurboModule::Animal &)arg; +- (NSNumber *)getRootTag:(double)arg; +- (NSDictionary *)getValue:(double)x +getValuegetValuegetValuegetValuegetValuey:(NSString *)getValuegetValuegetValuegetValuegetValuey + z:(NSDictionary *)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(BOOL)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'SampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +namespace JS { + namespace NativeSampleTurboModuleArrays { + struct ConstantsIdElement { + + struct Builder { + struct Input { + RCTRequired prop; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ConstantsIdElement */ + Builder(ConstantsIdElement i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ConstantsIdElement fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ConstantsIdElement(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} + +namespace JS { + namespace NativeSampleTurboModuleArrays { + struct Constants { + + struct Builder { + struct Input { + RCTRequired> const1; + RCTRequired> const2; + RCTRequired> const3; + folly::Optional>> id_; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleArraysSpec + +- (void)voidFunc; +- (NSArray *)getBool:(NSArray *)id; +- (NSArray *)getNumber:(NSArray *)arg; +- (NSArray *)getString:(NSArray *)arg; +- (NSArray> *> *)getArray:(NSArray *)arg; +- (NSArray *)getObject:(NSArray *)arg; +- (NSArray *)getObjectShape:(NSArray *)arg; +- (NSArray *)getAlias:(NSArray *)arg; +- (NSArray *)getRootTag:(NSArray *)arg; +- (NSArray *)getValue:(NSArray *)x + y:(NSArray *)y + z:(NSArray *)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(NSArray *)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'SampleTurboModuleArrays' + */ + class JSI_EXPORT NativeSampleTurboModuleArraysSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleArraysSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +namespace JS { + namespace NativeSampleTurboModuleNullable { + struct SpecGetObjectShapeArg { + folly::Optional prop() const; + + SpecGetObjectShapeArg(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleNullable_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_SpecGetObjectShapeArg:(id)json; +@end + + +namespace JS { + namespace NativeSampleTurboModuleNullable { + struct Animal { + NSString *name() const; + + Animal(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleNullable_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_Animal:(id)json; +@end + + +namespace JS { + namespace NativeSampleTurboModuleNullable { + struct Constants { + + struct Builder { + struct Input { + RCTRequired> const1; + RCTRequired> const2; + RCTRequired const3; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleNullableSpec + +- (void)voidFunc; +- (NSNumber * _Nullable)getBool:(NSNumber *)arg; +- (NSNumber * _Nullable)getNumber:(NSNumber *)arg; +- (NSString * _Nullable)getString:(NSString * _Nullable)arg; +- (NSArray> * _Nullable)getArray:(NSArray * _Nullable)arg; +- (NSDictionary * _Nullable)getObject:(NSDictionary * _Nullable)arg; +- (NSDictionary * _Nullable)getObjectShape:(JS::NativeSampleTurboModuleNullable::SpecGetObjectShapeArg &)arg; +- (NSDictionary * _Nullable)getAlias:(JS::NativeSampleTurboModuleNullable::Animal &)arg; +- (NSNumber * _Nullable)getRootTag:(NSNumber *)arg; +- (NSDictionary * _Nullable)getValue:(NSNumber *)x + y:(NSString * _Nullable)y + z:(NSDictionary * _Nullable)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(NSNumber *)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'SampleTurboModuleNullable' + */ + class JSI_EXPORT NativeSampleTurboModuleNullableSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleNullableSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +namespace JS { + namespace NativeSampleTurboModuleNullableAndOptional { + struct SpecGetObjectShapeArg { + folly::Optional prop() const; + + SpecGetObjectShapeArg(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg:(id)json; +@end + + +namespace JS { + namespace NativeSampleTurboModuleNullableAndOptional { + struct Animal { + NSString *name() const; + + Animal(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_Animal:(id)json; +@end + + +namespace JS { + namespace NativeSampleTurboModuleNullableAndOptional { + struct Constants { + + struct Builder { + struct Input { + folly::Optional const1; + folly::Optional const2; + NSString *const3; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleNullableAndOptionalSpec + +- (void)voidFunc; +- (NSNumber * _Nullable)getBool:(NSNumber *)arg; +- (NSNumber * _Nullable)getNumber:(NSNumber *)arg; +- (NSString * _Nullable)getString:(NSString * _Nullable)arg; +- (NSArray> * _Nullable)getArray:(NSArray * _Nullable)arg; +- (NSDictionary * _Nullable)getObject:(NSDictionary * _Nullable)arg; +- (NSDictionary *)getObjectShape:(JS::NativeSampleTurboModuleNullableAndOptional::SpecGetObjectShapeArg &)arg; +- (NSDictionary * _Nullable)getAlias:(JS::NativeSampleTurboModuleNullableAndOptional::Animal &)arg; +- (NSNumber * _Nullable)getRootTag:(NSNumber *)arg; +- (NSDictionary * _Nullable)getValue:(NSNumber *)x + y:(NSString * _Nullable)y + z:(NSDictionary * _Nullable)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(NSNumber *)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'SampleTurboModuleNullableAndOptional' + */ + class JSI_EXPORT NativeSampleTurboModuleNullableAndOptionalSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleNullableAndOptionalSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +namespace JS { + namespace NativeSampleTurboModuleOptional { + struct SpecGetObjectShapeArg { + folly::Optional prop() const; + + SpecGetObjectShapeArg(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleOptional_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_SpecGetObjectShapeArg:(id)json; +@end + + +namespace JS { + namespace NativeSampleTurboModuleOptional { + struct Animal { + NSString *name() const; + + Animal(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (NativeSampleTurboModuleOptional_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_Animal:(id)json; +@end + + +namespace JS { + namespace NativeSampleTurboModuleOptional { + struct Constants { + + struct Builder { + struct Input { + folly::Optional const1; + folly::Optional const2; + NSString *const3; + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing Constants */ + Builder(Constants i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + Constants(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +} +@protocol NativeSampleTurboModuleOptionalSpec + +- (void)voidFunc; +- (NSNumber *)getBool:(NSNumber *)arg; +- (NSNumber *)getNumber:(NSNumber *)arg; +- (NSString *)getString:(NSString *)arg; +- (NSArray> *)getArray:(NSArray *)arg; +- (NSDictionary *)getObject:(NSDictionary *)arg; +- (NSDictionary *)getObjectShape:(JS::NativeSampleTurboModuleOptional::SpecGetObjectShapeArg &)arg; +- (NSDictionary *)getAlias:(JS::NativeSampleTurboModuleOptional::Animal &)arg; +- (NSNumber *)getRootTag:(NSNumber *)arg; +- (NSDictionary *)getValue:(NSNumber *)x + y:(NSString *)y + z:(NSDictionary *)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(NSNumber *)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (facebook::react::ModuleConstants)constantsToExport; +- (facebook::react::ModuleConstants)getConstants; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'SampleTurboModuleOptional' + */ + class JSI_EXPORT NativeSampleTurboModuleOptionalSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleOptionalSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +@protocol NativeStringTurboModuleSpec + +- (NSString *)getString:(NSString *)arg; +- (NSString *)getStringWithAlias:(NSString *)arg; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'StringTurboModule' + */ + class JSI_EXPORT NativeStringTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeStringTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + + + + + + +inline bool JS::NativeObjectTurboModule::SpecDifficultObjectAE::D() const +{ + id const p = _v[@\\"D\\"]; + return RCTBridgingToBool(p); +} + + +inline double JS::NativeObjectTurboModule::SpecDifficultObjectAE::E() const +{ + id const p = _v[@\\"E\\"]; + return RCTBridgingToDouble(p); +} + + +inline NSString *JS::NativeObjectTurboModule::SpecDifficultObjectAE::F() const +{ + id const p = _v[@\\"F\\"]; + return RCTBridgingToString(p); +} + + +inline bool JS::NativeObjectTurboModule::SpecDifficultObjectA::D() const +{ + id const p = _v[@\\"D\\"]; + return RCTBridgingToBool(p); +} + + +inline JS::NativeObjectTurboModule::SpecDifficultObjectAE JS::NativeObjectTurboModule::SpecDifficultObjectA::E() const +{ + id const p = _v[@\\"E\\"]; + return JS::NativeObjectTurboModule::SpecDifficultObjectAE(p); +} + + +inline NSString *JS::NativeObjectTurboModule::SpecDifficultObjectA::F() const +{ + id const p = _v[@\\"F\\"]; + return RCTBridgingToString(p); +} + + +inline JS::NativeObjectTurboModule::ConstantsEEE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D.get(); + d[@\\"D\\"] = @(D); + auto E = i.E.get(); + d[@\\"E\\"] = @(E); + auto F = i.F.get(); + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeObjectTurboModule::ConstantsEEE::Builder::Builder(ConstantsEEE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeObjectTurboModule::ConstantsEE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D.get(); + d[@\\"D\\"] = @(D); + auto E = i.E.get(); + d[@\\"E\\"] = E.buildUnsafeRawValue(); + auto F = i.F.get(); + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeObjectTurboModule::ConstantsEE::Builder::Builder(ConstantsEE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeObjectTurboModule::ConstantsE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D.get(); + d[@\\"D\\"] = @(D); + auto E = i.E.get(); + d[@\\"E\\"] = E.buildUnsafeRawValue(); + auto F = i.F.get(); + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeObjectTurboModule::ConstantsE::Builder::Builder(ConstantsE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeObjectTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D.get(); + d[@\\"D\\"] = @(D); + auto E = i.E.get(); + d[@\\"E\\"] = E.buildUnsafeRawValue(); + auto F = i.F.get(); + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeObjectTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeOptionalObjectTurboModule::ConstantsEEE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D; + d[@\\"D\\"] = D.hasValue() ? @((BOOL)D.value()) : nil; + auto E = i.E; + d[@\\"E\\"] = E.hasValue() ? @((double)E.value()) : nil; + auto F = i.F; + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsEEE::Builder::Builder(ConstantsEEE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeOptionalObjectTurboModule::ConstantsEE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D; + d[@\\"D\\"] = D.hasValue() ? @((BOOL)D.value()) : nil; + auto E = i.E; + d[@\\"E\\"] = E.hasValue() ? E.value().buildUnsafeRawValue() : nil; + auto F = i.F; + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsEE::Builder::Builder(ConstantsEE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeOptionalObjectTurboModule::ConstantsE::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D; + d[@\\"D\\"] = D.hasValue() ? @((BOOL)D.value()) : nil; + auto E = i.E; + d[@\\"E\\"] = E.hasValue() ? E.value().buildUnsafeRawValue() : nil; + auto F = i.F; + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeOptionalObjectTurboModule::ConstantsE::Builder::Builder(ConstantsE i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeOptionalObjectTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto D = i.D; + d[@\\"D\\"] = D.hasValue() ? @((BOOL)D.value()) : nil; + auto A = i.A; + d[@\\"A\\"] = A; + auto E = i.E; + d[@\\"E\\"] = E.hasValue() ? E.value().buildUnsafeRawValue() : nil; + auto F = i.F; + d[@\\"F\\"] = F; + return d; +}) {} +inline JS::NativeOptionalObjectTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + + +inline double JS::NativeSampleTurboModule::SpecGetObjectShapeArg::prop() const +{ + id const p = _v[@\\"prop\\"]; + return RCTBridgingToDouble(p); +} + + +inline NSString *JS::NativeSampleTurboModule::Animal::name() const +{ + id const p = _v[@\\"name\\"]; + return RCTBridgingToString(p); +} + + +inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1.get(); + d[@\\"const1\\"] = @(const1); + auto const2 = i.const2.get(); + d[@\\"const2\\"] = @(const2); + auto const3 = i.const3.get(); + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeSampleTurboModuleArrays::ConstantsIdElement::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto prop = i.prop.get(); + d[@\\"prop\\"] = @(prop); + return d; +}) {} +inline JS::NativeSampleTurboModuleArrays::ConstantsIdElement::Builder::Builder(ConstantsIdElement i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline JS::NativeSampleTurboModuleArrays::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1.get(); + d[@\\"const1\\"] = RCTConvertVecToArray(const1, ^id(bool el_) { return @(el_); }); + auto const2 = i.const2.get(); + d[@\\"const2\\"] = RCTConvertVecToArray(const2, ^id(double el_) { return @(el_); }); + auto const3 = i.const3.get(); + d[@\\"const3\\"] = RCTConvertVecToArray(const3, ^id(NSString * el_) { return el_; }); + auto id_ = i.id_; + d[@\\"id_\\"] = RCTConvertOptionalVecToArray(id_, ^id(folly::Optional el_) { return el_.hasValue() ? el_.value().buildUnsafeRawValue() : nil; }); + return d; +}) {} +inline JS::NativeSampleTurboModuleArrays::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline folly::Optional JS::NativeSampleTurboModuleNullable::SpecGetObjectShapeArg::prop() const +{ + id const p = _v[@\\"prop\\"]; + return RCTBridgingToOptionalDouble(p); +} + + +inline NSString *JS::NativeSampleTurboModuleNullable::Animal::name() const +{ + id const p = _v[@\\"name\\"]; + return RCTBridgingToOptionalString(p); +} + + +inline JS::NativeSampleTurboModuleNullable::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1.get(); + d[@\\"const1\\"] = const1.hasValue() ? @((BOOL)const1.value()) : nil; + auto const2 = i.const2.get(); + d[@\\"const2\\"] = const2.hasValue() ? @((double)const2.value()) : nil; + auto const3 = i.const3.get(); + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModuleNullable::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline folly::Optional JS::NativeSampleTurboModuleNullableAndOptional::SpecGetObjectShapeArg::prop() const +{ + id const p = _v[@\\"prop\\"]; + return RCTBridgingToOptionalDouble(p); +} + + +inline NSString *JS::NativeSampleTurboModuleNullableAndOptional::Animal::name() const +{ + id const p = _v[@\\"name\\"]; + return RCTBridgingToOptionalString(p); +} + + +inline JS::NativeSampleTurboModuleNullableAndOptional::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1; + d[@\\"const1\\"] = const1.hasValue() ? @((BOOL)const1.value()) : nil; + auto const2 = i.const2; + d[@\\"const2\\"] = const2.hasValue() ? @((double)const2.value()) : nil; + auto const3 = i.const3; + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModuleNullableAndOptional::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +inline folly::Optional JS::NativeSampleTurboModuleOptional::SpecGetObjectShapeArg::prop() const +{ + id const p = _v[@\\"prop\\"]; + return RCTBridgingToOptionalDouble(p); +} + + +inline NSString *JS::NativeSampleTurboModuleOptional::Animal::name() const +{ + id const p = _v[@\\"name\\"]; + return RCTBridgingToOptionalString(p); +} + + +inline JS::NativeSampleTurboModuleOptional::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1; + d[@\\"const1\\"] = const1.hasValue() ? @((BOOL)const1.value()) : nil; + auto const2 = i.const2; + d[@\\"const2\\"] = const2.hasValue() ? @((double)const2.value()) : nil; + auto const3 = i.const3; + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModuleOptional::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} + +" +`; + +exports[`GenerateModuleObjCpp can generate an implementation file NativeModule specs 1`] = ` +" +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated by an internal genrule from Flow types. + * + * 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 \\"RNCodegenModuleFixtures.h\\" + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeArrayTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeArrayTurboModuleSpecJSI_getReadOnlyArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getReadOnlyArray\\", @selector(getReadOnlyArray:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeArrayTurboModuleSpecJSI_getArrayWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArrayWithAlias\\", @selector(getArrayWithAlias:b:), args, count); + } + + + NativeArrayTurboModuleSpecJSI::NativeArrayTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeArrayTurboModuleSpecJSI_getArray}; + + + + methodMap_[\\"getReadOnlyArray\\"] = MethodMetadata {1, __hostFunction_NativeArrayTurboModuleSpecJSI_getReadOnlyArray}; + + + + methodMap_[\\"getArrayWithAlias\\"] = MethodMetadata {2, __hostFunction_NativeArrayTurboModuleSpecJSI_getArrayWithAlias}; + + + } + } // namespace react +} // namespace facebook + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeBooleanTurboModuleSpecJSI_getBoolean(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getBoolean\\", @selector(getBoolean:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeBooleanTurboModuleSpecJSI_getBooleanWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getBooleanWithAlias\\", @selector(getBooleanWithAlias:), args, count); + } + + + NativeBooleanTurboModuleSpecJSI::NativeBooleanTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getBoolean\\"] = MethodMetadata {1, __hostFunction_NativeBooleanTurboModuleSpecJSI_getBoolean}; + + + + methodMap_[\\"getBooleanWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeBooleanTurboModuleSpecJSI_getBooleanWithAlias}; + + + } + } // namespace react +} // namespace facebook + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallbackWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallbackWithAlias\\", @selector(getValueWithCallbackWithAlias:), args, count); + } + + + NativeCallbackTurboModuleSpecJSI::NativeCallbackTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallback}; + + + + methodMap_[\\"getValueWithCallbackWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeCallbackTurboModuleSpecJSI_getValueWithCallbackWithAlias}; + + + } + } // namespace react +} // namespace facebook + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getBool\\", @selector(getBool:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeNullableTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:reject:), args, count); + } + + + NativeNullableTurboModuleSpecJSI::NativeNullableTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getBool}; + + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getNumber}; + + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getString}; + + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getArray}; + + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeNullableTurboModuleSpecJSI_getObject}; + + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {0, __hostFunction_NativeNullableTurboModuleSpecJSI_getValueWithPromise}; + + + } + } // namespace react +} // namespace facebook + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeNumberTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeNumberTurboModuleSpecJSI_getNumberWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumberWithAlias\\", @selector(getNumberWithAlias:), args, count); + } + + + NativeNumberTurboModuleSpecJSI::NativeNumberTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeNumberTurboModuleSpecJSI_getNumber}; + + + + methodMap_[\\"getNumberWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeNumberTurboModuleSpecJSI_getNumberWithAlias}; + + + } + } // namespace react +} // namespace facebook + + + +@implementation RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectAE) ++ (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectAE:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + + +@implementation RCTCxxConvert (NativeObjectTurboModule_SpecDifficultObjectA) ++ (RCTManagedPointer *)JS_NativeObjectTurboModule_SpecDifficultObjectA:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getGenericObject\\", @selector(getGenericObject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObjectReadOnly(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getGenericObjectReadOnly\\", @selector(getGenericObjectReadOnly:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObjectWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getGenericObjectWithAlias\\", @selector(getGenericObjectWithAlias:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_difficultObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"difficultObject\\", @selector(difficultObject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeObjectTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + + NativeObjectTurboModuleSpecJSI::NativeObjectTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getGenericObject\\"] = MethodMetadata {1, __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObject}; + + + + methodMap_[\\"getGenericObjectReadOnly\\"] = MethodMetadata {1, __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObjectReadOnly}; + + + + methodMap_[\\"getGenericObjectWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeObjectTurboModuleSpecJSI_getGenericObjectWithAlias}; + + + + methodMap_[\\"difficultObject\\"] = MethodMetadata {1, __hostFunction_NativeObjectTurboModuleSpecJSI_difficultObject}; + setMethodArgConversionSelector(@\\"difficultObject\\", 0, @\\"JS_NativeObjectTurboModule_SpecDifficultObjectA:\\"); + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeObjectTurboModuleSpecJSI_getConstants}; + + + } + } // namespace react +} // namespace facebook + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeOptionalObjectTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + + NativeOptionalObjectTurboModuleSpecJSI::NativeOptionalObjectTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeOptionalObjectTurboModuleSpecJSI_getConstants}; + + + } + } // namespace react +} // namespace facebook + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromiseWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromiseWithAlias\\", @selector(getValueWithPromiseWithAlias:resolve:reject:), args, count); + } + + + NativePromiseTurboModuleSpecJSI::NativePromiseTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromise}; + + + + methodMap_[\\"getValueWithPromiseWithAlias\\"] = MethodMetadata {1, __hostFunction_NativePromiseTurboModuleSpecJSI_getValueWithPromiseWithAlias}; + + + } + } // namespace react +} // namespace facebook + + + +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetObjectShapeArg:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + + +@implementation RCTCxxConvert (NativeSampleTurboModule_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_Animal:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getBool\\", @selector(getBool:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:getValuegetValuegetValuegetValuegetValuey:z:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; + + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; + + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; + + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; + + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; + + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObjectShape}; + setMethodArgConversionSelector(@\\"getObjectShape\\", 0, @\\"JS_NativeSampleTurboModule_SpecGetObjectShapeArg:\\"); + + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getAlias}; + setMethodArgConversionSelector(@\\"getAlias\\", 0, @\\"JS_NativeSampleTurboModule_Animal:\\"); + + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; + + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; + + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; + + + } + } // namespace react +} // namespace facebook + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getBool\\", @selector(getBool:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getString\\", @selector(getString:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getObject\\", @selector(getObject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + + NativeSampleTurboModuleArraysSpecJSI::NativeSampleTurboModuleArraysSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_voidFunc}; + + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getBool}; + + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getNumber}; + + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getString}; + + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getArray}; + + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getObject}; + + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getObjectShape}; + + + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getAlias}; + + + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getRootTag}; + + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValue}; + + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValueWithCallback}; + + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getValueWithPromise}; + + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleArraysSpecJSI_getConstants}; + + + } + } // namespace react +} // namespace facebook + + + +@implementation RCTCxxConvert (NativeSampleTurboModuleNullable_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_SpecGetObjectShapeArg:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + + +@implementation RCTCxxConvert (NativeSampleTurboModuleNullable_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullable_Animal:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getBool\\", @selector(getBool:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + + NativeSampleTurboModuleNullableSpecJSI::NativeSampleTurboModuleNullableSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_voidFunc}; + + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getBool}; + + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getNumber}; + + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getString}; + + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getArray}; + + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getObject}; + + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getObjectShape}; + setMethodArgConversionSelector(@\\"getObjectShape\\", 0, @\\"JS_NativeSampleTurboModuleNullable_SpecGetObjectShapeArg:\\"); + + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getAlias}; + setMethodArgConversionSelector(@\\"getAlias\\", 0, @\\"JS_NativeSampleTurboModuleNullable_Animal:\\"); + + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getRootTag}; + + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValue}; + + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValueWithCallback}; + + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getValueWithPromise}; + + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleNullableSpecJSI_getConstants}; + + + } + } // namespace react +} // namespace facebook + + + +@implementation RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + + +@implementation RCTCxxConvert (NativeSampleTurboModuleNullableAndOptional_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleNullableAndOptional_Animal:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getBool\\", @selector(getBool:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + + NativeSampleTurboModuleNullableAndOptionalSpecJSI::NativeSampleTurboModuleNullableAndOptionalSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_voidFunc}; + + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getBool}; + + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getNumber}; + + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getString}; + + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getArray}; + + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getObject}; + + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getObjectShape}; + setMethodArgConversionSelector(@\\"getObjectShape\\", 0, @\\"JS_NativeSampleTurboModuleNullableAndOptional_SpecGetObjectShapeArg:\\"); + + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getAlias}; + setMethodArgConversionSelector(@\\"getAlias\\", 0, @\\"JS_NativeSampleTurboModuleNullableAndOptional_Animal:\\"); + + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getRootTag}; + + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValue}; + + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValueWithCallback}; + + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getValueWithPromise}; + + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleNullableAndOptionalSpecJSI_getConstants}; + + + } + } // namespace react +} // namespace facebook + + + +@implementation RCTCxxConvert (NativeSampleTurboModuleOptional_SpecGetObjectShapeArg) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_SpecGetObjectShapeArg:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + + +@implementation RCTCxxConvert (NativeSampleTurboModuleOptional_Animal) ++ (RCTManagedPointer *)JS_NativeSampleTurboModuleOptional_Animal:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getBool\\", @selector(getBool:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getObjectShape(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObjectShape\\", @selector(getObjectShape:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getAlias\\", @selector(getAlias:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + + NativeSampleTurboModuleOptionalSpecJSI::NativeSampleTurboModuleOptionalSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_voidFunc}; + + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getBool}; + + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getNumber}; + + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getString}; + + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getArray}; + + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getObject}; + + + + methodMap_[\\"getObjectShape\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getObjectShape}; + setMethodArgConversionSelector(@\\"getObjectShape\\", 0, @\\"JS_NativeSampleTurboModuleOptional_SpecGetObjectShapeArg:\\"); + + + methodMap_[\\"getAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getAlias}; + setMethodArgConversionSelector(@\\"getAlias\\", 0, @\\"JS_NativeSampleTurboModuleOptional_Animal:\\"); + + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getRootTag}; + + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValue}; + + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValueWithCallback}; + + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getValueWithPromise}; + + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleOptionalSpecJSI_getConstants}; + + + } + } // namespace react +} // namespace facebook + + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeStringTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + } + + + static facebook::jsi::Value __hostFunction_NativeStringTurboModuleSpecJSI_getStringWithAlias(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getStringWithAlias\\", @selector(getStringWithAlias:), args, count); + } + + + NativeStringTurboModuleSpecJSI::NativeStringTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeStringTurboModuleSpecJSI_getString}; + + + + methodMap_[\\"getStringWithAlias\\"] = MethodMetadata {1, __hostFunction_NativeStringTurboModuleSpecJSI_getStringWithAlias}; + + + } + } // namespace react +} // namespace facebook + +" +`; diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index 6f6cac7bb3599f..014bd03565390b 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -24,6 +24,7 @@ }, "devDependencies": { "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", "@babel/plugin-proposal-object-rest-spread": "^7.0.0", "@babel/plugin-proposal-optional-chaining": "^7.0.0", diff --git a/packages/react-native-codegen/src/CodegenSchema.js b/packages/react-native-codegen/src/CodegenSchema.js index ffd3a1a4666173..7e35b52207aac7 100644 --- a/packages/react-native-codegen/src/CodegenSchema.js +++ b/packages/react-native-codegen/src/CodegenSchema.js @@ -248,7 +248,7 @@ export type SchemaType = $ReadOnly<{| [module: string]: $ReadOnly<{| components?: $ReadOnly<{[component: string]: ComponentShape, ...}>, nativeModules?: $ReadOnly<{ - [nativeModule: string]: NativeModuleShape, + [nativeModule: string]: NativeModuleSchema, ..., }>, |}>, @@ -258,112 +258,152 @@ export type SchemaType = $ReadOnly<{| /** * NativeModule Types + * + * TODO(T71923114): Remove nullable from NativeModule type annotations. + * This is necessary for us to start unifying the notion of a "type + * annotation" across the codegen schema as a whole. */ -export type NativeModuleShape = $ReadOnly<{| +export type Required = $ReadOnly<{...T, nullable: false}>; + +export type NativeModuleSchema = $ReadOnly<{| // We only support aliases to Objects - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, - properties: $ReadOnlyArray, + aliases: NativeModuleAliasMap, + properties: $ReadOnlyArray, |}>; -export type ObjectTypeAliasTypeShape = $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, +export type NativeModuleAliasMap = $ReadOnly<{| + [aliasName: string]: Required, |}>; -export type NativeModuleMethodTypeShape = $ReadOnly<{| +export type NativeModulePropertySchema = $ReadOnly<{| name: string, - typeAnnotation: FunctionTypeAnnotation, + optional: boolean, + typeAnnotation: NativeModuleFunctionTypeAnnotation, |}>; -export type FunctionTypeAnnotation = $ReadOnly<{| +export type NativeModuleFunctionTypeAnnotation = $ReadOnly<{| type: 'FunctionTypeAnnotation', - params: $ReadOnlyArray, - returnTypeAnnotation: FunctionTypeAnnotationReturn, + params: $ReadOnlyArray, + returnTypeAnnotation: NativeModuleReturnTypeAnnotation, + nullable: boolean, +|}>; + +export type NativeModuleMethodParamSchema = $ReadOnly<{| + name: string, optional: boolean, + typeAnnotation: NativeModuleParamTypeAnnotation, |}>; -export type FunctionTypeAnnotationReturn = - | $ReadOnly<{| - nullable: boolean, - type: - | 'GenericPromiseTypeAnnotation' - | 'VoidTypeAnnotation' - | PrimitiveTypeAnnotationType, - |}> - | $ReadOnly<{| - nullable: boolean, - type: 'ReservedFunctionValueTypeAnnotation', - name: ReservedFunctionValueTypeName, - |}> - | $ReadOnly<{| - nullable: boolean, - type: 'ArrayTypeAnnotation', - elementType: ?FunctionTypeAnnotationReturnArrayElementType, - |}> - | $ReadOnly<{| - nullable: boolean, - type: 'ObjectTypeAnnotation', - properties: ?$ReadOnlyArray, - |}>; +export type NativeModuleObjectTypeAnnotation = $ReadOnly<{| + type: 'ObjectTypeAnnotation', + properties: $ReadOnlyArray< + $ReadOnly<{| + name: string, + optional: boolean, + typeAnnotation: NativeModuleBaseTypeAnnotation, + |}>, + >, + nullable: boolean, +|}>; -export type FunctionTypeAnnotationReturnArrayElementType = - | FunctionTypeAnnotationParamTypeAnnotation // TODO: What does FunctionTypeAnnotationParamTypeAnnotation have to do with function returns? - | TypeAliasTypeAnnotation; +export type NativeModuleArrayTypeAnnotation< + T = NativeModuleBaseTypeAnnotation, +> = $ReadOnly<{| + type: 'ArrayTypeAnnotation', + /** + * TODO(T72031674): Migrate all our NativeModule specs to not use + * invalid Array ElementTypes. Then, make the elementType required. + */ + elementType?: T, + nullable: boolean, +|}>; -export type TypeAliasTypeAnnotation = $ReadOnly<{| - type: 'TypeAliasTypeAnnotation', - name: string, +export type NativeModuleStringTypeAnnotation = $ReadOnly<{| + type: 'StringTypeAnnotation', + nullable: boolean, |}>; -export type FunctionTypeAnnotationParam = $ReadOnly<{| +export type NativeModuleNumberTypeAnnotation = $ReadOnly<{| + type: 'NumberTypeAnnotation', nullable: boolean, - name: string, - typeAnnotation: - | FunctionTypeAnnotationParamTypeAnnotation - | TypeAliasTypeAnnotation, |}>; -export type FunctionTypeAnnotationParamTypeAnnotation = - | $ReadOnly<{| - type: - | 'AnyTypeAnnotation' - | 'FunctionTypeAnnotation' - | PrimitiveTypeAnnotationType, - |}> - | $ReadOnly<{| - type: 'ReservedFunctionValueTypeAnnotation', - name: ReservedFunctionValueTypeName, - |}> - | $ReadOnly<{| - type: 'ArrayTypeAnnotation', - elementType: - | ?FunctionTypeAnnotationParamTypeAnnotation - | ?TypeAliasTypeAnnotation, - |}> - | $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: ?$ReadOnlyArray, - |}>; +export type NativeModuleInt32TypeAnnotation = $ReadOnly<{| + type: 'Int32TypeAnnotation', + nullable: boolean, +|}>; -export type PrimitiveTypeAnnotationType = - | 'StringTypeAnnotation' - | 'NumberTypeAnnotation' - | 'Int32TypeAnnotation' - | 'DoubleTypeAnnotation' - | 'FloatTypeAnnotation' - | 'BooleanTypeAnnotation' - | 'GenericObjectTypeAnnotation'; +export type NativeModuleDoubleTypeAnnotation = $ReadOnly<{| + type: 'DoubleTypeAnnotation', + nullable: boolean, +|}>; -export type PrimitiveTypeAnnotation = $ReadOnly<{| - type: PrimitiveTypeAnnotationType, +export type NativeModuleFloatTypeAnnotation = $ReadOnly<{| + type: 'FloatTypeAnnotation', + nullable: boolean, |}>; -export type ReservedFunctionValueTypeName = 'RootTag'; // Union with more custom types. +export type NativeModuleBooleanTypeAnnotation = $ReadOnly<{| + type: 'BooleanTypeAnnotation', + nullable: boolean, +|}>; -export type ObjectParamTypeAnnotation = $ReadOnly<{| - optional: boolean, +export type NativeModuleGenericObjectTypeAnnotation = $ReadOnly<{| + type: 'GenericObjectTypeAnnotation', + nullable: boolean, +|}>; + +export type NativeModuleReservedFunctionValueTypeAnnotation = $ReadOnly<{| + type: 'ReservedFunctionValueTypeAnnotation', + name: ReservedFunctionValueTypeName, + nullable: boolean, +|}>; + +export type NativeModuleTypeAliasTypeAnnotation = $ReadOnly<{| + type: 'TypeAliasTypeAnnotation', name: string, - typeAnnotation?: - | FunctionTypeAnnotationParamTypeAnnotation - | TypeAliasTypeAnnotation, // TODO (T67898313): Workaround for NativeLinking's use of union type, typeAnnotations should not be optional + nullable: boolean, |}>; + +export type NativeModulePromiseTypeAnnotation = $ReadOnly<{| + type: 'PromiseTypeAnnotation', + nullable: boolean, +|}>; + +export type NativeModuleVoidTypeAnnotation = $ReadOnly<{| + type: 'VoidTypeAnnotation', + nullable: boolean, +|}>; + +export type NativeModuleBaseTypeAnnotation = + | NativeModuleStringTypeAnnotation + | NativeModuleNumberTypeAnnotation + | NativeModuleInt32TypeAnnotation + | NativeModuleDoubleTypeAnnotation + | NativeModuleFloatTypeAnnotation + | NativeModuleBooleanTypeAnnotation + | NativeModuleGenericObjectTypeAnnotation + | NativeModuleReservedFunctionValueTypeAnnotation + | NativeModuleTypeAliasTypeAnnotation + | NativeModuleArrayTypeAnnotation<> + | NativeModuleObjectTypeAnnotation; + +export type NativeModuleParamTypeAnnotation = + | NativeModuleBaseTypeAnnotation + | NativeModuleParamOnlyTypeAnnotation; + +export type NativeModuleReturnTypeAnnotation = + | NativeModuleBaseTypeAnnotation + | NativeModuleReturnOnlyTypeAnnotation; + +export type NativeModuleTypeAnnotation = + | NativeModuleBaseTypeAnnotation + | NativeModuleParamOnlyTypeAnnotation + | NativeModuleReturnOnlyTypeAnnotation; + +type NativeModuleParamOnlyTypeAnnotation = NativeModuleFunctionTypeAnnotation; +type NativeModuleReturnOnlyTypeAnnotation = + | NativeModulePromiseTypeAnnotation + | NativeModuleVoidTypeAnnotation; + +export type ReservedFunctionValueTypeName = 'RootTag'; // Union with more custom types. diff --git a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js index f9a0a07d8c90af..30443a09c35381 100644 --- a/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js +++ b/packages/react-native-codegen/src/cli/combine/combine-js-to-schema-cli.js @@ -32,6 +32,9 @@ fileList.forEach(file => { // NativeUIManager will be deprecated by Fabric UIManager. // For now, ignore this spec completely because the types are not fully supported. !f.endsWith('NativeUIManager.js') && + // NativeSampleTurboModule is for demo purpose. It should be added manually to the + // app for now. + !f.endsWith('NativeSampleTurboModule.js') && !f.includes('__tests'), ); allFiles.push(...dirFiles); diff --git a/packages/react-native-codegen/src/generators/RNCodegen.js b/packages/react-native-codegen/src/generators/RNCodegen.js index 576d984abd8d71..b6f6e02a922255 100644 --- a/packages/react-native-codegen/src/generators/RNCodegen.js +++ b/packages/react-native-codegen/src/generators/RNCodegen.js @@ -25,11 +25,10 @@ const generatePropsCpp = require('./components/GeneratePropsCpp.js'); const generatePropsH = require('./components/GeneratePropsH.js'); const generateModuleH = require('./modules/GenerateModuleH.js'); const generateModuleCpp = require('./modules/GenerateModuleCpp.js'); -const generateModuleHObjCpp = require('./modules/GenerateModuleHObjCpp.js'); +const generateModuleObjCpp = require('./modules/GenerateModuleObjCpp'); const generateModuleJavaSpec = require('./modules/GenerateModuleJavaSpec.js'); const GenerateModuleJniCpp = require('./modules/GenerateModuleJniCpp.js'); const GenerateModuleJniH = require('./modules/GenerateModuleJniH.js'); -const generateModuleMm = require('./modules/GenerateModuleMm.js'); const generatePropsJavaInterface = require('./components/GeneratePropsJavaInterface.js'); const generatePropsJavaDelegate = require('./components/GeneratePropsJavaDelegate.js'); const generateTests = require('./components/GenerateTests.js'); @@ -74,8 +73,7 @@ const GENERATORS = { modules: [ generateModuleCpp.generate, generateModuleH.generate, - generateModuleHObjCpp.generate, - generateModuleMm.generate, + generateModuleObjCpp.generate, ], // TODO: Refactor this to consolidate various C++ output variation instead of forking Android. modulesAndroid: [ diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js index cf02b4095b1c92..deb38646197c44 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js @@ -10,8 +10,15 @@ 'use strict'; -import type {SchemaType} from '../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('./Utils'); +import type { + SchemaType, + NativeModulePropertySchema, + NativeModuleMethodParamSchema, +} from '../../CodegenSchema'; + +import type {AliasResolver} from './Utils'; +const {createAliasResolver, getModules} = require('./Utils'); + type FilesOutput = Map; const propertyHeaderTemplate = @@ -44,7 +51,7 @@ Native::_MODULE_NAME_::CxxSpecJSI::Native::_MODULE_NAME_::CxxSpecJSI(std::shared const template = ` /** - * Copyright (c) Facebook, Inc. and its affiliates. + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -64,16 +71,21 @@ namespace react { } // namespace facebook `; -function traverseArg(arg, index, aliases): string { +function traverseArg( + arg: NativeModuleMethodParamSchema, + index: number, + resolveAlias: AliasResolver, +): string { function wrap(suffix) { return `args[${index}]${suffix}`; } const {typeAnnotation} = arg; - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + switch (realTypeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': switch (realTypeAnnotation.name) { @@ -90,7 +102,11 @@ function traverseArg(arg, index, aliases): string { case 'BooleanTypeAnnotation': return wrap('.getBool()'); case 'NumberTypeAnnotation': + return wrap('.getNumber()'); case 'FloatTypeAnnotation': + return wrap('.getNumber()'); + case 'DoubleTypeAnnotation': + return wrap('.getNumber()'); case 'Int32TypeAnnotation': return wrap('.getNumber()'); case 'ArrayTypeAnnotation': @@ -98,26 +114,27 @@ function traverseArg(arg, index, aliases): string { case 'FunctionTypeAnnotation': return `std::move(${wrap('.getObject(rt).getFunction(rt)')})`; case 'GenericObjectTypeAnnotation': + return wrap('.getObject(rt)'); case 'ObjectTypeAnnotation': return wrap('.getObject(rt)'); - case 'AnyTypeAnnotation': - throw new Error(`Any type is not allowed in params for "${arg.name}"`); default: - // TODO (T65847278): Figure out why this does not work. - // (type: empty); + (realTypeAnnotation.type: empty); throw new Error( `Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.type}"`, ); } } -function traverseProperty(property, aliases): string { +function traverseProperty( + property: NativeModulePropertySchema, + resolveAlias: AliasResolver, +): string { const propertyTemplate = property.typeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation' ? voidPropertyTemplate : nonvoidPropertyTemplate; const traversedArgs = property.typeAnnotation.params - .map((p, i) => traverseArg(p, i, aliases)) + .map((p, i) => traverseArg(p, i, resolveAlias)) .join(', '); return propertyTemplate .replace(/::_PROPERTY_NAME_::/g, property.name) @@ -130,23 +147,14 @@ module.exports = { schema: SchemaType, moduleSpecName: string, ): FilesOutput { - const nativeModules = Object.keys(schema.modules) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, modules) => Object.assign(acc, modules), {}); + const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) .map(name => { const {aliases, properties} = nativeModules[name]; + const resolveAlias = createAliasResolver(aliases); const traversedProperties = properties - .map(property => traverseProperty(property, aliases)) + .map(property => traverseProperty(property, resolveAlias)) .join('\n'); return moduleTemplate .replace(/::_MODULE_PROPERTIES_::/g, traversedProperties) diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js index 7342ad01a7c32a..420b6f6a33fa18 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js @@ -10,15 +10,10 @@ 'use strict'; -import type { - SchemaType, - FunctionTypeAnnotationParamTypeAnnotation, - FunctionTypeAnnotationReturn, - TypeAliasTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../CodegenSchema'; +import type {SchemaType, NativeModuleTypeAnnotation} from '../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('./Utils'); +import type {AliasResolver} from './Utils'; +const {createAliasResolver, getModules} = require('./Utils'); type FilesOutput = Map; @@ -32,8 +27,9 @@ public: };`; -const template = `/** - * Copyright (c) Facebook, Inc. and its affiliates. +const template = ` +/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -54,17 +50,15 @@ namespace react { `; function translatePrimitiveJSTypeToCpp( - typeAnnotation: - | FunctionTypeAnnotationParamTypeAnnotation - | FunctionTypeAnnotationReturn - | TypeAliasTypeAnnotation, + typeAnnotation: NativeModuleTypeAnnotation, createErrorMessage: (typeName: string) => string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + resolveAlias: AliasResolver, ) { - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + switch (realTypeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': switch (realTypeAnnotation.name) { @@ -79,6 +73,9 @@ function translatePrimitiveJSTypeToCpp( case 'StringTypeAnnotation': return 'jsi::String'; case 'NumberTypeAnnotation': + return 'double'; + case 'DoubleTypeAnnotation': + return 'double'; case 'FloatTypeAnnotation': return 'double'; case 'Int32TypeAnnotation': @@ -86,17 +83,17 @@ function translatePrimitiveJSTypeToCpp( case 'BooleanTypeAnnotation': return 'bool'; case 'GenericObjectTypeAnnotation': + return 'jsi::Object'; case 'ObjectTypeAnnotation': return 'jsi::Object'; case 'ArrayTypeAnnotation': return 'jsi::Array'; case 'FunctionTypeAnnotation': return 'jsi::Function'; - case 'GenericPromiseTypeAnnotation': + case 'PromiseTypeAnnotation': return 'jsi::Value'; default: - // TODO (T65847278): Figure out why this does not work. - // (type: empty); + (realTypeAnnotation.type: empty); throw new Error(createErrorMessage(realTypeAnnotation.type)); } } @@ -110,21 +107,13 @@ module.exports = { schema: SchemaType, moduleSpecName: string, ): FilesOutput { - const nativeModules = Object.keys(schema.modules) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, components) => Object.assign(acc, components), {}); + const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) .map(name => { const {aliases, properties} = nativeModules[name]; + const resolveAlias = createAliasResolver(aliases); + const traversedProperties = properties .map(prop => { const traversedArgs = prop.typeAnnotation.params @@ -133,7 +122,7 @@ module.exports = { param.typeAnnotation, typeName => `Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`, - aliases, + resolveAlias, ); const isObject = translatedParam.startsWith('jsi::'); return ( @@ -151,7 +140,7 @@ module.exports = { prop.typeAnnotation.returnTypeAnnotation, typeName => `Unsupported return type for ${prop.name}. Found: ${typeName}`, - aliases, + resolveAlias, ), ) .replace( diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js deleted file mode 100644 index c9f173df868e37..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleHObjCpp.js +++ /dev/null @@ -1,415 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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 - */ - -'use strict'; - -import type { - SchemaType, - FunctionTypeAnnotationParam, - FunctionTypeAnnotationReturn, - ObjectParamTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../CodegenSchema'; - -const { - translateObjectsForStructs, - capitalizeFirstLetter, - getNamespacedStructName, -} = require('./ObjCppUtils/GenerateStructs'); - -const {getTypeAliasTypeAnnotation} = require('./Utils'); - -type FilesOutput = Map; - -const moduleTemplate = ` /** - * ObjC++ class for module '::_MODULE_NAME_::' - */ - class JSI_EXPORT Native::_MODULE_NAME_::SpecJSI : public ObjCTurboModule { - public: - Native::_MODULE_NAME_::SpecJSI(const ObjCTurboModule::InitParams ¶ms); - };`; - -const protocolTemplate = `::_STRUCTS_:: - -@protocol Native::_MODULE_NAME_::Spec -::_MODULE_PROPERTIES_:: -@end -`; - -const callbackArgs = prop => - prop.typeAnnotation.returnTypeAnnotation.type === - 'GenericPromiseTypeAnnotation' - ? `${ - prop.typeAnnotation.params.length === 0 ? '' : '\n resolve' - }:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject` - : ''; - -const template = ` -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * ${'@'}generated by codegen project: GenerateModuleHObjCpp.js - */ - -#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 - -#import - -#import - -#import - -#import -#import -#import - -#import -#import -#import - -#import - -::_PROTOCOLS_:: - -namespace facebook { - namespace react { -::_MODULES_:: - } // namespace react -} // namespace facebook -`; - -type ObjectForGeneratingStructs = $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, -|}>; - -const constants = `- (facebook::react::ModuleConstants)constantsToExport; -- (facebook::react::ModuleConstants)getConstants;`; - -function translatePrimitiveJSTypeToObjCType( - param: FunctionTypeAnnotationParam, - createErrorMessage: (typeName: string) => string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -) { - const {nullable, typeAnnotation} = param; - - function wrapIntoNullableIfNeeded(generatedType: string) { - return nullable ? `${generatedType} _Nullable` : generatedType; - } - - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; - switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (realTypeAnnotation.name) { - case 'RootTag': - return nullable ? 'NSNumber *' : 'double'; - default: - (realTypeAnnotation.name: empty); - throw new Error(createErrorMessage(realTypeAnnotation.name)); - } - case 'StringTypeAnnotation': - return wrapIntoNullableIfNeeded('NSString *'); - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return nullable ? 'NSNumber *' : 'double'; - case 'BooleanTypeAnnotation': - return nullable ? 'NSNumber * _Nullable' : 'BOOL'; - case 'ObjectTypeAnnotation': - if (typeAnnotation.type === 'TypeAliasTypeAnnotation') { - return getNamespacedStructName(typeAnnotation.name) + ' &'; - } - return wrapIntoNullableIfNeeded('NSDictionary *'); - case 'GenericObjectTypeAnnotation': - return wrapIntoNullableIfNeeded('NSDictionary *'); - case 'ArrayTypeAnnotation': - return wrapIntoNullableIfNeeded('NSArray *'); - case 'FunctionTypeAnnotation': - return 'RCTResponseSenderBlock'; - default: - // TODO (T65847278): Figure out why this does not work. - // (type: empty); - throw new Error(createErrorMessage(realTypeAnnotation.type)); - } -} - -function translatePrimitiveJSTypeToObjCTypeForReturn( - typeAnnotation: FunctionTypeAnnotationReturn, - createErrorMessage: (typeName: string) => string, -) { - function wrapIntoNullableIfNeeded(generatedType: string) { - return typeAnnotation.nullable - ? `${generatedType} _Nullable` - : generatedType; - } - switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (typeAnnotation.name) { - case 'RootTag': - return wrapIntoNullableIfNeeded('NSNumber *'); - default: - (typeAnnotation.name: empty); - throw new Error(createErrorMessage(typeAnnotation.name)); - } - case 'VoidTypeAnnotation': - case 'GenericPromiseTypeAnnotation': - return 'void'; - case 'StringTypeAnnotation': - return wrapIntoNullableIfNeeded('NSString *'); - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return wrapIntoNullableIfNeeded('NSNumber *'); - case 'BooleanTypeAnnotation': - return typeAnnotation.nullable ? 'NSNumber * _Nullable' : 'BOOL'; - case 'GenericObjectTypeAnnotation': - return wrapIntoNullableIfNeeded('NSDictionary *'); - case 'ArrayTypeAnnotation': - return wrapIntoNullableIfNeeded('NSArray> *'); - case 'ObjectTypeAnnotation': - return wrapIntoNullableIfNeeded('NSDictionary *'); - default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.type: empty); - throw new Error(createErrorMessage(typeAnnotation.type)); - } -} - -function handleArrayOfObjects( - objectForGeneratingStructs: Array, - propOrParam: FunctionTypeAnnotationParam, - name: string, -) { - if ( - propOrParam.typeAnnotation.type === 'ArrayTypeAnnotation' && - propOrParam.typeAnnotation.elementType - ) { - const typeAnnotation = propOrParam.typeAnnotation.elementType; - const type = typeAnnotation.type; - - if ( - type === 'ObjectTypeAnnotation' && - typeAnnotation.properties && - typeAnnotation.properties.length > 0 - ) { - objectForGeneratingStructs.push({ - name, - object: { - type: 'ObjectTypeAnnotation', - properties: typeAnnotation.properties, - }, - }); - } - } -} - -const methodImplementationTemplate = - '- (::_RETURN_VALUE_::) ::_PROPERTY_NAME_::::_ARGS_::;'; - -module.exports = { - generate( - libraryName: string, - schema: SchemaType, - moduleSpecName: string, - ): FilesOutput { - const nativeModules = Object.keys(schema.modules) - .sort() - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, components) => Object.assign(acc, components), {}); - - const modules = Object.keys(nativeModules) - .map(name => moduleTemplate.replace(/::_MODULE_NAME_::/g, name)) - .join('\n'); - - const protocols = Object.keys(nativeModules) - .sort() - .map(name => { - const objectForGeneratingStructs: Array = []; - const {aliases, properties} = nativeModules[name]; - const implementations = properties - .map(prop => { - const nativeArgs = prop.typeAnnotation.params - .map((param, i) => { - let paramObjCType; - if ( - param.typeAnnotation.type === 'ObjectTypeAnnotation' && - param.typeAnnotation.properties - ) { - const variableName = - capitalizeFirstLetter(prop.name) + - capitalizeFirstLetter(param.name); - const structName = 'Spec' + variableName; - objectForGeneratingStructs.push({ - name: structName, - object: { - type: 'ObjectTypeAnnotation', - properties: param.typeAnnotation.properties, - }, - }); - paramObjCType = getNamespacedStructName(structName) + ' &'; - - param.typeAnnotation.properties.map(aProp => { - return handleArrayOfObjects( - objectForGeneratingStructs, - aProp, - 'Spec' + - capitalizeFirstLetter(prop.name) + - capitalizeFirstLetter(param.name) + - capitalizeFirstLetter(aProp.name) + - 'Element', - ); - }); - } else if ( - param.typeAnnotation.type === 'TypeAliasTypeAnnotation' - ) { - const typeAnnotation = getTypeAliasTypeAnnotation( - param.typeAnnotation.name, - aliases, - ); - if (typeAnnotation.type === 'ObjectTypeAnnotation') { - paramObjCType = - getNamespacedStructName(param.typeAnnotation.name) + ' &'; - } else { - throw Error( - `Unsupported type for "${param.typeAnnotation.name}". Found: ${typeAnnotation.type}`, - ); - } - } else { - paramObjCType = translatePrimitiveJSTypeToObjCType( - param, - typeName => - `Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`, - aliases, - ); - - handleArrayOfObjects( - objectForGeneratingStructs, - param, - 'Spec' + - capitalizeFirstLetter(prop.name) + - capitalizeFirstLetter(param.name) + - 'Element', - ); - } - return `${i === 0 ? '' : param.name}:(${paramObjCType})${ - param.name - }`; - }) - .join('\n ') - .concat(callbackArgs(prop)); - const {returnTypeAnnotation} = prop.typeAnnotation; - if ( - returnTypeAnnotation.type === 'ObjectTypeAnnotation' && - returnTypeAnnotation.properties - ) { - objectForGeneratingStructs.push({ - name: 'Spec' + capitalizeFirstLetter(prop.name) + 'ReturnType', - object: { - type: 'ObjectTypeAnnotation', - properties: returnTypeAnnotation.properties, - }, - }); - } - const implementation = methodImplementationTemplate - .replace('::_PROPERTY_NAME_::', prop.name) - .replace( - '::_RETURN_VALUE_::', - translatePrimitiveJSTypeToObjCTypeForReturn( - returnTypeAnnotation, - typeName => - `Unsupported return type for ${prop.name}. Found: ${typeName}`, - ), - ) - .replace('::_ARGS_::', nativeArgs); - if (prop.name === 'getConstants') { - if ( - prop.typeAnnotation.returnTypeAnnotation.properties && - prop.typeAnnotation.returnTypeAnnotation.properties.length === 0 - ) { - return ''; - } - return constants.replace(/::_MODULE_NAME_::/, name); - } - return implementation; - }) - .join('\n'); - - Object.keys(aliases) - .reverse() - .map((aliasName, i) => { - const alias = aliases[aliasName]; - - let paramObjCType = ''; - - switch (alias.type) { - case 'ObjectTypeAnnotation': - if (alias.properties) { - objectForGeneratingStructs.push({ - name: aliasName, - object: { - type: 'ObjectTypeAnnotation', - properties: alias.properties, - }, - }); - paramObjCType = getNamespacedStructName(alias.name) + ' &'; - } - break; - default: - throw Error( - `Unsupported type for "${aliasName}". Found: ${alias.type}`, - ); - } - return `${i === 0 ? '' : aliasName}:(${paramObjCType})${aliasName}`; - }) - .join('\n'); - - return protocolTemplate - .replace( - /::_STRUCTS_::/g, - translateObjectsForStructs( - objectForGeneratingStructs, - name, - aliases, - ), - ) - .replace(/::_MODULE_PROPERTIES_::/g, implementations) - .replace(/::_MODULE_NAME_::/g, name) - .replace('::_PROPERTIES_MAP_::', ''); - }) - .join('\n'); - - const fileName = `${moduleSpecName}.h`; - const replacedTemplate = template - .replace(/::_MODULES_::/g, modules) - .replace(/::_PROTOCOLS_::/g, protocols); - - return new Map([[fileName, replacedTemplate]]); - }, -}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js index 5054146e4ffc56..69958ca41d6950 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js @@ -11,18 +11,20 @@ 'use strict'; import type { - FunctionTypeAnnotationParam, - FunctionTypeAnnotationReturn, - NativeModuleMethodTypeShape, - ObjectTypeAliasTypeShape, SchemaType, + NativeModulePropertySchema, + NativeModuleMethodParamSchema, + NativeModuleReturnTypeAnnotation, } from '../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('./Utils'); + +import type {AliasResolver} from './Utils'; +const {createAliasResolver, getModules} = require('./Utils'); type FilesOutput = Map; -const moduleTemplate = `/** - * Copyright (c) Facebook, Inc. and its affiliates. +const moduleTemplate = ` +/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root * directory of this source tree. @@ -46,30 +48,32 @@ public abstract class ::_CLASSNAME_:: extends ReactContextBaseJavaModule impleme `; function translateFunctionParamToJavaType( - param: FunctionTypeAnnotationParam, + param: NativeModuleMethodParamSchema, createErrorMessage: (typeName: string) => string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + resolveAlias: AliasResolver, imports: Set, ): string { - const {nullable, typeAnnotation} = param; + const {optional, typeAnnotation} = param; + const isRequired = !optional && !typeAnnotation.nullable; function wrapIntoNullableIfNeeded(generatedType: string) { - if (nullable) { + if (!isRequired) { imports.add('javax.annotation.Nullable'); return `@Nullable ${generatedType}`; } return generatedType; } - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + switch (realTypeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': - return nullable ? 'Double' : 'double'; + return !isRequired ? 'Double' : 'double'; default: (realTypeAnnotation.name: empty); throw new Error(createErrorMessage(realTypeAnnotation.name)); @@ -77,11 +81,15 @@ function translateFunctionParamToJavaType( case 'StringTypeAnnotation': return wrapIntoNullableIfNeeded('String'); case 'NumberTypeAnnotation': + return !isRequired ? 'Double' : 'double'; case 'FloatTypeAnnotation': + return !isRequired ? 'Double' : 'double'; + case 'DoubleTypeAnnotation': + return !isRequired ? 'Double' : 'double'; case 'Int32TypeAnnotation': - return nullable ? 'Double' : 'double'; + return !isRequired ? 'Double' : 'double'; case 'BooleanTypeAnnotation': - return nullable ? 'Boolean' : 'boolean'; + return !isRequired ? 'Boolean' : 'boolean'; case 'ObjectTypeAnnotation': imports.add('com.facebook.react.bridge.ReadableMap'); if (typeAnnotation.type === 'TypeAliasTypeAnnotation') { @@ -100,13 +108,15 @@ function translateFunctionParamToJavaType( imports.add('com.facebook.react.bridge.Callback'); return 'Callback'; default: + (realTypeAnnotation.type: empty); throw new Error(createErrorMessage(realTypeAnnotation.type)); } } function translateFunctionReturnTypeToJavaType( - returnTypeAnnotation: FunctionTypeAnnotationReturn, + returnTypeAnnotation: NativeModuleReturnTypeAnnotation, createErrorMessage: (typeName: string) => string, + resolveAlias: AliasResolver, imports: Set, ): string { const {nullable} = returnTypeAnnotation; @@ -119,23 +129,32 @@ function translateFunctionReturnTypeToJavaType( return generatedType; } - // TODO: Support aliased return type. This doesn't exist in React Native Android yet. - switch (returnTypeAnnotation.type) { + let realTypeAnnotation = returnTypeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + + switch (realTypeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': - switch (returnTypeAnnotation.name) { + switch (realTypeAnnotation.name) { case 'RootTag': return nullable ? 'Double' : 'double'; default: - (returnTypeAnnotation.name: empty); - throw new Error(createErrorMessage(returnTypeAnnotation.name)); + (realTypeAnnotation.name: empty); + throw new Error(createErrorMessage(realTypeAnnotation.name)); } case 'VoidTypeAnnotation': - case 'GenericPromiseTypeAnnotation': + return 'void'; + case 'PromiseTypeAnnotation': return 'void'; case 'StringTypeAnnotation': return wrapIntoNullableIfNeeded('String'); case 'NumberTypeAnnotation': + return nullable ? 'Double' : 'double'; case 'FloatTypeAnnotation': + return nullable ? 'Double' : 'double'; + case 'DoubleTypeAnnotation': + return nullable ? 'Double' : 'double'; case 'Int32TypeAnnotation': return nullable ? 'Double' : 'double'; case 'BooleanTypeAnnotation': @@ -150,13 +169,14 @@ function translateFunctionReturnTypeToJavaType( imports.add('com.facebook.react.bridge.WritableArray'); return 'WritableArray'; default: - throw new Error(createErrorMessage(returnTypeAnnotation.type)); + (realTypeAnnotation.type: empty); + throw new Error(createErrorMessage(realTypeAnnotation.type)); } } // Build special-cased runtime check for getConstants(). function buildGetConstantsMethod( - method: NativeModuleMethodTypeShape, + method: NativeModulePropertySchema, imports: Set, ): string { if ( @@ -240,20 +260,11 @@ module.exports = { const files = new Map(); // TODO: Allow package configuration. const packageName = 'com.facebook.fbreact.specs.beta'; - const nativeModules = Object.keys(schema.modules) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, components) => Object.assign(acc, components), {}); + const nativeModules = getModules(schema); Object.keys(nativeModules).forEach(name => { const {aliases, properties} = nativeModules[name]; + const resolveAlias = createAliasResolver(aliases); const className = `Native${name}Spec`; const imports: Set = new Set([ @@ -275,11 +286,12 @@ module.exports = { method.typeAnnotation.returnTypeAnnotation, typeName => `Unsupported return type for method ${method.name}. Found: ${typeName}`, + resolveAlias, imports, ); const returningPromise = method.typeAnnotation.returnTypeAnnotation.type === - 'GenericPromiseTypeAnnotation'; + 'PromiseTypeAnnotation'; const isSyncMethod = method.typeAnnotation.returnTypeAnnotation.type !== 'VoidTypeAnnotation' && !returningPromise; @@ -290,7 +302,7 @@ module.exports = { param, typeName => `Unsupported type for param "${param.name}" in ${method.name}. Found: ${typeName}`, - aliases, + resolveAlias, imports, ); return `${translatedParam} ${param.name}`; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js index aac88138b51f45..72b48a7fcdab72 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniCpp.js @@ -11,14 +11,14 @@ 'use strict'; import type { - FunctionTypeAnnotationParam, - FunctionTypeAnnotationReturn, - NativeModuleShape, - ObjectTypeAliasTypeShape, SchemaType, + NativeModulePropertySchema, + NativeModuleMethodParamSchema, + NativeModuleReturnTypeAnnotation, } from '../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('./Utils'); +import type {AliasResolver} from './Utils'; +const {createAliasResolver, getModules} = require('./Utils'); type FilesOutput = Map; @@ -50,7 +50,7 @@ const oneModuleLookupTemplate = ` if (moduleName == "::_MODULE_NAME_::") { const template = ` /** - * Copyright (c) Facebook, Inc. and its affiliates. + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -75,17 +75,23 @@ std::shared_ptr ::_LIBRARY_NAME_::_ModuleProvider(const std::string `; function translateReturnTypeToKind( - typeAnnotation: FunctionTypeAnnotationReturn, + typeAnnotation: NativeModuleReturnTypeAnnotation, + resolveAlias: AliasResolver, ): string { - switch (typeAnnotation.type) { + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + + switch (realTypeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': - switch (typeAnnotation.name) { + switch (realTypeAnnotation.name) { case 'RootTag': return 'NumberKind'; default: - (typeAnnotation.name: empty); + (realTypeAnnotation.name: empty); throw new Error( - `Invalid ReservedFunctionValueTypeName name, got ${typeAnnotation.name}`, + `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } case 'VoidTypeAnnotation': @@ -95,62 +101,66 @@ function translateReturnTypeToKind( case 'BooleanTypeAnnotation': return 'BooleanKind'; case 'NumberTypeAnnotation': + return 'NumberKind'; case 'DoubleTypeAnnotation': + return 'NumberKind'; case 'FloatTypeAnnotation': + return 'NumberKind'; case 'Int32TypeAnnotation': return 'NumberKind'; - case 'GenericPromiseTypeAnnotation': + case 'PromiseTypeAnnotation': return 'PromiseKind'; case 'GenericObjectTypeAnnotation': + return 'ObjectKind'; case 'ObjectTypeAnnotation': return 'ObjectKind'; case 'ArrayTypeAnnotation': return 'ArrayKind'; default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.type: empty); + (realTypeAnnotation.type: empty); throw new Error( - `Unknown prop type for returning value, found: ${typeAnnotation.type}"`, + `Unknown prop type for returning value, found: ${realTypeAnnotation.type}"`, ); } } function translateParamTypeToJniType( - param: FunctionTypeAnnotationParam, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + param: NativeModuleMethodParamSchema, + resolveAlias: AliasResolver, ): string { - const {nullable, typeAnnotation} = param; + const {optional, typeAnnotation} = param; + const isRequired = !optional && !typeAnnotation.nullable; - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } switch (realTypeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': - return 'D'; + return !isRequired ? 'Ljava/lang/Double;' : 'D'; default: (realTypeAnnotation.name: empty); throw new Error( `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } - case 'VoidTypeAnnotation': - return 'V'; case 'StringTypeAnnotation': return 'Ljava/lang/String;'; case 'BooleanTypeAnnotation': - return nullable ? 'Ljava/lang/Boolean' : 'Z'; + return !isRequired ? 'Ljava/lang/Boolean' : 'Z'; case 'NumberTypeAnnotation': + return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'DoubleTypeAnnotation': + return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'FloatTypeAnnotation': + return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'Int32TypeAnnotation': - return nullable ? 'Ljava/lang/Double;' : 'D'; - case 'GenericPromiseTypeAnnotation': - return 'Lcom/facebook/react/bridge/Promise;'; + return !isRequired ? 'Ljava/lang/Double;' : 'D'; case 'GenericObjectTypeAnnotation': + return 'Lcom/facebook/react/bridge/ReadableMap;'; case 'ObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/ReadableMap;'; case 'ArrayTypeAnnotation': @@ -158,6 +168,7 @@ function translateParamTypeToJniType( case 'FunctionTypeAnnotation': return 'Lcom/facebook/react/bridge/Callback;'; default: + (realTypeAnnotation.type: empty); throw new Error( `Unknown prop type for method arg, found: ${realTypeAnnotation.type}"`, ); @@ -165,19 +176,25 @@ function translateParamTypeToJniType( } function translateReturnTypeToJniType( - typeAnnotation: FunctionTypeAnnotationReturn, + typeAnnotation: NativeModuleReturnTypeAnnotation, + resolveAlias: AliasResolver, ): string { const {nullable} = typeAnnotation; - switch (typeAnnotation.type) { + let realTypeAnnotation = typeAnnotation; + if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { + realTypeAnnotation = resolveAlias(realTypeAnnotation.name); + } + + switch (realTypeAnnotation.type) { case 'ReservedFunctionValueTypeAnnotation': - switch (typeAnnotation.name) { + switch (realTypeAnnotation.name) { case 'RootTag': - return 'D'; + return nullable ? 'Ljava/lang/Double;' : 'D'; default: - (typeAnnotation.name: empty); + (realTypeAnnotation.name: empty); throw new Error( - `Invalid ReservedFunctionValueTypeName name, got ${typeAnnotation.name}`, + `Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`, ); } case 'VoidTypeAnnotation': @@ -187,35 +204,39 @@ function translateReturnTypeToJniType( case 'BooleanTypeAnnotation': return nullable ? 'Ljava/lang/Boolean' : 'Z'; case 'NumberTypeAnnotation': + return nullable ? 'Ljava/lang/Double;' : 'D'; case 'DoubleTypeAnnotation': + return nullable ? 'Ljava/lang/Double;' : 'D'; case 'FloatTypeAnnotation': + return nullable ? 'Ljava/lang/Double;' : 'D'; case 'Int32TypeAnnotation': return nullable ? 'Ljava/lang/Double;' : 'D'; - case 'GenericPromiseTypeAnnotation': + case 'PromiseTypeAnnotation': return 'Lcom/facebook/react/bridge/Promise;'; case 'GenericObjectTypeAnnotation': + return 'Lcom/facebook/react/bridge/WritableMap;'; case 'ObjectTypeAnnotation': return 'Lcom/facebook/react/bridge/WritableMap;'; case 'ArrayTypeAnnotation': return 'Lcom/facebook/react/bridge/WritableArray;'; default: + (realTypeAnnotation.type: empty); throw new Error( - `Unknown prop type for method return type, found: ${typeAnnotation.type}"`, + `Unknown prop type for method return type, found: ${realTypeAnnotation.type}"`, ); } } function translateMethodTypeToJniSignature( - property, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + property: NativeModulePropertySchema, + resolveAlias: AliasResolver, ): string { const {name, typeAnnotation} = property; const {returnTypeAnnotation} = typeAnnotation; const params = [...typeAnnotation.params]; let processedReturnTypeAnnotation = returnTypeAnnotation; - const isPromiseReturn = - returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation'; + const isPromiseReturn = returnTypeAnnotation.type === 'PromiseTypeAnnotation'; if (isPromiseReturn) { processedReturnTypeAnnotation = { nullable: false, @@ -224,36 +245,39 @@ function translateMethodTypeToJniSignature( } const argsSignatureParts = params.map(t => { - return translateParamTypeToJniType(t, aliases); + return translateParamTypeToJniType(t, resolveAlias); }); if (isPromiseReturn) { // Additional promise arg for this case. - argsSignatureParts.push(translateReturnTypeToJniType(returnTypeAnnotation)); + argsSignatureParts.push( + translateReturnTypeToJniType(returnTypeAnnotation, resolveAlias), + ); } const argsSignature = argsSignatureParts.join(''); const returnSignature = name === 'getConstants' ? 'Ljava/util/Map;' - : translateReturnTypeToJniType(processedReturnTypeAnnotation); + : translateReturnTypeToJniType( + processedReturnTypeAnnotation, + resolveAlias, + ); return `(${argsSignature})${returnSignature}`; } function translateMethodForImplementation( - property, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, + property: NativeModulePropertySchema, + resolveAlias: AliasResolver, ): string { const {returnTypeAnnotation} = property.typeAnnotation; const numberOfParams = property.typeAnnotation.params.length + - (returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation' ? 1 : 0); + (returnTypeAnnotation.type === 'PromiseTypeAnnotation' ? 1 : 0); const translatedArguments = property.typeAnnotation.params .map(param => param.name) .concat( - returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation' - ? ['promise'] - : [], + returnTypeAnnotation.type === 'PromiseTypeAnnotation' ? ['promise'] : [], ) .slice(1) .join(':') @@ -267,7 +291,10 @@ function translateMethodForImplementation( return ''; } return propertyTemplate - .replace(/::_KIND_::/g, translateReturnTypeToKind(returnTypeAnnotation)) + .replace( + /::_KIND_::/g, + translateReturnTypeToKind(returnTypeAnnotation, resolveAlias), + ) .replace(/::_PROPERTY_NAME_::/g, property.name) .replace( /::_ARGS_::/g, @@ -277,7 +304,7 @@ function translateMethodForImplementation( ) .replace( /::_SIGNATURE_::/g, - translateMethodTypeToJniSignature(property, aliases), + translateMethodTypeToJniSignature(property, resolveAlias), ); } @@ -287,25 +314,17 @@ module.exports = { schema: SchemaType, moduleSpecName: string, ): FilesOutput { - const nativeModules: {[name: string]: NativeModuleShape, ...} = Object.keys( - schema.modules, - ) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, modules) => Object.assign(acc, modules), {}); + const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) .map(name => { const {aliases, properties} = nativeModules[name]; + const resolveAlias = createAliasResolver(aliases); + const translatedMethods = properties - .map(property => translateMethodForImplementation(property, aliases)) + .map(property => + translateMethodForImplementation(property, resolveAlias), + ) .join('\n'); return moduleTemplate .replace(/::_TURBOMODULE_METHOD_INVOKERS_::/g, translatedMethods) diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js index 4d9a5aac0cf688..18dde67c9b1297 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJniH.js @@ -14,6 +14,8 @@ import type {SchemaType} from '../../CodegenSchema'; type FilesOutput = Map; +const {getModules} = require('./Utils'); + const moduleTemplate = `/** * JNI C++ class for module '::_MODULE_NAME_::' */ @@ -23,8 +25,9 @@ public: }; `; -const template = `/** - * Copyright (c) Facebook, Inc. and its affiliates. +const template = ` +/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -84,19 +87,7 @@ module.exports = { schema: SchemaType, moduleSpecName: string, ): FilesOutput { - const nativeModules = Object.keys(schema.modules) - .sort() - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, components) => Object.assign(acc, components), {}); - + const nativeModules = getModules(schema); const modules = Object.keys(nativeModules) .map(name => moduleTemplate.replace(/::_MODULE_NAME_::/g, name)) .join('\n'); diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js deleted file mode 100644 index 8b60d07e127429..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleMm.js +++ /dev/null @@ -1,320 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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 - */ - -'use strict'; - -import type {SchemaType, NativeModuleShape} from '../../CodegenSchema'; - -const {capitalizeFirstLetter} = require('./ObjCppUtils/GenerateStructs'); -const {flatObjects} = require('./ObjCppUtils/Utils'); -const {getTypeAliasTypeAnnotation} = require('./Utils'); - -type FilesOutput = Map; - -const propertyHeaderTemplate = - ' static facebook::jsi::Value __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {'; - -const propertyCastTemplate = `static_cast(turboModule) - .invokeObjCMethod(rt, ::_KIND_::, "::_PROPERTY_NAME_::", @selector(::_PROPERTY_NAME_::::_ARGS_::), args, count);`; - -const propertyTemplate = ` -${propertyHeaderTemplate} - return ${propertyCastTemplate} - }`; - -const propertyDefTemplate = - ' methodMap_["::_PROPERTY_NAME_::"] = MethodMetadata {::_ARGS_COUNT_::, __hostFunction_Native::_MODULE_NAME_::SpecJSI_::_PROPERTY_NAME_::};'; - -const moduleTemplate = ` - ::_TURBOMODULE_METHOD_INVOKERS_:: - - Native::_MODULE_NAME_::SpecJSI::Native::_MODULE_NAME_::SpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - ::_PROPERTIES_MAP_::::_CONVERSION_SELECTORS_:: - }`.trim(); - -const getterTemplate = ` -@implementation RCTCxxConvert (Native::_MODULE_NAME_::_::_GETTER_NAME_::) -+ (RCTManagedPointer *)JS_Native::_MODULE_NAME_::_::_GETTER_NAME_:::(id)json -{ - return facebook::react::managedPointer(json); -} -@end -`; - -const argConvertionTemplate = - '\n setMethodArgConversionSelector(@"::_ARG_NAME_::", ::_ARG_NUMBER_::, @"JS_Native::_MODULE_NAME_::_::_SELECTOR_NAME_:::");'; - -const template = ` -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * ${'@'}generated by codegen project: GenerateModuleMm.js - */ - -#include <::_INCLUDE_::> -#import - -::_GETTERS_:: -namespace facebook { - namespace react { -::_MODULES_:: - } // namespace react -} // namespace facebook -`; - -function translateReturnTypeToKind(typeAnnotation): string { - switch (typeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (typeAnnotation.name) { - case 'RootTag': - return 'NumberKind'; - default: - (typeAnnotation.name: empty); - throw new Error( - `Invalid ReservedFunctionValueTypeName name, got ${typeAnnotation.name}`, - ); - } - case 'VoidTypeAnnotation': - return 'VoidKind'; - case 'StringTypeAnnotation': - return 'StringKind'; - case 'BooleanTypeAnnotation': - return 'BooleanKind'; - case 'NumberTypeAnnotation': - case 'DoubleTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return 'NumberKind'; - case 'GenericPromiseTypeAnnotation': - return 'PromiseKind'; - case 'GenericObjectTypeAnnotation': - case 'ObjectTypeAnnotation': - return 'ObjectKind'; - case 'ArrayTypeAnnotation': - return 'ArrayKind'; - default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.type: empty); - throw new Error( - `Unknown prop type for returning value, found: ${typeAnnotation.type}"`, - ); - } -} - -function translateMethodForImplementation(property): string { - const {returnTypeAnnotation} = property.typeAnnotation; - - const numberOfParams = - property.typeAnnotation.params.length + - (returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation' ? 2 : 0); - const translatedArguments = property.typeAnnotation.params - .map(param => param.name) - .concat( - returnTypeAnnotation.type === 'GenericPromiseTypeAnnotation' - ? ['resolve', 'reject'] - : [], - ) - .slice(1) - .join(':') - .concat(':'); - if ( - property.name === 'getConstants' && - returnTypeAnnotation.type === 'ObjectTypeAnnotation' && - returnTypeAnnotation.properties && - returnTypeAnnotation.properties.length === 0 - ) { - return ''; - } - return propertyTemplate - .replace(/::_KIND_::/g, translateReturnTypeToKind(returnTypeAnnotation)) - .replace(/::_PROPERTY_NAME_::/g, property.name) - .replace( - /::_ARGS_::/g, - numberOfParams === 0 - ? '' - : (numberOfParams === 1 ? '' : ':') + translatedArguments, - ); -} - -module.exports = { - generate( - libraryName: string, - schema: SchemaType, - moduleSpecName: string, - ): FilesOutput { - const nativeModules: {[name: string]: NativeModuleShape, ...} = Object.keys( - schema.modules, - ) - .map(moduleName => { - const modules = schema.modules[moduleName].nativeModules; - if (modules == null) { - return null; - } - - return modules; - }) - .filter(Boolean) - .reduce((acc, modules) => Object.assign(acc, modules), {}); - - const gettersImplementations = Object.keys(nativeModules) - .reduce((acc, moduleName: string) => { - const module: NativeModuleShape = nativeModules[moduleName]; - return acc.concat( - flatObjects( - module.properties - .reduce((moduleAcc, property) => { - const {returnTypeAnnotation} = property.typeAnnotation; - if (returnTypeAnnotation.type === 'ObjectTypeAnnotation') { - const {properties} = returnTypeAnnotation; - if (properties) { - moduleAcc.push({ - name: - 'Spec' + - capitalizeFirstLetter(property.name) + - 'ReturnType', - object: { - type: 'ObjectTypeAnnotation', - properties: properties, - }, - }); - } - } - if (property.typeAnnotation.params) { - return moduleAcc.concat( - property.typeAnnotation.params - .map(param => { - if ( - param.typeAnnotation.type === 'ObjectTypeAnnotation' - ) { - const {properties} = param.typeAnnotation; - if (properties) { - return { - name: - 'Spec' + - capitalizeFirstLetter(property.name) + - capitalizeFirstLetter(param.name), - object: { - type: 'ObjectTypeAnnotation', - properties: properties, - }, - }; - } - } - }) - .filter(Boolean), - ); - } - return moduleAcc; - }, []) - .concat( - Object.keys(module.aliases).map(aliasName => { - const alias = getTypeAliasTypeAnnotation( - aliasName, - module.aliases, - ); - return { - name: aliasName, - object: {type: alias.type, properties: alias.properties}, - }; - }), - ), - false, - module.aliases, - ) - .map(object => - getterTemplate - .replace(/::_GETTER_NAME_::/g, object.name) - .replace(/::_MODULE_NAME_::/g, moduleName), - ) - .join('\n'), - ); - }, []) - .join('\n'); - - const modules = Object.keys(nativeModules) - .map(name => { - const {aliases, properties} = nativeModules[name]; - const translatedMethods = properties - .map(property => translateMethodForImplementation(property)) - .join('\n'); - return moduleTemplate - .replace(/::_TURBOMODULE_METHOD_INVOKERS_::/g, translatedMethods) - .replace( - '::_PROPERTIES_MAP_::', - properties - .map( - ({ - name: propertyName, - typeAnnotation: {params, returnTypeAnnotation}, - }) => - propertyName === 'getConstants' && - returnTypeAnnotation.type === 'ObjectTypeAnnotation' && - returnTypeAnnotation.properties && - returnTypeAnnotation.properties.length === 0 - ? '' - : propertyDefTemplate - .replace(/::_PROPERTY_NAME_::/g, propertyName) - .replace(/::_ARGS_COUNT_::/g, params.length.toString()), - ) - .join('\n'), - ) - .replace( - '::_CONVERSION_SELECTORS_::', - properties - .map(({name: propertyName, typeAnnotation: {params}}) => - params - .map((param, index) => { - const typeAnnotation = - param.typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation( - param.typeAnnotation.name, - aliases, - ) - : param.typeAnnotation; - const selectorName = - param.typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? param.typeAnnotation.name - : 'Spec' + - capitalizeFirstLetter(propertyName) + - capitalizeFirstLetter(param.name); - - if ( - typeAnnotation.type === 'ObjectTypeAnnotation' && - typeAnnotation.properties - ) { - return argConvertionTemplate - .replace('::_SELECTOR_NAME_::', selectorName) - .replace('::_ARG_NUMBER_::', index.toString()) - .replace('::_ARG_NAME_::', propertyName); - } - - return ''; - }) - .join(''), - ) - .join(''), - ) - .replace(/::_MODULE_NAME_::/g, name); - }) - .join('\n'); - - const fileName = `${moduleSpecName}-generated.mm`; - const replacedTemplate = template - .replace(/::_GETTERS_::/g, gettersImplementations) - .replace(/::_MODULES_::/g, modules) - .replace(/::_LIBRARY_NAME_::/g, libraryName) - .replace(/::_INCLUDE_::/g, `${moduleSpecName}/${moduleSpecName}.h`); - return new Map([[fileName, replacedTemplate]]); - }, -}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js new file mode 100644 index 00000000000000..71855f15f4f864 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/StructCollector.js @@ -0,0 +1,191 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +import type { + Required, + NativeModuleObjectTypeAnnotation, + NativeModuleStringTypeAnnotation, + NativeModuleNumberTypeAnnotation, + NativeModuleInt32TypeAnnotation, + NativeModuleDoubleTypeAnnotation, + NativeModuleFloatTypeAnnotation, + NativeModuleBooleanTypeAnnotation, + NativeModuleGenericObjectTypeAnnotation, + NativeModuleReservedFunctionValueTypeAnnotation, + NativeModuleTypeAliasTypeAnnotation, + NativeModuleArrayTypeAnnotation, + NativeModuleBaseTypeAnnotation, +} from '../../../CodegenSchema'; + +import type {AliasResolver} from '../Utils'; + +const {capitalize} = require('./Utils'); + +type StructContext = 'CONSTANTS' | 'REGULAR'; + +export type RegularStruct = $ReadOnly<{| + context: 'REGULAR', + name: string, + properties: $ReadOnlyArray, +|}>; + +export type ConstantsStruct = $ReadOnly<{| + context: 'CONSTANTS', + name: string, + properties: $ReadOnlyArray, +|}>; + +export type Struct = RegularStruct | ConstantsStruct; + +export type StructProperty = $ReadOnly<{| + name: string, + optional: boolean, + typeAnnotation: StructTypeAnnotation, +|}>; + +export type StructTypeAnnotation = + | NativeModuleStringTypeAnnotation + | NativeModuleNumberTypeAnnotation + | NativeModuleInt32TypeAnnotation + | NativeModuleDoubleTypeAnnotation + | NativeModuleFloatTypeAnnotation + | NativeModuleBooleanTypeAnnotation + | NativeModuleGenericObjectTypeAnnotation + | NativeModuleReservedFunctionValueTypeAnnotation + | NativeModuleTypeAliasTypeAnnotation + | NativeModuleArrayTypeAnnotation; + +class StructCollector { + _structs: Map = new Map(); + + process( + structName: string, + structContext: StructContext, + resolveAlias: AliasResolver, + typeAnnotation: NativeModuleBaseTypeAnnotation, + ): StructTypeAnnotation { + switch (typeAnnotation.type) { + case 'ObjectTypeAnnotation': { + this._insertStruct(structName, structContext, resolveAlias, { + ...typeAnnotation, + // The nullability status of this struct is recorded in the type-alias we create for it below. + nullable: false, + }); + return { + type: 'TypeAliasTypeAnnotation', + name: structName, + nullable: typeAnnotation.nullable, + }; + } + case 'ArrayTypeAnnotation': { + if (typeAnnotation.elementType == null) { + return { + type: 'ArrayTypeAnnotation', + nullable: typeAnnotation.nullable, + }; + } + + return { + type: 'ArrayTypeAnnotation', + nullable: typeAnnotation.nullable, + elementType: this.process( + structName + 'Element', + structContext, + resolveAlias, + typeAnnotation.elementType, + ), + }; + } + case 'TypeAliasTypeAnnotation': { + this._insertAlias(typeAnnotation.name, structContext, resolveAlias); + return typeAnnotation; + } + default: { + return typeAnnotation; + } + } + } + + _insertAlias( + aliasName: string, + structContext: StructContext, + resolveAlias: AliasResolver, + ): void { + const usedStruct = this._structs.get(aliasName); + if (usedStruct == null) { + this._insertStruct( + aliasName, + structContext, + resolveAlias, + resolveAlias(aliasName), + ); + } else if (usedStruct.context !== structContext) { + throw new Error( + `Tried to use alias '${aliasName}' in a getConstants() return type and inside a regular struct.`, + ); + } + } + + _insertStruct( + structName: string, + structContext: StructContext, + resolveAlias: AliasResolver, + objectTypeAnnotation: Required, + ): void { + const properties = objectTypeAnnotation.properties.map(property => { + const {typeAnnotation: propertyTypeAnnotation} = property; + const propertyStructName = structName + capitalize(property.name); + + return { + ...property, + typeAnnotation: this.process( + propertyStructName, + structContext, + resolveAlias, + propertyTypeAnnotation, + ), + }; + }); + + switch (structContext) { + case 'REGULAR': + this._structs.set(structName, { + name: structName, + context: 'REGULAR', + properties: properties, + }); + break; + case 'CONSTANTS': + this._structs.set(structName, { + name: structName, + context: 'CONSTANTS', + properties: properties, + }); + break; + default: + (structContext: empty); + throw new Error(`Detected an invalid struct context: ${structContext}`); + } + } + + getAllStructs(): $ReadOnlyArray { + return [...this._structs.values()]; + } + + getStruct(name: string): ?Struct { + return this._structs.get(name); + } +} + +module.exports = { + StructCollector, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/Utils.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/Utils.js new file mode 100644 index 00000000000000..0b989b12e03d02 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/Utils.js @@ -0,0 +1,36 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +import type {StructProperty} from './StructCollector'; + +function capitalize(string: string): string { + return string.charAt(0).toUpperCase() + string.slice(1); +} +function getSafePropertyName(property: StructProperty): string { + if (property.name === 'id') { + return `${property.name}_`; + } + return property.name; +} + +function getNamespacedStructName( + moduleName: string, + structName: string, +): string { + return `JS::Native${moduleName}::${structName}`; +} + +module.exports = { + capitalize, + getSafePropertyName, + getNamespacedStructName, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js new file mode 100644 index 00000000000000..27a71f43a32cf1 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeConstantsStruct.js @@ -0,0 +1,263 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +const { + capitalize, + getSafePropertyName, + getNamespacedStructName, +} = require('../Utils'); + +import type {StructTypeAnnotation, ConstantsStruct} from '../StructCollector'; +import type {StructSerilizationOutput} from './serializeStruct'; + +const StructTemplate = ({ + moduleName, + structName, + builderInputProps, +}: $ReadOnly<{| + moduleName: string, + structName: string, + builderInputProps: string, +|}>) => ` +namespace JS { + namespace Native${moduleName} { + struct ${structName} { + + struct Builder { + struct Input { + ${builderInputProps} + }; + + /** Initialize with a set of values */ + Builder(const Input i); + /** Initialize with an existing ${structName} */ + Builder(${structName} i); + /** Builds the object. Generally used only by the infrastructure. */ + NSDictionary *buildUnsafeRawValue() const { return _factory(); }; + private: + NSDictionary *(^_factory)(void); + }; + + static ${structName} fromUnsafeRawValue(NSDictionary *const v) { return {v}; } + NSDictionary *unsafeRawValue() const { return _v; } + private: + ${structName}(NSDictionary *const v) : _v(v) {} + NSDictionary *_v; + }; + } +}`; + +const MethodTemplate = ({ + moduleName, + structName, + properties, +}: $ReadOnly<{| + moduleName: string, + structName: string, + properties: string, +|}>) => ` +inline JS::Native${moduleName}::${structName}::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; +${properties} + return d; +}) {} +inline JS::Native${moduleName}::${structName}::Builder::Builder(${structName} i) : _factory(^{ + return i.unsafeRawValue(); +}) {}`; + +function toObjCType( + moduleName: string, + typeAnnotation: StructTypeAnnotation, + isOptional: boolean = false, +): string { + const isRequired = !typeAnnotation.nullable && !isOptional; + const wrapFollyOptional = (type: string) => { + return isRequired ? type : `folly::Optional<${type}>`; + }; + + switch (typeAnnotation.type) { + case 'ReservedFunctionValueTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return wrapFollyOptional('double'); + default: + (typeAnnotation.name: empty); + throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`); + } + case 'StringTypeAnnotation': + return 'NSString *'; + case 'NumberTypeAnnotation': + return wrapFollyOptional('double'); + case 'FloatTypeAnnotation': + return wrapFollyOptional('double'); + case 'Int32TypeAnnotation': + return wrapFollyOptional('double'); + case 'DoubleTypeAnnotation': + return wrapFollyOptional('double'); + case 'BooleanTypeAnnotation': + return wrapFollyOptional('bool'); + case 'GenericObjectTypeAnnotation': + return isRequired ? 'id ' : 'id _Nullable '; + case 'ArrayTypeAnnotation': + if (typeAnnotation.elementType == null) { + return isRequired ? 'id ' : 'id _Nullable '; + } + + return wrapFollyOptional( + `std::vector<${toObjCType(moduleName, typeAnnotation.elementType)}>`, + ); + case 'TypeAliasTypeAnnotation': + const structName = capitalize(typeAnnotation.name); + const namespacedStructName = getNamespacedStructName( + moduleName, + structName, + ); + return wrapFollyOptional(`${namespacedStructName}::Builder`); + default: + (typeAnnotation.type: empty); + throw new Error( + `Couldn't convert into ObjC type: ${typeAnnotation.type}"`, + ); + } +} + +function toObjCValue( + moduleName: string, + typeAnnotation: StructTypeAnnotation, + value: string, + depth: number, + isOptional: boolean = false, +): string { + const isRequired = !isOptional && !typeAnnotation.nullable; + + function wrapPrimitive(type: string) { + return !isRequired + ? `${value}.hasValue() ? @((${type})${value}.value()) : nil` + : `@(${value})`; + } + + switch (typeAnnotation.type) { + case 'ReservedFunctionValueTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return wrapPrimitive('double'); + default: + (typeAnnotation.name: empty); + throw new Error( + `Couldn't convert into ObjC type: ${typeAnnotation.type}"`, + ); + } + case 'StringTypeAnnotation': + return value; + case 'NumberTypeAnnotation': + return wrapPrimitive('double'); + case 'FloatTypeAnnotation': + return wrapPrimitive('double'); + case 'Int32TypeAnnotation': + return wrapPrimitive('double'); + case 'DoubleTypeAnnotation': + return wrapPrimitive('double'); + case 'BooleanTypeAnnotation': + return wrapPrimitive('BOOL'); + case 'GenericObjectTypeAnnotation': + return value; + case 'ArrayTypeAnnotation': + const {elementType} = typeAnnotation; + if (elementType == null) { + return value; + } + + const localVarName = `el${'_'.repeat(depth + 1)}`; + const elementObjCType = toObjCType(moduleName, elementType); + const elementObjCValue = toObjCValue( + moduleName, + elementType, + localVarName, + depth + 1, + ); + + const RCTConvertVecToArray = transformer => { + return `RCTConvert${ + !isRequired ? 'Optional' : '' + }VecToArray(${value}, ${transformer})`; + }; + + return RCTConvertVecToArray( + `^id(${elementObjCType} ${localVarName}) { return ${elementObjCValue}; }`, + ); + case 'TypeAliasTypeAnnotation': + return !isRequired + ? `${value}.hasValue() ? ${value}.value().buildUnsafeRawValue() : nil` + : `${value}.buildUnsafeRawValue()`; + default: + (typeAnnotation.type: empty); + throw new Error( + `Couldn't convert into ObjC value: ${typeAnnotation.type}"`, + ); + } +} + +function serializeConstantsStruct( + moduleName: string, + struct: ConstantsStruct, +): StructSerilizationOutput { + const declaration = StructTemplate({ + moduleName, + structName: struct.name, + builderInputProps: struct.properties + .map(property => { + const {typeAnnotation, optional} = property; + const propName = getSafePropertyName(property); + const objCType = toObjCType(moduleName, typeAnnotation, optional); + + if (!optional) { + return `RCTRequired<${objCType}> ${propName};`; + } + + const space = ' '.repeat(objCType.endsWith('*') ? 0 : 1); + return `${objCType}${space}${propName};`; + }) + .join('\n '), + }); + + const methods = MethodTemplate({ + moduleName, + structName: struct.name, + properties: struct.properties + .map(property => { + const {typeAnnotation, optional} = property; + const propName = getSafePropertyName(property); + const objCValue = toObjCValue( + moduleName, + typeAnnotation, + propName, + 0, + optional, + ); + + let varDecl = `auto ${propName} = i.${propName}`; + if (!optional) { + varDecl += '.get()'; + } + + const assignment = `d[@"${propName}"] = ` + objCValue; + return ` ${varDecl};\n ${assignment};`; + }) + .join('\n'), + }); + + return {declaration, methods}; +} + +module.exports = { + serializeConstantsStruct, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js new file mode 100644 index 00000000000000..ce7b5f12d4f5bb --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeRegularStruct.js @@ -0,0 +1,251 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +const { + capitalize, + getSafePropertyName, + getNamespacedStructName, +} = require('../Utils'); + +import type {StructTypeAnnotation, RegularStruct} from '../StructCollector'; +import type {StructSerilizationOutput} from './serializeStruct'; + +const StructTemplate = ({ + moduleName, + structName, + structProperties, +}: $ReadOnly<{| + moduleName: string, + structName: string, + structProperties: string, +|}>) => ` +namespace JS { + namespace Native${moduleName} { + struct ${structName} { + ${structProperties} + + ${structName}(NSDictionary *const v) : _v(v) {} + private: + NSDictionary *_v; + }; + } +} + +@interface RCTCxxConvert (Native${moduleName}_${structName}) ++ (RCTManagedPointer *)JS_Native${moduleName}_${structName}:(id)json; +@end +`; + +const MethodTemplate = ({ + returnType, + returnValue, + moduleName, + structName, + propertyName, +}: $ReadOnly<{| + returnType: string, + returnValue: string, + moduleName: string, + structName: string, + propertyName: string, +|}>) => ` +inline ${returnType}JS::Native${moduleName}::${structName}::${propertyName}() const +{ + id const p = _v[@"${propertyName}"]; + return ${returnValue}; +} +`; + +function toObjCType( + moduleName: string, + typeAnnotation: StructTypeAnnotation, + isOptional: boolean = false, +): string { + const isRequired = !typeAnnotation.nullable && !isOptional; + const wrapFollyOptional = (type: string) => { + return isRequired ? type : `folly::Optional<${type}>`; + }; + + switch (typeAnnotation.type) { + case 'ReservedFunctionValueTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return wrapFollyOptional('double'); + default: + (typeAnnotation.name: empty); + throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`); + } + case 'StringTypeAnnotation': + return 'NSString *'; + case 'NumberTypeAnnotation': + return wrapFollyOptional('double'); + case 'FloatTypeAnnotation': + return wrapFollyOptional('double'); + case 'Int32TypeAnnotation': + return wrapFollyOptional('double'); + case 'DoubleTypeAnnotation': + return wrapFollyOptional('double'); + case 'BooleanTypeAnnotation': + return wrapFollyOptional('bool'); + case 'GenericObjectTypeAnnotation': + return isRequired ? 'id ' : 'id _Nullable'; + case 'ArrayTypeAnnotation': + if (typeAnnotation.elementType == null) { + return isRequired ? 'id ' : 'id _Nullable'; + } + return wrapFollyOptional( + `facebook::react::LazyVector<${toObjCType( + moduleName, + typeAnnotation.elementType, + )}>`, + ); + case 'TypeAliasTypeAnnotation': + const structName = capitalize(typeAnnotation.name); + const namespacedStructName = getNamespacedStructName( + moduleName, + structName, + ); + return wrapFollyOptional(namespacedStructName); + default: + (typeAnnotation.type: empty); + throw new Error( + `Couldn't convert into ObjC type: ${typeAnnotation.type}"`, + ); + } +} + +function toObjCValue( + moduleName: string, + typeAnnotation: StructTypeAnnotation, + value: string, + depth: number, + isOptional: boolean = false, +): string { + const isRequired = !typeAnnotation.nullable && !isOptional; + const RCTBridgingTo = (type: string, arg?: string) => { + const args = [value, arg].filter(Boolean).join(', '); + return isRequired + ? `RCTBridgingTo${type}(${args})` + : `RCTBridgingToOptional${type}(${args})`; + }; + + switch (typeAnnotation.type) { + case 'ReservedFunctionValueTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return RCTBridgingTo('Double'); + default: + (typeAnnotation.name: empty); + throw new Error( + `Couldn't convert into ObjC type: ${typeAnnotation.type}"`, + ); + } + case 'StringTypeAnnotation': + return RCTBridgingTo('String'); + case 'NumberTypeAnnotation': + return RCTBridgingTo('Double'); + case 'FloatTypeAnnotation': + return RCTBridgingTo('Double'); + case 'Int32TypeAnnotation': + return RCTBridgingTo('Double'); + case 'DoubleTypeAnnotation': + return RCTBridgingTo('Double'); + case 'BooleanTypeAnnotation': + return RCTBridgingTo('Bool'); + case 'GenericObjectTypeAnnotation': + return value; + case 'ArrayTypeAnnotation': + const {elementType} = typeAnnotation; + if (elementType == null) { + return value; + } + + const localVarName = `itemValue_${depth}`; + const elementObjCType = toObjCType(moduleName, elementType); + const elementObjCValue = toObjCValue( + moduleName, + elementType, + localVarName, + depth + 1, + ); + + return RCTBridgingTo( + 'Vec', + `^${elementObjCType}(id ${localVarName}) { return ${elementObjCValue}; }`, + ); + case 'TypeAliasTypeAnnotation': + const structName = capitalize(typeAnnotation.name); + const namespacedStructName = getNamespacedStructName( + moduleName, + structName, + ); + + return !isRequired + ? `(p == nil ? folly::none : folly::make_optional(${namespacedStructName}(p)))` + : `${namespacedStructName}(p)`; + default: + (typeAnnotation.type: empty); + throw new Error( + `Couldn't convert into ObjC value: ${typeAnnotation.type}"`, + ); + } +} + +function serializeRegularStruct( + moduleName: string, + struct: RegularStruct, +): StructSerilizationOutput { + const declaration = StructTemplate({ + moduleName: moduleName, + structName: struct.name, + structProperties: struct.properties + .map(property => { + const {typeAnnotation, optional} = property; + const propName = getSafePropertyName(property); + const returnType = toObjCType(moduleName, typeAnnotation, optional); + + const padding = ' '.repeat(returnType.endsWith('*') ? 0 : 1); + return `${returnType}${padding}${propName}() const;`; + }) + .join('\n '), + }); + + const methods = struct.properties + .map(property => { + const {typeAnnotation, optional} = property; + const propName = getSafePropertyName(property); + const returnType = toObjCType(moduleName, typeAnnotation, optional); + const returnValue = toObjCValue( + moduleName, + typeAnnotation, + 'p', + 0, + optional, + ); + + const padding = ' '.repeat(returnType.endsWith('*') ? 0 : 1); + return MethodTemplate({ + moduleName, + structName: struct.name, + returnType: returnType + padding, + returnValue: returnValue, + propertyName: propName, + }); + }) + .join('\n'); + + return {methods, declaration}; +} + +module.exports = { + serializeRegularStruct, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js new file mode 100644 index 00000000000000..fe2355333b3a83 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/header/serializeStruct.js @@ -0,0 +1,35 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +import type {Struct} from '../StructCollector'; + +const {serializeConstantsStruct} = require('./serializeConstantsStruct'); +const {serializeRegularStruct} = require('./serializeRegularStruct'); + +export type StructSerilizationOutput = $ReadOnly<{| + methods: string, + declaration: string, +|}>; + +function serializeStruct( + moduleName: string, + struct: Struct, +): StructSerilizationOutput { + if (struct.context === 'REGULAR') { + return serializeRegularStruct(moduleName, struct); + } + return serializeConstantsStruct(moduleName, struct); +} + +module.exports = { + serializeStruct, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js new file mode 100644 index 00000000000000..ee2d5e1e42d375 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/index.js @@ -0,0 +1,210 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +import type {SchemaType} from '../../../CodegenSchema'; +import type {MethodSerializationOutput} from './serializeMethod'; + +const {createAliasResolver, getModules} = require('../Utils'); + +const {StructCollector} = require('./StructCollector'); +const {serializeStruct} = require('./header/serializeStruct'); +const {serializeMethod} = require('./serializeMethod'); +const {serializeModuleSource} = require('./source/serializeModule'); + +type FilesOutput = Map; + +const ModuleDeclarationTemplate = ({ + moduleName, + structDeclarations, + protocolMethods, +}: $ReadOnly<{| + moduleName: string, + structDeclarations: string, + protocolMethods: string, +|}>) => ` +${structDeclarations} +@protocol Native${moduleName}Spec + +${protocolMethods} + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module '${moduleName}' + */ + class JSI_EXPORT Native${moduleName}SpecJSI : public ObjCTurboModule { + public: + Native${moduleName}SpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook +`; + +const HeaderFileTemplate = ({ + moduleDeclarations, + structInlineMethods, +}: $ReadOnly<{| + moduleDeclarations: string, + structInlineMethods: string, +|}>) => ` +/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * ${'@'}generated by codegen project: GenerateModuleHObjCpp.js + */ + +#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 + +#import + +#import + +#import + +#import +#import +#import + +#import +#import +#import + +#import + +${moduleDeclarations} + +${structInlineMethods} +`; + +const SourceFileTemplate = ({ + headerFileName, + moduleImplementations, +}: $ReadOnly<{| + headerFileName: string, + moduleImplementations: string, +|}>) => ` +/** + * ${'C'}opyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * ${'@'}generated by an internal genrule from Flow types. + * + * 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 "${headerFileName}" + +${moduleImplementations} +`; + +module.exports = { + generate( + libraryName: string, + schema: SchemaType, + moduleSpecName: string, + ): FilesOutput { + const nativeModules = getModules(schema); + + const moduleDeclarations: Array = []; + const structInlineMethods: Array = []; + const moduleImplementations: Array = []; + + const moduleNames: Array = Object.keys(nativeModules).sort(); + for (const moduleName of moduleNames) { + const {aliases, properties} = nativeModules[moduleName]; + const resolveAlias = createAliasResolver(aliases); + const structCollector = new StructCollector(); + + const methodSerializations: Array = []; + const serializeProperty = property => { + methodSerializations.push( + ...serializeMethod( + moduleName, + property, + structCollector, + resolveAlias, + ), + ); + }; + + /** + * Note: As we serialize NativeModule methods, we insert structs into + * StructCollector, as we encounter them. + */ + properties + .filter(property => property.name !== 'getConstants') + .forEach(serializeProperty); + properties + .filter(property => property.name === 'getConstants') + .forEach(serializeProperty); + + const generatedStructs = structCollector.getAllStructs(); + const structStrs = []; + const methodStrs = []; + + for (const struct of generatedStructs) { + const {methods, declaration} = serializeStruct(moduleName, struct); + structStrs.push(declaration); + methodStrs.push(methods); + } + + moduleDeclarations.push( + ModuleDeclarationTemplate({ + moduleName: moduleName, + structDeclarations: structStrs.join('\n'), + protocolMethods: methodSerializations + .map(({protocolMethod}) => protocolMethod) + .join('\n'), + }), + ); + + structInlineMethods.push(methodStrs.join('\n')); + + moduleImplementations.push( + serializeModuleSource( + moduleName, + generatedStructs, + methodSerializations.filter( + ({selector}) => selector !== '@selector(constantsToExport)', + ), + ), + ); + } + + const headerFileName = `${moduleSpecName}.h`; + const headerFile = HeaderFileTemplate({ + moduleDeclarations: moduleDeclarations.join('\n'), + structInlineMethods: structInlineMethods.join('\n'), + }); + + const sourceFileName = `${moduleSpecName}-generated.mm`; + const sourceFile = SourceFileTemplate({ + headerFileName, + moduleImplementations: moduleImplementations.join('\n'), + }); + + return new Map([ + [headerFileName, headerFile], + [sourceFileName, sourceFile], + ]); + }, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeMethod.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeMethod.js new file mode 100644 index 00000000000000..bec84f59d6de76 --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/serializeMethod.js @@ -0,0 +1,427 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +import type { + NativeModuleMethodParamSchema, + NativeModuleReturnTypeAnnotation, + NativeModulePropertySchema, +} from '../../../CodegenSchema'; + +import type {AliasResolver} from '../Utils'; + +const invariant = require('invariant'); +const {StructCollector} = require('./StructCollector'); +const {capitalize, getNamespacedStructName} = require('./Utils'); + +const ProtocolMethodTemplate = ({ + returnObjCType, + methodName, + params, +}: $ReadOnly<{| + returnObjCType: string, + methodName: string, + params: string, +|}>) => `- (${returnObjCType})${methodName}${params};`; + +export type StructParameterRecord = $ReadOnly<{| + paramIndex: number, + structName: string, +|}>; + +type ReturnJSType = + | 'VoidKind' + | 'PromiseKind' + | 'ObjectKind' + | 'ArrayKind' + | 'NumberKind' + | 'StringKind'; + +export type MethodSerializationOutput = $ReadOnly<{| + methodName: string, + protocolMethod: string, + selector: string, + structParamRecords: $ReadOnlyArray, + returnJSType: ReturnJSType, + argCount: number, +|}>; + +function serializeMethod( + moduleName: string, + property: NativeModulePropertySchema, + structCollector: StructCollector, + resolveAlias: AliasResolver, +): $ReadOnlyArray { + const { + name: methodName, + typeAnnotation: {params, returnTypeAnnotation}, + } = property; + + if (methodName === 'getConstants') { + return serializeConstantsProtocolMethods( + moduleName, + property, + structCollector, + resolveAlias, + ); + } + + const methodParams: Array<{|paramName: string, objCType: string|}> = []; + const structParamRecords: Array = []; + + params.forEach((param, index) => { + const structName = getParamStructName(methodName, param); + const {objCType, isStruct} = getParamObjCType( + moduleName, + methodName, + param, + structName, + structCollector, + resolveAlias, + ); + + methodParams.push({paramName: param.name, objCType}); + + if (isStruct) { + structParamRecords.push({paramIndex: index, structName}); + } + }); + + if (returnTypeAnnotation.type === 'PromiseTypeAnnotation') { + methodParams.push( + {paramName: 'resolve', objCType: 'RCTPromiseResolveBlock'}, + {paramName: 'reject', objCType: 'RCTPromiseRejectBlock'}, + ); + } + + /** + * Build Protocol Method + **/ + const returnObjCType = getReturnObjCType(methodName, returnTypeAnnotation); + const paddingMax = `- (${returnObjCType})${methodName}`.length; + + const objCParams = methodParams.reduce( + ($objCParams, {objCType, paramName}, i) => { + const rhs = `(${objCType})${paramName}`; + const padding = ' '.repeat(Math.max(0, paddingMax - paramName.length)); + return i === 0 + ? `:${rhs}` + : `${$objCParams}\n${padding}${paramName}:${rhs}`; + }, + '', + ); + + const protocolMethod = ProtocolMethodTemplate({ + methodName, + returnObjCType, + params: objCParams, + }); + + /** + * Build ObjC Selector + */ + const selector = methodParams + .map(({paramName}) => paramName) + .reduce(($selector, paramName, i) => { + return i === 0 ? `${$selector}:` : `${$selector}${paramName}:`; + }, methodName); + + /** + * Build JS Return type + */ + const returnJSType = getReturnJSType(methodName, returnTypeAnnotation); + + return [ + { + methodName, + protocolMethod, + selector: `@selector(${selector})`, + structParamRecords, + returnJSType, + argCount: params.length, + }, + ]; +} + +function getParamStructName( + methodName: string, + param: NativeModuleMethodParamSchema, +): string { + if (param.typeAnnotation.type === 'TypeAliasTypeAnnotation') { + return param.typeAnnotation.name; + } + + return `Spec${capitalize(methodName)}${capitalize(param.name)}`; +} + +function getParamObjCType( + moduleName: string, + methodName: string, + param: NativeModuleMethodParamSchema, + structName: string, + structCollector: StructCollector, + resolveAlias: AliasResolver, +): $ReadOnly<{|objCType: string, isStruct: boolean|}> { + const {name: paramName, typeAnnotation} = param; + const notRequired = param.optional || typeAnnotation.nullable; + + function wrapIntoNullableIfNeeded(generatedType: string) { + return typeAnnotation.nullable + ? `${generatedType} _Nullable` + : generatedType; + } + + const isStruct = (objCType: string) => ({ + isStruct: true, + objCType, + }); + + const notStruct = (objCType: string) => ({ + isStruct: false, + objCType, + }); + + // Handle types that can only be in parameters + switch (typeAnnotation.type) { + case 'FunctionTypeAnnotation': { + return notStruct('RCTResponseSenderBlock'); + } + case 'ArrayTypeAnnotation': { + /** + * Array in params always codegen NSArray * + * + * TODO(T73933406): Support codegen for Arrays of structs and primitives + * + * For example: + * Array => NSArray + * type Animal = {||}; + * Array => NSArray, etc. + */ + return notStruct(wrapIntoNullableIfNeeded('NSArray *')); + } + } + + const structTypeAnnotation = structCollector.process( + structName, + 'REGULAR', + resolveAlias, + typeAnnotation, + ); + + invariant( + structTypeAnnotation.type !== 'ArrayTypeAnnotation', + 'ArrayTypeAnnotations should have been processed earlier', + ); + + switch (structTypeAnnotation.type) { + case 'TypeAliasTypeAnnotation': { + /** + * TODO(T73943261): Support nullable object literals and aliases? + */ + return isStruct( + getNamespacedStructName(moduleName, structTypeAnnotation.name) + ' &', + ); + } + case 'ReservedFunctionValueTypeAnnotation': + switch (structTypeAnnotation.name) { + case 'RootTag': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + default: + (structTypeAnnotation.name: empty); + throw new Error( + `Unsupported type for param "${paramName}" in ${methodName}. Found: ${structTypeAnnotation.type}`, + ); + } + case 'StringTypeAnnotation': + return notStruct(wrapIntoNullableIfNeeded('NSString *')); + case 'NumberTypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + case 'FloatTypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + case 'DoubleTypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + case 'Int32TypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'double'); + case 'BooleanTypeAnnotation': + return notStruct(notRequired ? 'NSNumber *' : 'BOOL'); + case 'GenericObjectTypeAnnotation': + return notStruct(wrapIntoNullableIfNeeded('NSDictionary *')); + default: + (structTypeAnnotation.type: empty); + throw new Error( + `Unsupported type for param "${paramName}" in ${methodName}. Found: ${typeAnnotation.type}`, + ); + } +} + +function getReturnObjCType( + methodName: string, + typeAnnotation: NativeModuleReturnTypeAnnotation, +) { + function wrapIntoNullableIfNeeded(generatedType: string) { + return typeAnnotation.nullable + ? `${generatedType} _Nullable` + : generatedType; + } + + switch (typeAnnotation.type) { + case 'VoidTypeAnnotation': + return 'void'; + case 'PromiseTypeAnnotation': + return 'void'; + case 'ObjectTypeAnnotation': + return wrapIntoNullableIfNeeded('NSDictionary *'); + case 'TypeAliasTypeAnnotation': + return wrapIntoNullableIfNeeded('NSDictionary *'); + case 'ArrayTypeAnnotation': + if (typeAnnotation.elementType == null) { + return wrapIntoNullableIfNeeded('NSArray> *'); + } + + return wrapIntoNullableIfNeeded( + `NSArray<${getReturnObjCType( + methodName, + typeAnnotation.elementType, + )}> *`, + ); + case 'ReservedFunctionValueTypeAnnotation': + switch (typeAnnotation.name) { + case 'RootTag': + return wrapIntoNullableIfNeeded('NSNumber *'); + default: + (typeAnnotation.name: empty); + throw new Error( + `Unsupported return type for ${methodName}. Found: ${typeAnnotation.name}`, + ); + } + case 'StringTypeAnnotation': + // TODO: Can NSString * returns not be _Nullable? + // In the legacy codegen, we don't surround NSSTring * with _Nullable + return wrapIntoNullableIfNeeded('NSString *'); + case 'NumberTypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'FloatTypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'DoubleTypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'Int32TypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'BooleanTypeAnnotation': + return wrapIntoNullableIfNeeded('NSNumber *'); + case 'GenericObjectTypeAnnotation': + return wrapIntoNullableIfNeeded('NSDictionary *'); + default: + (typeAnnotation.type: empty); + throw new Error( + `Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`, + ); + } +} + +function getReturnJSType( + methodName: string, + typeAnnotation: NativeModuleReturnTypeAnnotation, +): ReturnJSType { + switch (typeAnnotation.type) { + case 'VoidTypeAnnotation': + return 'VoidKind'; + case 'PromiseTypeAnnotation': + return 'PromiseKind'; + case 'ObjectTypeAnnotation': + return 'ObjectKind'; + case 'TypeAliasTypeAnnotation': + return 'ObjectKind'; + case 'ArrayTypeAnnotation': + return 'ArrayKind'; + case 'ReservedFunctionValueTypeAnnotation': + return 'NumberKind'; + case 'StringTypeAnnotation': + return 'StringKind'; + case 'NumberTypeAnnotation': + return 'NumberKind'; + case 'FloatTypeAnnotation': + return 'NumberKind'; + case 'DoubleTypeAnnotation': + return 'NumberKind'; + case 'Int32TypeAnnotation': + return 'NumberKind'; + case 'BooleanTypeAnnotation': + return 'NumberKind'; + case 'GenericObjectTypeAnnotation': + return 'ObjectKind'; + default: + (typeAnnotation.type: empty); + throw new Error( + `Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`, + ); + } +} + +function serializeConstantsProtocolMethods( + moduleName: string, + property: NativeModulePropertySchema, + structCollector: StructCollector, + resolveAlias: AliasResolver, +): $ReadOnlyArray { + if (property.typeAnnotation.params.length !== 0) { + throw new Error( + `${moduleName}.getConstants() may only accept 0 arguments.`, + ); + } + + const {returnTypeAnnotation} = property.typeAnnotation; + if (returnTypeAnnotation.type !== 'ObjectTypeAnnotation') { + throw new Error( + `${moduleName}.getConstants() may only return an object literal: {|...|}.`, + ); + } + + if (returnTypeAnnotation.properties.length === 0) { + return []; + } + + const realTypeAnnotation = structCollector.process( + 'Constants', + 'CONSTANTS', + resolveAlias, + returnTypeAnnotation, + ); + + invariant( + realTypeAnnotation.type === 'TypeAliasTypeAnnotation', + "Unable to generate C++ struct from module's getConstants() method return type.", + ); + + const returnObjCType = `facebook::react::ModuleConstants`; + + return ['constantsToExport', 'getConstants'].map( + methodName => { + const protocolMethod = ProtocolMethodTemplate({ + methodName, + returnObjCType, + params: '', + }); + + return { + methodName, + protocolMethod, + returnJSType: 'ObjectKind', + selector: `@selector(${methodName})`, + structParamRecords: [], + argCount: 0, + }; + }, + ); +} + +module.exports = { + serializeMethod, +}; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js new file mode 100644 index 00000000000000..72013475009fbe --- /dev/null +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleObjCpp/source/serializeModule.js @@ -0,0 +1,127 @@ +/** + * Copyright (c) Facebook, Inc. and its 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 + */ + +'use strict'; + +import type {Struct} from '../StructCollector'; +import type { + MethodSerializationOutput, + StructParameterRecord, +} from '../serializeMethod'; + +const ModuleTemplate = ({ + moduleName, + structs, + methodSerializationOutputs, +}: $ReadOnly<{| + moduleName: string, + structs: $ReadOnlyArray, + methodSerializationOutputs: $ReadOnlyArray, +|}>) => ` +${structs + .map(struct => + RCTCxxConvertCategoryTemplate({moduleName, structName: struct.name}), + ) + .join('\n')} +namespace facebook { + namespace react { + ${methodSerializationOutputs + .map(serializedMethodParts => + InlineHostFunctionTemplate({ + moduleName, + methodName: serializedMethodParts.methodName, + returnJSType: serializedMethodParts.returnJSType, + selector: serializedMethodParts.selector, + }), + ) + .join('\n')} + + Native${moduleName}SpecJSI::Native${moduleName}SpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + ${methodSerializationOutputs + .map(({methodName, structParamRecords, argCount}) => + MethodMapEntryTemplate({ + moduleName, + methodName, + structParamRecords, + argCount, + }), + ) + .join('\n' + ' '.repeat(8))} + } + } // namespace react +} // namespace facebook +`; + +const RCTCxxConvertCategoryTemplate = ({ + moduleName, + structName, +}: $ReadOnly<{| + moduleName: string, + structName: string, +|}>) => ` +@implementation RCTCxxConvert (Native${moduleName}_${structName}) ++ (RCTManagedPointer *)JS_Native${moduleName}_${structName}:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +`; + +const InlineHostFunctionTemplate = ({ + moduleName, + methodName, + returnJSType, + selector, +}: $ReadOnly<{| + moduleName: string, + methodName: string, + returnJSType: string, + selector: string, +|}>) => ` + static facebook::jsi::Value __hostFunction_Native${moduleName}SpecJSI_${methodName}(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ${returnJSType}, "${methodName}", ${selector}, args, count); + } +`; + +const MethodMapEntryTemplate = ({ + moduleName, + methodName, + structParamRecords, + argCount, +}: $ReadOnly<{| + moduleName: string, + methodName: string, + structParamRecords: $ReadOnlyArray, + argCount: number, +|}>) => ` + methodMap_["${methodName}"] = MethodMetadata {${argCount}, __hostFunction_Native${moduleName}SpecJSI_${methodName}}; + ${structParamRecords + .map(({paramIndex, structName}) => { + return `setMethodArgConversionSelector(@"${methodName}", ${paramIndex}, @"JS_Native${moduleName}_${structName}:");`; + }) + .join('\n' + ' '.repeat(8))} +`; + +function serializeModuleSource( + moduleName: string, + structs: $ReadOnlyArray, + methodSerializationOutputs: $ReadOnlyArray, +): string { + return ModuleTemplate({ + moduleName, + structs: structs.filter(({context}) => context !== 'CONSTANTS'), + methodSerializationOutputs, + }); +} + +module.exports = { + serializeModuleSource, +}; diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js deleted file mode 100644 index c9e1d817a296d1..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructs.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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 - */ - -'use strict'; - -import type { - ObjectParamTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../../CodegenSchema'; -const { - flatObjects, - capitalizeFirstLetter, - getSafePropertyName, -} = require('./Utils'); -const {getTypeAliasTypeAnnotation} = require('../Utils'); -const {generateStructsForConstants} = require('./GenerateStructsForConstants'); - -const template = ` -::_CONSTANTS_::::_STRUCTS_::::_INLINES_:: -`; - -const structTemplate = ` -namespace JS { - namespace Native::_MODULE_NAME_:: { - struct ::_STRUCT_NAME_:: { - ::_STRUCT_PROPERTIES_:: - - ::_STRUCT_NAME_::(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (Native::_MODULE_NAME_::_::_STRUCT_NAME_::) -+ (RCTManagedPointer *)JS_Native::_MODULE_NAME_::_::_STRUCT_NAME_:::(id)json; -@end -`; - -const inlineTemplate = ` -inline ::_RETURN_TYPE_::JS::Native::_MODULE_NAME_::::::_STRUCT_NAME_::::::_PROPERTY_NAME_::() const -{ - id const p = _v[@"::_PROPERTY_NAME_::"]; - return ::_RETURN_VALUE_::; -} -`; - -function getNamespacedStructName(structName: string): string { - return `JS::Native::_MODULE_NAME_::::${structName}`; -} - -function getElementTypeForArray( - property: ObjectParamTypeAnnotation, - name: string, - moduleName: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const {typeAnnotation} = property; - - // TODO(T67898313): Workaround for NativeLinking's use of union type. This check may be removed once typeAnnotation is non-optional. - if (!typeAnnotation) { - throw new Error( - `Cannot get array element type, property ${property.name} does not contain a type annotation`, - ); - } - - if (typeAnnotation.type !== 'ArrayTypeAnnotation') { - throw new Error( - `Cannot get array element type for non-array type ${typeAnnotation.type}`, - ); - } - - if (!typeAnnotation.elementType) { - return 'id'; - } - - const type = - typeAnnotation.elementType.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.elementType.name, aliases) - .type - : typeAnnotation.elementType.type; - switch (type) { - case 'StringTypeAnnotation': - return 'NSString *'; - case 'DoubleTypeAnnotation': - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return 'double'; - case 'ObjectTypeAnnotation': - const structName = - typeAnnotation.elementType.type === 'TypeAliasTypeAnnotation' - ? typeAnnotation.elementType.name - : `${property.name}Element`; - return getNamespacedStructName(structName); - case 'GenericObjectTypeAnnotation': - // TODO(T67565166): Generic objects are not type safe and should be disallowed in the schema. This case should throw an error once it is disallowed in schema. - console.error( - `Warning: Generic objects are not type safe and should be avoided whenever possible (see '${property.name}' in ${moduleName}'s ${name})`, - ); - return 'id'; - case 'BooleanTypeAnnotation': - case 'AnyObjectTypeAnnotation': - case 'AnyTypeAnnotation': - case 'ArrayTypeAnnotation': - case 'FunctionTypeAnnotation': - case 'ReservedFunctionValueTypeAnnotation': - case 'ReservedPropTypeAnnotation': - case 'StringEnumTypeAnnotation': - throw new Error(`Unsupported array element type, found: ${type}"`); - default: - (type: empty); - throw new Error(`Unknown array element type, found: ${type}"`); - } -} - -function getInlineMethodSignature( - property: ObjectParamTypeAnnotation, - name: string, - moduleName: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const {typeAnnotation} = property; - function markOptionalTypeIfNecessary(type: string) { - if (property.optional) { - return `folly::Optional<${type}>`; - } - return type; - } - - // TODO(T67672788): Workaround for values key in NativeLinking which lacks a typeAnnotation. id is not type safe! - if (!typeAnnotation) { - console.error( - `Warning: Unsafe type found (see '${property.name}' in ${moduleName}'s ${name})`, - ); - return `id ${getSafePropertyName(property)}() const;`; - } - - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; - - const variableName = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? `${capitalizeFirstLetter(typeAnnotation.name)}` - : `${capitalizeFirstLetter(name)}${capitalizeFirstLetter( - getSafePropertyName(property), - )}`; - - switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (realTypeAnnotation.name) { - case 'RootTag': - return `double ${getSafePropertyName(property)}() const;`; - default: - (realTypeAnnotation.name: empty); - throw new Error( - `Unknown prop type, found: ${realTypeAnnotation.name}"`, - ); - } - case 'StringTypeAnnotation': - return `NSString *${getSafePropertyName(property)}() const;`; - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return `${markOptionalTypeIfNecessary('double')} ${getSafePropertyName( - property, - )}() const;`; - case 'BooleanTypeAnnotation': - return `${markOptionalTypeIfNecessary('bool')} ${getSafePropertyName( - property, - )}() const;`; - case 'ObjectTypeAnnotation': - return `${markOptionalTypeIfNecessary( - getNamespacedStructName(variableName), - )} ${getSafePropertyName(property)}() const;`; - case 'GenericObjectTypeAnnotation': - case 'AnyTypeAnnotation': - return `id ${ - property.optional ? '_Nullable ' : ' ' - }${getSafePropertyName(property)}() const;`; - case 'ArrayTypeAnnotation': - return `${markOptionalTypeIfNecessary( - `facebook::react::LazyVector<${getElementTypeForArray( - property, - name, - moduleName, - aliases, - )}>`, - )} ${getSafePropertyName(property)}() const;`; - case 'FunctionTypeAnnotation': - default: - throw new Error(`Unknown prop type, found: ${realTypeAnnotation.type}"`); - } -} - -function getInlineMethodImplementation( - property: ObjectParamTypeAnnotation, - name: string, - moduleName: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const {typeAnnotation} = property; - function markOptionalTypeIfNecessary(type: string): string { - if (property.optional) { - return `folly::Optional<${type}> `; - } - return `${type} `; - } - function markOptionalValueIfNecessary(value: string): string { - if (property.optional) { - return `RCTBridgingToOptional${capitalizeFirstLetter(value)}`; - } - return `RCTBridgingTo${capitalizeFirstLetter(value)}`; - } - function bridgeArrayElementValueIfNecessary(element: string): string { - // TODO(T67898313): Workaround for NativeLinking's use of union type - if (!typeAnnotation) { - throw new Error( - `Cannot get array element type, property ${property.name} does not contain a type annotation`, - ); - } - - if (typeAnnotation.type !== 'ArrayTypeAnnotation') { - throw new Error( - `Cannot get array element type for non-array type ${typeAnnotation.type}`, - ); - } - - if (!typeAnnotation.elementType) { - throw new Error(`Cannot get array element type for ${name}`); - } - - const type = - typeAnnotation.elementType.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.elementType.name, aliases) - .type - : typeAnnotation.elementType.type; - - switch (type) { - case 'StringTypeAnnotation': - return `RCTBridgingToString(${element})`; - case 'DoubleTypeAnnotation': - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return `RCTBridgingToDouble(${element})`; - case 'BooleanTypeAnnotation': - return `RCTBridgingToBool(${element})`; - case 'ObjectTypeAnnotation': - const structName = - typeAnnotation.elementType.type === 'TypeAliasTypeAnnotation' - ? `${typeAnnotation.elementType.name}(${element})` - : `${getSafePropertyName(property)}Element(${element})`; - return getNamespacedStructName(structName); - case 'GenericObjectTypeAnnotation': - return element; - case 'AnyObjectTypeAnnotation': - case 'AnyTypeAnnotation': - case 'ArrayTypeAnnotation': - case 'FunctionTypeAnnotation': - case 'ReservedFunctionValueTypeAnnotation': - case 'ReservedPropTypeAnnotation': - case 'StringEnumTypeAnnotation': - case 'TupleTypeAnnotation': - throw new Error(`Unsupported array element type, found: ${type}"`); - default: - (type: empty); - throw new Error(`Unknown array element type, found: ${type}"`); - } - } - - // TODO(T67672788): Workaround for values key in NativeLinking which lacks a typeAnnotation. id is not type safe! - if (!typeAnnotation) { - console.error( - `Warning: Unsafe type found (see '${property.name}' in ${moduleName}'s ${name})`, - ); - return inlineTemplate - .replace( - /::_RETURN_TYPE_::/, - property.optional ? 'id _Nullable ' : 'id ', - ) - .replace(/::_RETURN_VALUE_::/, 'p'); - } - - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; - - switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (realTypeAnnotation.name) { - case 'RootTag': - return inlineTemplate - .replace(/::_RETURN_TYPE_::/, 'double ') - .replace(/::_RETURN_VALUE_::/, 'RCTBridgingToDouble(p)'); - default: - (realTypeAnnotation.name: empty); - throw new Error( - `Unknown prop type, found: ${realTypeAnnotation.name}"`, - ); - } - case 'StringTypeAnnotation': - return inlineTemplate - .replace(/::_RETURN_TYPE_::/, 'NSString *') - .replace(/::_RETURN_VALUE_::/, 'RCTBridgingToString(p)'); - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return inlineTemplate - .replace(/::_RETURN_TYPE_::/, markOptionalTypeIfNecessary('double')) - .replace( - /::_RETURN_VALUE_::/, - `${markOptionalValueIfNecessary('double')}(p)`, - ); - case 'BooleanTypeAnnotation': - return inlineTemplate - .replace(/::_RETURN_TYPE_::/, markOptionalTypeIfNecessary('bool')) - .replace( - /::_RETURN_VALUE_::/, - `${markOptionalValueIfNecessary('bool')}(p)`, - ); - case 'GenericObjectTypeAnnotation': - case 'AnyTypeAnnotation': - return inlineTemplate - .replace( - /::_RETURN_TYPE_::/, - property.optional ? 'id _Nullable ' : 'id ', - ) - .replace(/::_RETURN_VALUE_::/, 'p'); - case 'ObjectTypeAnnotation': - const structName = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? `${capitalizeFirstLetter(typeAnnotation.name)}` - : `${name}${capitalizeFirstLetter(getSafePropertyName(property))}`; - const namespacedStructName = getNamespacedStructName(structName); - return inlineTemplate - .replace( - /::_RETURN_TYPE_::/, - markOptionalTypeIfNecessary(namespacedStructName), - ) - .replace( - /::_RETURN_VALUE_::/, - property.optional - ? `(p == nil ? folly::none : folly::make_optional(${namespacedStructName}(p)))` - : `${namespacedStructName}(p)`, - ); - case 'ArrayTypeAnnotation': - return inlineTemplate - .replace( - /::_RETURN_TYPE_::/, - markOptionalTypeIfNecessary( - `facebook::react::LazyVector<${getElementTypeForArray( - property, - name, - moduleName, - aliases, - )}>`, - ), - ) - .replace( - /::_RETURN_VALUE_::/, - `${markOptionalValueIfNecessary('vec')}(p, ^${getElementTypeForArray( - property, - name, - moduleName, - aliases, - )}(id itemValue_0) { return ${bridgeArrayElementValueIfNecessary( - 'itemValue_0', - )}; })`, - ); - case 'FunctionTypeAnnotation': - default: - throw new Error(`Unknown prop type, found: ${realTypeAnnotation.type}"`); - } -} - -function translateObjectsForStructs( - annotations: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, - >, - moduleName: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const flattenObjects = flatObjects(annotations, false, aliases); - - const translatedInlineMethods = flattenObjects - .reduce( - (acc, object) => - acc.concat( - object.properties.map(property => - getInlineMethodImplementation( - property, - object.name, - moduleName, - aliases, - ) - .replace(/::_PROPERTY_NAME_::/g, getSafePropertyName(property)) - .replace(/::_STRUCT_NAME_::/g, object.name), - ), - ), - [], - ) - .join('\n'); - - const translatedStructs = flattenObjects - .map(object => { - return structTemplate - .replace( - /::_STRUCT_PROPERTIES_::/g, - object.properties - .map(property => - getInlineMethodSignature( - property, - object.name, - moduleName, - aliases, - ), - ) - .join('\n '), - ) - .replace(/::_STRUCT_NAME_::/g, object.name); - }) - .reverse() - .join('\n'); - const translatedConstants = generateStructsForConstants(annotations, aliases); - - return template - .replace(/::_STRUCTS_::/, translatedStructs) - .replace(/::_INLINES_::/, translatedInlineMethods) - .replace(/::_CONSTANTS_::/, translatedConstants); -} -module.exports = { - translateObjectsForStructs, - capitalizeFirstLetter, - getNamespacedStructName, -}; diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js deleted file mode 100644 index 0433152f7f627d..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/GenerateStructsForConstants.js +++ /dev/null @@ -1,275 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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 - */ - -'use strict'; - -import type { - ObjectParamTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../../CodegenSchema'; -const {flatObjects, capitalizeFirstLetter} = require('./Utils'); -const {getTypeAliasTypeAnnotation} = require('../Utils'); - -const structTemplate = ` -namespace JS { - namespace Native::_MODULE_NAME_:: { - struct ::_STRUCT_NAME_:: { - - struct Builder { - struct Input { - ::_INPUT_:: - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing ::_STRUCT_NAME_:: */ - Builder(::_STRUCT_NAME_:: i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static ::_STRUCT_NAME_:: fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - ::_STRUCT_NAME_::(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -inline JS::Native::_MODULE_NAME_::::::_STRUCT_NAME_::::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - ::_PROPERTIES_:: - return d; -}) {} -inline JS::Native::_MODULE_NAME_::::::_STRUCT_NAME_::::Builder::Builder(::_STRUCT_NAME_:: i) : _factory(^{ - return i.unsafeRawValue(); -}) {}`; - -function getBuilderInputFieldDeclaration( - property: ObjectParamTypeAnnotation, - name: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - function markRequiredIfNecessary(annotation) { - if (!property.optional) { - return 'RCTRequired<' + annotation + '> ' + property.name + ';'; - } - return 'folly::Optional<' + annotation + '> ' + property.name + ';'; - } - const {typeAnnotation} = property; - - // TODO(T67898313): Workaround for NativeLinking's use of union type. This check may be removed once typeAnnotation is non-optional. - if (!typeAnnotation) { - throw new Error( - `Cannot get array element type, property ${property.name} does not contain a type annotation`, - ); - } - - const realTypeAnnotation = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases) - : typeAnnotation; - - const variableName = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? typeAnnotation.name - : `${name}${capitalizeFirstLetter(property.name)}`; - - switch (realTypeAnnotation.type) { - case 'ReservedFunctionValueTypeAnnotation': - switch (realTypeAnnotation.name) { - case 'RootTag': - return markRequiredIfNecessary('double'); - default: - (realTypeAnnotation.name: empty); - throw new Error( - `Unknown prop type, found: ${realTypeAnnotation.name}"`, - ); - } - case 'StringTypeAnnotation': - if (property.optional) { - return 'NSString *' + property.name + ';'; - } - return markRequiredIfNecessary('NSString *'); - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return markRequiredIfNecessary('double'); - case 'BooleanTypeAnnotation': - return markRequiredIfNecessary('bool'); - case 'ObjectTypeAnnotation': - return markRequiredIfNecessary( - `JS::Native::_MODULE_NAME_::::${variableName}::Builder`, - ); - case 'GenericObjectTypeAnnotation': - case 'AnyTypeAnnotation': - if (property.optional) { - return 'id _Nullable ' + property.name + ';'; - } - return markRequiredIfNecessary('id'); - case 'ArrayTypeAnnotation': - return markRequiredIfNecessary('std::vector>'); - case 'FunctionTypeAnnotation': - default: - throw new Error(`Unknown prop type, found: ${realTypeAnnotation.type}"`); - } -} - -function safeGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = ${name}; - `.trim(); -} - -function arrayGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = RCTConvert${ - optional ? 'Optional' : '' - }VecToArray(${name}, ^id(id el_) { return el_; }); - `.trim(); -} - -function boolGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = ${ - optional - ? `${name}.hasValue() ? @((BOOL)${name}.value()) : nil` - : `@(${name})` - }; - `.trim(); -} - -function numberGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = ${ - optional - ? `${name}.hasValue() ? @((double)${name}.value()) : nil` - : `@(${name})` - }; - `.trim(); -} - -function unsafeGetter(name: string, optional: boolean) { - return ` - auto ${name} = i.${name}${optional ? '' : '.get()'}; - d[@"${name}"] = ${ - optional - ? `${name}.hasValue() ? ${name}.value().buildUnsafeRawValue() : nil` - : `${name}.buildUnsafeRawValue()` - }; - `.trim(); -} - -function getObjectProperty( - property: ObjectParamTypeAnnotation, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - const {typeAnnotation} = property; - - // TODO(T67898313): Workaround for NativeLinking's use of union type. This check may be removed once typeAnnotation is non-optional. - if (!typeAnnotation) { - throw new Error( - `Cannot get array element type, property ${property.name} does not contain a type annotation`, - ); - } - - const type = - typeAnnotation.type === 'TypeAliasTypeAnnotation' - ? getTypeAliasTypeAnnotation(typeAnnotation.name, aliases).type - : typeAnnotation.type; - - switch (type) { - case 'ReservedFunctionValueTypeAnnotation': - if (typeAnnotation.name == null) { - throw new Error(`Prop type ${type} has no name.`); - } - switch (typeAnnotation.name) { - case 'RootTag': - return numberGetter(property.name, property.optional); - default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.name: empty); - throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`); - } - case 'NumberTypeAnnotation': - case 'FloatTypeAnnotation': - case 'Int32TypeAnnotation': - return numberGetter(property.name, property.optional); - case 'BooleanTypeAnnotation': - return boolGetter(property.name, property.optional); - case 'StringTypeAnnotation': - case 'GenericObjectTypeAnnotation': - case 'AnyTypeAnnotation': - return safeGetter(property.name, property.optional); - case 'ObjectTypeAnnotation': - return unsafeGetter(property.name, property.optional); - case 'ArrayTypeAnnotation': - return arrayGetter(property.name, property.optional); - case 'FunctionTypeAnnotation': - default: - throw new Error(`Unknown prop type, found: ${type}"`); - } -} - -function generateStructsForConstants( - annotations: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, - >, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): string { - return flatObjects(annotations, true, aliases) - .reduce( - (acc, object) => - acc.concat( - structTemplate - .replace( - /::_INPUT_::/g, - object.properties - .map(property => - getBuilderInputFieldDeclaration( - property, - object.name, - aliases, - ), - ) - .join('\n '), - ) - .replace( - /::_PROPERTIES_::/g, - object.properties - .map(property => getObjectProperty(property, aliases)) - .join('\n'), - ) - .replace(/::_STRUCT_NAME_::/g, object.name), - ), - [], - ) - .reverse() - .join('\n') - .replace(/SpecGetConstantsReturnType/g, 'Constants') - .replace(/GetConstantsReturnType/g, 'Constants'); -} -module.exports = { - generateStructsForConstants, - capitalizeFirstLetter, -}; diff --git a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/Utils.js b/packages/react-native-codegen/src/generators/modules/ObjCppUtils/Utils.js deleted file mode 100644 index fd4dca38468dad..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/ObjCppUtils/Utils.js +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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 - */ - -'use strict'; - -import type { - ObjectParamTypeAnnotation, - ObjectTypeAliasTypeShape, -} from '../../../CodegenSchema'; -const {getTypeAliasTypeAnnotation} = require('../Utils'); - -function capitalizeFirstLetter(string: string): string { - return string.charAt(0).toUpperCase() + string.slice(1); -} - -function flatObjects( - annotations: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, - >, - forConstants: boolean = false, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): $ReadOnlyArray< - $ReadOnly<{| - name: string, - properties: $ReadOnlyArray, - |}>, -> { - let objectTypesToFlatten: Array<{| - properties: $ReadOnlyArray, - name: string, - |}> = annotations - .map(annotation => { - if (annotation.object.type === 'TypeAliasTypeAnnotation') { - const alias = getTypeAliasTypeAnnotation(annotation.name, aliases); - return {name: annotation.name, properties: alias.properties}; - } - return { - name: annotation.name, - properties: annotation.object.properties, - }; - }) - .filter( - annotation => - (annotation.name === 'SpecGetConstantsReturnType') === forConstants, - ) - .filter( - annotation => - annotation.name !== 'SpecGetConstantsReturnType' || - annotation.properties.length > 0, - ); - - let flattenObjects: Array<{| - properties: $ReadOnlyArray, - name: string, - |}> = []; - - while (objectTypesToFlatten.length !== 0) { - const oldObjectTypesToFlatten = objectTypesToFlatten; - objectTypesToFlatten = []; - flattenObjects = flattenObjects.concat( - oldObjectTypesToFlatten.map(object => { - const {properties} = object; - if (properties !== undefined) { - objectTypesToFlatten = objectTypesToFlatten.concat( - properties.reduce((acc, curr) => { - if ( - curr.typeAnnotation && - curr.typeAnnotation.type === 'ObjectTypeAnnotation' && - curr.typeAnnotation.properties - ) { - return acc.concat({ - properties: curr.typeAnnotation.properties, - name: object.name + capitalizeFirstLetter(curr.name), - }); - } - return acc; - }, []), - ); - } - return object; - }), - ); - } - - return flattenObjects; -} - -function getSafePropertyName(property: ObjectParamTypeAnnotation): string { - if (property.name === 'id') { - return `${property.name}_`; - } - return property.name; -} - -module.exports = { - flatObjects, - capitalizeFirstLetter, - getSafePropertyName, -}; diff --git a/packages/react-native-codegen/src/generators/modules/Utils.js b/packages/react-native-codegen/src/generators/modules/Utils.js index 8ce5c95416f610..6985b861c7989e 100644 --- a/packages/react-native-codegen/src/generators/modules/Utils.js +++ b/packages/react-native-codegen/src/generators/modules/Utils.js @@ -10,35 +10,43 @@ 'use strict'; -import type {ObjectTypeAliasTypeShape} from '../../CodegenSchema'; +import type { + SchemaType, + NativeModuleAliasMap, + Required, + NativeModuleObjectTypeAnnotation, + NativeModuleSchema, +} from '../../CodegenSchema'; -function getTypeAliasTypeAnnotation( - name: string, - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, -): $ReadOnly { - const typeAnnotation = aliases[name]; - if (!typeAnnotation) { - throw Error(`No type annotation found for "${name}" in schema`); - } - if (typeAnnotation.type === 'ObjectTypeAnnotation') { - if (typeAnnotation.properties) { - return typeAnnotation; - } +const invariant = require('invariant'); - throw new Error( - `Unsupported type for "${name}". Please provide properties.`, - ); - } - // $FlowFixMe[incompatible-type] - if (typeAnnotation.type === 'TypeAliasTypeAnnotation') { - return getTypeAliasTypeAnnotation(typeAnnotation.name, aliases); - } +export type AliasResolver = ( + aliasName: string, +) => Required; + +function createAliasResolver(aliasMap: NativeModuleAliasMap): AliasResolver { + return (aliasName: string) => { + const alias = aliasMap[aliasName]; + invariant(alias != null, `Unable to resolve type alias '${aliasName}'.`); + return alias; + }; +} - throw Error( - `Unsupported type annotation in alias "${name}", found: ${typeAnnotation.type}`, - ); +function getModules( + schema: SchemaType, +): $ReadOnly<{|[moduleName: string]: NativeModuleSchema|}> { + return Object.keys(schema.modules) + .map( + moduleName => schema.modules[moduleName].nativeModules, + ) + .filter(Boolean) + .reduce<{+[string]: NativeModuleSchema}>( + (acc, modules) => ({...acc, ...modules}), + {}, + ); } module.exports = { - getTypeAliasTypeAnnotation, + createAliasResolver, + getModules, }; 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 cea663c8b1b425..92a7dc3489823e 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 @@ -34,6 +34,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { properties: [ { name: 'getConstants', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -45,6 +46,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { name: 'const1', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, { @@ -52,6 +54,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { name: 'const2', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -59,16 +62,18 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { name: 'const3', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, ], }, params: [], - optional: false, + nullable: false, }, }, { name: 'voidFunc', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -76,11 +81,12 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { type: 'VoidTypeAnnotation', }, params: [], - optional: false, + nullable: false, }, }, { name: 'getBool', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -89,18 +95,20 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'arg', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'getNumber', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -109,18 +117,20 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'arg', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'getString', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -129,44 +139,50 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'arg', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'getArray', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { nullable: false, type: 'ArrayTypeAnnotation', elementType: { - type: 'AnyTypeAnnotation', + type: 'GenericObjectTypeAnnotation', + nullable: false, }, }, params: [ { name: 'arg', - nullable: false, + optional: false, typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { - type: 'AnyTypeAnnotation', + type: 'GenericObjectTypeAnnotation', + nullable: false, }, }, }, ], - optional: false, + nullable: false, }, }, { name: 'getObject', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -175,18 +191,20 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'arg', typeAnnotation: { type: 'GenericObjectTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'getRootTag', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -196,19 +214,21 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'arg', typeAnnotation: { type: 'ReservedFunctionValueTypeAnnotation', name: 'RootTag', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'getValue', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -217,32 +237,36 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'x', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { - nullable: false, + optional: false, name: 'y', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { - nullable: false, + optional: false, name: 'z', typeAnnotation: { type: 'GenericObjectTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'getValueWithCallback', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -252,33 +276,41 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { params: [ { name: 'callback', - nullable: false, + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', + params: [], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + nullable: false, + }, + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'getValueWithPromise', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { nullable: false, - type: 'GenericPromiseTypeAnnotation', + type: 'PromiseTypeAnnotation', }, params: [ { - nullable: false, + optional: false, name: 'error', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, ], @@ -297,6 +329,7 @@ const TWO_MODULES_SAME_FILE: SchemaType = { properties: [ { name: 'voidFunc', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -304,7 +337,7 @@ const TWO_MODULES_SAME_FILE: SchemaType = { type: 'VoidTypeAnnotation', }, params: [], - optional: false, + nullable: false, }, }, ], @@ -314,6 +347,7 @@ const TWO_MODULES_SAME_FILE: SchemaType = { properties: [ { name: 'voidFunc', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -321,7 +355,7 @@ const TWO_MODULES_SAME_FILE: SchemaType = { type: 'VoidTypeAnnotation', }, params: [], - optional: false, + nullable: false, }, }, ], @@ -340,6 +374,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = { properties: [ { name: 'voidFunc', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -347,7 +382,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = { type: 'VoidTypeAnnotation', }, params: [], - optional: false, + nullable: false, }, }, ], @@ -361,6 +396,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = { properties: [ { name: 'getConstants', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -369,11 +405,12 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = { properties: [], }, params: [], - optional: false, + nullable: false, }, }, { name: 'voidFunc', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -381,7 +418,7 @@ const TWO_MODULES_DIFFERENT_FILES: SchemaType = { type: 'VoidTypeAnnotation', }, params: [], - optional: false, + nullable: false, }, }, ], @@ -400,6 +437,7 @@ const COMPLEX_OBJECTS: SchemaType = { properties: [ { name: 'difficult', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -411,6 +449,7 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'D', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, { @@ -418,6 +457,7 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'E', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -425,22 +465,25 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'F', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, ], }, params: [ { - nullable: false, + optional: false, name: 'A', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'D', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, { @@ -448,12 +491,14 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'E', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'D', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, { @@ -461,6 +506,7 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'E', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -468,6 +514,7 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'F', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -475,6 +522,7 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'id', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], @@ -485,17 +533,19 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'F', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, ], }, }, ], - optional: false, + nullable: false, }, }, { name: 'optionals', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -504,16 +554,18 @@ const COMPLEX_OBJECTS: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'A', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: true, name: 'optionalNumberProperty', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -521,8 +573,10 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'optionalArrayProperty', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'NumberTypeAnnotation', + nullable: false, }, }, }, @@ -531,12 +585,14 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'optionalObjectProperty', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'x', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -544,6 +600,7 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'y', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], @@ -554,6 +611,7 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'optionalGenericObjectProperty', typeAnnotation: { type: 'GenericObjectTypeAnnotation', + nullable: false, }, }, { @@ -561,17 +619,19 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'optionalBooleanTypeProperty', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, ], }, }, ], - optional: false, + nullable: false, }, }, { name: 'optionalMethod', + optional: true, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -580,48 +640,63 @@ const COMPLEX_OBJECTS: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'options', typeAnnotation: { type: 'GenericObjectTypeAnnotation', + nullable: false, }, }, { name: 'callback', - nullable: false, + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', + params: [], + returnTypeAnnotation: { + type: 'VoidTypeAnnotation', + nullable: false, + }, + nullable: false, }, }, { name: 'extras', - nullable: true, + optional: true, typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'key', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { optional: false, name: 'value', + typeAnnotation: { + type: 'GenericObjectTypeAnnotation', + nullable: false, + }, }, ], }, }, }, ], - optional: true, + nullable: true, }, }, { name: 'getArrays', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -630,18 +705,21 @@ const COMPLEX_OBJECTS: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'options', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'arrayOfNumbers', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'NumberTypeAnnotation', + nullable: false, }, }, }, @@ -650,8 +728,10 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'optionalArrayOfNumbers', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'NumberTypeAnnotation', + nullable: false, }, }, }, @@ -660,8 +740,10 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'arrayOfStrings', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'StringTypeAnnotation', + nullable: false, }, }, }, @@ -670,8 +752,10 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'optionalArrayOfStrings', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'StringTypeAnnotation', + nullable: false, }, }, }, @@ -680,14 +764,17 @@ const COMPLEX_OBJECTS: SchemaType = { name: 'arrayOfObjects', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'numberProperty', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], @@ -698,7 +785,7 @@ const COMPLEX_OBJECTS: SchemaType = { }, }, ], - optional: false, + nullable: false, }, }, ], @@ -715,18 +802,22 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { AliasTurboModule: { aliases: { Options: { + type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'offset', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'x', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -734,6 +825,7 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { name: 'y', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], @@ -744,12 +836,14 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { name: 'size', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'width', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -757,6 +851,7 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { name: 'height', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], @@ -767,12 +862,14 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { name: 'displaySize', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'width', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -780,6 +877,7 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { name: 'height', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], @@ -790,6 +888,7 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { name: 'resizeMode', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -797,15 +896,16 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { name: 'allowExternalStorage', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, ], - type: 'ObjectTypeAnnotation', }, }, properties: [ { name: 'getConstants', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -814,11 +914,12 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { properties: [], }, params: [], - optional: false, + nullable: false, }, }, { name: 'cropImage', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -827,15 +928,16 @@ const NATIVE_MODULES_WITH_TYPE_ALIASES: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'cropData', typeAnnotation: { type: 'TypeAliasTypeAnnotation', name: 'Options', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, ], @@ -853,12 +955,14 @@ const REAL_MODULE_EXAMPLE: SchemaType = { aliases: { PhotoIdentifierImage: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'uri', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -866,6 +970,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'playableDuration', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -873,6 +978,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'width', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -880,6 +986,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'height', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -887,6 +994,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'isStored', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, { @@ -894,18 +1002,21 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'filename', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, ], }, PhotoIdentifier: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'node', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, @@ -913,6 +1024,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { typeAnnotation: { type: 'TypeAliasTypeAnnotation', name: 'PhotoIdentifierImage', + nullable: false, }, }, { @@ -920,6 +1032,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'type', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -927,6 +1040,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'group_name', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -934,6 +1048,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'timestamp', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -941,12 +1056,14 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'location', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'longitude', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -954,6 +1071,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'latitude', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -961,6 +1079,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'altitude', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -968,6 +1087,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'heading', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -975,6 +1095,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'speed', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], @@ -987,15 +1108,18 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, PhotoIdentifiersPage: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'edges', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'TypeAliasTypeAnnotation', name: 'PhotoIdentifier', + nullable: false, }, }, }, @@ -1004,12 +1128,14 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'page_info', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'has_next_page', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, { @@ -1017,6 +1143,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'start_cursor', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1024,6 +1151,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'end_cursor', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, ], @@ -1033,12 +1161,14 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, GetPhotosParams: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'first', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -1046,6 +1176,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'after', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1053,6 +1184,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'groupName', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1060,6 +1192,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'groupTypes', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1067,6 +1200,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'assetType', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1074,6 +1208,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'maxSize', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -1081,8 +1216,10 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'mimeTypes', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'StringTypeAnnotation', + nullable: false, }, }, }, @@ -1092,6 +1229,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { properties: [ { name: 'getConstants', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -1100,78 +1238,86 @@ const REAL_MODULE_EXAMPLE: SchemaType = { properties: [], }, params: [], - optional: false, + nullable: false, }, }, { name: 'getPhotos', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { - type: 'GenericPromiseTypeAnnotation', + type: 'PromiseTypeAnnotation', nullable: false, }, params: [ { - nullable: false, + optional: false, name: 'params', typeAnnotation: { type: 'TypeAliasTypeAnnotation', name: 'GetPhotosParams', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'saveToCameraRoll', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { - type: 'GenericPromiseTypeAnnotation', + type: 'PromiseTypeAnnotation', nullable: false, }, params: [ { - nullable: false, + optional: false, name: 'uri', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { - nullable: false, + optional: false, name: 'type', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'deletePhotos', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { - type: 'GenericPromiseTypeAnnotation', + type: 'PromiseTypeAnnotation', nullable: false, }, params: [ { name: 'assets', - nullable: false, + optional: false, typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'StringTypeAnnotation', + nullable: false, }, }, }, ], - optional: false, + nullable: false, }, }, ], @@ -1185,6 +1331,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { properties: [ { name: 'openCameraDialog', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -1193,16 +1340,18 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'config', typeAnnotation: { type: 'ObjectTypeAnnotation', + nullable: false, properties: [ { optional: false, name: 'unmirrorFrontFacingCamera', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, { @@ -1210,6 +1359,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'videoMode', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, ], @@ -1217,20 +1367,32 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, { name: 'successCallback', - nullable: false, + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', + params: [], + returnTypeAnnotation: { + nullable: false, + type: 'VoidTypeAnnotation', + }, + nullable: false, }, }, { name: 'cancelCallback', - nullable: false, + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', + params: [], + returnTypeAnnotation: { + nullable: false, + type: 'VoidTypeAnnotation', + }, + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, ], @@ -1248,6 +1410,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'column', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -1255,6 +1418,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'file', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1262,6 +1426,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'lineNumber', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -1269,6 +1434,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'methodName', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1276,10 +1442,12 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'collapse', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, ], type: 'ObjectTypeAnnotation', + nullable: false, }, ExceptionData: { properties: [ @@ -1288,6 +1456,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'message', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1295,6 +1464,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'originalMessage', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1302,6 +1472,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'name', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1309,6 +1480,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'componentStack', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { @@ -1316,9 +1488,11 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'stack', typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'TypeAliasTypeAnnotation', name: 'StackFrame', + nullable: false, }, }, }, @@ -1327,6 +1501,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'id', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, { @@ -1334,6 +1509,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'isFatal', typeAnnotation: { type: 'BooleanTypeAnnotation', + nullable: false, }, }, { @@ -1341,15 +1517,18 @@ const REAL_MODULE_EXAMPLE: SchemaType = { name: 'extraData', typeAnnotation: { type: 'GenericObjectTypeAnnotation', + nullable: false, }, }, ], type: 'ObjectTypeAnnotation', + nullable: false, }, }, properties: [ { name: 'reportFatalException', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -1358,36 +1537,41 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'message', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { name: 'stack', - nullable: false, + optional: false, typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'TypeAliasTypeAnnotation', name: 'StackFrame', + nullable: false, }, }, }, { - nullable: false, + optional: false, name: 'exceptionId', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'reportSoftException', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -1396,36 +1580,41 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'message', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { name: 'stack', - nullable: false, + optional: false, typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'TypeAliasTypeAnnotation', name: 'StackFrame', + nullable: false, }, }, }, { - nullable: false, + optional: false, name: 'exceptionId', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'reportException', + optional: true, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -1434,19 +1623,21 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'data', typeAnnotation: { type: 'TypeAliasTypeAnnotation', name: 'ExceptionData', + nullable: false, }, }, ], - optional: true, + nullable: true, }, }, { name: 'updateExceptionMessage', + optional: false, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -1455,36 +1646,41 @@ const REAL_MODULE_EXAMPLE: SchemaType = { }, params: [ { - nullable: false, + optional: false, name: 'message', typeAnnotation: { type: 'StringTypeAnnotation', + nullable: false, }, }, { name: 'stack', - nullable: false, + optional: false, typeAnnotation: { type: 'ArrayTypeAnnotation', + nullable: false, elementType: { type: 'TypeAliasTypeAnnotation', name: 'StackFrame', + nullable: false, }, }, }, { - nullable: false, + optional: false, name: 'exceptionId', typeAnnotation: { type: 'NumberTypeAnnotation', + nullable: false, }, }, ], - optional: false, + nullable: false, }, }, { name: 'dismissRedbox', + optional: true, typeAnnotation: { type: 'FunctionTypeAnnotation', returnTypeAnnotation: { @@ -1492,7 +1688,7 @@ const REAL_MODULE_EXAMPLE: SchemaType = { type: 'VoidTypeAnnotation', }, params: [], - optional: true, + nullable: true, }, }, ], diff --git a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/structFixtures.js b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/structFixtures.js deleted file mode 100644 index 2de452b87c2c39..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/structFixtures.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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-local - * @format - */ - -'use strict'; - -import type {ObjectParamTypeAnnotation} from '../../../CodegenSchema.js'; -const SIMPLE_STRUCT: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, -> = [ - { - name: 'SpecSampleFuncReturnType', - object: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'a', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'b', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'c', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: false, - name: 'd', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'e', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'f', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'g', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'h', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'i', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'j', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - ], - }, - }, - ], - }, - }, - { - optional: false, - name: 'k', - typeAnnotation: { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }, - }, - ], - }, - }, -]; - -const SIMPLE_CONSTANTS: $ReadOnlyArray< - $ReadOnly<{| - name: string, - object: $ReadOnly<{| - type: 'ObjectTypeAnnotation', - properties: $ReadOnlyArray, - |}>, - |}>, -> = [ - { - name: 'SpecGetConstantsReturnType', - object: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'a', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'b', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'c', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - { - optional: false, - name: 'd', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'e', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'f', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'g', - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: [ - { - optional: false, - name: 'h', - typeAnnotation: { - type: 'BooleanTypeAnnotation', - }, - }, - { - optional: false, - name: 'i', - typeAnnotation: { - type: 'NumberTypeAnnotation', - }, - }, - { - optional: false, - name: 'j', - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }, - ], - }, - }, - ], - }, - }, - { - optional: false, - name: 'k', - typeAnnotation: { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }, - }, - ], - }, - }, -]; -module.exports = { - SIMPLE_STRUCT, - SIMPLE_CONSTANTS, -}; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js index b41441cb2daf7c..3c4943971857b0 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleHObjCpp-test.js @@ -12,7 +12,7 @@ 'use strict'; const fixtures = require('../__test_fixtures__/fixtures.js'); -const generator = require('../GenerateModuleHObjCpp.js'); +const generator = require('../GenerateModuleObjCpp'); describe('GenerateModuleHObjCpp', () => { Object.keys(fixtures) @@ -21,8 +21,9 @@ describe('GenerateModuleHObjCpp', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { + const output = generator.generate(fixtureName, fixture, 'SampleSpec'); expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + new Map([['SampleSpec.h', output.get('SampleSpec.h')]]), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleMm-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleMm-test.js index 5bfd8c79e07682..ec8f4842a106bf 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleMm-test.js +++ b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateModuleMm-test.js @@ -12,7 +12,7 @@ 'use strict'; const fixtures = require('../__test_fixtures__/fixtures.js'); -const generator = require('../GenerateModuleMm.js'); +const generator = require('../GenerateModuleObjCpp'); describe('GenerateModuleMm', () => { Object.keys(fixtures) @@ -21,8 +21,11 @@ describe('GenerateModuleMm', () => { const fixture = fixtures[fixtureName]; it(`can generate fixture ${fixtureName}`, () => { + const output = generator.generate(fixtureName, fixture, 'SampleSpec'); expect( - generator.generate(fixtureName, fixture, 'SampleSpec'), + new Map([ + ['SampleSpec-generated.mm', output.get('SampleSpec-generated.mm')], + ]), ).toMatchSnapshot(); }); }); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateStructs-test.js b/packages/react-native-codegen/src/generators/modules/__tests__/GenerateStructs-test.js deleted file mode 100644 index a66b5ff7e4c28c..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/__tests__/GenerateStructs-test.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @emails oncall+react_native - * @flow strict-local - * @format - */ - -'use strict'; - -const fixtures = require('../__test_fixtures__/structFixtures.js'); -const generator = require('../ObjCppUtils/GenerateStructs.js'); - -describe('GenerateStructs', () => { - Object.keys(fixtures) - .sort() - .forEach(fixtureName => { - const fixture = fixtures[fixtureName]; - - it(`can generate fixture ${fixtureName}`, () => { - expect( - generator - .translateObjectsForStructs(fixture, fixtureName, {}) - .replace(/::_MODULE_NAME_::/g, 'SampleTurboModule'), - ).toMatchSnapshot(); - }); - }); -}); 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 fbdcb15bae2c68..4e55a6343121fe 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 @@ -2,7 +2,8 @@ exports[`GenerateModuleH can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "NativeModules.h" => "/** + "NativeModules.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -38,7 +39,8 @@ virtual void getArrays(jsi::Runtime &rt, const jsi::Object &options) = 0; exports[`GenerateModuleH can generate fixture EMPTY_NATIVE_MODULES 1`] = ` Map { - "NativeModules.h" => "/** + "NativeModules.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -71,7 +73,8 @@ public: exports[`GenerateModuleH can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "NativeModules.h" => "/** + "NativeModules.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -105,7 +108,8 @@ virtual void cropImage(jsi::Runtime &rt, const jsi::Object &cropData) = 0; exports[`GenerateModuleH can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "NativeModules.h" => "/** + "NativeModules.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -163,7 +167,8 @@ virtual void dismissRedbox(jsi::Runtime &rt) = 0; exports[`GenerateModuleH can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "NativeModules.h" => "/** + "NativeModules.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -206,7 +211,8 @@ virtual jsi::Value getValueWithPromise(jsi::Runtime &rt, bool error) = 0; exports[`GenerateModuleH can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "NativeModules.h" => "/** + "NativeModules.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -249,7 +255,8 @@ virtual void voidFunc(jsi::Runtime &rt) = 0; exports[`GenerateModuleH can generate fixture TWO_MODULES_SAME_FILE 1`] = ` Map { - "NativeModules.h" => "/** + "NativeModules.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the 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 939b9bcea8d2f2..2d7f078c5257b9 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 @@ -34,24 +34,6 @@ Map { -namespace JS { - namespace NativeSampleTurboModule { - struct SpecOptionalsAOptionalObjectProperty { - double x() const; - double y() const; - - SpecOptionalsAOptionalObjectProperty(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json; -@end - - namespace JS { namespace NativeSampleTurboModule { struct SpecDifficultAE { @@ -74,57 +56,38 @@ namespace JS { namespace JS { namespace NativeSampleTurboModule { - struct SpecGetArraysOptionsArrayOfObjectsElement { - double numberProperty() const; - - SpecGetArraysOptionsArrayOfObjectsElement(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement:(id)json; -@end - - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecGetArraysOptions { - facebook::react::LazyVector arrayOfNumbers() const; - folly::Optional> optionalArrayOfNumbers() const; - facebook::react::LazyVector arrayOfStrings() const; - folly::Optional> optionalArrayOfStrings() const; - facebook::react::LazyVector arrayOfObjects() const; + struct SpecDifficultA { + bool D() const; + JS::NativeSampleTurboModule::SpecDifficultAE E() const; + NSString *F() const; - SpecGetArraysOptions(NSDictionary *const v) : _v(v) {} + SpecDifficultA(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptions) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptions:(id)json; +@interface RCTCxxConvert (NativeSampleTurboModule_SpecDifficultA) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultA:(id)json; @end namespace JS { namespace NativeSampleTurboModule { - struct SpecOptionalMethodExtrasElement { - NSString *key() const; - id value() const; + struct SpecOptionalsAOptionalObjectProperty { + double x() const; + double y() const; - SpecOptionalMethodExtrasElement(NSDictionary *const v) : _v(v) {} + SpecOptionalsAOptionalObjectProperty(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalMethodExtrasElement) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalMethodExtrasElement:(id)json; +@interface RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json; @end @@ -151,83 +114,128 @@ namespace JS { namespace JS { namespace NativeSampleTurboModule { - struct SpecDifficultReturnType { - bool D() const; - double E() const; - NSString *F() const; + struct SpecGetArraysOptionsArrayOfObjectsElement { + double numberProperty() const; - SpecDifficultReturnType(NSDictionary *const v) : _v(v) {} + SpecGetArraysOptionsArrayOfObjectsElement(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeSampleTurboModule_SpecDifficultReturnType) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultReturnType:(id)json; +@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement:(id)json; @end namespace JS { namespace NativeSampleTurboModule { - struct SpecDifficultA { - bool D() const; - JS::NativeSampleTurboModule::SpecDifficultAE E() const; - NSString *F() const; + struct SpecGetArraysOptions { + facebook::react::LazyVector arrayOfNumbers() const; + folly::Optional> optionalArrayOfNumbers() const; + facebook::react::LazyVector arrayOfStrings() const; + folly::Optional> optionalArrayOfStrings() const; + facebook::react::LazyVector arrayOfObjects() const; - SpecDifficultA(NSDictionary *const v) : _v(v) {} + SpecGetArraysOptions(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeSampleTurboModule_SpecDifficultA) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultA:(id)json; +@interface RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptions) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptions:(id)json; @end -inline bool JS::NativeSampleTurboModule::SpecDifficultA::D() const +@protocol NativeSampleTurboModuleSpec + +- (NSDictionary *)difficult:(JS::NativeSampleTurboModule::SpecDifficultA &)A; +- (void)optionals:(JS::NativeSampleTurboModule::SpecOptionalsA &)A; +- (void)optionalMethod:(NSDictionary *)options + callback:(RCTResponseSenderBlock)callback + extras:(NSArray *)extras; +- (void)getArrays:(JS::NativeSampleTurboModule::SpecGetArraysOptions &)options; + +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'SampleTurboModule' + */ + class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + + + +inline bool JS::NativeSampleTurboModule::SpecDifficultAE::D() const { id const p = _v[@\\"D\\"]; return RCTBridgingToBool(p); } -inline JS::NativeSampleTurboModule::SpecDifficultAE JS::NativeSampleTurboModule::SpecDifficultA::E() const +inline double JS::NativeSampleTurboModule::SpecDifficultAE::E() const { id const p = _v[@\\"E\\"]; - return JS::NativeSampleTurboModule::SpecDifficultAE(p); + return RCTBridgingToDouble(p); } -inline NSString *JS::NativeSampleTurboModule::SpecDifficultA::F() const +inline NSString *JS::NativeSampleTurboModule::SpecDifficultAE::F() const { id const p = _v[@\\"F\\"]; return RCTBridgingToString(p); } -inline bool JS::NativeSampleTurboModule::SpecDifficultReturnType::D() const +inline double JS::NativeSampleTurboModule::SpecDifficultAE::id_() const +{ + id const p = _v[@\\"id_\\"]; + return RCTBridgingToDouble(p); +} + + +inline bool JS::NativeSampleTurboModule::SpecDifficultA::D() const { id const p = _v[@\\"D\\"]; return RCTBridgingToBool(p); } -inline double JS::NativeSampleTurboModule::SpecDifficultReturnType::E() const +inline JS::NativeSampleTurboModule::SpecDifficultAE JS::NativeSampleTurboModule::SpecDifficultA::E() const { id const p = _v[@\\"E\\"]; - return RCTBridgingToDouble(p); + return JS::NativeSampleTurboModule::SpecDifficultAE(p); } -inline NSString *JS::NativeSampleTurboModule::SpecDifficultReturnType::F() const +inline NSString *JS::NativeSampleTurboModule::SpecDifficultA::F() const { id const p = _v[@\\"F\\"]; return RCTBridgingToString(p); } +inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::x() const +{ + id const p = _v[@\\"x\\"]; + return RCTBridgingToDouble(p); +} + + +inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::y() const +{ + id const p = _v[@\\"y\\"]; + return RCTBridgingToDouble(p); +} + + inline folly::Optional JS::NativeSampleTurboModule::SpecOptionalsA::optionalNumberProperty() const { id const p = _v[@\\"optionalNumberProperty\\"]; @@ -263,17 +271,10 @@ inline folly::Optional JS::NativeSampleTurboModule::SpecOptionalsA::option } -inline NSString *JS::NativeSampleTurboModule::SpecOptionalMethodExtrasElement::key() const -{ - id const p = _v[@\\"key\\"]; - return RCTBridgingToString(p); -} - - -inline id JS::NativeSampleTurboModule::SpecOptionalMethodExtrasElement::value() const +inline double JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement::numberProperty() const { - id const p = _v[@\\"value\\"]; - return p; + id const p = _v[@\\"numberProperty\\"]; + return RCTBridgingToDouble(p); } @@ -305,84 +306,12 @@ inline folly::Optional> JS::NativeSample } -inline facebook::react::LazyVector JS::NativeSampleTurboModule::SpecGetArraysOptions::arrayOfObjects() const +inline facebook::react::LazyVector JS::NativeSampleTurboModule::SpecGetArraysOptions::arrayOfObjects() const { id const p = _v[@\\"arrayOfObjects\\"]; - return RCTBridgingToVec(p, ^JS::NativeSampleTurboModule::arrayOfObjectsElement(id itemValue_0) { return JS::NativeSampleTurboModule::arrayOfObjectsElement(itemValue_0); }); -} - - -inline double JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement::numberProperty() const -{ - id const p = _v[@\\"numberProperty\\"]; - return RCTBridgingToDouble(p); -} - - -inline bool JS::NativeSampleTurboModule::SpecDifficultAE::D() const -{ - id const p = _v[@\\"D\\"]; - return RCTBridgingToBool(p); -} - - -inline double JS::NativeSampleTurboModule::SpecDifficultAE::E() const -{ - id const p = _v[@\\"E\\"]; - return RCTBridgingToDouble(p); -} - - -inline NSString *JS::NativeSampleTurboModule::SpecDifficultAE::F() const -{ - id const p = _v[@\\"F\\"]; - return RCTBridgingToString(p); -} - - -inline double JS::NativeSampleTurboModule::SpecDifficultAE::id_() const -{ - id const p = _v[@\\"id_\\"]; - return RCTBridgingToDouble(p); -} - - -inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::x() const -{ - id const p = _v[@\\"x\\"]; - return RCTBridgingToDouble(p); -} - - -inline double JS::NativeSampleTurboModule::SpecOptionalsAOptionalObjectProperty::y() const -{ - id const p = _v[@\\"y\\"]; - return RCTBridgingToDouble(p); + return RCTBridgingToVec(p, ^JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement(id itemValue_0) { return JS::NativeSampleTurboModule::SpecGetArraysOptionsArrayOfObjectsElement(p); }); } - - -@protocol NativeSampleTurboModuleSpec -- (NSDictionary *) difficult:(JS::NativeSampleTurboModule::SpecDifficultA &)A; -- (void) optionals:(JS::NativeSampleTurboModule::SpecOptionalsA &)A; -- (void) optionalMethod:(NSDictionary *)options - callback:(RCTResponseSenderBlock)callback - extras:(NSArray * _Nullable)extras; -- (void) getArrays:(JS::NativeSampleTurboModule::SpecGetArraysOptions &)options; -@end - - -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'SampleTurboModule' - */ - class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - } // namespace react -} // namespace facebook ", } `; @@ -421,24 +350,25 @@ Map { - - @protocol NativeSampleTurboModuleSpec -@end +@end namespace facebook { namespace react { /** - * ObjC++ class for module 'SampleTurboModule' - */ + * ObjC++ class for module 'SampleTurboModule' + */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { public: NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; } // namespace react } // namespace facebook + + + ", } `; @@ -479,19 +409,19 @@ Map { namespace JS { namespace NativeAliasTurboModule { - struct OptionsDisplaySize { - double width() const; - double height() const; + struct OptionsOffset { + double x() const; + double y() const; - OptionsDisplaySize(NSDictionary *const v) : _v(v) {} + OptionsOffset(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeAliasTurboModule_OptionsDisplaySize) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsDisplaySize:(id)json; +@interface RCTCxxConvert (NativeAliasTurboModule_OptionsOffset) ++ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsOffset:(id)json; @end @@ -515,19 +445,19 @@ namespace JS { namespace JS { namespace NativeAliasTurboModule { - struct OptionsOffset { - double x() const; - double y() const; + struct OptionsDisplaySize { + double width() const; + double height() const; - OptionsOffset(NSDictionary *const v) : _v(v) {} + OptionsDisplaySize(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeAliasTurboModule_OptionsOffset) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsOffset:(id)json; +@interface RCTCxxConvert (NativeAliasTurboModule_OptionsDisplaySize) ++ (RCTManagedPointer *)JS_NativeAliasTurboModule_OptionsDisplaySize:(id)json; @end @@ -551,40 +481,24 @@ namespace JS { + (RCTManagedPointer *)JS_NativeAliasTurboModule_Options:(id)json; @end -inline JS::NativeAliasTurboModule::OptionsOffset JS::NativeAliasTurboModule::Options::offset() const -{ - id const p = _v[@\\"offset\\"]; - return JS::NativeAliasTurboModule::OptionsOffset(p); -} +@protocol NativeAliasTurboModuleSpec +- (void)cropImage:(JS::NativeAliasTurboModule::Options &)cropData; -inline JS::NativeAliasTurboModule::OptionsSize JS::NativeAliasTurboModule::Options::size() const -{ - id const p = _v[@\\"size\\"]; - return JS::NativeAliasTurboModule::OptionsSize(p); -} +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'AliasTurboModule' + */ + class JSI_EXPORT NativeAliasTurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeAliasTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook -inline folly::Optional JS::NativeAliasTurboModule::Options::displaySize() const -{ - id const p = _v[@\\"displaySize\\"]; - return (p == nil ? folly::none : folly::make_optional(JS::NativeAliasTurboModule::OptionsDisplaySize(p))); -} - - -inline NSString *JS::NativeAliasTurboModule::Options::resizeMode() const -{ - id const p = _v[@\\"resizeMode\\"]; - return RCTBridgingToString(p); -} - - -inline folly::Optional JS::NativeAliasTurboModule::Options::allowExternalStorage() const -{ - id const p = _v[@\\"allowExternalStorage\\"]; - return RCTBridgingToOptionalBool(p); -} - inline double JS::NativeAliasTurboModule::OptionsOffset::x() const { @@ -628,24 +542,40 @@ inline double JS::NativeAliasTurboModule::OptionsDisplaySize::height() const } +inline JS::NativeAliasTurboModule::OptionsOffset JS::NativeAliasTurboModule::Options::offset() const +{ + id const p = _v[@\\"offset\\"]; + return JS::NativeAliasTurboModule::OptionsOffset(p); +} -@protocol NativeAliasTurboModuleSpec -- (void) cropImage:(JS::NativeAliasTurboModule::Options &)cropData; -@end +inline JS::NativeAliasTurboModule::OptionsSize JS::NativeAliasTurboModule::Options::size() const +{ + id const p = _v[@\\"size\\"]; + return JS::NativeAliasTurboModule::OptionsSize(p); +} -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'AliasTurboModule' - */ - class JSI_EXPORT NativeAliasTurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeAliasTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - } // namespace react -} // namespace facebook +inline folly::Optional JS::NativeAliasTurboModule::Options::displaySize() const +{ + id const p = _v[@\\"displaySize\\"]; + return (p == nil ? folly::none : folly::make_optional(JS::NativeAliasTurboModule::OptionsDisplaySize(p))); +} + + +inline NSString *JS::NativeAliasTurboModule::Options::resizeMode() const +{ + id const p = _v[@\\"resizeMode\\"]; + return RCTBridgingToOptionalString(p); +} + + +inline folly::Optional JS::NativeAliasTurboModule::Options::allowExternalStorage() const +{ + id const p = _v[@\\"allowExternalStorage\\"]; + return RCTBridgingToOptionalBool(p); +} + ", } `; @@ -686,143 +616,164 @@ Map { namespace JS { namespace NativeCameraRollManager { - struct PhotoIdentifierNodeLocation { - double longitude() const; - double latitude() const; - folly::Optional altitude() const; - folly::Optional heading() const; - folly::Optional speed() const; - - PhotoIdentifierNodeLocation(NSDictionary *const v) : _v(v) {} + struct GetPhotosParams { + double first() const; + NSString *after() const; + NSString *groupName() const; + NSString *groupTypes() const; + NSString *assetType() const; + folly::Optional maxSize() const; + folly::Optional> mimeTypes() const; + + GetPhotosParams(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNodeLocation) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNodeLocation:(id)json; +@interface RCTCxxConvert (NativeCameraRollManager_GetPhotosParams) ++ (RCTManagedPointer *)JS_NativeCameraRollManager_GetPhotosParams:(id)json; @end +@protocol NativeCameraRollManagerSpec -namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifierNode { - JS::NativeCameraRollManager::PhotoIdentifierImage image() const; - NSString *type() const; - NSString *group_name() const; - double timestamp() const; - JS::NativeCameraRollManager::PhotoIdentifierNodeLocation location() const; - - PhotoIdentifierNode(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} +- (void)getPhotos:(JS::NativeCameraRollManager::GetPhotosParams &)params + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (void)saveToCameraRoll:(NSString *)uri + type:(NSString *)type + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; +- (void)deletePhotos:(NSArray *)assets + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNode) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNode:(id)json; @end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'CameraRollManager' + */ + class JSI_EXPORT NativeCameraRollManagerSpecJSI : public ObjCTurboModule { + public: + NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook + namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifiersPagePage_info { - bool has_next_page() const; - NSString *start_cursor() const; - NSString *end_cursor() const; + namespace NativeExceptionsManager { + struct StackFrame { + folly::Optional column() const; + NSString *file() const; + folly::Optional lineNumber() const; + NSString *methodName() const; + folly::Optional collapse() const; - PhotoIdentifiersPagePage_info(NSDictionary *const v) : _v(v) {} + StackFrame(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPagePage_info) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPagePage_info:(id)json; +@interface RCTCxxConvert (NativeExceptionsManager_StackFrame) ++ (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json; @end namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifierImage { - NSString *uri() const; - double playableDuration() const; - double width() const; - double height() const; - folly::Optional isStored() const; - NSString *filename() const; + namespace NativeExceptionsManager { + struct ExceptionData { + NSString *message() const; + NSString *originalMessage() const; + NSString *name() const; + NSString *componentStack() const; + facebook::react::LazyVector stack() const; + double id_() const; + bool isFatal() const; + id _Nullable extraData() const; - PhotoIdentifierImage(NSDictionary *const v) : _v(v) {} + ExceptionData(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierImage) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierImage:(id)json; +@interface RCTCxxConvert (NativeExceptionsManager_ExceptionData) ++ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionData:(id)json; @end +@protocol NativeExceptionsManagerSpec -namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifier { - JS::NativeCameraRollManager::PhotoIdentifierNode node() const; +- (void)reportFatalException:(NSString *)message + stack:(NSArray *)stack + exceptionId:(double)exceptionId; +- (void)reportSoftException:(NSString *)message + stack:(NSArray *)stack + exceptionId:(double)exceptionId; +- (void)reportException:(JS::NativeExceptionsManager::ExceptionData &)data; +- (void)updateExceptionMessage:(NSString *)message + stack:(NSArray *)stack + exceptionId:(double)exceptionId; +- (void)dismissRedbox; - PhotoIdentifier(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'ExceptionsManager' + */ + class JSI_EXPORT NativeExceptionsManagerSpecJSI : public ObjCTurboModule { + public: + NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; - } -} + } // namespace react +} // namespace facebook -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifier) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifier:(id)json; -@end namespace JS { - namespace NativeCameraRollManager { - struct PhotoIdentifiersPage { - facebook::react::LazyVector edges() const; - JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info page_info() const; + namespace NativeImagePickerIOS { + struct SpecOpenCameraDialogConfig { + bool unmirrorFrontFacingCamera() const; + bool videoMode() const; - PhotoIdentifiersPage(NSDictionary *const v) : _v(v) {} + SpecOpenCameraDialogConfig(NSDictionary *const v) : _v(v) {} private: NSDictionary *_v; }; } } -@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPage) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPage:(id)json; +@interface RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) ++ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json; @end +@protocol NativeImagePickerIOSSpec -namespace JS { - namespace NativeCameraRollManager { - struct GetPhotosParams { - double first() const; - NSString *after() const; - NSString *groupName() const; - NSString *groupTypes() const; - NSString *assetType() const; - folly::Optional maxSize() const; - folly::Optional> mimeTypes() const; +- (void)openCameraDialog:(JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig &)config + successCallback:(RCTResponseSenderBlock)successCallback + cancelCallback:(RCTResponseSenderBlock)cancelCallback; - GetPhotosParams(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'ImagePickerIOS' + */ + class JSI_EXPORT NativeImagePickerIOSSpecJSI : public ObjCTurboModule { + public: + NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; - } -} + } // namespace react +} // namespace facebook + -@interface RCTCxxConvert (NativeCameraRollManager_GetPhotosParams) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_GetPhotosParams:(id)json; -@end inline double JS::NativeCameraRollManager::GetPhotosParams::first() const { @@ -834,28 +785,28 @@ inline double JS::NativeCameraRollManager::GetPhotosParams::first() const inline NSString *JS::NativeCameraRollManager::GetPhotosParams::after() const { id const p = _v[@\\"after\\"]; - return RCTBridgingToString(p); + return RCTBridgingToOptionalString(p); } inline NSString *JS::NativeCameraRollManager::GetPhotosParams::groupName() const { id const p = _v[@\\"groupName\\"]; - return RCTBridgingToString(p); + return RCTBridgingToOptionalString(p); } inline NSString *JS::NativeCameraRollManager::GetPhotosParams::groupTypes() const { id const p = _v[@\\"groupTypes\\"]; - return RCTBridgingToString(p); + return RCTBridgingToOptionalString(p); } inline NSString *JS::NativeCameraRollManager::GetPhotosParams::assetType() const { id const p = _v[@\\"assetType\\"]; - return RCTBridgingToString(p); + return RCTBridgingToOptionalString(p); } @@ -873,220 +824,40 @@ inline folly::Optional> JS::NativeCamera } -inline facebook::react::LazyVector JS::NativeCameraRollManager::PhotoIdentifiersPage::edges() const -{ - id const p = _v[@\\"edges\\"]; - return RCTBridgingToVec(p, ^JS::NativeCameraRollManager::PhotoIdentifier(id itemValue_0) { return JS::NativeCameraRollManager::PhotoIdentifier(itemValue_0); }); -} - - -inline JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info JS::NativeCameraRollManager::PhotoIdentifiersPage::page_info() const -{ - id const p = _v[@\\"page_info\\"]; - return JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info(p); -} - - -inline JS::NativeCameraRollManager::PhotoIdentifierNode JS::NativeCameraRollManager::PhotoIdentifier::node() const -{ - id const p = _v[@\\"node\\"]; - return JS::NativeCameraRollManager::PhotoIdentifierNode(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifierImage::uri() const -{ - id const p = _v[@\\"uri\\"]; - return RCTBridgingToString(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierImage::playableDuration() const -{ - id const p = _v[@\\"playableDuration\\"]; - return RCTBridgingToDouble(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierImage::width() const -{ - id const p = _v[@\\"width\\"]; - return RCTBridgingToDouble(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierImage::height() const -{ - id const p = _v[@\\"height\\"]; - return RCTBridgingToDouble(p); -} - - -inline folly::Optional JS::NativeCameraRollManager::PhotoIdentifierImage::isStored() const -{ - id const p = _v[@\\"isStored\\"]; - return RCTBridgingToOptionalBool(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifierImage::filename() const -{ - id const p = _v[@\\"filename\\"]; - return RCTBridgingToString(p); -} - - -inline bool JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::has_next_page() const -{ - id const p = _v[@\\"has_next_page\\"]; - return RCTBridgingToBool(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::start_cursor() const -{ - id const p = _v[@\\"start_cursor\\"]; - return RCTBridgingToString(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::end_cursor() const -{ - id const p = _v[@\\"end_cursor\\"]; - return RCTBridgingToString(p); -} - - -inline JS::NativeCameraRollManager::PhotoIdentifierImage JS::NativeCameraRollManager::PhotoIdentifierNode::image() const -{ - id const p = _v[@\\"image\\"]; - return JS::NativeCameraRollManager::PhotoIdentifierImage(p); -} - - -inline NSString *JS::NativeCameraRollManager::PhotoIdentifierNode::type() const +inline folly::Optional JS::NativeExceptionsManager::StackFrame::column() const { - id const p = _v[@\\"type\\"]; - return RCTBridgingToString(p); + id const p = _v[@\\"column\\"]; + return RCTBridgingToOptionalDouble(p); } -inline NSString *JS::NativeCameraRollManager::PhotoIdentifierNode::group_name() const +inline NSString *JS::NativeExceptionsManager::StackFrame::file() const { - id const p = _v[@\\"group_name\\"]; + id const p = _v[@\\"file\\"]; return RCTBridgingToString(p); } -inline double JS::NativeCameraRollManager::PhotoIdentifierNode::timestamp() const -{ - id const p = _v[@\\"timestamp\\"]; - return RCTBridgingToDouble(p); -} - - -inline JS::NativeCameraRollManager::PhotoIdentifierNodeLocation JS::NativeCameraRollManager::PhotoIdentifierNode::location() const -{ - id const p = _v[@\\"location\\"]; - return JS::NativeCameraRollManager::PhotoIdentifierNodeLocation(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::longitude() const -{ - id const p = _v[@\\"longitude\\"]; - return RCTBridgingToDouble(p); -} - - -inline double JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::latitude() const -{ - id const p = _v[@\\"latitude\\"]; - return RCTBridgingToDouble(p); -} - - -inline folly::Optional JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::altitude() const +inline folly::Optional JS::NativeExceptionsManager::StackFrame::lineNumber() const { - id const p = _v[@\\"altitude\\"]; + id const p = _v[@\\"lineNumber\\"]; return RCTBridgingToOptionalDouble(p); } -inline folly::Optional JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::heading() const +inline NSString *JS::NativeExceptionsManager::StackFrame::methodName() const { - id const p = _v[@\\"heading\\"]; - return RCTBridgingToOptionalDouble(p); + id const p = _v[@\\"methodName\\"]; + return RCTBridgingToString(p); } -inline folly::Optional JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::speed() const +inline folly::Optional JS::NativeExceptionsManager::StackFrame::collapse() const { - id const p = _v[@\\"speed\\"]; - return RCTBridgingToOptionalDouble(p); -} - - - -@protocol NativeCameraRollManagerSpec - -- (void) getPhotos:(JS::NativeCameraRollManager::GetPhotosParams &)params - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void) saveToCameraRoll:(NSString *)uri - type:(NSString *)type - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -- (void) deletePhotos:(NSArray *)assets - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -@end - - - -namespace JS { - namespace NativeExceptionsManager { - struct StackFrame { - folly::Optional column() const; - NSString *file() const; - folly::Optional lineNumber() const; - NSString *methodName() const; - folly::Optional collapse() const; - - StackFrame(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeExceptionsManager_StackFrame) -+ (RCTManagedPointer *)JS_NativeExceptionsManager_StackFrame:(id)json; -@end - - -namespace JS { - namespace NativeExceptionsManager { - struct ExceptionData { - NSString *message() const; - NSString *originalMessage() const; - NSString *name() const; - NSString *componentStack() const; - facebook::react::LazyVector stack() const; - double id_() const; - bool isFatal() const; - id _Nullable extraData() const; - - ExceptionData(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } + id const p = _v[@\\"collapse\\"]; + return RCTBridgingToOptionalBool(p); } -@interface RCTCxxConvert (NativeExceptionsManager_ExceptionData) -+ (RCTManagedPointer *)JS_NativeExceptionsManager_ExceptionData:(id)json; -@end inline NSString *JS::NativeExceptionsManager::ExceptionData::message() const { @@ -1119,7 +890,7 @@ inline NSString *JS::NativeExceptionsManager::ExceptionData::componentStack() co inline facebook::react::LazyVector JS::NativeExceptionsManager::ExceptionData::stack() const { id const p = _v[@\\"stack\\"]; - return RCTBridgingToVec(p, ^JS::NativeExceptionsManager::StackFrame(id itemValue_0) { return JS::NativeExceptionsManager::StackFrame(itemValue_0); }); + return RCTBridgingToVec(p, ^JS::NativeExceptionsManager::StackFrame(id itemValue_0) { return JS::NativeExceptionsManager::StackFrame(p); }); } @@ -1144,75 +915,6 @@ inline id _Nullable JS::NativeExceptionsManager::ExceptionData::extraD } -inline folly::Optional JS::NativeExceptionsManager::StackFrame::column() const -{ - id const p = _v[@\\"column\\"]; - return RCTBridgingToOptionalDouble(p); -} - - -inline NSString *JS::NativeExceptionsManager::StackFrame::file() const -{ - id const p = _v[@\\"file\\"]; - return RCTBridgingToString(p); -} - - -inline folly::Optional JS::NativeExceptionsManager::StackFrame::lineNumber() const -{ - id const p = _v[@\\"lineNumber\\"]; - return RCTBridgingToOptionalDouble(p); -} - - -inline NSString *JS::NativeExceptionsManager::StackFrame::methodName() const -{ - id const p = _v[@\\"methodName\\"]; - return RCTBridgingToString(p); -} - - -inline folly::Optional JS::NativeExceptionsManager::StackFrame::collapse() const -{ - id const p = _v[@\\"collapse\\"]; - return RCTBridgingToOptionalBool(p); -} - - - -@protocol NativeExceptionsManagerSpec -- (void) reportFatalException:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void) reportSoftException:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void) reportException:(JS::NativeExceptionsManager::ExceptionData &)data; -- (void) updateExceptionMessage:(NSString *)message - stack:(NSArray *)stack - exceptionId:(double)exceptionId; -- (void) dismissRedbox; -@end - - - -namespace JS { - namespace NativeImagePickerIOS { - struct SpecOpenCameraDialogConfig { - bool unmirrorFrontFacingCamera() const; - bool videoMode() const; - - SpecOpenCameraDialogConfig(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) -+ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json; -@end - inline bool JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig::unmirrorFrontFacingCamera() const { id const p = _v[@\\"unmirrorFrontFacingCamera\\"]; @@ -1226,40 +928,6 @@ inline bool JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig::videoMode() co return RCTBridgingToBool(p); } - - -@protocol NativeImagePickerIOSSpec -- (void) openCameraDialog:(JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig &)config - successCallback:(RCTResponseSenderBlock)successCallback - cancelCallback:(RCTResponseSenderBlock)cancelCallback; -@end - - -namespace facebook { - namespace react { - /** - * ObjC++ class for module 'CameraRollManager' - */ - class JSI_EXPORT NativeCameraRollManagerSpecJSI : public ObjCTurboModule { - public: - NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - /** - * ObjC++ class for module 'ExceptionsManager' - */ - class JSI_EXPORT NativeExceptionsManagerSpecJSI : public ObjCTurboModule { - public: - NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - /** - * ObjC++ class for module 'ImagePickerIOS' - */ - class JSI_EXPORT NativeImagePickerIOSSpecJSI : public ObjCTurboModule { - public: - NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; - } // namespace react -} // namespace facebook ", } `; @@ -1327,53 +995,53 @@ namespace JS { }; } } - -inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto const1 = i.const1.get(); - d[@\\"const1\\"] = @(const1); -auto const2 = i.const2.get(); - d[@\\"const2\\"] = @(const2); -auto const3 = i.const3.get(); - d[@\\"const3\\"] = const3; - return d; -}) {} -inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} - - @protocol NativeSampleTurboModuleSpec + +- (void)voidFunc; +- (NSNumber *)getBool:(BOOL)arg; +- (NSNumber *)getNumber:(double)arg; +- (NSString *)getString:(NSString *)arg; +- (NSArray *)getArray:(NSArray *)arg; +- (NSDictionary *)getObject:(NSDictionary *)arg; +- (NSNumber *)getRootTag:(double)arg; +- (NSDictionary *)getValue:(double)x + y:(NSString *)y + z:(NSDictionary *)z; +- (void)getValueWithCallback:(RCTResponseSenderBlock)callback; +- (void)getValueWithPromise:(BOOL)error + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject; - (facebook::react::ModuleConstants)constantsToExport; - (facebook::react::ModuleConstants)getConstants; -- (void) voidFunc; -- (BOOL) getBool:(BOOL)arg; -- (NSNumber *) getNumber:(double)arg; -- (NSString *) getString:(NSString *)arg; -- (NSArray> *) getArray:(NSArray *)arg; -- (NSDictionary *) getObject:(NSDictionary *)arg; -- (NSNumber *) getRootTag:(double)arg; -- (NSDictionary *) getValue:(double)x - y:(NSString *)y - z:(NSDictionary *)z; -- (void) getValueWithCallback:(RCTResponseSenderBlock)callback; -- (void) getValueWithPromise:(BOOL)error - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject; -@end - +@end namespace facebook { namespace react { /** - * ObjC++ class for module 'SampleTurboModule' - */ + * ObjC++ class for module 'SampleTurboModule' + */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { public: NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; } // namespace react } // namespace facebook + + + +inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ + NSMutableDictionary *d = [NSMutableDictionary new]; + auto const1 = i.const1.get(); + d[@\\"const1\\"] = @(const1); + auto const2 = i.const2.get(); + d[@\\"const2\\"] = @(const2); + auto const3 = i.const3.get(); + d[@\\"const3\\"] = const3; + return d; +}) {} +inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ + return i.unsafeRawValue(); +}) {} ", } `; @@ -1412,40 +1080,45 @@ Map { - - @protocol NativeSample2TurboModuleSpec -- (void) voidFunc; -@end - +- (void)voidFunc; +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'Sample2TurboModule' + */ + class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook @protocol NativeSampleTurboModuleSpec -- (void) voidFunc; -@end +- (void)voidFunc; +@end namespace facebook { namespace react { /** - * ObjC++ class for module 'SampleTurboModule' - */ + * ObjC++ class for module 'SampleTurboModule' + */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { public: NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; - /** - * ObjC++ class for module 'Sample2TurboModule' - */ - class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; } // namespace react } // namespace facebook + + + + ", } `; @@ -1484,39 +1157,45 @@ Map { - - @protocol NativeSample2TurboModuleSpec -- (void) voidFunc; -@end +- (void)voidFunc; +@end +namespace facebook { + namespace react { + /** + * ObjC++ class for module 'Sample2TurboModule' + */ + class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { + public: + NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); + }; + } // namespace react +} // namespace facebook @protocol NativeSampleTurboModuleSpec -- (void) voidFunc; -@end +- (void)voidFunc; +@end namespace facebook { namespace react { /** - * ObjC++ class for module 'SampleTurboModule' - */ + * ObjC++ class for module 'SampleTurboModule' + */ class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule { public: NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); }; - /** - * ObjC++ class for module 'Sample2TurboModule' - */ - class JSI_EXPORT NativeSample2TurboModuleSpecJSI : public ObjCTurboModule { - public: - NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms); - }; } // namespace react } // namespace facebook + + + + ", } `; 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 13eeb45cc922e6..c9a415a2064dee 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 @@ -2,7 +2,8 @@ exports[`GenerateModuleJavaSpec can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** + "NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -48,7 +49,8 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo exports[`GenerateModuleJavaSpec can generate fixture EMPTY_NATIVE_MODULES 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** + "NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -80,7 +82,8 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo exports[`GenerateModuleJavaSpec can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "NativeAliasTurboModuleSpec.java" => "/** + "NativeAliasTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -114,7 +117,8 @@ public abstract class NativeAliasTurboModuleSpec extends ReactContextBaseJavaMod exports[`GenerateModuleJavaSpec can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "NativeCameraRollManagerSpec.java" => "/** + "NativeCameraRollManagerSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -151,7 +155,8 @@ public abstract class NativeCameraRollManagerSpec extends ReactContextBaseJavaMo public abstract void deletePhotos(ReadableArray assets, Promise promise); } ", - "NativeImagePickerIOSSpec.java" => "/** + "NativeImagePickerIOSSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -181,7 +186,8 @@ public abstract class NativeImagePickerIOSSpec extends ReactContextBaseJavaModul public abstract void openCameraDialog(ReadableMap config, Callback successCallback, Callback cancelCallback); } ", - "NativeExceptionsManagerSpec.java" => "/** + "NativeExceptionsManagerSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -228,7 +234,8 @@ public abstract class NativeExceptionsManagerSpec extends ReactContextBaseJavaMo exports[`GenerateModuleJavaSpec can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** + "NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -327,7 +334,8 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo exports[`GenerateModuleJavaSpec can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** + "NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -355,7 +363,8 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo public abstract void voidFunc(); } ", - "NativeSample2TurboModuleSpec.java" => "/** + "NativeSample2TurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -388,7 +397,8 @@ public abstract class NativeSample2TurboModuleSpec extends ReactContextBaseJavaM exports[`GenerateModuleJavaSpec can generate fixture TWO_MODULES_SAME_FILE 1`] = ` Map { - "NativeSampleTurboModuleSpec.java" => "/** + "NativeSampleTurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root @@ -416,7 +426,8 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo public abstract void voidFunc(); } ", - "NativeSample2TurboModuleSpec.java" => "/** + "NativeSample2TurboModuleSpec.java" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the LICENSE file in the root 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 efe08283828084..64cbc779b30315 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 @@ -2,7 +2,8 @@ exports[`GenerateModuleJniH can generate fixture COMPLEX_OBJECTS 1`] = ` Map { - "SampleSpec.h" => "/** + "SampleSpec.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -67,7 +68,8 @@ include $(BUILD_SHARED_LIBRARY) exports[`GenerateModuleJniH can generate fixture EMPTY_NATIVE_MODULES 1`] = ` Map { - "SampleSpec.h" => "/** + "SampleSpec.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -132,7 +134,8 @@ include $(BUILD_SHARED_LIBRARY) exports[`GenerateModuleJniH can generate fixture NATIVE_MODULES_WITH_TYPE_ALIASES 1`] = ` Map { - "SampleSpec.h" => "/** + "SampleSpec.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -197,7 +200,8 @@ include $(BUILD_SHARED_LIBRARY) exports[`GenerateModuleJniH can generate fixture REAL_MODULE_EXAMPLE 1`] = ` Map { - "SampleSpec.h" => "/** + "SampleSpec.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -224,19 +228,19 @@ public: }; /** - * JNI C++ class for module 'ExceptionsManager' + * JNI C++ class for module 'ImagePickerIOS' */ -class JSI_EXPORT NativeExceptionsManagerSpecJSI : public JavaTurboModule { +class JSI_EXPORT NativeImagePickerIOSSpecJSI : public JavaTurboModule { public: - NativeExceptionsManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); + NativeImagePickerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); }; /** - * JNI C++ class for module 'ImagePickerIOS' + * JNI C++ class for module 'ExceptionsManager' */ -class JSI_EXPORT NativeImagePickerIOSSpecJSI : public JavaTurboModule { +class JSI_EXPORT NativeExceptionsManagerSpecJSI : public JavaTurboModule { public: - NativeImagePickerIOSSpecJSI(const JavaTurboModule::InitParams ¶ms); + NativeExceptionsManagerSpecJSI(const JavaTurboModule::InitParams ¶ms); }; @@ -278,7 +282,8 @@ include $(BUILD_SHARED_LIBRARY) exports[`GenerateModuleJniH can generate fixture SIMPLE_NATIVE_MODULES 1`] = ` Map { - "SampleSpec.h" => "/** + "SampleSpec.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -343,7 +348,8 @@ include $(BUILD_SHARED_LIBRARY) exports[`GenerateModuleJniH can generate fixture TWO_MODULES_DIFFERENT_FILES 1`] = ` Map { - "SampleSpec.h" => "/** + "SampleSpec.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the @@ -416,7 +422,8 @@ include $(BUILD_SHARED_LIBRARY) exports[`GenerateModuleJniH can generate fixture TWO_MODULES_SAME_FILE 1`] = ` Map { - "SampleSpec.h" => "/** + "SampleSpec.h" => " +/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the 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 192e19235d1cf1..53e98c9fdf939a 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 @@ -9,17 +9,21 @@ Map { * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by an internal genrule from Flow types. + * + * 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. */ -#include -#import +#import \\"SampleSpec.h\\" + -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultReturnType) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultReturnType:(id)json +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultAE) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultAE:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end @@ -32,72 +36,82 @@ Map { @end -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsA) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsA:(id)json +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptions) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptions:(id)json +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsA) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsA:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecDifficultAE) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecDifficultAE:(id)json +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptionsArrayOfObjectsElement:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end -@implementation RCTCxxConvert (NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecOptionalsAOptionalObjectProperty:(id)json +@implementation RCTCxxConvert (NativeSampleTurboModule_SpecGetArraysOptions) ++ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecGetArraysOptions:(id)json { - return facebook::react::managedPointer(json); + return facebook::react::managedPointer(json); } @end namespace facebook { namespace react { - + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_difficult(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"difficult\\", @selector(difficult:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"difficult\\", @selector(difficult:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_optionals(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"optionals\\", @selector(optionals:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"optionals\\", @selector(optionals:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_optionalMethod(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"optionalMethod\\", @selector(optionalMethod:callback:extras:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"optionalMethod\\", @selector(optionalMethod:callback:extras:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"getArrays\\", @selector(getArrays:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getArrays\\", @selector(getArrays:), args, count); } + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_difficult}; - methodMap_[\\"optionals\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_optionals}; - methodMap_[\\"optionalMethod\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_optionalMethod}; - methodMap_[\\"getArrays\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays}; - setMethodArgConversionSelector(@\\"difficult\\", 0, @\\"JS_NativeSampleTurboModule_SpecDifficultA:\\"); - setMethodArgConversionSelector(@\\"optionals\\", 0, @\\"JS_NativeSampleTurboModule_SpecOptionalsA:\\"); - setMethodArgConversionSelector(@\\"getArrays\\", 0, @\\"JS_NativeSampleTurboModule_SpecGetArraysOptions:\\"); + + methodMap_[\\"difficult\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_difficult}; + setMethodArgConversionSelector(@\\"difficult\\", 0, @\\"JS_NativeSampleTurboModule_SpecDifficultA:\\"); + + + methodMap_[\\"optionals\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_optionals}; + setMethodArgConversionSelector(@\\"optionals\\", 0, @\\"JS_NativeSampleTurboModule_SpecOptionalsA:\\"); + + + methodMap_[\\"optionalMethod\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_optionalMethod}; + + + + methodMap_[\\"getArrays\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays}; + setMethodArgConversionSelector(@\\"getArrays\\", 0, @\\"JS_NativeSampleTurboModule_SpecGetArraysOptions:\\"); + } } // namespace react } // namespace facebook + ", } `; @@ -111,23 +125,28 @@ Map { * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by an internal genrule from Flow types. + * + * 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. */ -#include -#import +#import \\"SampleSpec.h\\" + namespace facebook { namespace react { - + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - + } } // namespace react } // namespace facebook + ", } `; @@ -141,19 +160,15 @@ Map { * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by an internal genrule from Flow types. + * + * 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. */ -#include -#import - +#import \\"SampleSpec.h\\" -@implementation RCTCxxConvert (NativeAliasTurboModule_Options) -+ (RCTManagedPointer *)JS_NativeAliasTurboModule_Options:(id)json -{ - return facebook::react::managedPointer(json); -} -@end @implementation RCTCxxConvert (NativeAliasTurboModule_OptionsOffset) @@ -179,23 +194,32 @@ Map { } @end -namespace facebook { - namespace react { +@implementation RCTCxxConvert (NativeAliasTurboModule_Options) ++ (RCTManagedPointer *)JS_NativeAliasTurboModule_Options:(id)json +{ + return facebook::react::managedPointer(json); +} +@end +namespace facebook { + namespace react { + static facebook::jsi::Value __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"cropImage\\", @selector(cropImage:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"cropImage\\", @selector(cropImage:), args, count); } + NativeAliasTurboModuleSpecJSI::NativeAliasTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - - methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage}; - setMethodArgConversionSelector(@\\"cropImage\\", 0, @\\"JS_NativeAliasTurboModule_Options:\\"); + + methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage}; + setMethodArgConversionSelector(@\\"cropImage\\", 0, @\\"JS_NativeAliasTurboModule_Options:\\"); + } } // namespace react } // namespace facebook + ", } `; @@ -209,35 +233,15 @@ Map { * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by an internal genrule from Flow types. + * + * 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. */ -#include -#import - - -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierImage) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierImage:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - - -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifier) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifier:(id)json -{ - return facebook::react::managedPointer(json); -} -@end - +#import \\"SampleSpec.h\\" -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPage) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPage:(id)json -{ - return facebook::react::managedPointer(json); -} -@end @implementation RCTCxxConvert (NativeCameraRollManager_GetPhotosParams) @@ -247,37 +251,42 @@ Map { } @end +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getPhotos\\", @selector(getPhotos:resolve:reject:), args, count); + } -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNode) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNode:(id)json -{ - return facebook::react::managedPointer(json); -} -@end + + static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"saveToCameraRoll\\", @selector(saveToCameraRoll:type:resolve:reject:), args, count); + } -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPagePage_info) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPagePage_info:(id)json -{ - return facebook::react::managedPointer(json); -} -@end + static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"deletePhotos\\", @selector(deletePhotos:resolve:reject:), args, count); + } -@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNodeLocation) -+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNodeLocation:(id)json -{ - return facebook::react::managedPointer(json); -} -@end + NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) + : ObjCTurboModule(params) { + + methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos}; + setMethodArgConversionSelector(@\\"getPhotos\\", 0, @\\"JS_NativeCameraRollManager_GetPhotosParams:\\"); + + methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll}; + + + + methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos}; + + + } + } // namespace react +} // namespace facebook -@implementation RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) -+ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json -{ - return facebook::react::managedPointer(json); -} -@end @implementation RCTCxxConvert (NativeExceptionsManager_StackFrame) @@ -297,79 +306,85 @@ Map { namespace facebook { namespace react { + + static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"reportFatalException\\", @selector(reportFatalException:stack:exceptionId:), args, count); + } - static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"getPhotos\\", @selector(getPhotos:resolve:reject:), args, count); + static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"reportSoftException\\", @selector(reportSoftException:stack:exceptionId:), args, count); } - static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"saveToCameraRoll\\", @selector(saveToCameraRoll:type:resolve:reject:), args, count); - } - static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"deletePhotos\\", @selector(deletePhotos:resolve:reject:), args, count); + static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"reportException\\", @selector(reportException:), args, count); } - NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) - : ObjCTurboModule(params) { - - methodMap_[\\"getPhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos}; - methodMap_[\\"saveToCameraRoll\\"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll}; - methodMap_[\\"deletePhotos\\"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos}; - setMethodArgConversionSelector(@\\"getPhotos\\", 0, @\\"JS_NativeCameraRollManager_GetPhotosParams:\\"); + + static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"updateExceptionMessage\\", @selector(updateExceptionMessage:stack:exceptionId:), args, count); } - static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"openCameraDialog\\", @selector(openCameraDialog:successCallback:cancelCallback:), args, count); + + static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"dismissRedbox\\", @selector(dismissRedbox), args, count); } - NativeImagePickerIOSSpecJSI::NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) + + NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"openCameraDialog\\"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog}; - setMethodArgConversionSelector(@\\"openCameraDialog\\", 0, @\\"JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:\\"); - } + + methodMap_[\\"reportFatalException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException}; + - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"reportFatalException\\", @selector(reportFatalException:stack:exceptionId:), args, count); - } + + methodMap_[\\"reportSoftException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException}; + - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"reportSoftException\\", @selector(reportSoftException:stack:exceptionId:), args, count); - } + + methodMap_[\\"reportException\\"] = MethodMetadata {1, __hostFunction_NativeExceptionsManagerSpecJSI_reportException}; + setMethodArgConversionSelector(@\\"reportException\\", 0, @\\"JS_NativeExceptionsManager_ExceptionData:\\"); - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_reportException(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"reportException\\", @selector(reportException:), args, count); - } + + methodMap_[\\"updateExceptionMessage\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage}; + + + + methodMap_[\\"dismissRedbox\\"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox}; + - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"updateExceptionMessage\\", @selector(updateExceptionMessage:stack:exceptionId:), args, count); } + } // namespace react +} // namespace facebook - static facebook::jsi::Value __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"dismissRedbox\\", @selector(dismissRedbox), args, count); + + +@implementation RCTCxxConvert (NativeImagePickerIOS_SpecOpenCameraDialogConfig) ++ (RCTManagedPointer *)JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:(id)json +{ + return facebook::react::managedPointer(json); +} +@end + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"openCameraDialog\\", @selector(openCameraDialog:successCallback:cancelCallback:), args, count); } - NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const ObjCTurboModule::InitParams ¶ms) + + NativeImagePickerIOSSpecJSI::NativeImagePickerIOSSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"reportFatalException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportFatalException}; - methodMap_[\\"reportSoftException\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_reportSoftException}; - methodMap_[\\"reportException\\"] = MethodMetadata {1, __hostFunction_NativeExceptionsManagerSpecJSI_reportException}; - methodMap_[\\"updateExceptionMessage\\"] = MethodMetadata {3, __hostFunction_NativeExceptionsManagerSpecJSI_updateExceptionMessage}; - methodMap_[\\"dismissRedbox\\"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox}; - setMethodArgConversionSelector(@\\"reportException\\", 0, @\\"JS_NativeExceptionsManager_ExceptionData:\\"); + + methodMap_[\\"openCameraDialog\\"] = MethodMetadata {3, __hostFunction_NativeImagePickerIOSSpecJSI_openCameraDialog}; + setMethodArgConversionSelector(@\\"openCameraDialog\\", 0, @\\"JS_NativeImagePickerIOS_SpecOpenCameraDialogConfig:\\"); + } } // namespace react } // namespace facebook + ", } `; @@ -383,87 +398,125 @@ Map { * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by an internal genrule from Flow types. + * + * 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. */ -#include -#import +#import \\"SampleSpec.h\\" + namespace facebook { namespace react { - - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); - } - + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getBool(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, BooleanKind, \\"getBool\\", @selector(getBool:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getBool\\", @selector(getBool:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getNumber\\", @selector(getNumber:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getString(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, StringKind, \\"getString\\", @selector(getString:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArray(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, ArrayKind, \\"getArray\\", @selector(getArray:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObject(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getObject\\", @selector(getObject:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getRootTag\\", @selector(getRootTag:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); + return static_cast(turboModule).invokeObjCMethod(rt, PromiseKind, \\"getValueWithPromise\\", @selector(getValueWithPromise:resolve:reject:), args, count); } + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getConstants\\", @selector(getConstants), args, count); + } + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; - methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; - methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; - methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; - methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; - methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; - methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; - methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; - methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; - methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + + + methodMap_[\\"getBool\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool}; + + + + methodMap_[\\"getNumber\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber}; + + + + methodMap_[\\"getString\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString}; + + + + methodMap_[\\"getArray\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray}; + + + + methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; + + + + methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; + + + + methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + + + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; + + + + methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; + + + + methodMap_[\\"getConstants\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants}; + + } } // namespace react } // namespace facebook + ", } `; @@ -477,40 +530,55 @@ Map { * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by an internal genrule from Flow types. + * + * 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. */ -#include -#import +#import \\"SampleSpec.h\\" namespace facebook { namespace react { - - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + + static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); } - NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + + NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; + + } + } // namespace react +} // namespace facebook - static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); } - NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + } } // namespace react } // namespace facebook + ", } `; @@ -524,38 +592,55 @@ Map { * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated by codegen project: GenerateModuleMm.js + * @generated by an internal genrule from Flow types. + * + * 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. */ -#include -#import +#import \\"SampleSpec.h\\" namespace facebook { namespace react { - - static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + + static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); } - NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + + NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; + + } + } // namespace react +} // namespace facebook - static facebook::jsi::Value __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { - return static_cast(turboModule) - .invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); + + +namespace facebook { + namespace react { + + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"voidFunc\\", @selector(voidFunc), args, count); } - NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) + + NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms) : ObjCTurboModule(params) { - methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc}; + + methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc}; + + } } // namespace react } // namespace facebook + ", } `; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateStructs-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateStructs-test.js.snap deleted file mode 100644 index 75bb7bfe5dbde1..00000000000000 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateStructs-test.js.snap +++ /dev/null @@ -1,284 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`GenerateStructs can generate fixture SIMPLE_CONSTANTS 1`] = ` -" - -namespace JS { - namespace NativeSampleTurboModule { - struct ConstantsDG { - - struct Builder { - struct Input { - RCTRequired h; - RCTRequired i; - RCTRequired j; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing ConstantsDG */ - Builder(ConstantsDG i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static ConstantsDG fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - ConstantsDG(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -inline JS::NativeSampleTurboModule::ConstantsDG::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto h = i.h.get(); - d[@\\"h\\"] = @(h); -auto i = i.i.get(); - d[@\\"i\\"] = @(i); -auto j = i.j.get(); - d[@\\"j\\"] = j; - return d; -}) {} -inline JS::NativeSampleTurboModule::ConstantsDG::Builder::Builder(ConstantsDG i) : _factory(^{ - return i.unsafeRawValue(); -}) {} - -namespace JS { - namespace NativeSampleTurboModule { - struct ConstantsD { - - struct Builder { - struct Input { - RCTRequired e; - RCTRequired f; - RCTRequired g; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing ConstantsD */ - Builder(ConstantsD i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static ConstantsD fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - ConstantsD(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -inline JS::NativeSampleTurboModule::ConstantsD::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto e = i.e.get(); - d[@\\"e\\"] = @(e); -auto f = i.f.get(); - d[@\\"f\\"] = @(f); -auto g = i.g.get(); - d[@\\"g\\"] = g.buildUnsafeRawValue(); - return d; -}) {} -inline JS::NativeSampleTurboModule::ConstantsD::Builder::Builder(ConstantsD i) : _factory(^{ - return i.unsafeRawValue(); -}) {} - -namespace JS { - namespace NativeSampleTurboModule { - struct Constants { - - struct Builder { - struct Input { - RCTRequired a; - RCTRequired b; - RCTRequired c; - RCTRequired d; - RCTRequired k; - }; - - /** Initialize with a set of values */ - Builder(const Input i); - /** Initialize with an existing Constants */ - Builder(Constants i); - /** Builds the object. Generally used only by the infrastructure. */ - NSDictionary *buildUnsafeRawValue() const { return _factory(); }; - private: - NSDictionary *(^_factory)(void); - }; - - static Constants fromUnsafeRawValue(NSDictionary *const v) { return {v}; } - NSDictionary *unsafeRawValue() const { return _v; } - private: - Constants(NSDictionary *const v) : _v(v) {} - NSDictionary *_v; - }; - } -} - -inline JS::NativeSampleTurboModule::Constants::Builder::Builder(const Input i) : _factory(^{ - NSMutableDictionary *d = [NSMutableDictionary new]; - auto a = i.a.get(); - d[@\\"a\\"] = @(a); -auto b = i.b.get(); - d[@\\"b\\"] = @(b); -auto c = i.c.get(); - d[@\\"c\\"] = c; -auto d = i.d.get(); - d[@\\"d\\"] = d.buildUnsafeRawValue(); -auto k = i.k.get(); - d[@\\"k\\"] = @(k); - return d; -}) {} -inline JS::NativeSampleTurboModule::Constants::Builder::Builder(Constants i) : _factory(^{ - return i.unsafeRawValue(); -}) {} -" -`; - -exports[`GenerateStructs can generate fixture SIMPLE_STRUCT 1`] = ` -" - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecSampleFuncReturnTypeDG { - bool h() const; - double i() const; - NSString *j() const; - - SpecSampleFuncReturnTypeDG(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecSampleFuncReturnTypeDG) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecSampleFuncReturnTypeDG:(id)json; -@end - - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecSampleFuncReturnTypeD { - bool e() const; - double f() const; - JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG g() const; - - SpecSampleFuncReturnTypeD(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecSampleFuncReturnTypeD) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecSampleFuncReturnTypeD:(id)json; -@end - - -namespace JS { - namespace NativeSampleTurboModule { - struct SpecSampleFuncReturnType { - bool a() const; - double b() const; - NSString *c() const; - JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD d() const; - double k() const; - - SpecSampleFuncReturnType(NSDictionary *const v) : _v(v) {} - private: - NSDictionary *_v; - }; - } -} - -@interface RCTCxxConvert (NativeSampleTurboModule_SpecSampleFuncReturnType) -+ (RCTManagedPointer *)JS_NativeSampleTurboModule_SpecSampleFuncReturnType:(id)json; -@end - -inline bool JS::NativeSampleTurboModule::SpecSampleFuncReturnType::a() const -{ - id const p = _v[@\\"a\\"]; - return RCTBridgingToBool(p); -} - - -inline double JS::NativeSampleTurboModule::SpecSampleFuncReturnType::b() const -{ - id const p = _v[@\\"b\\"]; - return RCTBridgingToDouble(p); -} - - -inline NSString *JS::NativeSampleTurboModule::SpecSampleFuncReturnType::c() const -{ - id const p = _v[@\\"c\\"]; - return RCTBridgingToString(p); -} - - -inline JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD JS::NativeSampleTurboModule::SpecSampleFuncReturnType::d() const -{ - id const p = _v[@\\"d\\"]; - return JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD(p); -} - - -inline double JS::NativeSampleTurboModule::SpecSampleFuncReturnType::k() const -{ - id const p = _v[@\\"k\\"]; - return RCTBridgingToDouble(p); -} - - -inline bool JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD::e() const -{ - id const p = _v[@\\"e\\"]; - return RCTBridgingToBool(p); -} - - -inline double JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD::f() const -{ - id const p = _v[@\\"f\\"]; - return RCTBridgingToDouble(p); -} - - -inline JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeD::g() const -{ - id const p = _v[@\\"g\\"]; - return JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG(p); -} - - -inline bool JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG::h() const -{ - id const p = _v[@\\"h\\"]; - return RCTBridgingToBool(p); -} - - -inline double JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG::i() const -{ - id const p = _v[@\\"i\\"]; - return RCTBridgingToDouble(p); -} - - -inline NSString *JS::NativeSampleTurboModule::SpecSampleFuncReturnTypeDG::j() const -{ - id const p = _v[@\\"j\\"]; - return RCTBridgingToString(p); -} - -" -`; diff --git a/packages/react-native-codegen/src/parsers/flow/components/commands.js b/packages/react-native-codegen/src/parsers/flow/components/commands.js index 769039be7a074d..92aef0a2ad0b18 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/commands.js +++ b/packages/react-native-codegen/src/parsers/flow/components/commands.js @@ -11,13 +11,13 @@ 'use strict'; import type {CommandTypeShape} from '../../../CodegenSchema.js'; -import type {TypeMap} from '../utils.js'; +import type {TypeDeclarationMap} from '../utils.js'; const {getValueFromTypes} = require('../utils.js'); type EventTypeAST = Object; -function buildCommandSchema(property, types: TypeMap) { +function buildCommandSchema(property, types: TypeDeclarationMap) { const name = property.key.name; const optional = property.optional; const value = getValueFromTypes(property.value, types); @@ -98,7 +98,7 @@ function buildCommandSchema(property, types: TypeMap) { function getCommands( commandTypeAST: $ReadOnlyArray, - types: TypeMap, + types: TypeDeclarationMap, ): $ReadOnlyArray { return commandTypeAST .filter(property => property.type === 'ObjectTypeProperty') diff --git a/packages/react-native-codegen/src/parsers/flow/components/extends.js b/packages/react-native-codegen/src/parsers/flow/components/extends.js index 77081974a30a69..7d5e899b80828b 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/extends.js +++ b/packages/react-native-codegen/src/parsers/flow/components/extends.js @@ -11,9 +11,9 @@ 'use strict'; import type {ExtendsPropsShape} from '../../../CodegenSchema.js'; -import type {TypeMap} from '../utils.js'; +import type {TypeDeclarationMap} from '../utils.js'; -function extendsForProp(prop: PropsAST, types: TypeMap) { +function extendsForProp(prop: PropsAST, types: TypeDeclarationMap) { if (!prop.argument) { console.log('null', prop); } @@ -38,7 +38,7 @@ function extendsForProp(prop: PropsAST, types: TypeMap) { function removeKnownExtends( typeDefinition: $ReadOnlyArray, - types: TypeMap, + types: TypeDeclarationMap, ): $ReadOnlyArray { return typeDefinition.filter( prop => @@ -52,7 +52,7 @@ type PropsAST = Object; function getExtendsProps( typeDefinition: $ReadOnlyArray, - types: TypeMap, + types: TypeDeclarationMap, ): $ReadOnlyArray { return typeDefinition .filter(prop => prop.type === 'ObjectTypeSpreadProperty') diff --git a/packages/react-native-codegen/src/parsers/flow/components/index.js b/packages/react-native-codegen/src/parsers/flow/components/index.js index eb8867401d5372..f3b9f4770fb87b 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/index.js +++ b/packages/react-native-codegen/src/parsers/flow/components/index.js @@ -167,7 +167,7 @@ function getCommandProperties(commandTypeName, types, commandOptions) { } // $FlowFixMe there's no flowtype for AST -function processComponent(ast, types): ComponentSchemaBuilderConfig { +function buildComponentSchema(ast, types): ComponentSchemaBuilderConfig { const { componentName, propsTypeName, @@ -205,5 +205,5 @@ function processComponent(ast, types): ComponentSchemaBuilderConfig { } module.exports = { - processComponent, + buildComponentSchema, }; diff --git a/packages/react-native-codegen/src/parsers/flow/components/props.js b/packages/react-native-codegen/src/parsers/flow/components/props.js index 9b549ac2337acd..50e887bcd93b9e 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/props.js +++ b/packages/react-native-codegen/src/parsers/flow/components/props.js @@ -13,9 +13,12 @@ const {getValueFromTypes} = require('../utils.js'); import type {PropTypeShape} from '../../../CodegenSchema.js'; -import type {TypeMap} from '../utils.js'; +import type {TypeDeclarationMap} from '../utils.js'; -function getPropProperties(propsTypeName: string, types: TypeMap): $FlowFixMe { +function getPropProperties( + propsTypeName: string, + types: TypeDeclarationMap, +): $FlowFixMe { const typeAlias = types[propsTypeName]; try { return typeAlias.right.typeParameters.params[0].properties; @@ -321,7 +324,7 @@ function getTypeAnnotation( } } -function buildPropSchema(property, types: TypeMap): ?PropTypeShape { +function buildPropSchema(property, types: TypeDeclarationMap): ?PropTypeShape { const name = property.key.name; const value = getValueFromTypes(property.value, types); @@ -426,7 +429,7 @@ function verifyPropNotAlreadyDefined( function flattenProperties( typeDefinition: $ReadOnlyArray, - types: TypeMap, + types: TypeDeclarationMap, ) { return typeDefinition .map(property => { @@ -456,7 +459,7 @@ function flattenProperties( function getProps( typeDefinition: $ReadOnlyArray, - types: TypeMap, + types: TypeDeclarationMap, ): $ReadOnlyArray { return flattenProperties(typeDefinition, types) .map(property => buildPropSchema(property, types)) diff --git a/packages/react-native-codegen/src/parsers/flow/components/schema.js b/packages/react-native-codegen/src/parsers/flow/components/schema.js index f55e77f162753a..c561f9e0b182fe 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/schema.js +++ b/packages/react-native-codegen/src/parsers/flow/components/schema.js @@ -29,7 +29,7 @@ export type ComponentSchemaBuilderConfig = $ReadOnly<{| options?: ?OptionsShape, |}>; -function buildComponentSchema({ +function wrapComponentSchema({ filename, componentName, extendsProps, @@ -56,5 +56,5 @@ function buildComponentSchema({ } module.exports = { - buildComponentSchema, + wrapComponentSchema, }; diff --git a/packages/react-native-codegen/src/parsers/flow/index.js b/packages/react-native-codegen/src/parsers/flow/index.js index 4de02b0094393d..6f0669f998de7e 100644 --- a/packages/react-native-codegen/src/parsers/flow/index.js +++ b/packages/react-native-codegen/src/parsers/flow/index.js @@ -15,15 +15,20 @@ import type {SchemaType} from '../../CodegenSchema.js'; const flowParser = require('flow-parser'); const fs = require('fs'); const path = require('path'); -const {buildModuleSchema} = require('./modules/schema'); -const {buildComponentSchema} = require('./components/schema'); -const {processComponent} = require('./components'); -const {processModule} = require('./modules'); +const {buildComponentSchema} = require('./components'); +const {wrapComponentSchema} = require('./components/schema'); +const {buildModuleSchema} = require('./modules'); +const {wrapModuleSchema} = require('./modules/schema'); -function getTypes(ast) { +import type {TypeDeclarationMap} from './utils'; + +function getTypes(ast): TypeDeclarationMap { return ast.body.reduce((types, node) => { - if (node.type === 'ExportNamedDeclaration') { - if (node.declaration && node.declaration.type !== 'VariableDeclaration') { + if (node.type === 'ExportNamedDeclaration' && node.exportKind === 'type') { + if ( + node.declaration.type === 'TypeAlias' || + node.declaration.type === 'InterfaceDeclaration' + ) { types[node.declaration.id.name] = node.declaration; } } else if ( @@ -36,63 +41,84 @@ function getTypes(ast) { }, {}); } -function getConfigType(ast, types): 'module' | 'component' { +function isComponent(ast) { const defaultExports = ast.body.filter( node => node.type === 'ExportDefaultDeclaration', ); - let isComponent = false; + if (defaultExports.length === 0) { + return false; + } - if (defaultExports.length > 0) { - let declaration = defaultExports[0].declaration; - // codegenNativeComponent can be nested inside a cast - // expression so we need to go one level deeper - if (declaration.type === 'TypeCastExpression') { - declaration = declaration.expression; - } + let declaration = defaultExports[0].declaration; + // codegenNativeComponent can be nested inside a cast + // expression so we need to go one level deeper + if (declaration.type === 'TypeCastExpression') { + declaration = declaration.expression; + } - isComponent = - declaration && - declaration.callee && - declaration.callee.name === 'codegenNativeComponent'; + if (declaration.type !== 'CallExpression') { + return false; } - const typesExtendingTurboModule = Object.keys(types) - .map(typeName => types[typeName]) - .filter( - type => - type.extends && - type.extends[0] && - type.extends[0].id.name === 'TurboModule', - ); + return ( + declaration.callee.type === 'Identifier' && + declaration.callee.name === 'codegenNativeComponent' + ); +} - if (typesExtendingTurboModule.length > 1) { +function isModule(types: TypeDeclarationMap) { + const declaredModuleNames: Array = Object.keys(types).filter( + (typeName: string) => { + const declaration = types[typeName]; + return ( + declaration.type === 'InterfaceDeclaration' && + declaration.extends.length === 1 && + declaration.extends[0].type === 'InterfaceExtends' && + declaration.extends[0].id.name === 'TurboModule' + ); + }, + ); + + if (declaredModuleNames.length === 0) { + return false; + } + + if (declaredModuleNames.length > 1) { throw new Error( - 'Found two types extending "TurboModule" is one file. Split them into separated files.', + 'File contains declarations of more than one module: ' + + declaredModuleNames.join(', ') + + '. Please declare exactly one module in this file.', ); } - const isModule = typesExtendingTurboModule.length === 1; + return true; +} + +function getConfigType(ast, types: TypeDeclarationMap): 'module' | 'component' { + const isConfigAComponent = isComponent(ast); + const isConfigAModule = isModule(types); - if (isModule && isComponent) { + if (isConfigAModule && isConfigAComponent) { throw new Error( 'Found type extending "TurboModule" and exported "codegenNativeComponent" declaration in one file. Split them into separated files.', ); } - if (isModule) { + if (isConfigAModule) { return 'module'; - } else if (isComponent) { + } else if (isConfigAComponent) { return 'component'; } else { throw new Error( - `Default export for module specified incorrectly. It should containts - either type extending "TurboModule" or "codegenNativeComponent".`, + 'File neither contains a module declaration, nor a component declaration. ' + + 'For module declarations, please make sure your file has an InterfaceDeclaration extending TurboModule. ' + + 'For component declarations, please make sure your file has a default export calling the codegenNativeComponent(...) macro.', ); } } -function buildSchema(contents: string, filename: ?string): ?SchemaType { +function buildSchema(contents: string, filename: ?string): SchemaType { const ast = flowParser.parse(contents); const types = getTypes(ast); @@ -100,30 +126,30 @@ function buildSchema(contents: string, filename: ?string): ?SchemaType { const configType = getConfigType(ast, types); if (configType === 'component') { - return buildComponentSchema(processComponent(ast, types)); + return wrapComponentSchema(buildComponentSchema(ast, types)); } else { if (filename === undefined || filename === null) { throw new Error('Filepath expected while parasing a module'); } const moduleName = path.basename(filename).slice(6, -3); - return buildModuleSchema(processModule(types), moduleName); + return wrapModuleSchema(buildModuleSchema(moduleName, types), moduleName); } } -function parseFile(filename: string): ?SchemaType { +function parseFile(filename: string): SchemaType { const contents = fs.readFileSync(filename, 'utf8'); return buildSchema(contents, filename); } -function parseModuleFixture(filename: string): ?SchemaType { +function parseModuleFixture(filename: string): SchemaType { const contents = fs.readFileSync(filename, 'utf8'); return buildSchema(contents, 'path/NativeSampleTurboModule.js'); } -function parseString(contents: string): ?SchemaType { - return buildSchema(contents); +function parseString(contents: string, filename: ?string): SchemaType { + return buildSchema(contents, filename); } module.exports = { 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 a326be96accd23..7a9b29a3d868c9 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 @@ -200,7 +200,7 @@ type Foo = {| export interface Spec extends TurboModule { // Exported methods. - foo1: (x: Foo) => void; + foo1: (x: Foo) => Foo; foo2: (x: Foo) => void; } @@ -367,6 +367,7 @@ export interface Spec extends TurboModule { export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); `; + const NATIVE_MODULE_WITH_ARRAY_WITH_UNION_AND_TOUPLE = ` /** * Copyright (c) Facebook, Inc. and its affiliates. @@ -434,7 +435,7 @@ import type {TurboModule} from '../RCTExport'; import * as TurboModuleRegistry from '../TurboModuleRegistry'; export interface Spec extends TurboModule { - +getArray: (arg: Array>>>>) => Array>>; + +getArray: (arg: Array>>>>) => Array>>; } export default TurboModuleRegistry.getEnforcing('SampleTurboModule'); diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-test.js.snap b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap similarity index 81% rename from packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-test.js.snap rename to packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap index 0aeb307d1b2201..6c35735fee2055 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-test.js.snap +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/__snapshots__/module-parser-snapshot-test.js.snap @@ -1,23 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT 1`] = `"Unsupported return type for getString: expected to find annotation for type of array contents"`; +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT 1`] = `"Module SampleTurboModule: Detected a type of Array, without type parameters."`; -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT_AS_PARAM 1`] = `"Unsupported type for getString, param: \\"arg\\": expected to find annotation for type of array contents"`; +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_ARRAY_WITH_NO_TYPE_FOR_CONTENT_AS_PARAM 1`] = `"Module SampleTurboModule: Detected a type of Array, without type parameters."`; exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_NOT_ONLY_METHODS 1`] = `"Only methods are supported as module properties. Found BooleanTypeAnnotation in sampleBool"`; -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_PROMISE_WITHOUT_TYPE 1`] = `"Unsupported return promise type for getBool: expected to find annotation for type of promise content"`; +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_PROMISE_WITHOUT_TYPE 1`] = `"Module SampleTurboModule: Detected a type of Promise, without type parameters."`; -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_READ_ONLY_OBJECT_NO_TYPE_FOR_CONTENT 1`] = `"Unsupported param for method \\"getString\\", param \\"arg\\". No type specified for $ReadOnly"`; +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_READ_ONLY_OBJECT_NO_TYPE_FOR_CONTENT 1`] = `"Module SampleTurboModule: Detected a type of $ReadOnly, with 0 type parameters specified. Expected exactly 1."`; -exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_UNNAMED_PARAMS 1`] = `"Unsupported type for getBool. Please provide a name for every parameter."`; +exports[`RN Codegen Flow Parser Fails with error message NATIVE_MODULES_WITH_UNNAMED_PARAMS 1`] = `"Module SampleTurboModule: Detected a FunctionTypeAnnotation with an unnamed param. Please name all params."`; -exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_EXTENDING_TURBO_MODULE 1`] = `"Found two types extending \\"TurboModule\\" is one file. Split them into separated files."`; +exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_EXTENDING_TURBO_MODULE 1`] = `"File contains declarations of more than one module: Spec, Spec2. Please declare exactly one module in this file."`; -exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT 1`] = ` -"Default export for module specified incorrectly. It should containts - either type extending \\"TurboModule\\" or \\"codegenNativeComponent\\"." -`; +exports[`RN Codegen Flow Parser Fails with error message TWO_NATIVE_MODULES_EXPORTED_WITH_DEFAULT 1`] = `"File neither contains a module declaration, nor a component declaration. For module declarations, please make sure your file has an InterfaceDeclaration extending TurboModule. For component declarations, please make sure your file has a default export calling the codegenNativeComponent(...) macro."`; exports[`RN Codegen Flow Parser can generate fixture EMPTY_NATIVE_MODULE 1`] = ` Object { @@ -42,11 +39,13 @@ Object { "SampleTurboModule": Object { "aliases": Object { "ObjectAlias": Object { + "nullable": false, "properties": Array [ Object { "name": "x", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -54,6 +53,7 @@ Object { "name": "y", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -61,6 +61,7 @@ Object { "name": "label", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "StringTypeAnnotation", }, }, @@ -68,6 +69,7 @@ Object { "name": "truthy", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -78,13 +80,15 @@ Object { "properties": Array [ Object { "name": "getNumber", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -98,8 +102,9 @@ Object { }, Object { "name": "getVoid", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [], "returnTypeAnnotation": Object { "nullable": false, @@ -110,16 +115,19 @@ Object { }, Object { "name": "getArray", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "a", - "nullable": false, + "optional": false, "typeAnnotation": Object { "elementType": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, }, @@ -131,6 +139,7 @@ Object { "name": "a", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -142,14 +151,16 @@ Object { }, Object { "name": "getStringFromAlias", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "a", - "nullable": false, + "optional": false, "typeAnnotation": Object { "name": "ObjectAlias", + "nullable": false, "type": "TypeAliasTypeAnnotation", }, }, @@ -179,22 +190,26 @@ Object { "properties": Array [ Object { "name": "getArray", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { "elementType": Object { + "nullable": false, "type": "StringTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, }, ], "returnTypeAnnotation": Object { "elementType": Object { + "nullable": false, "type": "StringTypeAnnotation", }, "nullable": false, @@ -221,20 +236,20 @@ Object { "properties": Array [ Object { "name": "getArray", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { - "elementType": undefined, + "nullable": false, "type": "ArrayTypeAnnotation", }, }, ], "returnTypeAnnotation": Object { - "elementType": undefined, "nullable": false, "type": "ArrayTypeAnnotation", }, @@ -259,22 +274,26 @@ Object { "properties": Array [ Object { "name": "getArray", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { "elementType": Object { + "nullable": false, "type": "StringTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, }, ], "returnTypeAnnotation": Object { "elementType": Object { + "nullable": false, "type": "StringTypeAnnotation", }, "nullable": false, @@ -285,22 +304,26 @@ Object { }, Object { "name": "getArray", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { "elementType": Object { + "nullable": false, "type": "StringTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, }, ], "returnTypeAnnotation": Object { "elementType": Object { + "nullable": false, "type": "StringTypeAnnotation", }, "nullable": false, @@ -327,13 +350,15 @@ Object { "properties": Array [ Object { "name": "passBool", + "optional": true, "typeAnnotation": Object { - "optional": true, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -347,13 +372,15 @@ Object { }, Object { "name": "passNumber", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -367,13 +394,15 @@ Object { }, Object { "name": "passString", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "StringTypeAnnotation", }, }, @@ -387,13 +416,15 @@ Object { }, Object { "name": "passStringish", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "StringTypeAnnotation", }, }, @@ -423,13 +454,45 @@ Object { "properties": Array [ Object { "name": "getValueWithCallback", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "callback", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, + "params": Array [ + Object { + "name": "value", + "optional": false, + "typeAnnotation": Object { + "nullable": false, + "type": "StringTypeAnnotation", + }, + }, + Object { + "name": "arr", + "optional": false, + "typeAnnotation": Object { + "elementType": Object { + "elementType": Object { + "nullable": false, + "type": "StringTypeAnnotation", + }, + "nullable": false, + "type": "ArrayTypeAnnotation", + }, + "nullable": false, + "type": "ArrayTypeAnnotation", + }, + }, + ], + "returnTypeAnnotation": Object { + "nullable": false, + "type": "VoidTypeAnnotation", + }, "type": "FunctionTypeAnnotation", }, }, @@ -459,28 +522,35 @@ Object { "properties": Array [ Object { "name": "getArray", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { "elementType": Object { "elementType": Object { "elementType": Object { "elementType": Object { "elementType": Object { - "type": "AnyTypeAnnotation", + "nullable": false, + "type": "StringTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, }, @@ -489,10 +559,13 @@ Object { "elementType": Object { "elementType": Object { "elementType": Object { + "nullable": false, "type": "StringTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, + "nullable": false, "type": "ArrayTypeAnnotation", }, "nullable": false, @@ -519,23 +592,27 @@ Object { "properties": Array [ Object { "name": "getObject", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -555,11 +632,13 @@ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -575,23 +654,27 @@ Object { }, Object { "name": "getReadOnlyObject", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -611,11 +694,13 @@ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -631,18 +716,21 @@ Object { }, Object { "name": "getObject2", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "a", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "StringTypeAnnotation", }, }, @@ -660,23 +748,27 @@ Object { }, Object { "name": "getObjectInArray", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -691,16 +783,19 @@ Object { ], "returnTypeAnnotation": Object { "elementType": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "const1", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -735,8 +830,9 @@ Object { "properties": Array [ Object { "name": "getConstants", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [], "returnTypeAnnotation": Object { "nullable": false, @@ -745,6 +841,7 @@ Object { "name": "isTesting", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -752,11 +849,13 @@ Object { "name": "reactNativeVersion", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "major", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -764,6 +863,7 @@ Object { "name": "minor", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -771,13 +871,15 @@ Object { "name": "patch", "optional": true, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, Object { "name": "prerelease", - "optional": true, + "optional": false, "typeAnnotation": Object { + "nullable": true, "type": "NumberTypeAnnotation", }, }, @@ -789,6 +891,7 @@ Object { "name": "forceTouchAvailable", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "BooleanTypeAnnotation", }, }, @@ -796,6 +899,7 @@ Object { "name": "osVersion", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "StringTypeAnnotation", }, }, @@ -803,6 +907,7 @@ Object { "name": "systemName", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "StringTypeAnnotation", }, }, @@ -810,6 +915,7 @@ Object { "name": "interfaceIdiom", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "StringTypeAnnotation", }, }, @@ -837,13 +943,15 @@ Object { "properties": Array [ Object { "name": "getInt", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "Int32TypeAnnotation", }, }, @@ -857,13 +965,15 @@ Object { }, Object { "name": "getFloat", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "FloatTypeAnnotation", }, }, @@ -891,11 +1001,13 @@ Object { "SampleTurboModule": Object { "aliases": Object { "Bar": Object { + "nullable": false, "properties": Array [ Object { "name": "z", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -903,12 +1015,14 @@ Object { "type": "ObjectTypeAnnotation", }, "Foo": Object { + "nullable": false, "properties": Array [ Object { "name": "bar1", "optional": false, "typeAnnotation": Object { "name": "Bar", + "nullable": false, "type": "TypeAliasTypeAnnotation", }, }, @@ -917,6 +1031,7 @@ Object { "optional": false, "typeAnnotation": Object { "name": "Bar", + "nullable": false, "type": "TypeAliasTypeAnnotation", }, }, @@ -927,35 +1042,40 @@ Object { "properties": Array [ Object { "name": "foo1", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "x", - "nullable": false, + "optional": false, "typeAnnotation": Object { "name": "Foo", + "nullable": false, "type": "TypeAliasTypeAnnotation", }, }, ], "returnTypeAnnotation": Object { + "name": "Foo", "nullable": false, - "type": "VoidTypeAnnotation", + "type": "TypeAliasTypeAnnotation", }, "type": "FunctionTypeAnnotation", }, }, Object { "name": "foo2", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "x", - "nullable": false, + "optional": false, "typeAnnotation": Object { "name": "Foo", + "nullable": false, "type": "TypeAliasTypeAnnotation", }, }, @@ -985,13 +1105,15 @@ Object { "properties": Array [ Object { "name": "voidFunc", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "arg", - "nullable": true, + "optional": false, "typeAnnotation": Object { + "nullable": true, "type": "StringTypeAnnotation", }, }, @@ -1019,11 +1141,13 @@ Object { "SampleTurboModule": Object { "aliases": Object { "DisplayMetricsAndroid": Object { + "nullable": false, "properties": Array [ Object { "name": "width", "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "NumberTypeAnnotation", }, }, @@ -1034,8 +1158,9 @@ Object { "properties": Array [ Object { "name": "getConstants", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [], "returnTypeAnnotation": Object { "nullable": false, @@ -1044,12 +1169,14 @@ Object { "name": "Dimensions", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "windowPhysicalPixels", "optional": false, "typeAnnotation": Object { "name": "DisplayMetricsAndroid", + "nullable": false, "type": "TypeAliasTypeAnnotation", }, }, @@ -1065,8 +1192,9 @@ Object { }, Object { "name": "getConstants2", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [], "returnTypeAnnotation": Object { "nullable": false, @@ -1075,12 +1203,14 @@ Object { "name": "Dimensions", "optional": false, "typeAnnotation": Object { + "nullable": false, "properties": Array [ Object { "name": "windowPhysicalPixels", "optional": false, "typeAnnotation": Object { "name": "DisplayMetricsAndroid", + "nullable": false, "type": "TypeAliasTypeAnnotation", }, }, @@ -1108,53 +1238,43 @@ Object { "NativeSampleTurboModule": Object { "nativeModules": Object { "SampleTurboModule": Object { - "aliases": Object { - "SomeObj": Object { - "properties": Array [ - Object { - "name": "a", - "optional": false, - "typeAnnotation": Object { - "type": "StringTypeAnnotation", - }, - }, - ], - "type": "ObjectTypeAnnotation", - }, - }, + "aliases": Object {}, "properties": Array [ Object { "name": "getValueWithPromise", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [], "returnTypeAnnotation": Object { "nullable": false, - "type": "GenericPromiseTypeAnnotation", + "type": "PromiseTypeAnnotation", }, "type": "FunctionTypeAnnotation", }, }, Object { "name": "getValueWithPromiseDefinedSomewhereElse", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [], "returnTypeAnnotation": Object { "nullable": false, - "type": "GenericPromiseTypeAnnotation", + "type": "PromiseTypeAnnotation", }, "type": "FunctionTypeAnnotation", }, }, Object { "name": "getValueWithPromiseObjDefinedSomewhereElse", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [], "returnTypeAnnotation": Object { "nullable": false, - "type": "GenericPromiseTypeAnnotation", + "type": "PromiseTypeAnnotation", }, "type": "FunctionTypeAnnotation", }, @@ -1177,14 +1297,16 @@ Object { "properties": Array [ Object { "name": "getRootTag", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "rootTag", - "nullable": false, + "optional": false, "typeAnnotation": Object { "name": "RootTag", + "nullable": false, "type": "ReservedFunctionValueTypeAnnotation", }, }, @@ -1215,13 +1337,15 @@ Object { "properties": Array [ Object { "name": "getObject", + "optional": false, "typeAnnotation": Object { - "optional": false, + "nullable": false, "params": Array [ Object { "name": "o", - "nullable": false, + "optional": false, "typeAnnotation": Object { + "nullable": false, "type": "GenericObjectTypeAnnotation", }, }, diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js new file mode 100644 index 00000000000000..b48f155accf153 --- /dev/null +++ b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-e2e-test.js @@ -0,0 +1,1186 @@ +/** + * Copyright (c) Facebook, Inc. and its 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-local + * @format + */ + +import type { + ReservedFunctionValueTypeName, + NativeModuleSchema, +} from '../../../../CodegenSchema'; +const {parseString} = require('../../index.js'); +const { + FlowGenericNotTypeParameterizedParserError, + UnrecognizedFlowTypeAnnotationParserError, + UnrecognizedFlowGenericParserError, + UnnamedFunctionTypeAnnotationParamError, +} = require('../errors.js'); +const invariant = require('invariant'); + +type PrimitiveTypeAnnotationType = + | 'StringTypeAnnotation' + | 'NumberTypeAnnotation' + | 'Int32TypeAnnotation' + | 'DoubleTypeAnnotation' + | 'FloatTypeAnnotation' + | 'BooleanTypeAnnotation'; + +const PRIMITIVES: $ReadOnlyArray<[string, PrimitiveTypeAnnotationType]> = [ + ['string', 'StringTypeAnnotation'], + ['number', 'NumberTypeAnnotation'], + ['Int32', 'Int32TypeAnnotation'], + ['Double', 'DoubleTypeAnnotation'], + ['Float', 'FloatTypeAnnotation'], + ['boolean', 'BooleanTypeAnnotation'], +]; + +const RESERVED_FUNCTION_VALUE_TYPE_NAME: $ReadOnlyArray = [ + 'RootTag', +]; + +const MODULE_NAME = 'Foo'; + +const TYPE_ALIAS_DECLARATIONS = ` +type Animal = {| + name: string, +|}; + +type AnimalPointer = Animal; +`; + +function expectAnimalTypeAliasToExist(module: NativeModuleSchema) { + const animalAlias = module.aliases.Animal; + + expect(animalAlias).not.toBe(null); + invariant(animalAlias != null, ''); + expect(animalAlias.type).toBe('ObjectTypeAnnotation'); + expect(animalAlias.nullable).toBe(false); + expect(animalAlias.properties.length).toBe(1); + expect(animalAlias.properties[0].name).toBe('name'); + expect(animalAlias.properties[0].optional).toBe(false); + expect(animalAlias.properties[0].typeAnnotation.type).toBe( + 'StringTypeAnnotation', + ); + expect(animalAlias.properties[0].typeAnnotation.nullable).toBe(false); +} + +describe('Flow Module Parser', () => { + describe('Parameter Parsing', () => { + it("should fail parsing when a method has an parameter of type 'any'", () => { + const parser = () => + parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + export interface Spec extends TurboModule { + +useArg(arg: any): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(parser).toThrow( + new UnrecognizedFlowTypeAnnotationParserError( + MODULE_NAME, + 'AnyTypeAnnotation', + ), + ); + }); + + it('should fail parsing when a function param type is unamed', () => { + const parser = () => + parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + export interface Spec extends TurboModule { + +useArg(boolean): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(parser).toThrow( + new UnnamedFunctionTypeAnnotationParamError(MODULE_NAME), + ); + }); + + [ + {nullable: false, optional: false}, + {nullable: false, optional: true}, + {nullable: true, optional: false}, + {nullable: true, optional: true}, + ].forEach(({nullable, optional}) => { + const PARAM_TYPE_DESCRIPTION = + nullable && optional + ? 'a nullable and optional' + : nullable + ? 'a nullable' + : optional + ? 'an optional' + : 'a required'; + + function annotateArg(paramName: string, paramType: string) { + if (nullable && optional) { + return `${paramName}?: ?${paramType}`; + } + if (nullable) { + return `${paramName}: ?${paramType}`; + } + if (optional) { + return `${paramName}?: ${paramType}`; + } + return `${paramName}: ${paramType}`; + } + + function parseParamType(paramName: string, paramType: string) { + const module = parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + + ${TYPE_ALIAS_DECLARATIONS} + + export interface Spec extends TurboModule { + +useArg(${annotateArg(paramName, paramType)}): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(module.properties[0]).not.toBe(null); + const param = module.properties[0].typeAnnotation.params[0]; + expect(param).not.toBe(null); + expect(param.name).toBe(paramName); + expect(param.optional).toBe(optional); + expect(param.typeAnnotation.nullable).toBe(nullable); + + return [param, module]; + } + + describe( + (nullable && optional + ? 'Nullable and Optional' + : nullable + ? 'Nullable' + : optional + ? 'Optional' + : 'Required') + ' Parameter', + () => { + it(`should not parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Function'`, () => { + expect(() => parseParamType('arg', 'Function')).toThrow( + new UnrecognizedFlowGenericParserError(MODULE_NAME, 'Function'), + ); + }); + + describe('Primitive types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} primitive parameter of type '${FLOW_TYPE}'`, () => { + const [param] = parseParamType('arg', FLOW_TYPE); + expect(param.typeAnnotation.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Object'`, () => { + const [param] = parseParamType('arg', 'Object'); + expect(param.typeAnnotation.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + describe('Reserved Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of reserved type '${FLOW_TYPE}'`, () => { + const [param] = parseParamType('arg', FLOW_TYPE); + + expect(param.typeAnnotation.type).toBe( + 'ReservedFunctionValueTypeAnnotation', + ); + invariant( + param.typeAnnotation.type === + 'ReservedFunctionValueTypeAnnotation', + 'Param must be a Reserved type', + ); + + expect(param.typeAnnotation.name).toBe(FLOW_TYPE); + }); + }); + }); + + describe('Array Types', () => { + it(`should not parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array'`, () => { + expect(() => parseParamType('arg', 'Array')).toThrow( + new FlowGenericNotTypeParameterizedParserError( + MODULE_NAME, + 'Array', + ), + ); + }); + + function parseParamArrayElementType( + paramName: string, + paramType: string, + ) { + const [param, module] = parseParamType( + paramName, + `Array<${paramType}>`, + ); + + expect(param.typeAnnotation.type).toBe('ArrayTypeAnnotation'); + invariant( + param.typeAnnotation.type === 'ArrayTypeAnnotation', + '', + ); + + expect(param.typeAnnotation.elementType).not.toBe(null); + invariant(param.typeAnnotation.elementType != null, ''); + return [param.typeAnnotation.elementType, module]; + } + + // TODO: Do we support nullable element types? + + describe('Primitive Element Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseParamArrayElementType( + 'arg', + FLOW_TYPE, + ); + expect(elementType.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + describe('Reserved Element Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseParamArrayElementType( + 'arg', + FLOW_TYPE, + ); + expect(elementType.type).toBe( + 'ReservedFunctionValueTypeAnnotation', + ); + invariant( + elementType.type === 'ReservedFunctionValueTypeAnnotation', + '', + ); + + expect(elementType.name).toBe(FLOW_TYPE); + }); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array'`, () => { + const [elementType] = parseParamArrayElementType('arg', 'Object'); + expect(elementType.type).toBe('GenericObjectTypeAnnotation'); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of some array of an alias`, () => { + const [elementType, module] = parseParamArrayElementType( + 'arg', + 'Animal', + ); + expect(elementType.type).toBe('TypeAliasTypeAnnotation'); + invariant(elementType.type === 'TypeAliasTypeAnnotation', ''); + + expect(elementType.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter of type 'Array<{|foo: ?string|}>'`, () => { + const [elementType] = parseParamArrayElementType( + 'arg', + '{|foo: ?string|}', + ); + expect(elementType).not.toBe(null); + + expect(elementType.type).toBe('ObjectTypeAnnotation'); + invariant(elementType.type === 'ObjectTypeAnnotation', ''); + + const {properties} = elementType; + invariant(properties != null, ''); + + expect(properties).not.toBe(null); + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].typeAnnotation).not.toBe(null); + expect(properties[0].typeAnnotation?.type).toBe( + 'StringTypeAnnotation', + ); + expect(properties[0].typeAnnotation?.nullable).toBe(true); + expect(properties[0].optional).toBe(false); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of some type alias`, () => { + const [param, module] = parseParamType('arg', 'Animal'); + expect(param.typeAnnotation.type).toBe('TypeAliasTypeAnnotation'); + invariant( + param.typeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + + expect(param.typeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of some type alias that points to another type alias`, () => { + const [param, module] = parseParamType('arg', 'AnimalPointer'); + expect(param.typeAnnotation.type).toBe('TypeAliasTypeAnnotation'); + invariant( + param.typeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + + expect(param.typeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of some type alias that points to another nullable type alias`, () => { + const module = parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + + type Animal = ?{| + name: string, + |}; + + type AnimalPointer = Animal; + + export interface Spec extends TurboModule { + +useArg(${annotateArg('arg', 'AnimalPointer')}): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(module.properties[0]).not.toBe(null); + const param = module.properties[0].typeAnnotation.params[0]; + expect(param.name).toBe('arg'); + expect(param.optional).toBe(optional); + + // The TypeAliasAnnotation is called Animal, and is nullable + expect(param.typeAnnotation.type).toBe('TypeAliasTypeAnnotation'); + invariant( + param.typeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + expect(param.typeAnnotation.name).toBe('Animal'); + expect(param.typeAnnotation.nullable).toBe(true); + + // The Animal type alias RHS is valid, and non-null + expectAnimalTypeAliasToExist(module); + }); + + [ + {nullable: false, optional: false}, + {nullable: false, optional: true}, + {nullable: true, optional: false}, + {nullable: true, optional: true}, + ].forEach(({nullable: isPropNullable, optional: isPropOptional}) => { + const PROP_TYPE_DESCRIPTION = + isPropNullable && isPropOptional + ? 'a nullable and optional' + : isPropNullable + ? 'a nullable' + : isPropOptional + ? 'an optional' + : 'a required'; + + function annotateProp(propName: string, propType: string) { + if (isPropNullable && isPropOptional) { + return `${propName}?: ?${propType}`; + } + if (isPropNullable) { + return `${propName}: ?${propType}`; + } + if (isPropOptional) { + return `${propName}?: ${propType}`; + } + return `${propName}: ${propType}`; + } + + function parseParamTypeObjectLiteralProp( + propName: string, + propType: string, + ) { + const [param, module] = parseParamType( + 'arg', + `{|${annotateProp(propName, propType)}|}`, + ); + + expect(param.typeAnnotation.type).toBe('ObjectTypeAnnotation'); + invariant( + param.typeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + const {properties} = param.typeAnnotation; + + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties.length).toBe(1); + expect(properties[0].name).toBe(propName); + expect(properties[0].optional).toBe(isPropOptional); + expect(properties[0].typeAnnotation).not.toBe(null); + expect(properties[0].typeAnnotation.nullable).toBe( + isPropNullable, + ); + invariant(properties[0].typeAnnotation != null, ''); + + return [ + { + ...properties[0], + typeAnnotation: properties[0].typeAnnotation, + }, + module, + ]; + } + + describe( + (isPropNullable && isPropOptional + ? 'Nullable and Optional' + : isPropNullable + ? 'Nullable' + : isPropOptional + ? 'Optional' + : 'Required') + ' Property', + () => { + describe('Props with Primitive Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of primitive type '${FLOW_TYPE}'`, () => { + const [prop] = parseParamTypeObjectLiteralProp( + 'prop', + FLOW_TYPE, + ); + expect(prop.typeAnnotation.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Object'`, () => { + const [prop] = parseParamTypeObjectLiteralProp( + 'prop', + 'Object', + ); + expect(prop.typeAnnotation.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + describe('Props with Reserved Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of reserved type '${FLOW_TYPE}'`, () => { + const [prop] = parseParamTypeObjectLiteralProp( + 'prop', + FLOW_TYPE, + ); + expect(prop.typeAnnotation.type).toBe( + 'ReservedFunctionValueTypeAnnotation', + ); + invariant( + prop.typeAnnotation.type === + 'ReservedFunctionValueTypeAnnotation', + '', + ); + + expect(prop.typeAnnotation.name).toBe(FLOW_TYPE); + }); + }); + }); + + describe('Props with Array Types', () => { + it(`should not parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array`, () => { + expect(() => + parseParamTypeObjectLiteralProp('prop', 'Array'), + ).toThrow( + new FlowGenericNotTypeParameterizedParserError( + MODULE_NAME, + 'Array', + ), + ); + }); + + function parseArrayElementType( + propName: string, + arrayElementType: string, + ) { + const [property, module] = parseParamTypeObjectLiteralProp( + 'propName', + `Array<${arrayElementType}>`, + ); + expect(property.typeAnnotation.type).toBe( + 'ArrayTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'ArrayTypeAnnotation', + '', + ); + + const {elementType} = property.typeAnnotation; + expect(elementType).not.toBe(null); + invariant(elementType != null, ''); + return [elementType, module]; + } + + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + FLOW_TYPE, + ); + + expect(elementType.type).toBe(PARSED_TYPE_NAME); + }); + }); + + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + FLOW_TYPE, + ); + + expect(elementType.type).toBe( + 'ReservedFunctionValueTypeAnnotation', + ); + invariant( + elementType.type === + 'ReservedFunctionValueTypeAnnotation', + '', + ); + expect(elementType.name).toBe(FLOW_TYPE); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + 'Object', + ); + expect(elementType.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type of some array of an alias`, () => { + const [elementType, module] = parseArrayElementType( + 'prop', + 'Animal', + ); + + expect(elementType.type).toBe('TypeAliasTypeAnnotation'); + invariant( + elementType.type === 'TypeAliasTypeAnnotation', + '', + ); + + expect(elementType.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of 'Array<{|foo: ?string|}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + '{|foo: ?string|}', + ); + + expect(elementType.type).toBe('ObjectTypeAnnotation'); + invariant(elementType.type === 'ObjectTypeAnnotation', ''); + + const {properties} = elementType; + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].typeAnnotation).not.toBe(null); + expect(properties[0].typeAnnotation?.type).toBe( + 'StringTypeAnnotation', + ); + expect(properties[0].typeAnnotation?.nullable).toBe(true); + expect(properties[0].optional).toBe(false); + }); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type '{|foo: ?string|}'`, () => { + const [property] = parseParamTypeObjectLiteralProp( + 'prop', + '{|foo: ?string|}', + ); + + expect(property.typeAnnotation.type).toBe( + 'ObjectTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + const {properties} = property.typeAnnotation; + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].typeAnnotation).not.toBe(null); + expect(properties[0].typeAnnotation?.type).toBe( + 'StringTypeAnnotation', + ); + expect(properties[0].typeAnnotation?.nullable).toBe(true); + expect(properties[0].optional).toBe(false); + }); + + it(`should parse methods that have ${PARAM_TYPE_DESCRIPTION} parameter type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of some type alias`, () => { + const [property, module] = parseParamTypeObjectLiteralProp( + 'prop', + 'Animal', + ); + + expect(property.typeAnnotation.type).toBe( + 'TypeAliasTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + + expect(property.typeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + }, + ); + }); + }, + ); + }); + }); + + describe('Return Parsing', () => { + it('should parse methods that have a return type of void', () => { + const module = parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + export interface Spec extends TurboModule { + +useArg(): void; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(module.properties[0]).not.toBe(null); + const {returnTypeAnnotation} = module.properties[0].typeAnnotation; + expect(returnTypeAnnotation).not.toBe(null); + expect(returnTypeAnnotation.type).toBe('VoidTypeAnnotation'); + expect(returnTypeAnnotation.nullable).toBe(false); + }); + + [true, false].forEach(IS_RETURN_TYPE_NULLABLE => { + const RETURN_TYPE_DESCRIPTION = IS_RETURN_TYPE_NULLABLE + ? 'a nullable' + : 'a non-nullable'; + const annotateRet = retType => + IS_RETURN_TYPE_NULLABLE ? `?${retType}` : retType; + + function parseReturnType(flowType: string) { + const module = parseModule(` + import type {TurboModule} from 'RCTExport'; + import * as TurboModuleRegistry from 'TurboModuleRegistry'; + + ${TYPE_ALIAS_DECLARATIONS} + + export interface Spec extends TurboModule { + +useArg(): ${annotateRet(flowType)}; + } + export default TurboModuleRegistry.get('Foo'); + `); + + expect(module.properties[0]).not.toBe(null); + const {returnTypeAnnotation} = module.properties[0].typeAnnotation; + expect(returnTypeAnnotation).not.toBe(null); + expect(returnTypeAnnotation.nullable).toBe(IS_RETURN_TYPE_NULLABLE); + return [returnTypeAnnotation, module]; + } + + describe( + IS_RETURN_TYPE_NULLABLE ? 'Nullable Returns' : 'Non-Nullable Returns', + () => { + ['Promise', 'Promise<{||}>', 'Promise<*>'].forEach( + promiseFlowType => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type '${promiseFlowType}'`, () => { + const [returnTypeAnnotation] = parseReturnType(promiseFlowType); + expect(returnTypeAnnotation.type).toBe('PromiseTypeAnnotation'); + }); + }, + ); + + describe('Primitive Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} primitive return of type '${FLOW_TYPE}'`, () => { + const [returnTypeAnnotation] = parseReturnType(FLOW_TYPE); + expect(returnTypeAnnotation.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + describe('Reserved Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} reserved return of type '${FLOW_TYPE}'`, () => { + const [returnTypeAnnotation] = parseReturnType(FLOW_TYPE); + expect(returnTypeAnnotation.type).toBe( + 'ReservedFunctionValueTypeAnnotation', + ); + invariant( + returnTypeAnnotation.type === + 'ReservedFunctionValueTypeAnnotation', + '', + ); + expect(returnTypeAnnotation.name).toBe(FLOW_TYPE); + }); + }); + }); + + describe('Array Types', () => { + it(`should not parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array'`, () => { + expect(() => parseReturnType('Array')).toThrow( + new FlowGenericNotTypeParameterizedParserError( + MODULE_NAME, + 'Array', + ), + ); + }); + + function parseArrayElementReturnType(flowType: string) { + const [returnTypeAnnotation, module] = parseReturnType( + 'Array' + (flowType != null ? `<${flowType}>` : ''), + ); + expect(returnTypeAnnotation.type).toBe('ArrayTypeAnnotation'); + invariant( + returnTypeAnnotation.type === 'ArrayTypeAnnotation', + '', + ); + + const {elementType} = returnTypeAnnotation; + expect(elementType).not.toBe(null); + invariant(elementType != null, ''); + return [elementType, module]; + } + + // TODO: Do we support nullable element types? + + describe('Primitive Element Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType, module] = parseArrayElementReturnType( + FLOW_TYPE, + ); + expect(elementType.type).toBe(PARSED_TYPE_NAME); + }); + }); + }); + + describe('Reserved Element Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementReturnType(FLOW_TYPE); + expect(elementType.type).toBe( + 'ReservedFunctionValueTypeAnnotation', + ); + invariant( + elementType.type === 'ReservedFunctionValueTypeAnnotation', + '', + ); + + expect(elementType.name).toBe(FLOW_TYPE); + }); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array'`, () => { + const [elementType] = parseArrayElementReturnType('Object'); + expect(elementType.type).toBe('GenericObjectTypeAnnotation'); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of some array of an alias`, () => { + const [elementType, module] = parseArrayElementReturnType( + 'Animal', + ); + expect(elementType.type).toBe('TypeAliasTypeAnnotation'); + invariant(elementType.type === 'TypeAliasTypeAnnotation', ''); + expect(elementType.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Array<{|foo: ?string|}>'`, () => { + const [elementType] = parseArrayElementReturnType( + '{|foo: ?string|}', + ); + expect(elementType.type).toBe('ObjectTypeAnnotation'); + invariant(elementType.type === 'ObjectTypeAnnotation', ''); + + const {properties} = elementType; + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].typeAnnotation).not.toBe(null); + expect(properties[0].typeAnnotation?.type).toBe( + 'StringTypeAnnotation', + ); + expect(properties[0].typeAnnotation?.nullable).toBe(true); + expect(properties[0].optional).toBe(false); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of some type alias`, () => { + const [returnTypeAnnotation, module] = parseReturnType('Animal'); + expect(returnTypeAnnotation.type).toBe('TypeAliasTypeAnnotation'); + invariant( + returnTypeAnnotation.type === 'TypeAliasTypeAnnotation', + '', + ); + expect(returnTypeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should not parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Function'`, () => { + expect(() => parseReturnType('Function')).toThrow( + new UnrecognizedFlowGenericParserError(MODULE_NAME, 'Function'), + ); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return of type 'Object'`, () => { + const [returnTypeAnnotation] = parseReturnType('Object'); + expect(returnTypeAnnotation.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + describe('Object Literals Types', () => { + // TODO: Inexact vs exact object literals? + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an empty object literal`, () => { + const [returnTypeAnnotation] = parseReturnType('{||}'); + expect(returnTypeAnnotation.type).toBe('ObjectTypeAnnotation'); + invariant( + returnTypeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + // Validate properties of object literal + expect(returnTypeAnnotation.properties).not.toBe(null); + expect(returnTypeAnnotation.properties?.length).toBe(0); + }); + + [ + {nullable: false, optional: false}, + {nullable: false, optional: true}, + {nullable: true, optional: false}, + {nullable: true, optional: true}, + ].forEach(({nullable, optional}) => { + const PROP_TYPE_DESCRIPTION = + nullable && optional + ? 'a nullable and optional' + : nullable + ? 'a nullable' + : optional + ? 'an optional' + : 'a required'; + + function annotateProp(propName, propType) { + if (nullable && optional) { + return `${propName}?: ?${propType}`; + } + if (nullable) { + return `${propName}: ?${propType}`; + } + if (optional) { + return `${propName}?: ${propType}`; + } + return `${propName}: ${propType}`; + } + + function parseObjectLiteralReturnTypeProp( + propName: string, + propType: string, + ) { + const [returnTypeAnnotation, module] = parseReturnType( + `{|${annotateProp(propName, propType)}|}`, + ); + expect(returnTypeAnnotation.type).toBe('ObjectTypeAnnotation'); + invariant( + returnTypeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + const properties = returnTypeAnnotation.properties; + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties.length).toBe(1); + + // Validate property + const property = properties[0]; + expect(property.name).toBe(propName); + expect(property.optional).toBe(optional); + expect(property.typeAnnotation).not.toBe(null); + expect(property.typeAnnotation?.nullable).toBe(nullable); + invariant(property.typeAnnotation != null, ''); + return [ + { + ...property, + typeAnnotation: property.typeAnnotation, + }, + module, + ]; + } + + describe( + (nullable && optional + ? 'Nullable and Optional' + : nullable + ? 'Nullable' + : optional + ? 'Optional' + : 'Required') + ' Property', + () => { + /** + * TODO: Fill out props in promise + */ + + describe('Props with Primitive Types', () => { + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of primitive type '${FLOW_TYPE}'`, () => { + const [property] = parseObjectLiteralReturnTypeProp( + 'prop', + FLOW_TYPE, + ); + expect(property.typeAnnotation.type).toBe( + PARSED_TYPE_NAME, + ); + }); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Object'`, () => { + const [property] = parseObjectLiteralReturnTypeProp( + 'prop', + 'Object', + ); + + expect(property.typeAnnotation.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + describe('Props with Reserved Types', () => { + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of reserved type '${FLOW_TYPE}'`, () => { + const [property] = parseObjectLiteralReturnTypeProp( + 'prop', + FLOW_TYPE, + ); + + expect(property.typeAnnotation.type).toBe( + 'ReservedFunctionValueTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === + 'ReservedFunctionValueTypeAnnotation', + '', + ); + + expect(property.typeAnnotation.name).toBe(FLOW_TYPE); + }); + }); + }); + + describe('Props with Array Types', () => { + it(`should not parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array`, () => { + expect(() => + parseObjectLiteralReturnTypeProp('prop', 'Array'), + ).toThrow( + new FlowGenericNotTypeParameterizedParserError( + MODULE_NAME, + 'Array', + ), + ); + }); + + function parseArrayElementType( + propName: string, + arrayElementType: string, + ) { + const [ + property, + module, + ] = parseObjectLiteralReturnTypeProp( + propName, + `Array<${arrayElementType}>`, + ); + expect(property.name).toBe(propName); + expect(property.typeAnnotation.type).toBe( + 'ArrayTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'ArrayTypeAnnotation', + '', + ); + + const {elementType} = property.typeAnnotation; + expect(elementType).not.toBe(null); + invariant(elementType != null, ''); + return [elementType, module]; + } + + PRIMITIVES.forEach(([FLOW_TYPE, PARSED_TYPE_NAME]) => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + FLOW_TYPE, + ); + expect(elementType.type).toBe(PARSED_TYPE_NAME); + }); + }); + + RESERVED_FUNCTION_VALUE_TYPE_NAME.forEach(FLOW_TYPE => { + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<${FLOW_TYPE}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + FLOW_TYPE, + ); + expect(elementType.type).toBe( + 'ReservedFunctionValueTypeAnnotation', + ); + invariant( + elementType.type === + 'ReservedFunctionValueTypeAnnotation', + '', + ); + + expect(elementType.name).toBe(FLOW_TYPE); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + 'Object', + ); + expect(elementType).not.toBe(null); + expect(elementType.type).toBe( + 'GenericObjectTypeAnnotation', + ); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type of some array of an aliase`, () => { + const [elementType, module] = parseArrayElementType( + 'prop', + 'Animal', + ); + expect(elementType.type).toBe('TypeAliasTypeAnnotation'); + invariant( + elementType.type === 'TypeAliasTypeAnnotation', + '', + ); + expect(elementType.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of type 'Array<{|foo: ?string|}>'`, () => { + const [elementType] = parseArrayElementType( + 'prop', + '{|foo: ?string|}', + ); + expect(elementType.type).toBe('ObjectTypeAnnotation'); + invariant( + elementType.type === 'ObjectTypeAnnotation', + '', + ); + + const {properties} = elementType; + invariant(properties != null, ''); + expect(properties).not.toBe(null); + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].optional).toBe(false); + + expect(properties[0].typeAnnotation).not.toBe(null); + invariant(properties[0].typeAnnotation != null, ''); + + expect(properties[0].typeAnnotation.type).toBe( + 'StringTypeAnnotation', + ); + expect(properties[0].typeAnnotation.nullable).toBe(true); + }); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of '{|foo: ?string|}'`, () => { + const [property] = parseObjectLiteralReturnTypeProp( + 'prop', + '{|foo: ?string|}', + ); + + expect(property.typeAnnotation.type).toBe( + 'ObjectTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === 'ObjectTypeAnnotation', + '', + ); + + const {properties} = property.typeAnnotation; + + expect(properties).not.toBe(null); + invariant(properties != null, ''); + + expect(properties[0]).not.toBe(null); + expect(properties[0].name).toBe('foo'); + expect(properties[0].optional).toBe(false); + + expect(properties[0].typeAnnotation).not.toBe(null); + invariant(properties[0].typeAnnotation != null, ''); + + expect(properties[0].typeAnnotation.type).toBe( + 'StringTypeAnnotation', + ); + expect(properties[0].typeAnnotation.nullable).toBe(true); + }); + + it(`should parse methods that have ${RETURN_TYPE_DESCRIPTION} return type of an object literal with ${PROP_TYPE_DESCRIPTION} prop of some type alias`, () => { + const [property, module] = parseObjectLiteralReturnTypeProp( + 'prop', + 'Animal', + ); + + expect(property.typeAnnotation.type).toBe( + 'TypeAliasTypeAnnotation', + ); + invariant( + property.typeAnnotation.type === + 'TypeAliasTypeAnnotation', + '', + ); + + expect(property.typeAnnotation.name).toBe('Animal'); + expectAnimalTypeAliasToExist(module); + }); + }, + ); + }); + }); + }, + ); + }); + }); +}); + +function parseModule(source) { + const schema = parseString(source, `Native${MODULE_NAME}.js`); + const {nativeModules} = schema.modules.NativeFoo; + invariant( + nativeModules, + "'nativeModules' in Spec NativeFoo shouldn't be null", + ); + return nativeModules.Foo; +} diff --git a/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-test.js b/packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js similarity index 100% rename from packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-test.js rename to packages/react-native-codegen/src/parsers/flow/modules/__tests__/module-parser-snapshot-test.js diff --git a/packages/react-native-codegen/src/parsers/flow/modules/aliases.js b/packages/react-native-codegen/src/parsers/flow/modules/aliases.js deleted file mode 100644 index 7c55e4d9ff61a6..00000000000000 --- a/packages/react-native-codegen/src/parsers/flow/modules/aliases.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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-local - * @format - */ - -'use strict'; - -import type {ObjectTypeAliasTypeShape} from '../../../CodegenSchema.js'; - -import type {TypeMap} from '../utils.js'; - -const {getObjectProperties} = require('./properties'); - -// $FlowFixMe there's no flowtype for ASTs -type MethodAST = Object; - -function getAliases( - typeDefinition: $ReadOnlyArray, - types: TypeMap, -): $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}> { - const aliases = {}; - typeDefinition.map(moduleAlias => { - const aliasName = Object.keys(moduleAlias)[0]; - const typeAnnotation = moduleAlias[Object.keys(moduleAlias)[0]]; - - switch (typeAnnotation.type) { - case 'ObjectTypeAnnotation': - aliases[aliasName] = { - type: 'ObjectTypeAnnotation', - ...(typeAnnotation.properties && { - properties: getObjectProperties( - aliasName, - {properties: typeAnnotation.properties}, - aliasName, - types, - ), - }), - }; - return; - case 'GenericTypeAnnotation': - if (typeAnnotation.id.name && typeAnnotation.id.name !== '') { - aliases[aliasName] = { - type: 'TypeAliasTypeAnnotation', - name: typeAnnotation.id.name, - }; - return; - } else { - throw new Error( - `Cannot use "${typeAnnotation.type}" type annotation for "${aliasName}": must specify a type alias name`, - ); - } - default: - // TODO (T65847278): Figure out why this does not work. - // (typeAnnotation.type: empty); - throw new Error( - `Unknown prop type, found "${typeAnnotation.type}" in "${aliasName}"`, - ); - } - }); - return aliases; -} - -module.exports = { - getAliases, -}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/errors.js b/packages/react-native-codegen/src/parsers/flow/modules/errors.js new file mode 100644 index 00000000000000..537e4b1aedb78f --- /dev/null +++ b/packages/react-native-codegen/src/parsers/flow/modules/errors.js @@ -0,0 +1,112 @@ +/** + * Copyright (c) Facebook, Inc. and its 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-local + * @format + */ + +'use strict'; + +const invariant = require('invariant'); + +class UnrecognizedFlowTypeAnnotationParserError extends Error { + +typeAnnotationType: string; + constructor(moduleName: string, typeAnnotationType: string) { + super( + `Module ${moduleName}: Detected unsupported type annotation of type '${typeAnnotationType}'`, + ); + + // assign the error class name in your custom error (as a shortcut) + this.name = this.constructor.name; + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + this.typeAnnotationType = typeAnnotationType; + } +} + +class UnrecognizedFlowGenericParserError extends Error { + +genericName: string; + constructor(moduleName: string, genericName: string) { + super( + `Module ${moduleName}: Detected unsupported generic type '${genericName}'`, + ); + + // assign the error class name in your custom error (as a shortcut) + this.name = this.constructor.name; + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + this.genericName = genericName; + } +} + +class FlowGenericNotTypeParameterizedParserError extends Error { + +genericName: string; + constructor(moduleName: string, genericName: string) { + super( + `Module ${moduleName}: Detected a type of ${genericName}, without type parameters.`, + ); + + // assign the error class name in your custom error (as a shortcut) + this.name = this.constructor.name; + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + this.genericName = genericName; + } +} + +class FlowGenericTypeParameterCountMismatchParserError extends Error { + +genericName: string; + +numTypeParameters: number; + + constructor( + moduleName: string, + genericName: string, + numTypeParameters: number, + expectedNumTypeParameters: number, + ) { + invariant( + numTypeParameters !== expectedNumTypeParameters, + `FlowGenericNotTypeParameterizedWithExactlyOneTypeParserError can only be created with numTypeParameters != ${expectedNumTypeParameters}`, + ); + + super( + `Module ${moduleName}: Detected a type of ${genericName}, with ${numTypeParameters} type parameters specified. Expected exactly ${expectedNumTypeParameters}.`, + ); + + // assign the error class name in your custom error (as a shortcut) + this.name = this.constructor.name; + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + this.genericName = genericName; + this.numTypeParameters = numTypeParameters; + } +} + +class UnnamedFunctionTypeAnnotationParamError extends Error { + constructor(moduleName: string) { + super( + `Module ${moduleName}: Detected a FunctionTypeAnnotation with an unnamed param. Please name all params.`, + ); + + // assign the error class name in your custom error (as a shortcut) + this.name = this.constructor.name; + + // capturing the stack trace keeps the reference to your error class + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = { + FlowGenericNotTypeParameterizedParserError, + FlowGenericTypeParameterCountMismatchParserError, + UnrecognizedFlowTypeAnnotationParserError, + UnrecognizedFlowGenericParserError, + UnnamedFunctionTypeAnnotationParamError, +}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/index.js b/packages/react-native-codegen/src/parsers/flow/modules/index.js index c09c66acf47c51..a1da76184fba9c 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/index.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/index.js @@ -10,67 +10,440 @@ 'use strict'; -import type {NativeModuleSchemaBuilderConfig} from './schema.js'; -const {getAliases} = require('./aliases'); -const {getMethods} = require('./methods'); +import type { + NativeModulePropertySchema, + NativeModuleMethodParamSchema, + NativeModuleAliasMap, + NativeModuleSchema, + NativeModuleFunctionTypeAnnotation, +} from '../../../CodegenSchema.js'; -function getModuleProperties(types, interfaceName) { - if (types[interfaceName] && types[interfaceName].body) { - return types[interfaceName].body.properties; +import type {TypeDeclarationMap} from '../utils.js'; +const {resolveTypeAnnotation} = require('../utils.js'); +const { + FlowGenericNotTypeParameterizedParserError, + FlowGenericTypeParameterCountMismatchParserError, + UnrecognizedFlowTypeAnnotationParserError, + UnrecognizedFlowGenericParserError, + UnnamedFunctionTypeAnnotationParamError, +} = require('./errors.js'); +const invariant = require('invariant'); + +import type {NativeModuleTypeAnnotation} from '../../../CodegenSchema.js'; + +function translateTypeAnnotation( + moduleName: string, + /** + * TODO(T71778680): Flow-type this node. + */ + flowTypeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + aliasMap: {...NativeModuleAliasMap}, +): NativeModuleTypeAnnotation { + const { + nullable, + typeAnnotation, + typeAliasResolutionStatus, + } = resolveTypeAnnotation(flowTypeAnnotation, types); + + switch (typeAnnotation.type) { + case 'GenericTypeAnnotation': { + switch (typeAnnotation.id.name) { + case 'RootTag': + return { + nullable, + type: 'ReservedFunctionValueTypeAnnotation', + name: 'RootTag', + }; + case 'Promise': { + assertGenericTypeAnnotationHasExactlyOneTypeParameter( + moduleName, + typeAnnotation, + ); + return { + nullable, + type: 'PromiseTypeAnnotation', + }; + } + case 'Array': + case '$ReadOnlyArray': { + assertGenericTypeAnnotationHasExactlyOneTypeParameter( + moduleName, + typeAnnotation, + ); + + try { + /** + * TODO(T72031674): Migrate all our NativeModule specs to not use + * invalid Array ElementTypes. Then, make the elementType a required + * parameter. + */ + const elementType = translateTypeAnnotation( + moduleName, + typeAnnotation.typeParameters.params[0], + types, + aliasMap, + ); + + invariant( + elementType.type !== 'VoidTypeAnnotation', + `${typeAnnotation.id.name} element type cannot be 'void'.`, + ); + invariant( + elementType.type !== 'PromiseTypeAnnotation', + `${typeAnnotation.id.name} element type cannot be 'Promise'.`, + ); + + invariant( + elementType.type !== 'FunctionTypeAnnotation', + `${typeAnnotation.id.name} element type cannot be a function.`, + ); + + return { + nullable, + type: 'ArrayTypeAnnotation', + elementType: elementType, + }; + } catch (ex) { + return { + nullable, + type: 'ArrayTypeAnnotation', + }; + } + } + case '$ReadOnly': { + assertGenericTypeAnnotationHasExactlyOneTypeParameter( + moduleName, + typeAnnotation, + ); + return translateTypeAnnotation( + moduleName, + typeAnnotation.typeParameters.params[0], + types, + aliasMap, + ); + } + case 'Stringish': { + return { + nullable, + type: 'StringTypeAnnotation', + }; + } + case 'Int32': { + return { + nullable, + type: 'Int32TypeAnnotation', + }; + } + case 'Double': { + return { + nullable, + type: 'DoubleTypeAnnotation', + }; + } + case 'Float': { + return { + nullable, + type: 'FloatTypeAnnotation', + }; + } + case 'Object': { + return { + nullable, + type: 'GenericObjectTypeAnnotation', + }; + } + default: { + throw new UnrecognizedFlowGenericParserError( + moduleName, + typeAnnotation.id.name, + ); + } + } + } + case 'ObjectTypeAnnotation': { + const objectTypeAnnotationPartial = { + type: 'ObjectTypeAnnotation', + properties: typeAnnotation.properties.map(property => { + const {optional} = property; + return { + name: property.key.name, + optional, + typeAnnotation: translateTypeAnnotation( + moduleName, + property.value, + types, + aliasMap, + ), + }; + }), + }; + + if (!typeAliasResolutionStatus.successful) { + return { + nullable, + ...objectTypeAnnotationPartial, + }; + } + + /** + * All aliases RHS are required. + */ + aliasMap[typeAliasResolutionStatus.aliasName] = { + nullable: false, + ...objectTypeAnnotationPartial, + }; + + /** + * Nullability of type aliases is transitive. + * + * Consider this case: + * + * type Animal = ?{| + * name: string, + * |}; + * + * type B = Animal + * + * export interface Spec extends TurboModule { + * +greet: (animal: B) => void; + * } + * + * In this case, we follow B to Animal, and then Animal to ?{|name: string|}. + * + * We: + * 1. Replace `+greet: (animal: B) => void;` with `+greet: (animal: ?Animal) => void;`, + * 2. Pretend that Animal = {|name: string|}. + * + * Why do we do this? + * 1. In ObjC, we need to generate a struct called Animal, not B. + * 2. This design is simpler than managing nullability within both the type alias usage, and the type alias RHS. + * 3. What does it mean for a C++ struct, which is what this type alias RHS will generate, to be nullable? ¯\_(ツ)_/¯ + * Nullability is a concept that only makes sense when talking about instances (i.e: usages) of the C++ structs. + * Hence, it's better to manage nullability within the actual TypeAliasTypeAnnotation nodes, and not the + * associated ObjectTypeAnnotations. + */ + return { + nullable: nullable, + type: 'TypeAliasTypeAnnotation', + name: typeAliasResolutionStatus.aliasName, + }; + } + case 'BooleanTypeAnnotation': { + return { + nullable, + type: 'BooleanTypeAnnotation', + }; + } + case 'NumberTypeAnnotation': { + return { + nullable, + type: 'NumberTypeAnnotation', + }; + } + case 'VoidTypeAnnotation': { + return { + nullable, + type: 'VoidTypeAnnotation', + }; + } + case 'StringTypeAnnotation': { + return { + nullable, + type: 'StringTypeAnnotation', + }; + } + case 'FunctionTypeAnnotation': { + return translateFunctionTypeAnnotation( + moduleName, + typeAnnotation, + types, + nullable, + aliasMap, + ); + } + default: { + throw new UnrecognizedFlowTypeAnnotationParserError( + moduleName, + typeAnnotation.type, + ); + } } - throw new Error( - `Interface properties for "${interfaceName}" has been specified incorrectly.`, - ); } -function findInterfaceName(types) { - return Object.keys(types) - .map(typeName => types[typeName]) - .filter( - type => - type.extends && - type.extends[0] && - type.extends[0].id.name === 'TurboModule', - )[0].id.name; -} +function assertGenericTypeAnnotationHasExactlyOneTypeParameter( + moduleName: string, + /** + * TODO(T71778680): This is a GenericTypeAnnotation. Flow type this node + */ + typeAnnotation: $FlowFixMe, +) { + if (typeAnnotation.typeParameters == null) { + throw new FlowGenericNotTypeParameterizedParserError( + moduleName, + typeAnnotation.id.name, + ); + } + + invariant( + typeAnnotation.typeParameters.type === 'TypeParameterInstantiation', + "assertGenericTypeAnnotationHasExactlyOneTypeParameter: Type parameters must be an AST node of type 'TypeParameterInstantiation'", + ); -function findAliasNames(types) { - return Object.keys(types) - .map(typeName => types[typeName]) - .filter( - type => - type.type && - type.type === 'TypeAlias' && - type.right && - type.right.type === 'ObjectTypeAnnotation', - ) - .map(type => type.id.name); + if (typeAnnotation.typeParameters.params.length !== 1) { + throw new FlowGenericTypeParameterCountMismatchParserError( + moduleName, + typeAnnotation.id.name, + (typeAnnotation.typeParameters.params.length: number), + 1, + ); + } } -function getModuleAliases(types, aliasNames) { - return aliasNames.map(aliasName => { - if (types[aliasName] && types[aliasName].right) { - return {[aliasName]: types[aliasName].right}; +function translateFunctionTypeAnnotation( + moduleName: string, + // TODO(T71778680): This is a FunctionTypeAnnotation. Type this. + flowFunctionTypeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, + nullable: boolean, + aliasMap: {...NativeModuleAliasMap}, +): NativeModuleFunctionTypeAnnotation { + const params: Array = []; + for (const flowParam of (flowFunctionTypeAnnotation.params: $ReadOnlyArray<$FlowFixMe>)) { + if (flowParam.name == null) { + throw new UnnamedFunctionTypeAnnotationParamError(moduleName); } + + const paramName = flowParam.name.name; + const paramTypeAnnotation = translateTypeAnnotation( + moduleName, + flowParam.typeAnnotation, + types, + aliasMap, + ); + + invariant( + paramTypeAnnotation.type !== 'VoidTypeAnnotation', + `Parameter ${paramName} cannot have type 'void'.`, + ); + + invariant( + paramTypeAnnotation.type !== 'PromiseTypeAnnotation', + `Parameter ${paramName} cannot have type 'Promise'.`, + ); + + params.push({ + name: flowParam.name.name, + optional: flowParam.optional, + typeAnnotation: paramTypeAnnotation, + }); + } + + const returnTypeAnnotation = translateTypeAnnotation( + moduleName, + flowFunctionTypeAnnotation.returnType, + types, + aliasMap, + ); + + invariant( + returnTypeAnnotation.type !== 'FunctionTypeAnnotation', + "Return cannot have type 'Promise'.", + ); + + return { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation, + params, + nullable, + }; +} + +function buildPropertySchema( + moduleName: string, + // TODO(T71778680): This is an ObjectTypeProperty containing either: + // - a FunctionTypeAnnotation or GenericTypeAnnotation + // - a NullableTypeAnnoation containing a FunctionTypeAnnotation or GenericTypeAnnotation + // Flow type this node + property: $FlowFixMe, + types: TypeDeclarationMap, + aliasMap: {...NativeModuleAliasMap}, +): NativeModulePropertySchema { + let nullable = false; + let {key, value} = property; + + const methodName: string = key.name; + + ({nullable, typeAnnotation: value} = resolveTypeAnnotation(value, types)); + + if (value.type !== 'FunctionTypeAnnotation') { throw new Error( - `Interface properties for "${aliasName}" has been specified incorrectly.`, + `Only methods are supported as module properties. Found ${value.type} in ${property.key.name}`, ); - }); + } + + return { + name: methodName, + optional: property.optional, + typeAnnotation: translateFunctionTypeAnnotation( + moduleName, + value, + types, + nullable, + aliasMap, + ), + }; } -// $FlowFixMe there's no flowtype for AST -function processModule(types): NativeModuleSchemaBuilderConfig { - const interfaceName = findInterfaceName(types); - const moduleProperties = getModuleProperties(types, interfaceName); - const properties = getMethods(moduleProperties, types); +function buildModuleSchema( + moduleName: string, + types: TypeDeclarationMap, +): NativeModuleSchema { + const moduleInterfaceNames = (Object.keys( + types, + ): $ReadOnlyArray).filter((typeName: string) => { + const declaration = types[typeName]; + return ( + declaration.type === 'InterfaceDeclaration' && + declaration.extends.length === 1 && + declaration.extends[0].type === 'InterfaceExtends' && + declaration.extends[0].id.name === 'TurboModule' + ); + }); + + invariant( + moduleInterfaceNames.length === 1, + 'There must be exactly one module declaration per file.', + ); - const aliasNames = findAliasNames(types); - const moduleAliases = getModuleAliases(types, aliasNames); - const aliases = getAliases(moduleAliases, types); + const [moduleInterfaceName] = moduleInterfaceNames; - return {aliases, properties}; + const declaration = types[moduleInterfaceName]; + return (declaration.body.properties: $ReadOnlyArray<$FlowFixMe>) + .filter(property => property.type === 'ObjectTypeProperty') + .map(property => { + const aliasMap: {...NativeModuleAliasMap} = {}; + return { + aliasMap: aliasMap, + propertySchema: buildPropertySchema( + moduleName, + property, + types, + aliasMap, + ), + }; + }) + .reduce( + (moduleSchema: NativeModuleSchema, {aliasMap, propertySchema}) => { + return { + aliases: {...moduleSchema.aliases, ...aliasMap}, + properties: [...moduleSchema.properties, propertySchema], + }; + }, + {aliases: {}, properties: []}, + ); } module.exports = { - processModule, + buildModuleSchema, }; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/methods.js b/packages/react-native-codegen/src/parsers/flow/modules/methods.js deleted file mode 100644 index c63fc903692d56..00000000000000 --- a/packages/react-native-codegen/src/parsers/flow/modules/methods.js +++ /dev/null @@ -1,352 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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-local - * @format - */ - -'use strict'; - -import type { - NativeModuleMethodTypeShape, - FunctionTypeAnnotationParam, - FunctionTypeAnnotationReturn, -} from '../../../CodegenSchema.js'; - -import type {ASTNode, TypeMap} from '../utils.js'; -const {getValueFromTypes} = require('../utils.js'); -const { - getElementTypeForArrayOrObject, - getObjectProperties, -} = require('./properties'); - -// $FlowFixMe there's no flowtype for ASTs -type MethodAST = Object; - -function getTypeAnnotationForParam( - name: string, - paramAnnotation: ASTNode, - types: TypeMap, -): FunctionTypeAnnotationParam { - let param = paramAnnotation; - if (param.name === null) { - throw new Error( - `Unsupported type for ${name}. Please provide a name for every parameter.`, - ); - } - let paramName = param.name.name; - let nullable = false; - if (param.typeAnnotation.type === 'NullableTypeAnnotation') { - nullable = true; - param = paramAnnotation.typeAnnotation; - } - - const typeAnnotation = getValueFromTypes(param.typeAnnotation, types); - const type = - typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name - : typeAnnotation.type; - - switch (type) { - case 'RootTag': - return { - name: paramName, - nullable, - typeAnnotation: { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }, - }; - case 'Array': - case '$ReadOnlyArray': - if ( - typeAnnotation.typeParameters && - typeAnnotation.typeParameters.params[0] - ) { - return { - name: paramName, - nullable, - typeAnnotation: { - type: 'ArrayTypeAnnotation', - elementType: getElementTypeForArrayOrObject( - name, - typeAnnotation.typeParameters.params[0], - paramName, - types, - ), - }, - }; - } else { - throw new Error( - `Unsupported type for ${name}, param: "${paramName}": expected to find annotation for type of array contents`, - ); - } - case 'ObjectTypeAnnotation': - if (param.typeAnnotation.type === 'GenericTypeAnnotation') { - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'TypeAliasTypeAnnotation', - name: param.typeAnnotation.id.name, - }, - }; - } - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - name, - typeAnnotation, - paramName, - types, - ), - }, - }; - case '$ReadOnly': - if ( - typeAnnotation.typeParameters.params && - typeAnnotation.typeParameters.params[0] - ) { - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - name, - typeAnnotation.typeParameters.params[0], - paramName, - types, - ), - }, - }; - } else { - throw new Error( - `Unsupported param for method "${name}", param "${paramName}". No type specified for $ReadOnly`, - ); - } - case 'FunctionTypeAnnotation': - return { - name: paramName, - nullable, - typeAnnotation: { - type: 'FunctionTypeAnnotation', - }, - }; - case 'NumberTypeAnnotation': - case 'BooleanTypeAnnotation': - return { - nullable, - name: paramName, - typeAnnotation: { - type, - }, - }; - - case 'StringTypeAnnotation': - case 'Stringish': - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'StringTypeAnnotation', - }, - }; - case 'Int32': - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'Int32TypeAnnotation', - }, - }; - case 'Float': - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'FloatTypeAnnotation', - }, - }; - default: - return { - nullable, - name: paramName, - typeAnnotation: { - type: 'GenericObjectTypeAnnotation', - }, - }; - } -} - -function getReturnTypeAnnotation( - methodName: string, - returnType, - types: TypeMap, -): FunctionTypeAnnotationReturn { - let typeAnnotation = getValueFromTypes(returnType, types); - let nullable = false; - if (typeAnnotation.type === 'NullableTypeAnnotation') { - nullable = true; - typeAnnotation = typeAnnotation.typeAnnotation; - } - let type = - typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name - : typeAnnotation.type; - - switch (type) { - case 'RootTag': - return { - nullable, - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }; - case 'Promise': - if ( - typeAnnotation.typeParameters && - typeAnnotation.typeParameters.params[0] - ) { - return { - type: 'GenericPromiseTypeAnnotation', - nullable, - }; - } else { - throw new Error( - `Unsupported return promise type for ${methodName}: expected to find annotation for type of promise content`, - ); - } - case 'Array': - case '$ReadOnlyArray': - if ( - typeAnnotation.typeParameters && - typeAnnotation.typeParameters.params[0] - ) { - return { - nullable, - type: 'ArrayTypeAnnotation', - elementType: getElementTypeForArrayOrObject( - methodName, - typeAnnotation.typeParameters.params[0], - 'returning value', - types, - ), - }; - } else { - throw new Error( - `Unsupported return type for ${methodName}: expected to find annotation for type of array contents`, - ); - } - case 'ObjectTypeAnnotation': - return { - nullable, - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - methodName, - typeAnnotation, - 'returning value', - types, - ), - }; - case '$ReadOnly': - if ( - typeAnnotation.typeParameters.params && - typeAnnotation.typeParameters.params[0] - ) { - return { - nullable, - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - methodName, - typeAnnotation.typeParameters.params[0], - 'returning value', - types, - ), - }; - } else { - throw new Error( - `Unsupported return type for method "${methodName}", No type specified for $ReadOnly`, - ); - } - case 'BooleanTypeAnnotation': - case 'NumberTypeAnnotation': - case 'VoidTypeAnnotation': - return { - nullable, - type, - }; - case 'StringTypeAnnotation': - case 'Stringish': - return { - nullable, - type: 'StringTypeAnnotation', - }; - - case 'Int32': - return { - nullable, - type: 'Int32TypeAnnotation', - }; - case 'Float': - return { - nullable, - type: 'FloatTypeAnnotation', - }; - default: - return { - type: 'GenericObjectTypeAnnotation', - nullable, - }; - } -} - -function buildMethodSchema( - property: MethodAST, - types: TypeMap, -): NativeModuleMethodTypeShape { - const name: string = property.key.name; - const value = getValueFromTypes(property.value, types); - if (value.type !== 'FunctionTypeAnnotation') { - throw new Error( - `Only methods are supported as module properties. Found ${value.type} in ${property.key.name}`, - ); - } - const params = value.params.map(param => - getTypeAnnotationForParam(name, param, types), - ); - - const returnTypeAnnotation = getReturnTypeAnnotation( - name, - getValueFromTypes(value.returnType, types), - types, - ); - return { - name, - typeAnnotation: { - type: 'FunctionTypeAnnotation', - returnTypeAnnotation, - params, - optional: property.optional, - }, - }; -} - -function getMethods( - typeDefinition: $ReadOnlyArray, - types: TypeMap, -): $ReadOnlyArray { - return typeDefinition - .filter(property => property.type === 'ObjectTypeProperty') - .map(property => buildMethodSchema(property, types)) - .filter(Boolean); -} - -module.exports = { - getMethods, -}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/properties.js b/packages/react-native-codegen/src/parsers/flow/modules/properties.js deleted file mode 100644 index f1e8c51e7fe443..00000000000000 --- a/packages/react-native-codegen/src/parsers/flow/modules/properties.js +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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-local - * @format - */ - -'use strict'; - -import type { - FunctionTypeAnnotationParamTypeAnnotation, - ObjectParamTypeAnnotation, - TypeAliasTypeAnnotation, -} from '../../../CodegenSchema.js'; - -import type {ASTNode, TypeMap} from '../utils.js'; -const {getValueFromTypes} = require('../utils.js'); - -function getObjectProperties( - name: string, - objectParam: ASTNode, - paramName: string, - types: TypeMap, -): $ReadOnlyArray { - return objectParam.properties.map(objectTypeProperty => { - let optional = objectTypeProperty.optional; - let value = objectTypeProperty.value; - if (value.type === 'NullableTypeAnnotation') { - if ( - objectTypeProperty.value.typeAnnotation.type !== 'StringTypeAnnotation' - ) { - optional = true; - } - value = objectTypeProperty.value.typeAnnotation; - } - return { - optional, - name: objectTypeProperty.key.name, - typeAnnotation: getElementTypeForArrayOrObject( - name, - value, - paramName, - types, - ), - }; - }); -} - -function getElementTypeForArrayOrObject( - name: string, - arrayParam: ASTNode, - paramName: string, - types: TypeMap, -): - | FunctionTypeAnnotationParamTypeAnnotation - | TypeAliasTypeAnnotation - | typeof undefined { - const typeAnnotation = getValueFromTypes(arrayParam, types); - const type = - typeAnnotation.type === 'GenericTypeAnnotation' - ? typeAnnotation.id.name - : typeAnnotation.type; - - switch (type) { - case 'RootTag': - return { - type: 'ReservedFunctionValueTypeAnnotation', - name: 'RootTag', - }; - case 'Array': - case '$ReadOnlyArray': - if ( - typeAnnotation.typeParameters && - typeAnnotation.typeParameters.params[0] - ) { - return { - type: 'ArrayTypeAnnotation', - elementType: getElementTypeForArrayOrObject( - name, - typeAnnotation.typeParameters.params[0], - 'returning value', - types, - ), - }; - } else { - throw new Error( - `Unsupported type for "${name}", param: "${paramName}": expected to find annotation for type of nested array contents`, - ); - } - case 'ObjectTypeAnnotation': - if (arrayParam.id) { - return { - type: 'TypeAliasTypeAnnotation', - name: arrayParam.id.name, - }; - } - return { - type: 'ObjectTypeAnnotation', - properties: getObjectProperties(name, typeAnnotation, paramName, types), - }; - case '$ReadOnly': - if ( - typeAnnotation.typeParameters.params && - typeAnnotation.typeParameters.params[0] - ) { - return { - type: 'ObjectTypeAnnotation', - properties: getObjectProperties( - name, - typeAnnotation.typeParameters.params[0], - paramName, - types, - ), - }; - } else { - throw new Error( - `Unsupported param for method "${name}", param "${paramName}". No type specified for $ReadOnly`, - ); - } - case 'AnyTypeAnnotation': - return { - type, - }; - case 'NumberTypeAnnotation': - case 'BooleanTypeAnnotation': - return { - type, - }; - case 'StringTypeAnnotation': - case 'Stringish': - return { - type: 'StringTypeAnnotation', - }; - case 'Int32': - return { - type: 'Int32TypeAnnotation', - }; - case 'Float': - return { - type: 'FloatTypeAnnotation', - }; - case 'TupleTypeAnnotation': - case 'UnionTypeAnnotation': - return undefined; - default: - // TODO T67565166: Generic objects are not type safe and should be disallowed in the schema. - return { - type: 'GenericObjectTypeAnnotation', - }; - } -} - -module.exports = { - getElementTypeForArrayOrObject, - getObjectProperties, -}; diff --git a/packages/react-native-codegen/src/parsers/flow/modules/schema.js b/packages/react-native-codegen/src/parsers/flow/modules/schema.js index c1e4c80cfd5fed..f54053a0c86d84 100644 --- a/packages/react-native-codegen/src/parsers/flow/modules/schema.js +++ b/packages/react-native-codegen/src/parsers/flow/modules/schema.js @@ -10,19 +10,10 @@ 'use strict'; -import type { - SchemaType, - ObjectTypeAliasTypeShape, - NativeModuleMethodTypeShape, -} from '../../../CodegenSchema.js'; +import type {SchemaType, NativeModuleSchema} from '../../../CodegenSchema.js'; -export type NativeModuleSchemaBuilderConfig = $ReadOnly<{| - aliases: $ReadOnly<{[aliasName: string]: ObjectTypeAliasTypeShape, ...}>, - properties: $ReadOnlyArray, -|}>; - -function buildModuleSchema( - {aliases, properties}: NativeModuleSchemaBuilderConfig, +function wrapModuleSchema( + {aliases, properties}: NativeModuleSchema, moduleName: string, ): SchemaType { return { @@ -40,5 +31,5 @@ function buildModuleSchema( } module.exports = { - buildModuleSchema, + wrapModuleSchema, }; diff --git a/packages/react-native-codegen/src/parsers/flow/utils.js b/packages/react-native-codegen/src/parsers/flow/utils.js index 663b6b90bb941a..15b13c5949975a 100644 --- a/packages/react-native-codegen/src/parsers/flow/utils.js +++ b/packages/react-native-codegen/src/parsers/flow/utils.js @@ -10,13 +10,82 @@ 'use strict'; -// $FlowFixMe there's no flowtype for ASTs -export type TypeMap = $ReadOnly<{|[name: string]: Object|}>; +/** + * This FlowFixMe is supposed to refer to an InterfaceDeclaration or TypeAlias + * declaration type. Unfortunately, we don't have those types, because flow-parser + * generates them, and flow-parser is not type-safe. In the future, we should find + * a way to get these types from our flow parser library. + * + * TODO(T71778680): Flow type AST Nodes + */ +export type TypeDeclarationMap = {|[declarationName: string]: $FlowFixMe|}; // $FlowFixMe there's no flowtype for ASTs export type ASTNode = Object; -function getValueFromTypes(value: ASTNode, types: TypeMap): ASTNode { +const invariant = require('invariant'); + +type TypeAliasResolutionStatus = + | $ReadOnly<{| + successful: true, + aliasName: string, + |}> + | $ReadOnly<{| + successful: false, + |}>; + +function resolveTypeAnnotation( + // TODO(T71778680): This is an Flow TypeAnnotation. Flow-type this + typeAnnotation: $FlowFixMe, + types: TypeDeclarationMap, +): { + nullable: boolean, + typeAnnotation: $FlowFixMe, + typeAliasResolutionStatus: TypeAliasResolutionStatus, +} { + invariant( + typeAnnotation != null, + 'resolveTypeAnnotation(): typeAnnotation cannot be null', + ); + + let node = typeAnnotation; + let nullable = false; + let typeAliasResolutionStatus: TypeAliasResolutionStatus = { + successful: false, + }; + + for (;;) { + if (node.type === 'NullableTypeAnnotation') { + nullable = true; + node = node.typeAnnotation; + } else if (node.type === 'GenericTypeAnnotation') { + typeAliasResolutionStatus = { + successful: true, + aliasName: node.id.name, + }; + const resolvedTypeAnnotation = types[node.id.name]; + if (resolvedTypeAnnotation == null) { + break; + } + + invariant( + resolvedTypeAnnotation.type === 'TypeAlias', + `GenericTypeAnnotation '${node.id.name}' must resolve to a TypeAlias. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`, + ); + node = resolvedTypeAnnotation.right; + } else { + break; + } + } + + return { + nullable: nullable, + typeAnnotation: node, + typeAliasResolutionStatus, + }; +} + +function getValueFromTypes(value: ASTNode, types: TypeDeclarationMap): ASTNode { if (value.type === 'GenericTypeAnnotation' && types[value.id.name]) { return getValueFromTypes(types[value.id.name].right, types); } @@ -25,4 +94,5 @@ function getValueFromTypes(value: ASTNode, types: TypeMap): ASTNode { module.exports = { getValueFromTypes, + resolveTypeAnnotation, }; diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 0ea79d0fad55c3..1e99aa991cc571 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -524,7 +524,7 @@ SPEC CHECKSUMS: React-RCTText: 51a41bf9d18a91b2437b833ed4246754baf830d0 React-RCTVibration: a1cce36dd452eb88296d99d80d66f2c5bd50aad4 React-runtimeexecutor: 53867815d0a01e53a2c901cb7f01076216c5c799 - ReactCommon: dc40b68c9a72e99e07f831b0e87a859f4660208b + ReactCommon: d101410fc55088c91dc24595715c7b26ec760adf Yoga: 69ef0b2bba5387523f793957a9f80dbd61e89631 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/packages/rn-tester/android/app/build.gradle b/packages/rn-tester/android/app/build.gradle index 2e70e9014a3d9b..186a325259e28d 100644 --- a/packages/rn-tester/android/app/build.gradle +++ b/packages/rn-tester/android/app/build.gradle @@ -184,31 +184,12 @@ android { proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro" } } -} - -if (enableCodegen) { - def reactAndroidProjectDir = project(':ReactAndroid').projectDir; - android { - defaultConfig { - externalNativeBuild { - ndkBuild { - abiFilters "armeabi-v7a", "x86", "x86_64", "arm64-v8a" - arguments "APP_PLATFORM=android-16", - "APP_STL=c++_shared", - "NDK_TOOLCHAIN_VERSION=clang", - // The following paths assume building React Native from source. - "GENERATED_SRC_DIR=$buildDir/generated/source", - "REACT_ANDROID_DIR=$reactAndroidProjectDir" - cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1" - cppFlags "-std=c++1y" - targets "rntester_appmodules" - } - } - } - externalNativeBuild { - ndkBuild { - path "$projectDir/src/main/jni/Android.mk" - } + sourceSets.main { + java { + // SampleTurboModule. + srcDirs += [ + "$rootDir/ReactCommon/react/nativemodule/samples/platform/android", + ] } } } @@ -258,3 +239,59 @@ react { reactNativeRootDir = file("$rootDir") useJavaGenerator = System.getenv("USE_CODEGEN_JAVAPOET") ?: false } + +if (enableCodegen) { + // TODO: Move all this logic to CodegenPlugin.java. + def reactAndroidProjectDir = project(':ReactAndroid').projectDir; + def reactAndroidBuildDir = project(':ReactAndroid').buildDir; + + android { + defaultConfig { + externalNativeBuild { + ndkBuild { + abiFilters "armeabi-v7a", "x86", "x86_64", "arm64-v8a" + arguments "APP_PLATFORM=android-16", + "APP_STL=c++_shared", + "NDK_TOOLCHAIN_VERSION=clang", + // The following paths assume building React Native from source. + "GENERATED_SRC_DIR=$buildDir/generated/source", + "PROJECT_BUILD_DIR=$buildDir", + "REACT_ANDROID_DIR=$reactAndroidProjectDir" + cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1" + cppFlags "-std=c++1y" + targets "rntester_appmodules" + } + } + } + externalNativeBuild { + ndkBuild { + path "$projectDir/src/main/jni/Android.mk" + } + } + } + + def packageReactNdkLibs = tasks.register("packageReactNdkLibs", Copy) { + // TODO: handle extracting .so from prebuilt :ReactAndroid. + dependsOn(":ReactAndroid:packageReactNdkLibs") + from("$reactAndroidBuildDir/react-ndk/exported") + into("$buildDir/react-ndk/exported") + } + + def cleanProjectNdkBuild = tasks.register("cleanProjectNdkBuild", Exec) { + ignoreExitValue(true) + tasks.forEach { + t -> + if (t.name.startsWith("externalNativeBuildClean")) { + dependsOn(t); + } + } + // This .cxx folder may cause stale ndkBuild configuration. + // See https://stackoverflow.com/a/58288851. + commandLine("rm", "-rf", "$projectDir/.cxx") + } + + afterEvaluate { + preBuild.dependsOn(packageReactNdkLibs) + clean.dependsOn(cleanProjectNdkBuild) + } +} diff --git a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java index c191ecaec94d9d..710d8e0c7254e5 100644 --- a/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java +++ b/packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java @@ -10,16 +10,19 @@ import android.app.Application; import android.content.Context; import androidx.annotation.Nullable; +import com.facebook.fbreact.specs.SampleTurboModule; import com.facebook.react.ReactApplication; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; +import com.facebook.react.TurboReactPackage; import com.facebook.react.bridge.JSIModule; import com.facebook.react.bridge.JSIModulePackage; import com.facebook.react.bridge.JSIModuleProvider; import com.facebook.react.bridge.JSIModuleSpec; import com.facebook.react.bridge.JSIModuleType; import com.facebook.react.bridge.JavaScriptContextHolder; +import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.UIManager; import com.facebook.react.config.ReactFeatureFlags; @@ -27,6 +30,8 @@ import com.facebook.react.fabric.CoreComponentsRegistry; import com.facebook.react.fabric.FabricJSIModuleProvider; import com.facebook.react.fabric.ReactNativeConfig; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.shell.MainReactPackage; import com.facebook.react.turbomodule.core.TurboModuleManager; import com.facebook.react.views.text.ReactFontManager; @@ -34,7 +39,9 @@ import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class RNTesterApplication extends Application implements ReactApplication { @@ -57,7 +64,47 @@ public boolean getUseDeveloperSupport() { @Override public List getPackages() { - return Arrays.asList(new MainReactPackage()); + return Arrays.asList( + new MainReactPackage(), + new TurboReactPackage() { + public NativeModule getModule( + final String name, final ReactApplicationContext reactContext) { + if (!ReactFeatureFlags.useTurboModules) { + return null; + } + + if (SampleTurboModule.NAME.equals(name)) { + return new SampleTurboModule(reactContext); + } + + return null; + } + + // Note: Specialized annotation processor for @ReactModule isn't configured in OSS + // yet. For now, hardcode this information, though it's not necessary for most + // modules. + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return new ReactModuleInfoProvider() { + public Map getReactModuleInfos() { + final Map moduleInfos = new HashMap<>(); + if (ReactFeatureFlags.useTurboModules) { + moduleInfos.put( + SampleTurboModule.NAME, + new ReactModuleInfo( + SampleTurboModule.NAME, + "SampleTurboModule", + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + true // isTurboModule + )); + } + return moduleInfos; + } + }; + } + }); } @Nullable @@ -72,7 +119,7 @@ protected JSIModulePackage getJSIModulePackage() { public List getJSIModules( final ReactApplicationContext reactApplicationContext, final JavaScriptContextHolder jsContext) { - List specs = new ArrayList<>(); + final List specs = new ArrayList<>(); // Install the new native module system. if (ReactFeatureFlags.useTurboModules) { @@ -88,8 +135,9 @@ public JSIModuleProvider getJSIModuleProvider() { return new JSIModuleProvider() { @Override public JSIModule get() { - ReactInstanceManager reactInstanceManager = getReactInstanceManager(); - List packages = reactInstanceManager.getPackages(); + final ReactInstanceManager reactInstanceManager = + getReactInstanceManager(); + final List packages = reactInstanceManager.getPackages(); return new TurboModuleManager( jsContext, @@ -118,7 +166,7 @@ public JSIModuleType getJSIModuleType() { @Override public JSIModuleProvider getJSIModuleProvider() { - ComponentFactory ComponentFactory = new ComponentFactory(); + final ComponentFactory ComponentFactory = new ComponentFactory(); CoreComponentsRegistry.register(ComponentFactory); return new FabricJSIModuleProvider( reactApplicationContext, @@ -126,22 +174,22 @@ public JSIModuleProvider getJSIModuleProvider() { // TODO: T71362667 add ReactNativeConfig's support in RNTester new ReactNativeConfig() { @Override - public boolean getBool(String s) { + public boolean getBool(final String s) { return false; } @Override - public int getInt64(String s) { + public int getInt64(final String s) { return 0; } @Override - public String getString(String s) { + public String getString(final String s) { return ""; } @Override - public double getDouble(String s) { + public double getDouble(final String s) { return 0; } }); @@ -178,24 +226,24 @@ public ReactNativeHost getReactNativeHost() { * @param reactInstanceManager */ private static void initializeFlipper( - Context context, ReactInstanceManager reactInstanceManager) { + final Context context, final ReactInstanceManager reactInstanceManager) { if (BuildConfig.DEBUG) { try { /* We use reflection here to pick up the class that initializes Flipper, since Flipper library is not available in release mode */ - Class aClass = Class.forName("com.facebook.react.uiapp.ReactNativeFlipper"); + final Class aClass = Class.forName("com.facebook.react.uiapp.ReactNativeFlipper"); aClass .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) .invoke(null, context, reactInstanceManager); - } catch (ClassNotFoundException e) { + } catch (final ClassNotFoundException e) { e.printStackTrace(); - } catch (NoSuchMethodException e) { + } catch (final NoSuchMethodException e) { e.printStackTrace(); - } catch (IllegalAccessException e) { + } catch (final IllegalAccessException e) { e.printStackTrace(); - } catch (InvocationTargetException e) { + } catch (final InvocationTargetException e) { e.printStackTrace(); } } diff --git a/packages/rn-tester/android/app/src/main/jni/Android.mk b/packages/rn-tester/android/app/src/main/jni/Android.mk index 2029b87348dd24..6e003cdb953721 100644 --- a/packages/rn-tester/android/app/src/main/jni/Android.mk +++ b/packages/rn-tester/android/app/src/main/jni/Android.mk @@ -7,6 +7,9 @@ THIS_DIR := $(call my-dir) include $(REACT_ANDROID_DIR)/Android-prebuilt.mk +# SampleNativeModule +include $(REACT_COMMON_DIR)/react/nativemodule/samples/platform/android/Android.mk + LOCAL_PATH := $(THIS_DIR) include $(CLEAR_VARS) @@ -16,6 +19,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp) LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni LOCAL_SHARED_LIBRARIES := libfbjni libreact_nativemodule_core libturbomodulejsijni libreact_codegen_reactandroidspec +LOCAL_STATIC_LIBRARIES := libsampleturbomodule LOCAL_CFLAGS := \ -DLOG_TAG=\"ReactNative\" LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall diff --git a/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.cpp b/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.cpp index 493d8267e3cf03..06c20c981cd016 100644 --- a/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.cpp +++ b/packages/rn-tester/android/app/src/main/jni/RNTesterAppModuleProvider.cpp @@ -9,6 +9,7 @@ #include #include +#include namespace facebook { namespace react { @@ -19,6 +20,11 @@ std::shared_ptr RNTesterAppModuleProvider(const std::string moduleN return module; } + module = SampleTurboModuleSpec_ModuleProvider(moduleName, params); + if (module != nullptr) { + return module; + } + // TODO: fix up the ReactAndroidSpec_ModuleProvider() to avoid the Android prefix. if (moduleName == "DatePicker") { return std::make_shared(params); diff --git a/packages/rn-tester/js/utils/RNTesterList.android.js b/packages/rn-tester/js/utils/RNTesterList.android.js index bb509d0f3b0103..5971a0facf278c 100644 --- a/packages/rn-tester/js/utils/RNTesterList.android.js +++ b/packages/rn-tester/js/utils/RNTesterList.android.js @@ -264,6 +264,14 @@ const APIExamples: Array = [ }, ]; +if (global.__turboModuleProxy) { + APIExamples.push({ + key: 'TurboModuleExample', + category: 'Basic', + module: require('../examples/TurboModule/TurboModuleExample'), + }); +} + const Modules: any = {}; APIExamples.concat(ComponentExamples).forEach(Example => { diff --git a/repo-config/package.json b/repo-config/package.json index ea2ac36be0f543..3e7a2c74386a8e 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -33,7 +33,7 @@ "eslint-plugin-react-hooks": "^4.0.7", "eslint-plugin-react-native": "3.8.1", "eslint-plugin-relay": "1.7.1", - "flow-bin": "^0.134.0", + "flow-bin": "^0.135.0", "jest": "^26.0.1", "jest-junit": "^10.0.0", "jscodeshift": "^0.9.0", diff --git a/scripts/generate-native-modules-specs.sh b/scripts/generate-native-modules-specs.sh index c65f85aa8190c8..e72916bc138da1 100755 --- a/scripts/generate-native-modules-specs.sh +++ b/scripts/generate-native-modules-specs.sh @@ -42,13 +42,14 @@ step_build_codegen () { step_gen_schema () { describe "Generating schema from flow types" SRCS_DIR=$(cd "$RN_DIR/Libraries" && pwd) - grep --exclude NativeSampleTurboModule.js --exclude NativeUIManager.js --include=Native\*.js -rnwl "$SRCS_DIR" -e 'export interface Spec extends TurboModule' -e "export default \(TurboModuleRegistry.get(Enforcing)?\('.*\): Spec\);/" \ - | xargs "$YARN_BINARY" node "$CODEGEN_DIR/lib/cli/combine/combine-js-to-schema-cli.js" "$SCHEMA_FILE" + "$YARN_BINARY" node "$CODEGEN_DIR/lib/cli/combine/combine-js-to-schema-cli.js" "$SCHEMA_FILE" "$SRCS_DIR" } step_gen_specs () { describe "Generating native code from schema (iOS)" - "$YARN_BINARY" --silent node scripts/generate-native-modules-specs-cli.js ios "$SCHEMA_FILE" "$OUTPUT_DIR" + pushd "$RN_DIR" >/dev/null || exit + "$YARN_BINARY" --silent node scripts/generate-native-modules-specs-cli.js ios "$SCHEMA_FILE" "$OUTPUT_DIR" + popd >/dev/null || exit } step_build_codegen diff --git a/scripts/ios-configure-glog.sh b/scripts/ios-configure-glog.sh index f527702bbd03c9..9642c5322d48b5 100755 --- a/scripts/ios-configure-glog.sh +++ b/scripts/ios-configure-glog.sh @@ -30,6 +30,7 @@ fi ./configure --host arm-apple-darwin +cat << EOF >> src/config.h /* Add in so we have Apple Target Conditionals */ #ifdef __APPLE__ #include diff --git a/template/_flowconfig b/template/_flowconfig index b1e00ccf3aa23f..644e2a9d6cce2a 100644 --- a/template/_flowconfig +++ b/template/_flowconfig @@ -63,4 +63,4 @@ untyped-import untyped-type-import [version] -^0.134.0 +^0.135.0 diff --git a/template/android/build.gradle b/template/android/build.gradle index 2bafa1f491c53c..2131e76d46d75d 100644 --- a/template/android/build.gradle +++ b/template/android/build.gradle @@ -13,7 +13,7 @@ buildscript { jcenter() } dependencies { - classpath("com.android.tools.build:gradle:3.6.4") + classpath("com.android.tools.build:gradle:4.0.1") // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/tools/build_defs/oss/rn_defs.bzl b/tools/build_defs/oss/rn_defs.bzl index 5553eb884af16d..7112b3a400e8ef 100644 --- a/tools/build_defs/oss/rn_defs.bzl +++ b/tools/build_defs/oss/rn_defs.bzl @@ -189,18 +189,19 @@ def rn_robolectric_test(name, srcs, vm_args = None, *args, **kwargs): kwargs["deps"] = kwargs.pop("deps", []) + [ react_native_android_toplevel_dep("third-party/java/mockito2:mockito2"), react_native_xplat_dep("libraries/fbcore/src/test/java/com/facebook/powermock:powermock2"), - react_native_dep("third-party/java/robolectric/4.3.1:robolectric"), + react_native_dep("third-party/java/robolectric/4.4:robolectric"), ] extra_vm_args = [ "-XX:+UseConcMarkSweepGC", # required by -XX:+CMSClassUnloadingEnabled "-XX:+CMSClassUnloadingEnabled", "-XX:ReservedCodeCacheSize=150M", - "-Drobolectric.dependency.dir=buck-out/gen/ReactAndroid/src/main/third-party/java/robolectric/4.3.1", - "-Dlibraries=buck-out/gen/ReactAndroid/src/main/third-party/java/robolectric/4.3.1/*.jar", + "-Drobolectric.dependency.dir=buck-out/gen/ReactAndroid/src/main/third-party/java/robolectric/4.4", + "-Dlibraries=buck-out/gen/ReactAndroid/src/main/third-party/java/robolectric/4.4/*.jar", "-Drobolectric.logging.enabled=true", "-XX:MaxPermSize=620m", "-Drobolectric.offline=true", + "-Drobolectric.looperMode=LEGACY", ] if native.read_config("user", "use_dev_shm"): extra_vm_args.append("-Djava.io.tmpdir=/dev/shm") diff --git a/yarn.lock b/yarn.lock index a043e328e032cd..08bfcfa0829276 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3102,10 +3102,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -flow-bin@^0.134.0: - version "0.134.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.134.0.tgz#e98e5724f6ed5a1265cf904bbb5e4c096ea3a026" - integrity sha512-j5aCugO3jmwDsUKc+7KReArgnL6aVjHLo6DlozKhxKYN+TaP8BY+mintPSISjSQtKZFJyvoNAc1oXA79X5WjIA== +flow-bin@^0.135.0: + version "0.135.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.135.0.tgz#70bcd7bae0231777dd05cc8707ff34b37824bbad" + integrity sha512-E0JIKWopjULE/fl1X+j7rh0zgcgD5nubLs3HWYeYPo+nWFy8dALvrQbFcCFoPePrkhY/fffhN28t8P1zBxB2Yg== flow-parser@0.*, flow-parser@^0.121.0: version "0.121.0"