1a416e6dbSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2a416e6dbSŁukasz Kosmaty
3a416e6dbSŁukasz Kosmaty #include "JavaScriptValue.h"
4a416e6dbSŁukasz Kosmaty
5a416e6dbSŁukasz Kosmaty #include "JavaScriptRuntime.h"
6a416e6dbSŁukasz Kosmaty #include "JavaScriptObject.h"
705c5e37dSŁukasz Kosmaty #include "JavaScriptTypedArray.h"
8879827bbSŁukasz Kosmaty #include "JavaScriptFunction.h"
905c5e37dSŁukasz Kosmaty #include "TypedArray.h"
10ce6f2823SŁukasz Kosmaty #include "Exceptions.h"
11*29e8b6f8SŁukasz Kosmaty #include "JSIInteropModuleRegistry.h"
12a416e6dbSŁukasz Kosmaty
13a416e6dbSŁukasz Kosmaty namespace expo {
registerNatives()14a416e6dbSŁukasz Kosmaty void JavaScriptValue::registerNatives() {
15a416e6dbSŁukasz Kosmaty registerHybrid({
16a416e6dbSŁukasz Kosmaty makeNativeMethod("kind", JavaScriptValue::jniKind),
17a416e6dbSŁukasz Kosmaty makeNativeMethod("isNull", JavaScriptValue::isNull),
18a416e6dbSŁukasz Kosmaty makeNativeMethod("isUndefined", JavaScriptValue::isUndefined),
19a416e6dbSŁukasz Kosmaty makeNativeMethod("isBool", JavaScriptValue::isBool),
20a416e6dbSŁukasz Kosmaty makeNativeMethod("isNumber", JavaScriptValue::isNumber),
21a416e6dbSŁukasz Kosmaty makeNativeMethod("isString", JavaScriptValue::isString),
22a416e6dbSŁukasz Kosmaty makeNativeMethod("isSymbol", JavaScriptValue::isSymbol),
23a416e6dbSŁukasz Kosmaty makeNativeMethod("isFunction", JavaScriptValue::isFunction),
244b11e9d6SŁukasz Kosmaty makeNativeMethod("isArray", JavaScriptValue::isArray),
2505c5e37dSŁukasz Kosmaty makeNativeMethod("isTypedArray", JavaScriptValue::isTypedArray),
26a416e6dbSŁukasz Kosmaty makeNativeMethod("isObject", JavaScriptValue::isObject),
27a416e6dbSŁukasz Kosmaty makeNativeMethod("getBool", JavaScriptValue::getBool),
28a416e6dbSŁukasz Kosmaty makeNativeMethod("getDouble", JavaScriptValue::getDouble),
29a416e6dbSŁukasz Kosmaty makeNativeMethod("getString", JavaScriptValue::jniGetString),
30a416e6dbSŁukasz Kosmaty makeNativeMethod("getObject", JavaScriptValue::getObject),
314b11e9d6SŁukasz Kosmaty makeNativeMethod("getArray", JavaScriptValue::getArray),
3205c5e37dSŁukasz Kosmaty makeNativeMethod("getTypedArray", JavaScriptValue::getTypedArray),
33879827bbSŁukasz Kosmaty makeNativeMethod("jniGetFunction", JavaScriptValue::jniGetFunction),
34a416e6dbSŁukasz Kosmaty });
35a416e6dbSŁukasz Kosmaty }
36a416e6dbSŁukasz Kosmaty
JavaScriptValue(std::weak_ptr<JavaScriptRuntime> runtime,std::shared_ptr<jsi::Value> jsValue)37a416e6dbSŁukasz Kosmaty JavaScriptValue::JavaScriptValue(
38a416e6dbSŁukasz Kosmaty std::weak_ptr<JavaScriptRuntime> runtime,
39a416e6dbSŁukasz Kosmaty std::shared_ptr<jsi::Value> jsValue
40a416e6dbSŁukasz Kosmaty ) : runtimeHolder(std::move(runtime)), jsValue(std::move(jsValue)) {
41256b5942SŁukasz Kosmaty runtimeHolder.ensureRuntimeIsValid();
42256b5942SŁukasz Kosmaty }
43256b5942SŁukasz Kosmaty
JavaScriptValue(WeakRuntimeHolder runtime,std::shared_ptr<jsi::Value> jsValue)44256b5942SŁukasz Kosmaty JavaScriptValue::JavaScriptValue(
45256b5942SŁukasz Kosmaty WeakRuntimeHolder runtime,
46256b5942SŁukasz Kosmaty std::shared_ptr<jsi::Value> jsValue
47256b5942SŁukasz Kosmaty ) : runtimeHolder(std::move(runtime)), jsValue(std::move(jsValue)) {
48256b5942SŁukasz Kosmaty runtimeHolder.ensureRuntimeIsValid();
49a416e6dbSŁukasz Kosmaty }
50a416e6dbSŁukasz Kosmaty
get()5114c0f05dSŁukasz Kosmaty std::shared_ptr<jsi::Value> JavaScriptValue::get() {
5214c0f05dSŁukasz Kosmaty return jsValue;
5314c0f05dSŁukasz Kosmaty }
5414c0f05dSŁukasz Kosmaty
kind()55a416e6dbSŁukasz Kosmaty std::string JavaScriptValue::kind() {
56a416e6dbSŁukasz Kosmaty if (isNull()) {
57a416e6dbSŁukasz Kosmaty return "null";
58a416e6dbSŁukasz Kosmaty }
59a416e6dbSŁukasz Kosmaty if (isUndefined()) {
60a416e6dbSŁukasz Kosmaty return "undefined";
61a416e6dbSŁukasz Kosmaty }
62a416e6dbSŁukasz Kosmaty if (isBool()) {
63a416e6dbSŁukasz Kosmaty return "boolean";
64a416e6dbSŁukasz Kosmaty }
65a416e6dbSŁukasz Kosmaty if (isNumber()) {
66a416e6dbSŁukasz Kosmaty return "number";
67a416e6dbSŁukasz Kosmaty }
68a416e6dbSŁukasz Kosmaty if (isString()) {
69a416e6dbSŁukasz Kosmaty return "string";
70a416e6dbSŁukasz Kosmaty }
71a416e6dbSŁukasz Kosmaty if (isSymbol()) {
72a416e6dbSŁukasz Kosmaty return "symbol";
73a416e6dbSŁukasz Kosmaty }
74a416e6dbSŁukasz Kosmaty if (isFunction()) {
75a416e6dbSŁukasz Kosmaty return "function";
76a416e6dbSŁukasz Kosmaty }
774b11e9d6SŁukasz Kosmaty if (isArray()) {
784b11e9d6SŁukasz Kosmaty return "array";
794b11e9d6SŁukasz Kosmaty }
80a416e6dbSŁukasz Kosmaty if (isObject()) {
81a416e6dbSŁukasz Kosmaty return "object";
82a416e6dbSŁukasz Kosmaty }
83a416e6dbSŁukasz Kosmaty
84e0f520f5SKudo Chien throwNewJavaException(
85ce6f2823SŁukasz Kosmaty UnexpectedException::create("Unknown type").get()
86ce6f2823SŁukasz Kosmaty );
87a416e6dbSŁukasz Kosmaty }
88a416e6dbSŁukasz Kosmaty
isNull()89a416e6dbSŁukasz Kosmaty bool JavaScriptValue::isNull() {
90a416e6dbSŁukasz Kosmaty return jsValue->isNull();
91a416e6dbSŁukasz Kosmaty }
92a416e6dbSŁukasz Kosmaty
isUndefined()93a416e6dbSŁukasz Kosmaty bool JavaScriptValue::isUndefined() {
94a416e6dbSŁukasz Kosmaty return jsValue->isUndefined();
95a416e6dbSŁukasz Kosmaty }
96a416e6dbSŁukasz Kosmaty
isBool()97a416e6dbSŁukasz Kosmaty bool JavaScriptValue::isBool() {
98a416e6dbSŁukasz Kosmaty return jsValue->isBool();
99a416e6dbSŁukasz Kosmaty }
100a416e6dbSŁukasz Kosmaty
isNumber()101a416e6dbSŁukasz Kosmaty bool JavaScriptValue::isNumber() {
102a416e6dbSŁukasz Kosmaty return jsValue->isNumber();
103a416e6dbSŁukasz Kosmaty }
104a416e6dbSŁukasz Kosmaty
isString()105a416e6dbSŁukasz Kosmaty bool JavaScriptValue::isString() {
106a416e6dbSŁukasz Kosmaty return jsValue->isString();
107a416e6dbSŁukasz Kosmaty }
108a416e6dbSŁukasz Kosmaty
isSymbol()109a416e6dbSŁukasz Kosmaty bool JavaScriptValue::isSymbol() {
110a416e6dbSŁukasz Kosmaty return jsValue->isSymbol();
111a416e6dbSŁukasz Kosmaty }
112a416e6dbSŁukasz Kosmaty
isFunction()113a416e6dbSŁukasz Kosmaty bool JavaScriptValue::isFunction() {
114a416e6dbSŁukasz Kosmaty if (jsValue->isObject()) {
115256b5942SŁukasz Kosmaty auto &jsRuntime = runtimeHolder.getJSRuntime();
116256b5942SŁukasz Kosmaty return jsValue->asObject(jsRuntime).isFunction(jsRuntime);
117a416e6dbSŁukasz Kosmaty }
118a416e6dbSŁukasz Kosmaty
119a416e6dbSŁukasz Kosmaty return false;
120a416e6dbSŁukasz Kosmaty }
121a416e6dbSŁukasz Kosmaty
isArray()1224b11e9d6SŁukasz Kosmaty bool JavaScriptValue::isArray() {
1234b11e9d6SŁukasz Kosmaty if (jsValue->isObject()) {
124256b5942SŁukasz Kosmaty auto &jsRuntime = runtimeHolder.getJSRuntime();
125256b5942SŁukasz Kosmaty return jsValue->asObject(jsRuntime).isArray(jsRuntime);
1264b11e9d6SŁukasz Kosmaty }
1274b11e9d6SŁukasz Kosmaty
1284b11e9d6SŁukasz Kosmaty return false;
1294b11e9d6SŁukasz Kosmaty }
1304b11e9d6SŁukasz Kosmaty
isObject()131a416e6dbSŁukasz Kosmaty bool JavaScriptValue::isObject() {
132a416e6dbSŁukasz Kosmaty return jsValue->isObject();
133a416e6dbSŁukasz Kosmaty }
134a416e6dbSŁukasz Kosmaty
isTypedArray()13505c5e37dSŁukasz Kosmaty bool JavaScriptValue::isTypedArray() {
13605c5e37dSŁukasz Kosmaty if (jsValue->isObject()) {
13705c5e37dSŁukasz Kosmaty jsi::Runtime &jsRuntime = runtimeHolder.getJSRuntime();
13805c5e37dSŁukasz Kosmaty return expo::isTypedArray(jsRuntime, jsValue->getObject(jsRuntime));
13905c5e37dSŁukasz Kosmaty }
14005c5e37dSŁukasz Kosmaty return false;
14105c5e37dSŁukasz Kosmaty }
14205c5e37dSŁukasz Kosmaty
getBool()143a416e6dbSŁukasz Kosmaty bool JavaScriptValue::getBool() {
144a416e6dbSŁukasz Kosmaty return jsValue->getBool();
145a416e6dbSŁukasz Kosmaty }
146a416e6dbSŁukasz Kosmaty
getDouble()147a416e6dbSŁukasz Kosmaty double JavaScriptValue::getDouble() {
148a416e6dbSŁukasz Kosmaty return jsValue->getNumber();
149a416e6dbSŁukasz Kosmaty }
150a416e6dbSŁukasz Kosmaty
getString()151a416e6dbSŁukasz Kosmaty std::string JavaScriptValue::getString() {
152256b5942SŁukasz Kosmaty auto &jsRuntime = runtimeHolder.getJSRuntime();
153256b5942SŁukasz Kosmaty return jsValue->getString(jsRuntime).utf8(jsRuntime);
154a416e6dbSŁukasz Kosmaty }
155a416e6dbSŁukasz Kosmaty
getObject()156a416e6dbSŁukasz Kosmaty jni::local_ref<JavaScriptObject::javaobject> JavaScriptValue::getObject() {
157256b5942SŁukasz Kosmaty auto &jsRuntime = runtimeHolder.getJSRuntime();
158256b5942SŁukasz Kosmaty auto jsObject = std::make_shared<jsi::Object>(jsValue->getObject(jsRuntime));
159*29e8b6f8SŁukasz Kosmaty return JavaScriptObject::newInstance(
160*29e8b6f8SŁukasz Kosmaty runtimeHolder.getModuleRegistry(),
161*29e8b6f8SŁukasz Kosmaty runtimeHolder,
162*29e8b6f8SŁukasz Kosmaty jsObject
163*29e8b6f8SŁukasz Kosmaty );
164a416e6dbSŁukasz Kosmaty }
165a416e6dbSŁukasz Kosmaty
jniGetFunction()166879827bbSŁukasz Kosmaty jni::local_ref<JavaScriptFunction::javaobject> JavaScriptValue::jniGetFunction() {
167879827bbSŁukasz Kosmaty auto &jsRuntime = runtimeHolder.getJSRuntime();
168879827bbSŁukasz Kosmaty auto jsFunction = std::make_shared<jsi::Function>(
169879827bbSŁukasz Kosmaty jsValue->getObject(jsRuntime).asFunction(jsRuntime));
170*29e8b6f8SŁukasz Kosmaty return JavaScriptFunction::newInstance(
171*29e8b6f8SŁukasz Kosmaty runtimeHolder.getModuleRegistry(),
172*29e8b6f8SŁukasz Kosmaty runtimeHolder,
173*29e8b6f8SŁukasz Kosmaty jsFunction
174*29e8b6f8SŁukasz Kosmaty );
175879827bbSŁukasz Kosmaty }
176879827bbSŁukasz Kosmaty
getArray()1774b11e9d6SŁukasz Kosmaty jni::local_ref<jni::JArrayClass<JavaScriptValue::javaobject>> JavaScriptValue::getArray() {
178256b5942SŁukasz Kosmaty auto &jsRuntime = runtimeHolder.getJSRuntime();
179*29e8b6f8SŁukasz Kosmaty auto moduleRegistry = runtimeHolder.getModuleRegistry();
1804b11e9d6SŁukasz Kosmaty
1814b11e9d6SŁukasz Kosmaty auto jsArray = jsValue
182256b5942SŁukasz Kosmaty ->getObject(jsRuntime)
183256b5942SŁukasz Kosmaty .asArray(jsRuntime);
184256b5942SŁukasz Kosmaty size_t size = jsArray.size(jsRuntime);
1854b11e9d6SŁukasz Kosmaty
1864b11e9d6SŁukasz Kosmaty auto result = jni::JArrayClass<JavaScriptValue::javaobject>::newArray(size);
1874b11e9d6SŁukasz Kosmaty for (size_t i = 0; i < size; i++) {
188*29e8b6f8SŁukasz Kosmaty auto element = JavaScriptValue::newInstance(
189*29e8b6f8SŁukasz Kosmaty moduleRegistry,
1904b11e9d6SŁukasz Kosmaty runtimeHolder,
191256b5942SŁukasz Kosmaty std::make_shared<jsi::Value>(jsArray.getValueAtIndex(jsRuntime, i))
1924b11e9d6SŁukasz Kosmaty );
1934b11e9d6SŁukasz Kosmaty
1944b11e9d6SŁukasz Kosmaty result->setElement(i, element.release());
1954b11e9d6SŁukasz Kosmaty }
1964b11e9d6SŁukasz Kosmaty return result;
1974b11e9d6SŁukasz Kosmaty }
1984b11e9d6SŁukasz Kosmaty
jniKind()199a416e6dbSŁukasz Kosmaty jni::local_ref<jstring> JavaScriptValue::jniKind() {
200a416e6dbSŁukasz Kosmaty auto result = kind();
201a416e6dbSŁukasz Kosmaty return jni::make_jstring(result);
202a416e6dbSŁukasz Kosmaty }
203ce6f2823SŁukasz Kosmaty
jniGetString()204a416e6dbSŁukasz Kosmaty jni::local_ref<jstring> JavaScriptValue::jniGetString() {
205a416e6dbSŁukasz Kosmaty auto result = getString();
206a416e6dbSŁukasz Kosmaty return jni::make_jstring(result);
207a416e6dbSŁukasz Kosmaty }
20805c5e37dSŁukasz Kosmaty
getTypedArray()20905c5e37dSŁukasz Kosmaty jni::local_ref<JavaScriptTypedArray::javaobject> JavaScriptValue::getTypedArray() {
21005c5e37dSŁukasz Kosmaty auto &jsRuntime = runtimeHolder.getJSRuntime();
21105c5e37dSŁukasz Kosmaty auto jsObject = std::make_shared<jsi::Object>(jsValue->getObject(jsRuntime));
212*29e8b6f8SŁukasz Kosmaty return JavaScriptTypedArray::newInstance(
213*29e8b6f8SŁukasz Kosmaty runtimeHolder.getModuleRegistry(),
214*29e8b6f8SŁukasz Kosmaty runtimeHolder,
215*29e8b6f8SŁukasz Kosmaty jsObject
216*29e8b6f8SŁukasz Kosmaty );
217*29e8b6f8SŁukasz Kosmaty }
218*29e8b6f8SŁukasz Kosmaty
newInstance(JSIInteropModuleRegistry * jsiInteropModuleRegistry,std::weak_ptr<JavaScriptRuntime> runtime,std::shared_ptr<jsi::Value> jsValue)219*29e8b6f8SŁukasz Kosmaty jni::local_ref<JavaScriptValue::javaobject> JavaScriptValue::newInstance(
220*29e8b6f8SŁukasz Kosmaty JSIInteropModuleRegistry *jsiInteropModuleRegistry,
221*29e8b6f8SŁukasz Kosmaty std::weak_ptr<JavaScriptRuntime> runtime,
222*29e8b6f8SŁukasz Kosmaty std::shared_ptr<jsi::Value> jsValue
223*29e8b6f8SŁukasz Kosmaty ) {
224*29e8b6f8SŁukasz Kosmaty auto value = JavaScriptValue::newObjectCxxArgs(
225*29e8b6f8SŁukasz Kosmaty std::move(runtime),
226*29e8b6f8SŁukasz Kosmaty std::move(jsValue)
227*29e8b6f8SŁukasz Kosmaty );
228*29e8b6f8SŁukasz Kosmaty jsiInteropModuleRegistry->jniDeallocator->addReference(value);
229*29e8b6f8SŁukasz Kosmaty return value;
23005c5e37dSŁukasz Kosmaty }
231a416e6dbSŁukasz Kosmaty } // namespace expo
232