1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2 3 #include "JavaScriptObject.h" 4 #include "JavaScriptValue.h" 5 #include "JavaScriptRuntime.h" 6 #include "JSITypeConverter.h" 7 8 namespace expo { 9 void JavaScriptObject::registerNatives() { 10 registerHybrid({ 11 makeNativeMethod("hasProperty", JavaScriptObject::jniHasProperty), 12 makeNativeMethod("getProperty", JavaScriptObject::jniGetProperty), 13 makeNativeMethod("getPropertyNames", JavaScriptObject::jniGetPropertyNames), 14 makeNativeMethod("setBoolProperty", JavaScriptObject::setProperty<bool>), 15 makeNativeMethod("setDoubleProperty", JavaScriptObject::setProperty<double>), 16 makeNativeMethod("setStringProperty", 17 JavaScriptObject::setProperty<jni::alias_ref<jstring>>), 18 makeNativeMethod("setJSValueProperty", 19 JavaScriptObject::setProperty<jni::alias_ref<JavaScriptValue::javaobject>>), 20 makeNativeMethod("setJSObjectProperty", 21 JavaScriptObject::setProperty<jni::alias_ref<JavaScriptObject::javaobject>>), 22 makeNativeMethod("unsetProperty", JavaScriptObject::unsetProperty), 23 makeNativeMethod("defineBoolProperty", JavaScriptObject::defineProperty<bool>), 24 makeNativeMethod("defineDoubleProperty", 25 JavaScriptObject::defineProperty<double>), 26 makeNativeMethod("defineStringProperty", 27 JavaScriptObject::defineProperty<jni::alias_ref<jstring>>), 28 makeNativeMethod("defineJSValueProperty", 29 JavaScriptObject::defineProperty<jni::alias_ref<JavaScriptValue::javaobject>>), 30 makeNativeMethod("defineJSObjectProperty", 31 JavaScriptObject::defineProperty<jni::alias_ref<JavaScriptObject::javaobject>>), 32 }); 33 } 34 35 JavaScriptObject::JavaScriptObject( 36 std::weak_ptr<JavaScriptRuntime> runtime, 37 std::shared_ptr<jsi::Object> jsObject 38 ) : runtimeHolder(std::move(runtime)), jsObject(std::move(jsObject)) { 39 assert(runtimeHolder.lock() != nullptr); 40 } 41 42 std::shared_ptr<jsi::Object> JavaScriptObject::get() { 43 return jsObject; 44 } 45 46 bool JavaScriptObject::hasProperty(const std::string &name) { 47 auto runtime = runtimeHolder.lock(); 48 assert(runtime != nullptr); 49 return jsObject->hasProperty(*runtime->get(), name.c_str()); 50 } 51 52 jsi::Value JavaScriptObject::getProperty(const std::string &name) { 53 auto runtime = runtimeHolder.lock(); 54 assert(runtime != nullptr); 55 return jsObject->getProperty(*runtime->get(), name.c_str()); 56 } 57 58 bool JavaScriptObject::jniHasProperty(jni::alias_ref<jstring> name) { 59 return hasProperty(name->toStdString()); 60 } 61 62 jni::local_ref<JavaScriptValue::javaobject> JavaScriptObject::jniGetProperty( 63 jni::alias_ref<jstring> name 64 ) { 65 auto result = std::make_shared<jsi::Value>(getProperty(name->toStdString())); 66 return JavaScriptValue::newObjectCxxArgs(runtimeHolder, result); 67 } 68 69 std::vector<std::string> JavaScriptObject::getPropertyNames() { 70 auto runtime = runtimeHolder.lock(); 71 assert(runtime != nullptr); 72 73 jsi::Array properties = jsObject->getPropertyNames(*runtime->get()); 74 auto size = properties.size(*runtime->get()); 75 76 std::vector<std::string> names(size); 77 for (size_t i = 0; i < size; i++) { 78 auto propertyName = properties 79 .getValueAtIndex(*runtime->get(), i) 80 .asString(*runtime->get()) 81 .utf8(*runtime->get()); 82 names[i] = propertyName; 83 } 84 85 return names; 86 } 87 88 jni::local_ref<jni::JArrayClass<jstring>> JavaScriptObject::jniGetPropertyNames() { 89 std::vector<std::string> cResult = getPropertyNames(); 90 auto paredResult = jni::JArrayClass<jstring>::newArray(cResult.size()); 91 for (size_t i = 0; i < cResult.size(); i++) { 92 paredResult->setElement(i, jni::make_jstring(cResult[i]).get()); 93 } 94 95 return paredResult; 96 } 97 98 void JavaScriptObject::setProperty(const std::string &name, jsi::Value value) { 99 auto runtime = runtimeHolder.lock(); 100 assert(runtime != nullptr); 101 jsObject->setProperty(*runtime->get(), name.c_str(), value); 102 } 103 104 void JavaScriptObject::unsetProperty(jni::alias_ref<jstring> name) { 105 auto runtime = runtimeHolder.lock(); 106 assert(runtime != nullptr); 107 auto cName = name->toStdString(); 108 jsObject->setProperty( 109 *runtime->get(), 110 cName.c_str(), 111 jsi::Value::undefined() 112 ); 113 } 114 115 jsi::Object JavaScriptObject::preparePropertyDescriptor( 116 jsi::Runtime &jsRuntime, 117 int options 118 ) { 119 jsi::Object descriptor(jsRuntime); 120 descriptor.setProperty(jsRuntime, "configurable", (bool) ((1 << 0) & options)); 121 descriptor.setProperty(jsRuntime, "enumerable", (bool) ((1 << 1) & options)); 122 descriptor.setProperty(jsRuntime, "writable", (bool) ((1 << 2) & options)); 123 return descriptor; 124 } 125 } // namespace expo 126