Skip to content

Commit

Permalink
[ios] Fix weak objects implementation on Hermes
Browse files Browse the repository at this point in the history
  • Loading branch information
tsapeta committed Apr 4, 2023
1 parent 02091ff commit 712249f
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions packages/expo-modules-core/ios/JSI/EXJavaScriptWeakObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ @implementation EXJavaScriptWeakObject {
__weak EXJavaScriptRuntime *_runtime;

/**
Shared pointer to the `WeakRef` JS object.
Shared pointer to the `WeakRef` JS object. Available only on JSC engine.
*/
std::shared_ptr<jsi::Object> _jsObject;
std::shared_ptr<jsi::Object> _weakRef;

/**
A weak reference to a JS object. Available only on Hermes engine.
*/
std::shared_ptr<jsi::WeakObject> _weakObject;
}

- (nonnull instancetype)initWith:(std::shared_ptr<jsi::Object>)jsObject
Expand All @@ -24,25 +29,39 @@ - (nonnull instancetype)initWith:(std::shared_ptr<jsi::Object>)jsObject
if (self = [super init]) {
_runtime = runtime;

#if __has_include(<reacthermes/HermesExecutorFactory.h>)
_weakObject = std::make_shared<jsi::WeakObject>(*[runtime get], *jsObject);
#else
// Check whether the runtime supports `WeakRef` objects. If it does not,
// we consciously hold a strong reference to the object and cause memory leaks.
// This is the case on hermes and JSC prior to iOS 14.5.
// TODO: (@tsapeta) Use `jsi::WeakObject` on hermes
// This is the case on JSC prior to iOS 14.5.
if (expo::isWeakRefSupported(*[runtime get])) {
_jsObject = expo::createWeakRef(*[runtime get], jsObject);
_weakRef = expo::createWeakRef(*[runtime get], jsObject);
} else {
_jsObject = jsObject;
_weakRef = jsObject;
}
#endif
}
return self;
}

- (nullable EXJavaScriptObject *)lock
{
jsi::Runtime *runtime = [_runtime get];

#if __has_include(<reacthermes/HermesExecutorFactory.h>)
jsi::Value value = _weakObject->lock(*runtime);

// `lock` returns an undefined value if the underlying object no longer exists.
if (value.isUndefined()) {
return nil;
}
std::shared_ptr<jsi::Object> objectPtr = std::make_shared<jsi::Object>(value.asObject(*runtime));
#else
std::shared_ptr<jsi::Object> objectPtr = expo::isWeakRefSupported(*runtime)
? expo::derefWeakRef(*runtime, _jsObject)
: _jsObject;
? expo::derefWeakRef(*runtime, _weakRef)
: _weakRef;
#endif

if (!objectPtr) {
return nil;
Expand Down

0 comments on commit 712249f

Please sign in to comment.