package expo.modules.kotlin.jni import com.facebook.jni.HybridData import expo.modules.core.interfaces.DoNotStrip /** * A Kotlin representation of jsi::Object. * Should be used only on the runtime thread. */ @Suppress("KotlinJniMissingFunction") @DoNotStrip open class JavaScriptObject @DoNotStrip internal constructor(@DoNotStrip private val mHybridData: HybridData) : Destructible { /** * The property descriptor options for the property being defined or modified. */ enum class PropertyDescriptor(val value: Int) { /** * If set, the type of this property descriptor may be changed and if the property may be deleted from the corresponding object. */ Configurable(1 shl 0), /** * If set, the property shows up during enumeration of the properties on the corresponding object. */ Enumerable(1 shl 1), /** * If set, the value associated with the property may be changed with an assignment operator. */ Writable(1 shl 2) } fun isValid() = mHybridData.isValid external fun hasProperty(name: String): Boolean external fun getProperty(name: String): JavaScriptValue operator fun get(name: String): JavaScriptValue? { if (hasProperty(name)) { return getProperty(name) } return null } external fun getPropertyNames(): Array external fun createWeak(): JavaScriptWeakObject private external fun setBoolProperty(name: String, value: Boolean) private external fun setDoubleProperty(name: String, value: Double) private external fun setStringProperty(name: String, value: String?) private external fun setJSValueProperty(name: String, value: JavaScriptValue?) private external fun setJSObjectProperty(name: String, value: JavaScriptObject?) private external fun unsetProperty(name: String) private external fun defineBoolProperty(name: String, value: Boolean, options: Int) private external fun defineDoubleProperty(name: String, value: Double, options: Int) private external fun defineStringProperty(name: String, value: String?, options: Int) private external fun defineJSValueProperty(name: String, value: JavaScriptValue?, options: Int) private external fun defineJSObjectProperty(name: String, value: JavaScriptObject?, options: Int) private external fun defineNativeDeallocator(deallocator: JNIFunctionBody) internal fun defineDeallocator(deallocator: () -> Unit) { defineNativeDeallocator { deallocator() } } external fun setExternalMemoryPressure(size: Int) fun setProperty(name: String, value: Boolean) = setBoolProperty(name, value) operator fun set(name: String, value: Boolean) = setBoolProperty(name, value) fun setProperty(name: String, value: Int) = setDoubleProperty(name, value.toDouble()) operator fun set(name: String, value: Int) = setDoubleProperty(name, value.toDouble()) fun setProperty(name: String, value: Double) = setDoubleProperty(name, value) operator fun set(name: String, value: Double) = setDoubleProperty(name, value) fun setProperty(name: String, value: String?) = setStringProperty(name, value) operator fun set(name: String, value: String?) = setStringProperty(name, value) fun setProperty(name: String, value: JavaScriptValue?) = setJSValueProperty(name, value) operator fun set(name: String, value: JavaScriptValue?) = setJSValueProperty(name, value) fun setProperty(name: String, value: JavaScriptObject?) = setJSObjectProperty(name, value) operator fun set(name: String, value: JavaScriptObject?) = setJSObjectProperty(name, value) // Needed to handle untyped null value // Without it setProperty(name, null) won't work fun setProperty(name: String, @Suppress("UNUSED_PARAMETER") `null`: Nothing?) = unsetProperty(name) operator fun set(name: String, @Suppress("UNUSED_PARAMETER") `null`: Nothing?) = unsetProperty(name) fun defineProperty( name: String, value: Boolean, options: List = emptyList() ) = defineBoolProperty(name, value, options.toCppOptions()) fun defineProperty( name: String, value: Int, options: List = emptyList() ) = defineDoubleProperty(name, value.toDouble(), options.toCppOptions()) fun defineProperty( name: String, value: Double, options: List = emptyList() ) = defineDoubleProperty(name, value, options.toCppOptions()) fun defineProperty( name: String, value: String?, options: List = emptyList() ) = defineStringProperty(name, value, options.toCppOptions()) fun defineProperty( name: String, value: JavaScriptValue?, options: List = emptyList() ) = defineJSValueProperty(name, value, options.toCppOptions()) fun defineProperty( name: String, value: JavaScriptObject?, options: List = emptyList() ) = defineJSObjectProperty(name, value, options.toCppOptions()) // Needed to handle untyped null value fun defineProperty( name: String, @Suppress("UNUSED_PARAMETER") `null`: Nothing?, options: List = emptyList() ) = defineJSObjectProperty(name, null, options.toCppOptions()) @Throws(Throwable::class) protected fun finalize() { deallocate() } override fun deallocate() { mHybridData.resetNative() } } private fun List.toCppOptions(): Int = fold(0) { acc, current -> acc or current.value }