1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #include "JavaScriptValue.h" 4 5 #include "JavaScriptRuntime.h" 6 #include "JavaScriptObject.h" 7 #include "JavaScriptTypedArray.h" 8 #include "JavaScriptFunction.h" 9 #include "TypedArray.h" 10 #include "Exceptions.h" 11 12 namespace expo { 13 void JavaScriptValue::registerNatives() { 14 registerHybrid({ 15 makeNativeMethod("kind", JavaScriptValue::jniKind), 16 makeNativeMethod("isNull", JavaScriptValue::isNull), 17 makeNativeMethod("isUndefined", JavaScriptValue::isUndefined), 18 makeNativeMethod("isBool", JavaScriptValue::isBool), 19 makeNativeMethod("isNumber", JavaScriptValue::isNumber), 20 makeNativeMethod("isString", JavaScriptValue::isString), 21 makeNativeMethod("isSymbol", JavaScriptValue::isSymbol), 22 makeNativeMethod("isFunction", JavaScriptValue::isFunction), 23 makeNativeMethod("isArray", JavaScriptValue::isArray), 24 makeNativeMethod("isTypedArray", JavaScriptValue::isTypedArray), 25 makeNativeMethod("isObject", JavaScriptValue::isObject), 26 makeNativeMethod("getBool", JavaScriptValue::getBool), 27 makeNativeMethod("getDouble", JavaScriptValue::getDouble), 28 makeNativeMethod("getString", JavaScriptValue::jniGetString), 29 makeNativeMethod("getObject", JavaScriptValue::getObject), 30 makeNativeMethod("getArray", JavaScriptValue::getArray), 31 makeNativeMethod("getTypedArray", JavaScriptValue::getTypedArray), 32 makeNativeMethod("jniGetFunction", JavaScriptValue::jniGetFunction), 33 }); 34 } 35 36 JavaScriptValue::JavaScriptValue( 37 std::weak_ptr<JavaScriptRuntime> runtime, 38 std::shared_ptr<jsi::Value> jsValue 39 ) : runtimeHolder(std::move(runtime)), jsValue(std::move(jsValue)) { 40 runtimeHolder.ensureRuntimeIsValid(); 41 } 42 43 JavaScriptValue::JavaScriptValue( 44 WeakRuntimeHolder runtime, 45 std::shared_ptr<jsi::Value> jsValue 46 ) : runtimeHolder(std::move(runtime)), jsValue(std::move(jsValue)) { 47 runtimeHolder.ensureRuntimeIsValid(); 48 } 49 50 std::shared_ptr<jsi::Value> JavaScriptValue::get() { 51 return jsValue; 52 } 53 54 std::string JavaScriptValue::kind() { 55 if (isNull()) { 56 return "null"; 57 } 58 if (isUndefined()) { 59 return "undefined"; 60 } 61 if (isBool()) { 62 return "boolean"; 63 } 64 if (isNumber()) { 65 return "number"; 66 } 67 if (isString()) { 68 return "string"; 69 } 70 if (isSymbol()) { 71 return "symbol"; 72 } 73 if (isFunction()) { 74 return "function"; 75 } 76 if (isArray()) { 77 return "array"; 78 } 79 if (isObject()) { 80 return "object"; 81 } 82 83 throwNewJavaException( 84 UnexpectedException::create("Unknown type").get() 85 ); 86 } 87 88 bool JavaScriptValue::isNull() { 89 return jsValue->isNull(); 90 } 91 92 bool JavaScriptValue::isUndefined() { 93 return jsValue->isUndefined(); 94 } 95 96 bool JavaScriptValue::isBool() { 97 return jsValue->isBool(); 98 } 99 100 bool JavaScriptValue::isNumber() { 101 return jsValue->isNumber(); 102 } 103 104 bool JavaScriptValue::isString() { 105 return jsValue->isString(); 106 } 107 108 bool JavaScriptValue::isSymbol() { 109 return jsValue->isSymbol(); 110 } 111 112 bool JavaScriptValue::isFunction() { 113 if (jsValue->isObject()) { 114 auto &jsRuntime = runtimeHolder.getJSRuntime(); 115 return jsValue->asObject(jsRuntime).isFunction(jsRuntime); 116 } 117 118 return false; 119 } 120 121 bool JavaScriptValue::isArray() { 122 if (jsValue->isObject()) { 123 auto &jsRuntime = runtimeHolder.getJSRuntime(); 124 return jsValue->asObject(jsRuntime).isArray(jsRuntime); 125 } 126 127 return false; 128 } 129 130 bool JavaScriptValue::isObject() { 131 return jsValue->isObject(); 132 } 133 134 bool JavaScriptValue::isTypedArray() { 135 if (jsValue->isObject()) { 136 jsi::Runtime &jsRuntime = runtimeHolder.getJSRuntime(); 137 return expo::isTypedArray(jsRuntime, jsValue->getObject(jsRuntime)); 138 } 139 return false; 140 } 141 142 bool JavaScriptValue::getBool() { 143 return jsValue->getBool(); 144 } 145 146 double JavaScriptValue::getDouble() { 147 return jsValue->getNumber(); 148 } 149 150 std::string JavaScriptValue::getString() { 151 auto &jsRuntime = runtimeHolder.getJSRuntime(); 152 return jsValue->getString(jsRuntime).utf8(jsRuntime); 153 } 154 155 jni::local_ref<JavaScriptObject::javaobject> JavaScriptValue::getObject() { 156 auto &jsRuntime = runtimeHolder.getJSRuntime(); 157 auto jsObject = std::make_shared<jsi::Object>(jsValue->getObject(jsRuntime)); 158 return JavaScriptObject::newObjectCxxArgs(runtimeHolder, jsObject); 159 } 160 161 jni::local_ref<JavaScriptFunction::javaobject> JavaScriptValue::jniGetFunction() { 162 auto &jsRuntime = runtimeHolder.getJSRuntime(); 163 auto jsFunction = std::make_shared<jsi::Function>( 164 jsValue->getObject(jsRuntime).asFunction(jsRuntime)); 165 return JavaScriptFunction::newObjectCxxArgs(runtimeHolder, jsFunction); 166 } 167 168 jni::local_ref<jni::JArrayClass<JavaScriptValue::javaobject>> JavaScriptValue::getArray() { 169 auto &jsRuntime = runtimeHolder.getJSRuntime(); 170 171 auto jsArray = jsValue 172 ->getObject(jsRuntime) 173 .asArray(jsRuntime); 174 size_t size = jsArray.size(jsRuntime); 175 176 auto result = jni::JArrayClass<JavaScriptValue::javaobject>::newArray(size); 177 for (size_t i = 0; i < size; i++) { 178 auto element = JavaScriptValue::newObjectCxxArgs( 179 runtimeHolder, 180 std::make_shared<jsi::Value>(jsArray.getValueAtIndex(jsRuntime, i)) 181 ); 182 183 result->setElement(i, element.release()); 184 } 185 return result; 186 } 187 188 jni::local_ref<jstring> JavaScriptValue::jniKind() { 189 auto result = kind(); 190 return jni::make_jstring(result); 191 } 192 193 jni::local_ref<jstring> JavaScriptValue::jniGetString() { 194 auto result = getString(); 195 return jni::make_jstring(result); 196 } 197 198 jni::local_ref<JavaScriptTypedArray::javaobject> JavaScriptValue::getTypedArray() { 199 auto &jsRuntime = runtimeHolder.getJSRuntime(); 200 auto jsObject = std::make_shared<jsi::Object>(jsValue->getObject(jsRuntime)); 201 return JavaScriptTypedArray::newObjectCxxArgs(runtimeHolder, jsObject); 202 } 203 } // namespace expo 204