1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2 
3 #include "JavaScriptObject.h"
4 #include "JavaScriptValue.h"
5 #include "JavaScriptRuntime.h"
6 #include "JSITypeConverter.h"
7 
8 namespace expo {
9 void JavaScriptObject::registerNatives() {
10   registerHybrid({
11                    makeNativeMethod("hasProperty", JavaScriptObject::jniHasProperty),
12                    makeNativeMethod("getProperty", JavaScriptObject::jniGetProperty),
13                    makeNativeMethod("getPropertyNames", JavaScriptObject::jniGetPropertyNames),
14                    makeNativeMethod("setBoolProperty", JavaScriptObject::setProperty<bool>),
15                    makeNativeMethod("setDoubleProperty", JavaScriptObject::setProperty<double>),
16                    makeNativeMethod("setStringProperty",
17                                     JavaScriptObject::setProperty<jni::alias_ref<jstring>>),
18                    makeNativeMethod("setJSValueProperty",
19                                     JavaScriptObject::setProperty<jni::alias_ref<JavaScriptValue::javaobject>>),
20                    makeNativeMethod("setJSObjectProperty",
21                                     JavaScriptObject::setProperty<jni::alias_ref<JavaScriptObject::javaobject>>),
22                    makeNativeMethod("unsetProperty", JavaScriptObject::unsetProperty),
23                  });
24 }
25 
26 JavaScriptObject::JavaScriptObject(
27   std::weak_ptr<JavaScriptRuntime> runtime,
28   std::shared_ptr<jsi::Object> jsObject
29 ) : runtimeHolder(std::move(runtime)), jsObject(std::move(jsObject)) {
30   assert(runtimeHolder.lock() != nullptr);
31 }
32 
33 std::shared_ptr<jsi::Object> JavaScriptObject::get() {
34   return jsObject;
35 }
36 
37 bool JavaScriptObject::hasProperty(const std::string &name) {
38   auto runtime = runtimeHolder.lock();
39   assert(runtime != nullptr);
40   return jsObject->hasProperty(*runtime->get(), name.c_str());
41 }
42 
43 jsi::Value JavaScriptObject::getProperty(const std::string &name) {
44   auto runtime = runtimeHolder.lock();
45   assert(runtime != nullptr);
46   return jsObject->getProperty(*runtime->get(), name.c_str());
47 }
48 
49 bool JavaScriptObject::jniHasProperty(jni::alias_ref<jstring> name) {
50   return hasProperty(name->toStdString());
51 }
52 
53 jni::local_ref<JavaScriptValue::javaobject> JavaScriptObject::jniGetProperty(
54   jni::alias_ref<jstring> name
55 ) {
56   auto result = std::make_shared<jsi::Value>(getProperty(name->toStdString()));
57   return JavaScriptValue::newObjectCxxArgs(runtimeHolder, result);
58 }
59 
60 std::vector<std::string> JavaScriptObject::getPropertyNames() {
61   auto runtime = runtimeHolder.lock();
62   assert(runtime != nullptr);
63 
64   jsi::Array properties = jsObject->getPropertyNames(*runtime->get());
65   auto size = properties.size(*runtime->get());
66 
67   std::vector<std::string> names(size);
68   for (size_t i = 0; i < size; i++) {
69     auto propertyName = properties
70       .getValueAtIndex(*runtime->get(), i)
71       .asString(*runtime->get())
72       .utf8(*runtime->get());
73     names[i] = propertyName;
74   }
75 
76   return names;
77 }
78 
79 jni::local_ref<jni::JArrayClass<jstring>> JavaScriptObject::jniGetPropertyNames() {
80   std::vector<std::string> cResult = getPropertyNames();
81   auto paredResult = jni::JArrayClass<jstring>::newArray(cResult.size());
82   for (size_t i = 0; i < cResult.size(); i++) {
83     paredResult->setElement(i, jni::make_jstring(cResult[i]).get());
84   }
85 
86   return paredResult;
87 }
88 
89 void JavaScriptObject::setProperty(const std::string &name, jsi::Value value) {
90   auto runtime = runtimeHolder.lock();
91   assert(runtime != nullptr);
92   jsObject->setProperty(*runtime->get(), name.c_str(), value);
93 }
94 
95 void JavaScriptObject::unsetProperty(jni::alias_ref<jstring> name) {
96   auto runtime = runtimeHolder.lock();
97   assert(runtime != nullptr);
98   auto cName = name->toStdString();
99   jsObject->setProperty(
100     *runtime->get(),
101     cName.c_str(),
102     jsi::Value::undefined()
103   );
104 }
105 } // namespace expo
106