internal import jsi // MARK: - JavaScriptRepresentable /// A type whose values can be represented in the JS runtime. public protocol JavaScriptRepresentable: Sendable, ~Copyable { /// Creates an instance of this type from the given JS value. static func fromJavaScriptValue(_ value: JavaScriptValue) -> Self /// Creates a JS value representing this value in the given runtime. func toJavaScriptValue(in runtime: JavaScriptRuntime) -> JavaScriptValue } extension Optional: JavaScriptRepresentable where Wrapped: JavaScriptRepresentable { public static func fromJavaScriptValue(_ value: JavaScriptValue) -> Self { if value.isNull() || value.isUndefined() { return nil } return Wrapped.fromJavaScriptValue(value) } public func toJavaScriptValue(in runtime: JavaScriptRuntime) -> JavaScriptValue { guard let self else { return .null } return self.toJavaScriptValue(in: runtime) } } extension Array: JavaScriptRepresentable where Element: JavaScriptRepresentable { public static func fromJavaScriptValue(_ value: JavaScriptValue) -> Self { return value.getArray().map { Element.fromJavaScriptValue($0) } } public func toJavaScriptValue(in runtime: JavaScriptRuntime) -> JavaScriptValue { let values = map { $0.toJavaScriptValue(in: runtime) } return JavaScriptArray(runtime, items: values).asValue() } } extension Dictionary: JavaScriptRepresentable where Key == String, Value: JavaScriptRepresentable { public static func fromJavaScriptValue(_ value: JavaScriptValue) -> Self { let object = value.getObject() var result: Self = [:] for key in object.getPropertyNames() { result[key] = Value.fromJavaScriptValue(object.getProperty(key)) } return result } public func toJavaScriptValue(in runtime: JavaScriptRuntime) -> JavaScriptValue { let object = JavaScriptObject(runtime) for (key, value) in self { object.setProperty(key, value: value.toJavaScriptValue(in: runtime)) } return object.asValue() } }