1370fa39dSKudo Chien// Copyright 2022-present 650 Industries. All rights reserved. 2370fa39dSKudo Chien 3370fa39dSKudo Chien#import <ExpoModulesCore/EXJSIConversions.h> 478516026STomasz Sapeta#import <ExpoModulesCore/EXJavaScriptValue.h> 5370fa39dSKudo Chien#import <ExpoModulesCore/EXJavaScriptObject.h> 6370fa39dSKudo Chien#import <ExpoModulesCore/EXJavaScriptRuntime.h> 778516026STomasz Sapeta#import <ExpoModulesCore/EXJavaScriptWeakObject.h> 878516026STomasz Sapeta#import <ExpoModulesCore/EXJSIUtils.h> 9*e1f25825SŁukasz Kosmaty#import <ExpoModulesCore/JSIUtils.h> 10370fa39dSKudo Chien 11370fa39dSKudo Chien@implementation EXJavaScriptObject { 12370fa39dSKudo Chien /** 13370fa39dSKudo Chien Pointer to the `EXJavaScriptRuntime` wrapper. 14370fa39dSKudo Chien 15370fa39dSKudo Chien \note It must be weak because only then the original runtime can be safely deallocated 16370fa39dSKudo Chien when the JS engine wants to without unsetting it on each created object. 17370fa39dSKudo Chien */ 18370fa39dSKudo Chien __weak EXJavaScriptRuntime *_runtime; 19370fa39dSKudo Chien 20370fa39dSKudo Chien /** 21370fa39dSKudo Chien Shared pointer to the original JSI object that is being wrapped by `EXJavaScriptObject` class. 22370fa39dSKudo Chien */ 23370fa39dSKudo Chien std::shared_ptr<jsi::Object> _jsObjectPtr; 24370fa39dSKudo Chien} 25370fa39dSKudo Chien 26370fa39dSKudo Chien- (nonnull instancetype)initWith:(std::shared_ptr<jsi::Object>)jsObjectPtr 27370fa39dSKudo Chien runtime:(nonnull EXJavaScriptRuntime *)runtime 28370fa39dSKudo Chien{ 29370fa39dSKudo Chien if (self = [super init]) { 30370fa39dSKudo Chien _runtime = runtime; 31370fa39dSKudo Chien _jsObjectPtr = jsObjectPtr; 32370fa39dSKudo Chien } 33370fa39dSKudo Chien return self; 34370fa39dSKudo Chien} 35370fa39dSKudo Chien 36370fa39dSKudo Chien- (nonnull jsi::Object *)get 37370fa39dSKudo Chien{ 38370fa39dSKudo Chien return _jsObjectPtr.get(); 39370fa39dSKudo Chien} 40370fa39dSKudo Chien 41fa88aeb8STomasz Sapeta- (std::shared_ptr<jsi::Object>)getShared 42fa88aeb8STomasz Sapeta{ 43fa88aeb8STomasz Sapeta return _jsObjectPtr; 44fa88aeb8STomasz Sapeta} 45fa88aeb8STomasz Sapeta 469bc9ec42STomasz Sapeta#pragma mark - Accessing object properties 47370fa39dSKudo Chien 489bc9ec42STomasz Sapeta- (BOOL)hasProperty:(nonnull NSString *)name 49370fa39dSKudo Chien{ 509bc9ec42STomasz Sapeta return _jsObjectPtr->hasProperty(*[_runtime get], [name UTF8String]); 51370fa39dSKudo Chien} 52370fa39dSKudo Chien 539bc9ec42STomasz Sapeta- (nonnull EXJavaScriptValue *)getProperty:(nonnull NSString *)name 54370fa39dSKudo Chien{ 559bc9ec42STomasz Sapeta std::shared_ptr<jsi::Value> value = std::make_shared<jsi::Value>(_jsObjectPtr->getProperty(*[_runtime get], [name UTF8String])); 569bc9ec42STomasz Sapeta return [[EXJavaScriptValue alloc] initWithRuntime:_runtime value:value]; 579bc9ec42STomasz Sapeta} 58370fa39dSKudo Chien 599bc9ec42STomasz Sapeta- (nonnull NSArray<NSString *> *)getPropertyNames 609bc9ec42STomasz Sapeta{ 619bc9ec42STomasz Sapeta jsi::Runtime *runtime = [_runtime get]; 629bc9ec42STomasz Sapeta jsi::Array propertyNamesArray = _jsObjectPtr->getPropertyNames(*[_runtime get]); 639bc9ec42STomasz Sapeta return expo::convertJSIArrayToNSArray(*runtime, propertyNamesArray, nullptr); 64370fa39dSKudo Chien} 659bc9ec42STomasz Sapeta 669bc9ec42STomasz Sapeta#pragma mark - Modifying object properties 679bc9ec42STomasz Sapeta 689bc9ec42STomasz Sapeta- (void)setProperty:(nonnull NSString *)name value:(nullable id)value 699bc9ec42STomasz Sapeta{ 709bc9ec42STomasz Sapeta jsi::Value jsiValue = expo::convertObjCObjectToJSIValue(*[_runtime get], value); 719bc9ec42STomasz Sapeta _jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], jsiValue); 72370fa39dSKudo Chien} 739bc9ec42STomasz Sapeta 74ce45e284STomasz Sapeta- (void)defineProperty:(nonnull NSString *)name descriptor:(nonnull EXJavaScriptObject *)descriptor 75ce45e284STomasz Sapeta{ 76ce45e284STomasz Sapeta jsi::Runtime *runtime = [_runtime get]; 77*e1f25825SŁukasz Kosmaty jsi::Object *jsThis = _jsObjectPtr.get(); 78ce45e284STomasz Sapeta 79*e1f25825SŁukasz Kosmaty expo::common::definePropertyOnJSIObject(*runtime, jsThis, [name UTF8String], std::move(*[descriptor get])); 80ce45e284STomasz Sapeta} 81ce45e284STomasz Sapeta 829bc9ec42STomasz Sapeta- (void)defineProperty:(nonnull NSString *)name value:(nullable id)value options:(EXJavaScriptObjectPropertyDescriptor)options 839bc9ec42STomasz Sapeta{ 849bc9ec42STomasz Sapeta jsi::Runtime *runtime = [_runtime get]; 85*e1f25825SŁukasz Kosmaty jsi::Object *jsThis = _jsObjectPtr.get(); 869bc9ec42STomasz Sapeta 87*e1f25825SŁukasz Kosmaty jsi::Object descriptor = [self preparePropertyDescriptorWithOptions:options]; 889bc9ec42STomasz Sapeta descriptor.setProperty(*runtime, "value", expo::convertObjCObjectToJSIValue(*runtime, value)); 899bc9ec42STomasz Sapeta 90*e1f25825SŁukasz Kosmaty expo::common::definePropertyOnJSIObject(*runtime, jsThis, [name UTF8String], std::move(descriptor)); 91370fa39dSKudo Chien} 92370fa39dSKudo Chien 9378516026STomasz Sapeta#pragma mark - WeakObject 9478516026STomasz Sapeta 9578516026STomasz Sapeta- (nonnull EXJavaScriptWeakObject *)createWeak 9678516026STomasz Sapeta{ 9778516026STomasz Sapeta return [[EXJavaScriptWeakObject alloc] initWith:_jsObjectPtr runtime:_runtime]; 9878516026STomasz Sapeta} 9978516026STomasz Sapeta 10078516026STomasz Sapeta#pragma mark - Deallocator 10178516026STomasz Sapeta 10278516026STomasz Sapeta- (void)setObjectDeallocator:(void (^)(void))deallocatorBlock 10378516026STomasz Sapeta{ 104*e1f25825SŁukasz Kosmaty expo::common::setDeallocator(*[_runtime get], _jsObjectPtr, deallocatorBlock); 10578516026STomasz Sapeta} 10678516026STomasz Sapeta 10778516026STomasz Sapeta#pragma mark - Equality 10878516026STomasz Sapeta 10978516026STomasz Sapeta- (BOOL)isEqual:(id)object 11078516026STomasz Sapeta{ 11178516026STomasz Sapeta if ([object isKindOfClass:EXJavaScriptObject.class]) { 11278516026STomasz Sapeta jsi::Runtime *runtime = [_runtime get]; 11378516026STomasz Sapeta jsi::Object *a = _jsObjectPtr.get(); 11478516026STomasz Sapeta jsi::Object *b = [object get]; 11578516026STomasz Sapeta return jsi::Object::strictEquals(*runtime, *a, *b); 11678516026STomasz Sapeta } 11778516026STomasz Sapeta return false; 11878516026STomasz Sapeta} 11978516026STomasz Sapeta 1209bc9ec42STomasz Sapeta#pragma mark - Private helpers 1219bc9ec42STomasz Sapeta 1229bc9ec42STomasz Sapeta- (jsi::Object)preparePropertyDescriptorWithOptions:(EXJavaScriptObjectPropertyDescriptor)options 1239bc9ec42STomasz Sapeta{ 1249bc9ec42STomasz Sapeta jsi::Runtime *runtime = [_runtime get]; 1259bc9ec42STomasz Sapeta jsi::Object descriptor(*runtime); 1269bc9ec42STomasz Sapeta descriptor.setProperty(*runtime, "configurable", (bool)(options & EXJavaScriptObjectPropertyDescriptorConfigurable)); 1279bc9ec42STomasz Sapeta descriptor.setProperty(*runtime, "enumerable", (bool)(options & EXJavaScriptObjectPropertyDescriptorEnumerable)); 1289bc9ec42STomasz Sapeta descriptor.setProperty(*runtime, "writable", (bool)(options & EXJavaScriptObjectPropertyDescriptorWritable)); 1299bc9ec42STomasz Sapeta return descriptor; 1309bc9ec42STomasz Sapeta} 1319bc9ec42STomasz Sapeta 132370fa39dSKudo Chien@end 133