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