From 96bbcabc600d63209a97e6dcd84efda9f7ac75fc Mon Sep 17 00:00:00 2001 From: Alon Date: Sat, 16 Apr 2022 15:13:00 +0300 Subject: [PATCH 1/2] - implement jsi complex types --- .../TurboStarterModule.kt | 45 ++++++++++++++++ example/src/App.tsx | 23 +++++++- ios/TurboStarter.mm | 53 ++++++++++++++++++- src/NativeTurboStarter.ts | 16 +++++- src/index.tsx | 18 ++++++- 5 files changed, 150 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/reactnativeturbostarter/TurboStarterModule.kt b/android/src/main/java/com/reactnativeturbostarter/TurboStarterModule.kt index 3ab2eaf..dfa1c46 100644 --- a/android/src/main/java/com/reactnativeturbostarter/TurboStarterModule.kt +++ b/android/src/main/java/com/reactnativeturbostarter/TurboStarterModule.kt @@ -8,6 +8,51 @@ class TurboStarterModule(reactContext: ReactApplicationContext?) : return String.format("Hello, %s!", name) } + override fun getTurboArray(values: ReadableArray): WritableArray { + val array = values.toArrayList() + array.reverse() + val reversed = WritableNativeArray() + + for (item in array) { + if (item !is String) { + continue + } + + reversed.pushString(item) + } + return reversed + } + + override fun getTurboObject(options: ReadableMap): WritableMap { + val obj = WritableNativeMap() + obj.putString("helloString", "Hello, World!") + obj.putInt("magicNumber", 42) + obj.putString("response", "res") + return obj + } + + override fun getTurboObjectGeneric(options: ReadableMap): WritableMap { + val obj = WritableNativeMap() + val input = options.getInt("magicNumber") + + obj.putInt("magicNumber", input * 6) + return obj + } + + override fun getTurboPromise(magicNumber: Double, promise: Promise) { + when (magicNumber) { + 42.0 -> { + promise.resolve(true) + } + 7.0 -> { + promise.reject("1", "You stepped on a mine") + } + else -> { + promise.resolve(false) + } + } + } + override fun getName(): String { return NAME } diff --git a/example/src/App.tsx b/example/src/App.tsx index e420779..778c112 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -27,7 +27,10 @@ import { ReloadInstructions, } from 'react-native/Libraries/NewAppScreen'; import { - getGreeting + getGreeting, + getTurboObject, + getTurboObjectGeneric, + getTurboPromise, } from 'react-native-turbo-starter'; const Section: React.FC<{ @@ -66,6 +69,24 @@ const App = () => { React.useEffect(() => { setResult(getGreeting('Yotam')); + + const obj = getTurboObject({ + title: 'Hello, world!', + }); + console.log('object', obj, obj?.response); + + const gobj = getTurboObjectGeneric({ + magicNumber: 7, + }); + console.log('gobject', gobj); + + getTurboPromise(42).then((res) => console.log('t1', res)); + + getTurboPromise(7).catch((error: Error) => + console.log('t2', error.message) + ); + + getTurboPromise(1).then((res) => console.log('t3', res)); }, []); const backgroundStyle = { diff --git a/ios/TurboStarter.mm b/ios/TurboStarter.mm index a80818e..7ac30c0 100644 --- a/ios/TurboStarter.mm +++ b/ios/TurboStarter.mm @@ -9,11 +9,60 @@ @implementation TurboStarter - (std::shared_ptr)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params { - return std::make_shared(params); + return std::make_shared(params); } - (NSString *)getGreeting:(NSString *)name { - return [NSString stringWithFormat: @"Hello, %@!", name]; + return [NSString stringWithFormat: @"Hello, %@!", name]; +} + +- (NSArray *)getTurboArray:(NSArray *)values { + NSArray* reversedArray = [[values reverseObjectEnumerator] allObjects]; + return reversedArray; +} + +- (NSDictionary *)getTurboObject:(JS::NativeTurboStarter::SpecGetTurboObjectOptions &)options { + + NSLog(@"getTurboObject options (title): %@", options.title()); + + id keys[] = { @"helloString", @"magicNumber", @"response" }; + id objects[] = { @"Hello, World!", @42, @"res" }; + NSUInteger count = sizeof(objects) / sizeof(id); + + NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects + forKeys:keys + count:count]; + + return dictionary; +} +- (NSDictionary *)getTurboObjectGeneric:(NSDictionary *)options { + id num = @([[options valueForKey:@"magicNumber"] integerValue] * 6); + + id keys[] = { @"magicNumber" }; + id objects[] = { num }; + NSUInteger count = sizeof(objects) / sizeof(id); + + NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects + forKeys:keys + count:count]; + + return dictionary; +} + +- (void)getTurboPromise:(double)magicNumber + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject +{ + if (magicNumber == 42) { + resolve(@YES); + return; + } else if (magicNumber == 7) { + NSError *error = [NSError errorWithDomain:@"com.yourcompany.turbostarter" code:3456 userInfo:@{NSLocalizedDescriptionKey:@"Invalid user name."}]; + reject(@"1", @"You stepped on a mine", error); + return; + } + + resolve(@NO); } + (NSString *)moduleName { diff --git a/src/NativeTurboStarter.ts b/src/NativeTurboStarter.ts index fc1ea04..e13bcd9 100644 --- a/src/NativeTurboStarter.ts +++ b/src/NativeTurboStarter.ts @@ -4,8 +4,22 @@ import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { getConstants: () => {}; + + // + // Regular JSI + // getGreeting(name: string): string; + + // + // Complex types JSI + // + getTurboArray(values: Array): Array; + // On iOS, codegen generates a typed NSObject, but on Android it's just a generic dictionary. + // So for now, it can't be completely type-safe + getTurboObject(options: { title: string }): { response: string }; + getTurboObjectGeneric(options: Object): Object; + getTurboPromise(magicNumber: number): Promise; } // We know the module is going to be load so we export with the "!" so it doesn't add undefined to every function return value -export default TurboModuleRegistry.get('TurboStarter')!; \ No newline at end of file +export default TurboModuleRegistry.get('TurboStarter')!; diff --git a/src/index.tsx b/src/index.tsx index 740d080..0763baf 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,4 +2,20 @@ import NativeTurboStarter from './NativeTurboStarter'; export function getGreeting(name: string) { return NativeTurboStarter.getGreeting(name); -} \ No newline at end of file +} + +export function getTurboArray(values: string[]) { + return NativeTurboStarter.getTurboArray(values); +} + +export function getTurboObject(options: { title: string }) { + return NativeTurboStarter.getTurboObject(options); +} + +export function getTurboObjectGeneric(options: Object) { + return NativeTurboStarter.getTurboObjectGeneric(options); +} + +export async function getTurboPromise(magicNumber: number) { + return NativeTurboStarter.getTurboPromise(magicNumber); +} From fd112227ddc126850a2b28119bfa4256f566d7c0 Mon Sep 17 00:00:00 2001 From: Alon Date: Sat, 16 Apr 2022 21:18:45 +0300 Subject: [PATCH 2/2] addressed comment --- ios/TurboStarter.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/TurboStarter.mm b/ios/TurboStarter.mm index 7ac30c0..1462e63 100644 --- a/ios/TurboStarter.mm +++ b/ios/TurboStarter.mm @@ -57,7 +57,7 @@ - (void)getTurboPromise:(double)magicNumber resolve(@YES); return; } else if (magicNumber == 7) { - NSError *error = [NSError errorWithDomain:@"com.yourcompany.turbostarter" code:3456 userInfo:@{NSLocalizedDescriptionKey:@"Invalid user name."}]; + NSError *error = [NSError errorWithDomain:@"com.example.reactnativeturbostarter" code:3456 userInfo:@{NSLocalizedDescriptionKey:@"Invalid user name."}]; reject(@"1", @"You stepped on a mine", error); return; }