1 #include "Shareables.h"
2 
3 using namespace facebook;
4 
5 namespace reanimated {
6 
CoreFunction(JSRuntimeHelper * runtimeHelper,const jsi::Value & workletValue)7 CoreFunction::CoreFunction(
8     JSRuntimeHelper *runtimeHelper,
9     const jsi::Value &workletValue)
10     : runtimeHelper_(runtimeHelper) {
11   jsi::Runtime &rt = *runtimeHelper->rnRuntime();
12   auto workletObject = workletValue.asObject(rt);
13   rnFunction_ = std::make_unique<jsi::Function>(workletObject.asFunction(rt));
14   functionBody_ = workletObject.getPropertyAsObject(rt, "__initData")
15                       .getProperty(rt, "code")
16                       .asString(rt)
17                       .utf8(rt);
18   location_ = "worklet_" +
19       std::to_string(static_cast<uint64_t>(
20           workletObject.getProperty(rt, "__workletHash").getNumber()));
21 }
22 
getFunction(jsi::Runtime & rt)23 std::unique_ptr<jsi::Function> &CoreFunction::getFunction(jsi::Runtime &rt) {
24   if (runtimeHelper_->isUIRuntime(rt)) {
25     if (uiFunction_ == nullptr) {
26       // maybe need to initialize UI Function
27       // the newline before closing paren is needed because the last line can be
28       // an inline comment (specifically this happens when we attach source maps
29       // at the end) in which case the paren won't be parsed
30       auto codeBuffer = std::make_shared<const jsi::StringBuffer>(
31           "(" + functionBody_ + "\n)");
32       uiFunction_ = std::make_unique<jsi::Function>(
33           rt.evaluateJavaScript(codeBuffer, location_)
34               .asObject(rt)
35               .asFunction(rt));
36     }
37     return uiFunction_;
38   } else {
39     // running on the main RN runtime
40     return rnFunction_;
41   }
42 }
43 
extractShareableOrThrow(jsi::Runtime & rt,const jsi::Value & maybeShareableValue,const char * errorMessage)44 std::shared_ptr<Shareable> extractShareableOrThrow(
45     jsi::Runtime &rt,
46     const jsi::Value &maybeShareableValue,
47     const char *errorMessage) {
48   if (maybeShareableValue.isObject()) {
49     auto object = maybeShareableValue.asObject(rt);
50     if (object.isHostObject<ShareableJSRef>(rt)) {
51       return object.getHostObject<ShareableJSRef>(rt)->value();
52     }
53   } else if (maybeShareableValue.isUndefined()) {
54     return Shareable::undefined();
55   }
56   throw std::runtime_error(
57       errorMessage != nullptr
58           ? errorMessage
59           : "expecting the object to be of type ShareableJSRef");
60 }
61 
~Shareable()62 Shareable::~Shareable() {}
63 
ShareableArray(jsi::Runtime & rt,const jsi::Array & array)64 ShareableArray::ShareableArray(jsi::Runtime &rt, const jsi::Array &array)
65     : Shareable(ArrayType) {
66   auto size = array.size(rt);
67   data_.reserve(size);
68   for (size_t i = 0; i < size; i++) {
69     data_.push_back(extractShareableOrThrow(rt, array.getValueAtIndex(rt, i)));
70   }
71 }
72 
ShareableObject(jsi::Runtime & rt,const jsi::Object & object)73 ShareableObject::ShareableObject(jsi::Runtime &rt, const jsi::Object &object)
74     : Shareable(ObjectType) {
75   auto propertyNames = object.getPropertyNames(rt);
76   auto size = propertyNames.size(rt);
77   data_.reserve(size);
78   for (size_t i = 0; i < size; i++) {
79     auto key = propertyNames.getValueAtIndex(rt, i).asString(rt);
80     auto value = extractShareableOrThrow(rt, object.getProperty(rt, key));
81     data_.emplace_back(key.utf8(rt), value);
82   }
83 }
84 
undefined()85 std::shared_ptr<Shareable> Shareable::undefined() {
86   static auto undefined = std::make_shared<ShareableScalar>();
87   return undefined;
88 }
89 
90 } /* namespace reanimated */
91