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