1// Copyright 2022-present 650 Industries. All rights reserved. 2 3#import <ExpoModulesCore/EXJSIUtils.h> 4#import <ExpoModulesCore/EXJavaScriptWeakObject.h> 5 6@implementation EXJavaScriptWeakObject { 7 /** 8 Pointer to the `EXJavaScriptRuntime` wrapper. 9 10 \note It must be weak because only then the original runtime can be safely deallocated 11 when the JS engine wants to without unsetting it on each created object. 12 */ 13 __weak EXJavaScriptRuntime *_runtime; 14 15 /** 16 Shared pointer to the `WeakRef` JS object. 17 */ 18 std::shared_ptr<jsi::Object> _jsObject; 19} 20 21- (nonnull instancetype)initWith:(std::shared_ptr<jsi::Object>)jsObject 22 runtime:(nonnull EXJavaScriptRuntime *)runtime 23{ 24 if (self = [super init]) { 25 _runtime = runtime; 26 27 // Check whether the runtime supports `WeakRef` objects. If it does not, 28 // we consciously hold a strong reference to the object and cause memory leaks. 29 // This is the case on hermes and JSC prior to iOS 14.5. 30 // TODO: (@tsapeta) Use `jsi::WeakObject` on hermes 31 if (expo::isWeakRefSupported(*[runtime get])) { 32 _jsObject = expo::createWeakRef(*[runtime get], jsObject); 33 } else { 34 _jsObject = jsObject; 35 } 36 } 37 return self; 38} 39 40- (nullable EXJavaScriptObject *)lock 41{ 42 jsi::Runtime *runtime = [_runtime get]; 43 std::shared_ptr<jsi::Object> objectPtr = expo::isWeakRefSupported(*runtime) 44 ? expo::derefWeakRef(*runtime, _jsObject) 45 : _jsObject; 46 47 if (!objectPtr) { 48 return nil; 49 } 50 return [[EXJavaScriptObject alloc] initWith:objectPtr runtime:_runtime]; 51} 52 53@end 54