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#if __has_include(<reacthermes/HermesExecutorFactory.h>) 16 /** 17 A weak reference to a JS object. Available only on Hermes engine. 18 */ 19 std::shared_ptr<jsi::WeakObject> _weakObject; 20#else 21 /** 22 Shared pointer to the `WeakRef` JS object. Available only on JSC engine. 23 */ 24 std::shared_ptr<jsi::Object> _weakObject; 25#endif 26} 27 28- (nonnull instancetype)initWith:(std::shared_ptr<jsi::Object>)jsObject 29 runtime:(nonnull EXJavaScriptRuntime *)runtime 30{ 31 if (self = [super init]) { 32 _runtime = runtime; 33 34#if __has_include(<reacthermes/HermesExecutorFactory.h>) 35 _weakObject = std::make_shared<jsi::WeakObject>(*[runtime get], *jsObject); 36#else 37 // Check whether the runtime supports `WeakRef` objects. If it does not, 38 // we consciously hold a strong reference to the object and cause memory leaks. 39 // This is the case on JSC prior to iOS 14.5. 40 if (expo::isWeakRefSupported(*[runtime get])) { 41 _weakObject = expo::createWeakRef(*[runtime get], jsObject); 42 } else { 43 _weakObject = jsObject; 44 } 45#endif 46 } 47 return self; 48} 49 50- (nullable EXJavaScriptObject *)lock 51{ 52 jsi::Runtime *runtime = [_runtime get]; 53 54#if __has_include(<reacthermes/HermesExecutorFactory.h>) 55 jsi::Value value = _weakObject->lock(*runtime); 56 57 // `lock` returns an undefined value if the underlying object no longer exists. 58 if (value.isUndefined()) { 59 return nil; 60 } 61 std::shared_ptr<jsi::Object> objectPtr = std::make_shared<jsi::Object>(value.asObject(*runtime)); 62#else 63 std::shared_ptr<jsi::Object> objectPtr = expo::isWeakRefSupported(*runtime) 64 ? expo::derefWeakRef(*runtime, _weakObject) 65 : _weakObject; 66#endif 67 68 if (!objectPtr) { 69 return nil; 70 } 71 return [[EXJavaScriptObject alloc] initWith:objectPtr runtime:_runtime]; 72} 73 74@end 75