1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2 
3 #include "JavaScriptValue.h"
4 
5 #include "JavaScriptRuntime.h"
6 #include "JavaScriptObject.h"
7 
8 namespace expo {
9 void JavaScriptValue::registerNatives() {
10   registerHybrid({
11                    makeNativeMethod("kind", JavaScriptValue::jniKind),
12                    makeNativeMethod("isNull", JavaScriptValue::isNull),
13                    makeNativeMethod("isUndefined", JavaScriptValue::isUndefined),
14                    makeNativeMethod("isBool", JavaScriptValue::isBool),
15                    makeNativeMethod("isNumber", JavaScriptValue::isNumber),
16                    makeNativeMethod("isString", JavaScriptValue::isString),
17                    makeNativeMethod("isSymbol", JavaScriptValue::isSymbol),
18                    makeNativeMethod("isFunction", JavaScriptValue::isFunction),
19                    makeNativeMethod("isObject", JavaScriptValue::isObject),
20                    makeNativeMethod("getBool", JavaScriptValue::getBool),
21                    makeNativeMethod("getDouble", JavaScriptValue::getDouble),
22                    makeNativeMethod("getString", JavaScriptValue::jniGetString),
23                    makeNativeMethod("getObject", JavaScriptValue::getObject),
24                  });
25 }
26 
27 JavaScriptValue::JavaScriptValue(
28   std::weak_ptr<JavaScriptRuntime> runtime,
29   std::shared_ptr<jsi::Value> jsValue
30 ) : runtimeHolder(std::move(runtime)), jsValue(std::move(jsValue)) {
31   assert(runtimeHolder.lock() != nullptr);
32 }
33 
34 std::shared_ptr<jsi::Value> JavaScriptValue::get() {
35   return jsValue;
36 }
37 
38 std::string JavaScriptValue::kind() {
39   if (isNull()) {
40     return "null";
41   }
42   if (isUndefined()) {
43     return "undefined";
44   }
45   if (isBool()) {
46     return "boolean";
47   }
48   if (isNumber()) {
49     return "number";
50   }
51   if (isString()) {
52     return "string";
53   }
54   if (isSymbol()) {
55     return "symbol";
56   }
57   if (isFunction()) {
58     return "function";
59   }
60   if (isObject()) {
61     return "object";
62   }
63 
64   // TODO(@lukmccall): maybe throw exception?
65   return "unknown";
66 }
67 
68 bool JavaScriptValue::isNull() {
69   return jsValue->isNull();
70 }
71 
72 bool JavaScriptValue::isUndefined() {
73   return jsValue->isUndefined();
74 }
75 
76 bool JavaScriptValue::isBool() {
77   return jsValue->isBool();
78 }
79 
80 bool JavaScriptValue::isNumber() {
81   return jsValue->isNumber();
82 }
83 
84 bool JavaScriptValue::isString() {
85   return jsValue->isString();
86 }
87 
88 bool JavaScriptValue::isSymbol() {
89   return jsValue->isSymbol();
90 }
91 
92 bool JavaScriptValue::isFunction() {
93   if (jsValue->isObject()) {
94     auto runtime = runtimeHolder.lock();
95     assert(runtime != nullptr);
96     return jsValue->asObject(*runtime->get()).isFunction(*runtime->get());
97   }
98 
99   return false;
100 }
101 
102 bool JavaScriptValue::isObject() {
103   return jsValue->isObject();
104 }
105 
106 bool JavaScriptValue::getBool() {
107   return jsValue->getBool();
108 }
109 
110 double JavaScriptValue::getDouble() {
111   return jsValue->getNumber();
112 }
113 
114 std::string JavaScriptValue::getString() {
115   auto runtime = runtimeHolder.lock();
116   assert(runtime != nullptr);
117   return jsValue->getString(*runtime->get()).utf8(*runtime->get());
118 }
119 
120 jni::local_ref<JavaScriptObject::javaobject> JavaScriptValue::getObject() {
121   auto runtime = runtimeHolder.lock();
122   assert(runtime != nullptr);
123   auto jsObject = std::make_shared<jsi::Object>(jsValue->getObject(*runtime->get()));
124   return JavaScriptObject::newObjectCxxArgs(runtimeHolder, jsObject);
125 }
126 
127 jni::local_ref<jstring> JavaScriptValue::jniKind() {
128   auto result = kind();
129   return jni::make_jstring(result);
130 }
131 
132 jni::local_ref<jstring> JavaScriptValue::jniGetString() {
133   auto result = getString();
134   return jni::make_jstring(result);
135 }
136 } // namespace expo
137