1// Copyright 2022-present 650 Industries. All rights reserved. 2 3#import <ExpoModulesCore/EXJSIConversions.h> 4#import <ExpoModulesCore/EXJavaScriptObject.h> 5#import <ExpoModulesCore/EXJavaScriptRuntime.h> 6#import <ExpoModulesCore/ExpoModulesProxySpec.h> 7 8@implementation EXJavaScriptObject { 9 /** 10 Pointer to the `EXJavaScriptRuntime` wrapper. 11 12 \note It must be weak because only then the original runtime can be safely deallocated 13 when the JS engine wants to without unsetting it on each created object. 14 */ 15 __weak EXJavaScriptRuntime *_runtime; 16 17 /** 18 Shared pointer to the original JSI object that is being wrapped by `EXJavaScriptObject` class. 19 */ 20 std::shared_ptr<jsi::Object> _jsObjectPtr; 21} 22 23- (nonnull instancetype)initWith:(std::shared_ptr<jsi::Object>)jsObjectPtr 24 runtime:(nonnull EXJavaScriptRuntime *)runtime 25{ 26 if (self = [super init]) { 27 _runtime = runtime; 28 _jsObjectPtr = jsObjectPtr; 29 } 30 return self; 31} 32 33- (nonnull jsi::Object *)get 34{ 35 return _jsObjectPtr.get(); 36} 37 38#pragma mark - Subscripting 39 40- (nullable id)objectForKeyedSubscript:(nonnull NSString *)key 41{ 42 auto runtime = [_runtime get]; 43 auto callInvoker = [_runtime callInvoker]; 44 45 if (runtime && callInvoker) { 46 auto value = _jsObjectPtr->getProperty(*runtime, [key UTF8String]); 47 return expo::convertJSIValueToObjCObject(*runtime, value, callInvoker); 48 } 49 return nil; 50} 51 52- (void)setObject:(nullable id)obj forKeyedSubscript:(nonnull NSString *)key 53{ 54 auto runtime = [_runtime get]; 55 56 if (!runtime) { 57 NSLog(@"Cannot set '%@' property when the EXJavaScript runtime is no longer available.", key); 58 return; 59 } 60 if ([obj isKindOfClass:[EXJavaScriptObject class]]) { 61 _jsObjectPtr->setProperty(*runtime, [key UTF8String], *[obj get]); 62 } else { 63 _jsObjectPtr->setProperty(*runtime, [key UTF8String], expo::convertObjCObjectToJSIValue(*runtime, obj)); 64 } 65} 66 67#pragma mark - Functions 68 69- (void)setAsyncFunction:(nonnull NSString *)name 70 argsCount:(NSInteger)argsCount 71 block:(nonnull JSAsyncFunctionBlock)block 72{ 73 if (!_runtime) { 74 NSLog(@"Cannot set '%@' async function when the EXJavaScript runtime is no longer available.", name); 75 return; 76 } 77 jsi::Function function = [_runtime createAsyncFunction:name argsCount:argsCount block:block]; 78 _jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], function); 79} 80 81- (void)setSyncFunction:(nonnull NSString *)name 82 argsCount:(NSInteger)argsCount 83 block:(nonnull JSSyncFunctionBlock)block 84{ 85 if (!_runtime) { 86 NSLog(@"Cannot set '%@' sync function when the EXJavaScript runtime is no longer available.", name); 87 return; 88 } 89 jsi::Function function = [_runtime createSyncFunction:name argsCount:argsCount block:block]; 90 _jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], function); 91} 92 93@end 94