import CoreGraphics internal import ExpoModulesJSI_Cxx internal import jsi /// A type whose values can be represented as `facebook.jsi.Value`. internal protocol JSIRepresentable: JavaScriptRepresentable, Sendable, ~Copyable { /// Creates an instance of this type from the given `facebook.jsi.Value` in `facebook.jsi.IRuntime`. static func fromJSIValue(_ value: borrowing facebook.jsi.Value, in runtime: facebook.jsi.IRuntime) -> Self /// Creates a JSI value representing this value in the given JSI runtime. func toJSIValue(in runtime: facebook.jsi.IRuntime) -> facebook.jsi.Value } extension JSIRepresentable { public static func fromJavaScriptValue(_ value: JavaScriptValue) -> Self { guard let jsiRuntime = value.runtime else { FatalError.runtimeLost() } return Self.fromJSIValue(value.pointee, in: jsiRuntime.pointee) } public func toJavaScriptValue(in runtime: JavaScriptRuntime) -> JavaScriptValue { return JavaScriptValue(runtime, toJSIValue(in: runtime.pointee)) } static func fromJSIValue(_ value: borrowing facebook.jsi.Value, in runtime: facebook.jsi.IRuntime) -> Self { FatalError.unimplemented() } func toJSIValue(in runtime: facebook.jsi.IRuntime) -> facebook.jsi.Value { FatalError.unimplemented() } } // MARK: - Implementations extension Bool: JSIRepresentable { static func fromJSIValue(_ value: borrowing facebook.jsi.Value, in runtime: facebook.jsi.IRuntime) -> Bool { return value.getBool() } func toJSIValue(in runtime: facebook.jsi.IRuntime) -> facebook.jsi.Value { return facebook.jsi.Value(self) } } internal protocol JSIRepresentableNumber: JSIRepresentable {} extension JSIRepresentableNumber { static func fromJSIValue(_ value: borrowing facebook.jsi.Value, in runtime: facebook.jsi.IRuntime) -> Int where Self: FixedWidthInteger { return Int(value.getNumber()) } static func fromJSIValue(_ value: borrowing facebook.jsi.Value, in runtime: facebook.jsi.IRuntime) -> Double where Self: BinaryFloatingPoint { return value.getNumber() } func toJSIValue(in runtime: facebook.jsi.IRuntime) -> facebook.jsi.Value where Self: FixedWidthInteger { return facebook.jsi.Value(Double(self)) } func toJSIValue(in runtime: facebook.jsi.IRuntime) -> facebook.jsi.Value where Self: BinaryFloatingPoint { return facebook.jsi.Value(Double(self)) } } extension Int: JSIRepresentableNumber {} extension Int8: JSIRepresentableNumber {} extension Int16: JSIRepresentableNumber {} extension Int32: JSIRepresentableNumber {} extension Int64: JSIRepresentableNumber {} extension UInt: JSIRepresentableNumber {} extension UInt8: JSIRepresentableNumber {} extension UInt16: JSIRepresentableNumber {} extension UInt32: JSIRepresentableNumber {} extension UInt64: JSIRepresentableNumber {} #if arch(arm64) || (!os(macOS) && !targetEnvironment(macCatalyst)) extension Float16: JSIRepresentableNumber {} #endif extension Float32: JSIRepresentableNumber {} extension Float64: JSIRepresentableNumber {} extension CGFloat: JSIRepresentableNumber {} extension String: JSIRepresentable { static func fromJSIValue(_ value: borrowing facebook.jsi.Value, in runtime: facebook.jsi.IRuntime) -> String { return String(value.getString(runtime).utf8(runtime)) } func toJSIValue(in runtime: facebook.jsi.IRuntime) -> facebook.jsi.Value { return facebook.jsi.Value(runtime, facebook.jsi.String.createFromUtf8(runtime, std.string(self))) } } extension Optional: JSIRepresentable where Wrapped: JSIRepresentable { static func fromJSIValue(_ value: borrowing facebook.jsi.Value, in runtime: facebook.jsi.IRuntime) -> Self { if value.isNull() || value.isUndefined() { return nil } return Wrapped.fromJSIValue(value, in: runtime) } func toJSIValue(in runtime: facebook.jsi.IRuntime) -> facebook.jsi.Value { return self?.toJSIValue(in: runtime) ?? .null() } } extension Array: JSIRepresentable where Element: JSIRepresentable { static func fromJSIValue(_ value: borrowing facebook.jsi.Value, in runtime: facebook.jsi.IRuntime) -> [Element] { let jsiArray = value.getObject(runtime).getArray(runtime) let size = jsiArray.size(runtime) var result: Self = [] result.reserveCapacity(size) for index in 0.. facebook.jsi.Value { let jsiArray = facebook.jsi.Array(runtime, count) for index in 0.. [Key: Value] { let object = value.getObject(runtime) let propertyNames = object.getPropertyNames(runtime) let size = propertyNames.size(runtime) var result: Self = [:] for index in 0.. facebook.jsi.Value { let object = facebook.jsi.Object(runtime) for (key, value) in self { let keyString = String(describing: key) expo.setProperty(runtime, object, keyString, value.toJSIValue(in: runtime)) } return facebook.jsi.Value(runtime, object) } }