@@ -832,6 +832,8 @@ struct StackCodegen {
832832 return liftNullableExpression ( wrappedType: wrappedType, kind: kind)
833833 case . array( let elementType) :
834834 return liftArrayExpression ( elementType: elementType)
835+ case . dictionary( let valueType) :
836+ return liftDictionaryExpression ( valueType: valueType)
835837 case . closure:
836838 return " JSObject.bridgeJSLiftParameter() "
837839 case . void, . namespaceEnum:
@@ -849,7 +851,7 @@ struct StackCodegen {
849851 return liftArrayExpressionInline ( elementType: elementType)
850852 case . swiftProtocol( let protocolName) :
851853 return " [Any \( raw: protocolName) ].bridgeJSLiftParameter() "
852- case . nullable, . array, . closure:
854+ case . nullable, . array, . closure, . dictionary :
853855 return liftArrayExpressionInline ( elementType: elementType)
854856 case . void, . namespaceEnum:
855857 fatalError ( " Invalid array element type: \( elementType) " )
@@ -873,6 +875,51 @@ struct StackCodegen {
873875 """
874876 }
875877
878+ func liftDictionaryExpression( valueType: BridgeType ) -> ExprSyntax {
879+ switch valueType {
880+ case . int, . uint, . float, . double, . string, . bool, . jsValue,
881+ . jsObject( nil ) , . swiftStruct, . caseEnum, . swiftHeapObject,
882+ . unsafePointer, . rawValueEnum, . associatedValueEnum:
883+ return " [String: \( raw: valueType. swiftType) ].bridgeJSLiftParameter() "
884+ case . jsObject( let className? ) :
885+ return """
886+ {
887+ let __dict = [String: JSObject].bridgeJSLiftParameter()
888+ return __dict.mapValues { \( raw: className) (unsafelyWrapping: $0) }
889+ }()
890+ """
891+ case . swiftProtocol( let protocolName) :
892+ return """
893+ {
894+ let __dict = [String: JSObject].bridgeJSLiftParameter()
895+ return __dict.mapValues { $0 as! Any \( raw: protocolName) }
896+ }()
897+ """
898+ case . nullable, . array, . dictionary, . closure:
899+ return liftDictionaryExpressionInline ( valueType: valueType)
900+ case . void, . namespaceEnum:
901+ fatalError ( " Invalid dictionary value type: \( valueType) " )
902+ }
903+ }
904+
905+ private func liftDictionaryExpressionInline( valueType: BridgeType ) -> ExprSyntax {
906+ let valueLift = liftExpression ( for: valueType)
907+ let swiftTypeName = valueType. swiftType
908+ return """
909+ {
910+ let __count = Int(_swift_js_pop_i32())
911+ var __result: [String: \( raw: swiftTypeName) ] = [:]
912+ __result.reserveCapacity(__count)
913+ for _ in 0..<__count {
914+ let __value = \( valueLift)
915+ let __key = String.bridgeJSLiftParameter()
916+ __result[__key] = __value
917+ }
918+ return __result
919+ }()
920+ """
921+ }
922+
876923 private func liftNullableExpression( wrappedType: BridgeType , kind: JSOptionalKind ) -> ExprSyntax {
877924 let typeName = kind == . null ? " Optional " : " JSUndefinedOr "
878925 switch wrappedType {
@@ -897,6 +944,23 @@ struct StackCodegen {
897944 }
898945 }()
899946 """
947+ case . dictionary( let valueType) :
948+ let dictionaryLift = liftDictionaryExpression ( valueType: valueType)
949+ let swiftTypeName = valueType. swiftType
950+ let absentExpr =
951+ kind == . null
952+ ? " \( typeName) <[String: \( swiftTypeName) ]>.none "
953+ : " \( typeName) <[String: \( swiftTypeName) ]>.undefinedValue "
954+ return """
955+ {
956+ let __isSome = _swift_js_pop_i32()
957+ if __isSome == 0 {
958+ return \( raw: absentExpr)
959+ } else {
960+ return \( dictionaryLift)
961+ }
962+ }()
963+ """
900964 case . nullable, . void, . namespaceEnum, . closure, . unsafePointer, . swiftProtocol:
901965 fatalError ( " Invalid nullable wrapped type: \( wrappedType) " )
902966 }
@@ -935,6 +999,8 @@ struct StackCodegen {
935999 return [ ]
9361000 case . array( let elementType) :
9371001 return lowerArrayStatements ( elementType: elementType, accessor: accessor, varPrefix: varPrefix)
1002+ case . dictionary( let valueType) :
1003+ return lowerDictionaryStatements ( valueType: valueType, accessor: accessor, varPrefix: varPrefix)
9381004 }
9391005 }
9401006
@@ -952,7 +1018,7 @@ struct StackCodegen {
9521018 return [ " \( raw: accessor) .map { $0.jsObject }.bridgeJSLowerReturn() " ]
9531019 case . swiftProtocol( let protocolName) :
9541020 return [ " \( raw: accessor) .map { $0 as! Any \( raw: protocolName) }.bridgeJSLowerReturn() " ]
955- case . nullable, . array, . closure:
1021+ case . nullable, . array, . closure, . dictionary :
9561022 return lowerArrayStatementsInline (
9571023 elementType: elementType,
9581024 accessor: accessor,
@@ -986,6 +1052,65 @@ struct StackCodegen {
9861052 return statements
9871053 }
9881054
1055+ private func lowerDictionaryStatements(
1056+ valueType: BridgeType ,
1057+ accessor: String ,
1058+ varPrefix: String
1059+ ) -> [ CodeBlockItemSyntax ] {
1060+ switch valueType {
1061+ case . int, . uint, . float, . double, . string, . bool, . jsValue,
1062+ . jsObject( nil ) , . swiftStruct, . caseEnum, . swiftHeapObject,
1063+ . unsafePointer, . rawValueEnum, . associatedValueEnum:
1064+ return [ " \( raw: accessor) .bridgeJSLowerReturn() " ]
1065+ case . jsObject( _? ) :
1066+ return [ " \( raw: accessor) .mapValues { $0.jsObject }.bridgeJSLowerReturn() " ]
1067+ case . swiftProtocol( let protocolName) :
1068+ return [ " \( raw: accessor) .mapValues { $0 as! Any \( raw: protocolName) }.bridgeJSLowerReturn() " ]
1069+ case . nullable, . array, . dictionary, . closure:
1070+ return lowerDictionaryStatementsInline (
1071+ valueType: valueType,
1072+ accessor: accessor,
1073+ varPrefix: varPrefix
1074+ )
1075+ case . void, . namespaceEnum:
1076+ fatalError ( " Invalid dictionary value type: \( valueType) " )
1077+ }
1078+ }
1079+
1080+ private func lowerDictionaryStatementsInline(
1081+ valueType: BridgeType ,
1082+ accessor: String ,
1083+ varPrefix: String
1084+ ) -> [ CodeBlockItemSyntax ] {
1085+ var statements : [ CodeBlockItemSyntax ] = [ ]
1086+ let pairVarName = " __bjs_kv_ \( varPrefix) "
1087+ statements. append ( " for \( raw: pairVarName) in \( raw: accessor) { " )
1088+ statements. append ( " let __bjs_key_ \( raw: varPrefix) = \( raw: pairVarName) .key " )
1089+ statements. append ( " let __bjs_value_ \( raw: varPrefix) = \( raw: pairVarName) .value " )
1090+
1091+ let keyStatements = lowerStatements (
1092+ for: . string,
1093+ accessor: " __bjs_key_ \( varPrefix) " ,
1094+ varPrefix: " \( varPrefix) _key "
1095+ )
1096+ for stmt in keyStatements {
1097+ statements. append ( stmt)
1098+ }
1099+
1100+ let valueStatements = lowerStatements (
1101+ for: valueType,
1102+ accessor: " __bjs_value_ \( varPrefix) " ,
1103+ varPrefix: " \( varPrefix) _value "
1104+ )
1105+ for stmt in valueStatements {
1106+ statements. append ( stmt)
1107+ }
1108+
1109+ statements. append ( " } " )
1110+ statements. append ( " _swift_js_push_i32(Int32( \( raw: accessor) .count)) " )
1111+ return statements
1112+ }
1113+
9891114 private func lowerOptionalStatements(
9901115 wrappedType: BridgeType ,
9911116 accessor: String ,
@@ -1033,6 +1158,8 @@ struct StackCodegen {
10331158 return [ " \( raw: unwrappedVar) .jsObject.bridgeJSLowerStackReturn() " ]
10341159 case . array( let elementType) :
10351160 return lowerArrayStatements ( elementType: elementType, accessor: unwrappedVar, varPrefix: varPrefix)
1161+ case . dictionary( let valueType) :
1162+ return lowerDictionaryStatements ( valueType: valueType, accessor: unwrappedVar, varPrefix: varPrefix)
10361163 default :
10371164 return [ " preconditionFailure( \" BridgeJS: unsupported optional wrapped type \" ) " ]
10381165 }
@@ -1616,6 +1743,7 @@ extension BridgeType {
16161743 case . nullable( let wrappedType, let kind) :
16171744 return kind == . null ? " Optional< \( wrappedType. swiftType) > " : " JSUndefinedOr< \( wrappedType. swiftType) > "
16181745 case . array( let elementType) : return " [ \( elementType. swiftType) ] "
1746+ case . dictionary( let valueType) : return " [String: \( valueType. swiftType) ] "
16191747 case . caseEnum( let name) : return name
16201748 case . rawValueEnum( let name, _) : return name
16211749 case . associatedValueEnum( let name) : return name
@@ -1675,7 +1803,7 @@ extension BridgeType {
16751803 throw BridgeJSCoreError ( " Namespace enums are not supported to pass as parameters " )
16761804 case . closure:
16771805 return LiftingIntrinsicInfo ( parameters: [ ( " callbackId " , . i32) ] )
1678- case . array:
1806+ case . array, . dictionary :
16791807 return LiftingIntrinsicInfo ( parameters: [ ] )
16801808 }
16811809 }
@@ -1726,7 +1854,7 @@ extension BridgeType {
17261854 throw BridgeJSCoreError ( " Namespace enums are not supported to pass as parameters " )
17271855 case . closure:
17281856 return . swiftHeapObject
1729- case . array:
1857+ case . array, . dictionary :
17301858 return . array
17311859 }
17321860 }
0 commit comments