Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ class CallbackWrapper : public LongLivedObject {
jsi::Function&& callback,
jsi::Runtime& runtime,
std::shared_ptr<CallInvoker> jsInvoker)
: callback_(std::move(callback)),
runtime_(runtime),
: LongLivedObject(runtime),
callback_(std::move(callback)),
jsInvoker_(std::move(jsInvoker)) {}

jsi::Function callback_;
jsi::Runtime& runtime_;
std::shared_ptr<CallInvoker> jsInvoker_;

public:
Expand All @@ -39,7 +38,7 @@ class CallbackWrapper : public LongLivedObject {
std::shared_ptr<CallInvoker> jsInvoker) {
auto wrapper = std::shared_ptr<CallbackWrapper>(new CallbackWrapper(
std::move(callback), runtime, std::move(jsInvoker)));
LongLivedObjectCollection::get().add(wrapper);
LongLivedObjectCollection::get(runtime).add(wrapper);
return wrapper;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,24 @@
*/

#include "LongLivedObject.h"
#include <unordered_map>

namespace facebook::react {

// LongLivedObjectCollection
LongLivedObjectCollection& LongLivedObjectCollection::get() {
static LongLivedObjectCollection instance;
return instance;

LongLivedObjectCollection& LongLivedObjectCollection::get(
jsi::Runtime& runtime) {
static std::unordered_map<void*, std::shared_ptr<LongLivedObjectCollection>>
instances;
void* key = static_cast<void*>(&runtime);
auto entry = instances.find(key);
if (entry == instances.end()) {
entry =
instances.emplace(key, std::make_shared<LongLivedObjectCollection>())
.first;
}
return *(entry->second);
}

void LongLivedObjectCollection::add(std::shared_ptr<LongLivedObject> so) {
Expand Down Expand Up @@ -43,7 +54,7 @@ size_t LongLivedObjectCollection::size() const {
// LongLivedObject

void LongLivedObject::allowRelease() {
LongLivedObjectCollection::get().remove(this);
LongLivedObjectCollection::get(runtime_).remove(this);
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#pragma once

#include <jsi/jsi.h>
#include <memory>
#include <mutex>
#include <unordered_set>
Expand All @@ -31,16 +32,17 @@ class LongLivedObject {
virtual void allowRelease();

protected:
LongLivedObject() = default;
explicit LongLivedObject(jsi::Runtime& runtime) : runtime_(runtime) {}
virtual ~LongLivedObject() = default;
jsi::Runtime& runtime_;
};

/**
* A singleton, thread-safe, write-only collection for the `LongLivedObject`s.
*/
class LongLivedObjectCollection {
public:
static LongLivedObjectCollection& get();
static LongLivedObjectCollection& get(jsi::Runtime& runtime);

LongLivedObjectCollection() = default;
LongLivedObjectCollection(const LongLivedObjectCollection&) = delete;
Expand Down
8 changes: 5 additions & 3 deletions packages/react-native/ReactCommon/react/bridging/Promise.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ class AsyncPromise {
},
jsInvoker));

auto promiseHolder = std::make_shared<PromiseHolder>(promise.asObject(rt));
LongLivedObjectCollection::get().add(promiseHolder);
auto promiseHolder =
std::make_shared<PromiseHolder>(rt, promise.asObject(rt));
LongLivedObjectCollection::get(rt).add(promiseHolder);

// The shared state can retain the promise holder weakly now.
state_->promiseHolder = promiseHolder;
Expand Down Expand Up @@ -71,7 +72,8 @@ class AsyncPromise {

private:
struct PromiseHolder : LongLivedObject {
PromiseHolder(jsi::Object p) : promise(std::move(p)) {}
PromiseHolder(jsi::Runtime& runtime, jsi::Object p)
: LongLivedObject(runtime), promise(std::move(p)) {}

jsi::Object promise;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ TEST_F(BridgingTest, asyncCallbackInvalidation) {
[](jsi::Runtime& rt, jsi::Function& f) { f.call(rt, "hello"); });

// LongLivedObjectCollection goes away before callback is executed
LongLivedObjectCollection::get().clear();
LongLivedObjectCollection::get(rt).clear();

flushQueue();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ class BridgingTest : public ::testing::Test {
rt(*runtime) {}

~BridgingTest() {
LongLivedObjectCollection::get().clear();
LongLivedObjectCollection::get(rt).clear();
}

void TearDown() override {
flushQueue();

// After flushing the invoker queue, we shouldn't leak memory.
EXPECT_EQ(0, LongLivedObjectCollection::get().size());
EXPECT_EQ(0, LongLivedObjectCollection::get(rt).size());
}

jsi::Value eval(const std::string& js) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@ class BridgelessNativeModuleProxy : public jsi::HostObject {
*/

TurboModuleBinding::TurboModuleBinding(
jsi::Runtime& runtime,
TurboModuleProviderFunctionType&& moduleProvider,
std::shared_ptr<LongLivedObjectCollection> longLivedObjectCollection)
: moduleProvider_(std::move(moduleProvider)),
: runtime_(runtime),
moduleProvider_(std::move(moduleProvider)),
longLivedObjectCollection_(std::move(longLivedObjectCollection)) {}

void TurboModuleBinding::install(
Expand All @@ -85,7 +87,7 @@ void TurboModuleBinding::install(
jsi::PropNameID::forAscii(runtime, "__turboModuleProxy"),
1,
[binding = TurboModuleBinding(
std::move(moduleProvider), longLivedObjectCollection)](
runtime, std::move(moduleProvider), longLivedObjectCollection)](
jsi::Runtime& rt,
const jsi::Value& thisVal,
const jsi::Value* args,
Expand All @@ -102,7 +104,9 @@ void TurboModuleBinding::install(
bool rnTurboInterop = legacyModuleProvider != nullptr;
auto turboModuleBinding = legacyModuleProvider
? std::make_unique<TurboModuleBinding>(
std::move(legacyModuleProvider), longLivedObjectCollection)
runtime,
std::move(legacyModuleProvider),
longLivedObjectCollection)
: nullptr;
auto nativeModuleProxy = std::make_shared<BridgelessNativeModuleProxy>(
std::move(turboModuleBinding));
Expand All @@ -119,7 +123,7 @@ TurboModuleBinding::~TurboModuleBinding() {
if (longLivedObjectCollection_) {
longLivedObjectCollection_->clear();
} else {
LongLivedObjectCollection::get().clear();
LongLivedObjectCollection::get(runtime_).clear();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class TurboModuleBinding {
nullptr);

TurboModuleBinding(
jsi::Runtime& runtime,
TurboModuleProviderFunctionType&& moduleProvider,
std::shared_ptr<LongLivedObjectCollection> longLivedObjectCollection);

Expand All @@ -49,6 +50,7 @@ class TurboModuleBinding {
jsi::Value getModule(jsi::Runtime& runtime, const std::string& moduleName)
const;

jsi::Runtime& runtime_;
TurboModuleProviderFunctionType moduleProvider_;
std::shared_ptr<LongLivedObjectCollection> longLivedObjectCollection_;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ jsi::Array deepCopyJSIArray(jsi::Runtime& rt, const jsi::Array& arr) {
}

Promise::Promise(jsi::Runtime& rt, jsi::Function resolve, jsi::Function reject)
: runtime_(rt), resolve_(std::move(resolve)), reject_(std::move(reject)) {}
: LongLivedObject(rt),
resolve_(std::move(resolve)),
reject_(std::move(reject)) {}

void Promise::resolve(const jsi::Value& result) {
resolve_.call(runtime_, result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ struct Promise : public LongLivedObject {
void resolve(const jsi::Value& result);
void reject(const std::string& error);

jsi::Runtime& runtime_;
jsi::Function resolve_;
jsi::Function reject_;
};
Expand Down