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::string JavaScriptValue::kind() {
35   if (isNull()) {
36     return "null";
37   }
38   if (isUndefined()) {
39     return "undefined";
40   }
41   if (isBool()) {
42     return "boolean";
43   }
44   if (isNumber()) {
45     return "number";
46   }
47   if (isString()) {
48     return "string";
49   }
50   if (isSymbol()) {
51     return "symbol";
52   }
53   if (isFunction()) {
54     return "function";
55   }
56   if (isObject()) {
57     return "object";
58   }
59 
60   // TODO(@lukmccall): maybe throw exception?
61   return "unknown";
62 }
63 
64 bool JavaScriptValue::isNull() {
65   return jsValue->isNull();
66 }
67 
68 bool JavaScriptValue::isUndefined() {
69   return jsValue->isUndefined();
70 }
71 
72 bool JavaScriptValue::isBool() {
73   return jsValue->isBool();
74 }
75 
76 bool JavaScriptValue::isNumber() {
77   return jsValue->isNumber();
78 }
79 
80 bool JavaScriptValue::isString() {
81   return jsValue->isString();
82 }
83 
84 bool JavaScriptValue::isSymbol() {
85   return jsValue->isSymbol();
86 }
87 
88 bool JavaScriptValue::isFunction() {
89   if (jsValue->isObject()) {
90     auto runtime = runtimeHolder.lock();
91     assert(runtime != nullptr);
92     return jsValue->asObject(*runtime->get()).isFunction(*runtime->get());
93   }
94 
95   return false;
96 }
97 
98 bool JavaScriptValue::isObject() {
99   return jsValue->isObject();
100 }
101 
102 bool JavaScriptValue::getBool() {
103   return jsValue->getBool();
104 }
105 
106 double JavaScriptValue::getDouble() {
107   return jsValue->getNumber();
108 }
109 
110 std::string JavaScriptValue::getString() {
111   auto runtime = runtimeHolder.lock();
112   assert(runtime != nullptr);
113   return jsValue->getString(*runtime->get()).utf8(*runtime->get());
114 }
115 
116 jni::local_ref<JavaScriptObject::javaobject> JavaScriptValue::getObject() {
117   auto runtime = runtimeHolder.lock();
118   assert(runtime != nullptr);
119   auto jsObject = std::make_shared<jsi::Object>(jsValue->getObject(*runtime->get()));
120   return JavaScriptObject::newObjectCxxArgs(runtimeHolder, jsObject);
121 }
122 
123 jni::local_ref<jstring> JavaScriptValue::jniKind() {
124   auto result = kind();
125   return jni::make_jstring(result);
126 }
127 
128 jni::local_ref<jstring> JavaScriptValue::jniGetString() {
129   auto result = getString();
130   return jni::make_jstring(result);
131 }
132 } // namespace expo
133