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