1*fe5cfb17STomasz Sapeta #include "MutableValue.h"
2*fe5cfb17STomasz Sapeta #include "RuntimeDecorator.h"
3*fe5cfb17STomasz Sapeta #include "RuntimeManager.h"
4*fe5cfb17STomasz Sapeta #include "ShareableValue.h"
5*fe5cfb17STomasz Sapeta #include "SharedParent.h"
6*fe5cfb17STomasz Sapeta
7*fe5cfb17STomasz Sapeta #include <string>
8*fe5cfb17STomasz Sapeta
9*fe5cfb17STomasz Sapeta namespace ABI48_0_0reanimated {
10*fe5cfb17STomasz Sapeta
setValue(jsi::Runtime & rt,const jsi::Value & newValue)11*fe5cfb17STomasz Sapeta void MutableValue::setValue(jsi::Runtime &rt, const jsi::Value &newValue) {
12*fe5cfb17STomasz Sapeta std::lock_guard<std::mutex> lock(readWriteMutex);
13*fe5cfb17STomasz Sapeta value = ShareableValue::adapt(rt, newValue, runtimeManager);
14*fe5cfb17STomasz Sapeta
15*fe5cfb17STomasz Sapeta std::shared_ptr<MutableValue> thiz = shared_from_this();
16*fe5cfb17STomasz Sapeta auto notifyListeners = [thiz]() {
17*fe5cfb17STomasz Sapeta for (auto listener : thiz->listeners) {
18*fe5cfb17STomasz Sapeta listener.second();
19*fe5cfb17STomasz Sapeta }
20*fe5cfb17STomasz Sapeta };
21*fe5cfb17STomasz Sapeta if (RuntimeDecorator::isUIRuntime(rt)) {
22*fe5cfb17STomasz Sapeta notifyListeners();
23*fe5cfb17STomasz Sapeta } else {
24*fe5cfb17STomasz Sapeta runtimeManager->scheduler->scheduleOnUI(
25*fe5cfb17STomasz Sapeta [notifyListeners] { notifyListeners(); });
26*fe5cfb17STomasz Sapeta }
27*fe5cfb17STomasz Sapeta }
28*fe5cfb17STomasz Sapeta
getValue(jsi::Runtime & rt)29*fe5cfb17STomasz Sapeta jsi::Value MutableValue::getValue(jsi::Runtime &rt) {
30*fe5cfb17STomasz Sapeta std::lock_guard<std::mutex> lock(readWriteMutex);
31*fe5cfb17STomasz Sapeta return value->getValue(rt);
32*fe5cfb17STomasz Sapeta }
33*fe5cfb17STomasz Sapeta
set(jsi::Runtime & rt,const jsi::PropNameID & name,const jsi::Value & newValue)34*fe5cfb17STomasz Sapeta void MutableValue::set(
35*fe5cfb17STomasz Sapeta jsi::Runtime &rt,
36*fe5cfb17STomasz Sapeta const jsi::PropNameID &name,
37*fe5cfb17STomasz Sapeta const jsi::Value &newValue) {
38*fe5cfb17STomasz Sapeta auto propName = name.utf8(rt);
39*fe5cfb17STomasz Sapeta if (!runtimeManager->valueSetter) {
40*fe5cfb17STomasz Sapeta throw jsi::JSError(
41*fe5cfb17STomasz Sapeta rt,
42*fe5cfb17STomasz Sapeta "Value-Setter is not yet configured! Make sure the core-functions are installed.");
43*fe5cfb17STomasz Sapeta }
44*fe5cfb17STomasz Sapeta
45*fe5cfb17STomasz Sapeta if (RuntimeDecorator::isUIRuntime(rt)) {
46*fe5cfb17STomasz Sapeta // UI thread
47*fe5cfb17STomasz Sapeta if (propName == "value") {
48*fe5cfb17STomasz Sapeta auto setterProxy = jsi::Object::createFromHostObject(
49*fe5cfb17STomasz Sapeta rt, std::make_shared<MutableValueSetterProxy>(shared_from_this()));
50*fe5cfb17STomasz Sapeta runtimeManager->valueSetter->getValue(rt)
51*fe5cfb17STomasz Sapeta .asObject(rt)
52*fe5cfb17STomasz Sapeta .asFunction(rt)
53*fe5cfb17STomasz Sapeta .callWithThis(rt, setterProxy, newValue);
54*fe5cfb17STomasz Sapeta } else if (propName == "_animation") {
55*fe5cfb17STomasz Sapeta // TODO: assert to allow animation to be set from UI only
56*fe5cfb17STomasz Sapeta if (animation.expired()) {
57*fe5cfb17STomasz Sapeta animation = getWeakRef(rt);
58*fe5cfb17STomasz Sapeta }
59*fe5cfb17STomasz Sapeta *animation.lock() = jsi::Value(rt, newValue);
60*fe5cfb17STomasz Sapeta } else if (propName == "_value") {
61*fe5cfb17STomasz Sapeta auto setter =
62*fe5cfb17STomasz Sapeta std::make_shared<MutableValueSetterProxy>(shared_from_this());
63*fe5cfb17STomasz Sapeta setter->set(rt, jsi::PropNameID::forAscii(rt, "_value"), newValue);
64*fe5cfb17STomasz Sapeta }
65*fe5cfb17STomasz Sapeta } else {
66*fe5cfb17STomasz Sapeta // ABI48_0_0React-JS Thread or another threaded Runtime.
67*fe5cfb17STomasz Sapeta if (propName == "value") {
68*fe5cfb17STomasz Sapeta auto shareable = ShareableValue::adapt(rt, newValue, runtimeManager);
69*fe5cfb17STomasz Sapeta runtimeManager->scheduler->scheduleOnUI([this, shareable] {
70*fe5cfb17STomasz Sapeta jsi::Runtime &rt = *this->runtimeManager->runtime.get();
71*fe5cfb17STomasz Sapeta auto setterProxy = jsi::Object::createFromHostObject(
72*fe5cfb17STomasz Sapeta rt, std::make_shared<MutableValueSetterProxy>(shared_from_this()));
73*fe5cfb17STomasz Sapeta jsi::Value newValue = shareable->getValue(rt);
74*fe5cfb17STomasz Sapeta runtimeManager->valueSetter->getValue(rt)
75*fe5cfb17STomasz Sapeta .asObject(rt)
76*fe5cfb17STomasz Sapeta .asFunction(rt)
77*fe5cfb17STomasz Sapeta .callWithThis(rt, setterProxy, newValue);
78*fe5cfb17STomasz Sapeta });
79*fe5cfb17STomasz Sapeta }
80*fe5cfb17STomasz Sapeta }
81*fe5cfb17STomasz Sapeta }
82*fe5cfb17STomasz Sapeta
get(jsi::Runtime & rt,const jsi::PropNameID & name)83*fe5cfb17STomasz Sapeta jsi::Value MutableValue::get(jsi::Runtime &rt, const jsi::PropNameID &name) {
84*fe5cfb17STomasz Sapeta auto propName = name.utf8(rt);
85*fe5cfb17STomasz Sapeta
86*fe5cfb17STomasz Sapeta if (propName == "value") {
87*fe5cfb17STomasz Sapeta return getValue(rt);
88*fe5cfb17STomasz Sapeta }
89*fe5cfb17STomasz Sapeta
90*fe5cfb17STomasz Sapeta if (RuntimeDecorator::isUIRuntime(rt)) {
91*fe5cfb17STomasz Sapeta // _value and _animation should be accessed from UI only
92*fe5cfb17STomasz Sapeta if (propName == "_value") {
93*fe5cfb17STomasz Sapeta return getValue(rt);
94*fe5cfb17STomasz Sapeta } else if (propName == "_animation") {
95*fe5cfb17STomasz Sapeta // TODO: assert to allow animation to be read from UI only
96*fe5cfb17STomasz Sapeta if (animation.expired()) {
97*fe5cfb17STomasz Sapeta animation = getWeakRef(rt);
98*fe5cfb17STomasz Sapeta }
99*fe5cfb17STomasz Sapeta return jsi::Value(rt, *(animation.lock()));
100*fe5cfb17STomasz Sapeta }
101*fe5cfb17STomasz Sapeta }
102*fe5cfb17STomasz Sapeta
103*fe5cfb17STomasz Sapeta return jsi::Value::undefined();
104*fe5cfb17STomasz Sapeta }
105*fe5cfb17STomasz Sapeta
getPropertyNames(jsi::Runtime & rt)106*fe5cfb17STomasz Sapeta std::vector<jsi::PropNameID> MutableValue::getPropertyNames(jsi::Runtime &rt) {
107*fe5cfb17STomasz Sapeta std::vector<jsi::PropNameID> result;
108*fe5cfb17STomasz Sapeta result.push_back(jsi::PropNameID::forUtf8(rt, std::string("value")));
109*fe5cfb17STomasz Sapeta return result;
110*fe5cfb17STomasz Sapeta }
111*fe5cfb17STomasz Sapeta
MutableValue(jsi::Runtime & rt,const jsi::Value & initial,RuntimeManager * runtimeManager,std::shared_ptr<Scheduler> s)112*fe5cfb17STomasz Sapeta MutableValue::MutableValue(
113*fe5cfb17STomasz Sapeta jsi::Runtime &rt,
114*fe5cfb17STomasz Sapeta const jsi::Value &initial,
115*fe5cfb17STomasz Sapeta RuntimeManager *runtimeManager,
116*fe5cfb17STomasz Sapeta std::shared_ptr<Scheduler> s)
117*fe5cfb17STomasz Sapeta : StoreUser(s, *runtimeManager),
118*fe5cfb17STomasz Sapeta runtimeManager(runtimeManager),
119*fe5cfb17STomasz Sapeta value(ShareableValue::adapt(rt, initial, runtimeManager)) {}
120*fe5cfb17STomasz Sapeta
addListener(unsigned long id,std::function<void ()> listener)121*fe5cfb17STomasz Sapeta unsigned long int MutableValue::addListener(
122*fe5cfb17STomasz Sapeta unsigned long id,
123*fe5cfb17STomasz Sapeta std::function<void()> listener) {
124*fe5cfb17STomasz Sapeta listeners[id] = listener;
125*fe5cfb17STomasz Sapeta return id;
126*fe5cfb17STomasz Sapeta }
127*fe5cfb17STomasz Sapeta
removeListener(unsigned long listenerId)128*fe5cfb17STomasz Sapeta void MutableValue::removeListener(unsigned long listenerId) {
129*fe5cfb17STomasz Sapeta if (listeners.count(listenerId) > 0) {
130*fe5cfb17STomasz Sapeta listeners.erase(listenerId);
131*fe5cfb17STomasz Sapeta }
132*fe5cfb17STomasz Sapeta }
133*fe5cfb17STomasz Sapeta
134*fe5cfb17STomasz Sapeta } // namespace reanimated
135