@@ -81,6 +81,12 @@ public struct ImportTS {
8181 }
8282
8383 class CallJSEmission {
84+ private struct BorrowedStringArgument {
85+ let expression : String
86+ let forwardedParameterNames : [ String ]
87+ let isOptional : Bool
88+ }
89+
8490 let abiName : String
8591 let moduleName : String
8692 let context : BridgeContext
@@ -95,13 +101,35 @@ public struct ImportTS {
95101 var stackLoweringStmts : [ String ] = [ ]
96102 // Values to extend lifetime during call
97103 var valuesToExtendLifetimeDuringCall : [ String ] = [ ]
104+ // String-like parameters lowered through borrowed UTF-8 wrappers at call site.
105+ private var borrowedStringArguments : [ BorrowedStringArgument ] = [ ]
98106
99107 init ( moduleName: String , abiName: String , context: BridgeContext = . importTS) {
100108 self . moduleName = moduleName
101109 self . abiName = abiName
102110 self . context = context
103111 }
104112
113+ private func borrowedStringInfo( for param: Parameter ) -> ( expression: String , isOptional: Bool ) ? {
114+ switch param. type {
115+ case . string:
116+ return ( param. name, false )
117+ case . rawValueEnum( _, . string) :
118+ return ( " \( param. name) .rawValue " , false )
119+ case . nullable( let wrappedType, _) :
120+ switch wrappedType {
121+ case . string:
122+ return ( " \( param. name) .asOptional " , true )
123+ case . rawValueEnum( _, . string) :
124+ return ( " \( param. name) .asOptional?.rawValue " , true )
125+ default :
126+ return nil
127+ }
128+ default :
129+ return nil
130+ }
131+ }
132+
105133 func lowerParameter( param: Parameter ) throws {
106134 let loweringInfo = try param. type. loweringParameterInfo ( context: context)
107135
@@ -115,6 +143,35 @@ public struct ImportTS {
115143 default :
116144 break
117145 }
146+
147+ if let borrowed = borrowedStringInfo ( for: param) {
148+ let destructuredNames = loweringInfo. loweredParameters. map {
149+ " \( param. name) \( $0. name. capitalizedFirstLetter) "
150+ }
151+ if loweringInfo. loweredParameters. count != destructuredNames. count || destructuredNames. isEmpty {
152+ throw BridgeJSCoreError ( " Unexpected borrowed string lowering shape for parameter \( param. name) " )
153+ }
154+
155+ for (index, ( paramName, type) ) in loweringInfo. loweredParameters. enumerated ( ) {
156+ let abiParamName : String
157+ if loweringInfo. loweredParameters. count == 1 {
158+ abiParamName = param. name
159+ } else {
160+ abiParamName = " \( param. name) \( paramName. capitalizedFirstLetter) "
161+ }
162+ abiParameterSignatures. append ( ( abiParamName, type) )
163+ abiParameterForwardings. append ( destructuredNames [ index] )
164+ }
165+ borrowedStringArguments. append (
166+ BorrowedStringArgument (
167+ expression: borrowed. expression,
168+ forwardedParameterNames: destructuredNames,
169+ isOptional: borrowed. isOptional
170+ )
171+ )
172+ return
173+ }
174+
118175 let initializerExpr = ExprSyntax ( " \( raw: param. name) .bridgeJSLowerParameter() " )
119176
120177 if loweringInfo. loweredParameters. isEmpty {
@@ -164,19 +221,35 @@ public struct ImportTS {
164221 let assign =
165222 ( returnType == . void || returnType. usesSideChannelForOptionalReturn ( ) || liftingInfo. valueToLift == nil )
166223 ? " " : " let ret = "
167- let callExpr = " \( abiName) ( \( abiParameterForwardings. joined ( separator: " , " ) ) ) "
224+ var callExpr = " \( abiName) ( \( abiParameterForwardings. joined ( separator: " , " ) ) ) "
168225
169226 if !valuesToExtendLifetimeDuringCall. isEmpty {
170- body. write (
171- " \( assign) withExtendedLifetime(( \( valuesToExtendLifetimeDuringCall. joined ( separator: " , " ) ) )) { "
172- )
173- body. indent {
174- body. write ( callExpr)
227+ callExpr =
228+ " withExtendedLifetime(( \( valuesToExtendLifetimeDuringCall. joined ( separator: " , " ) ) )) { \( callExpr) } "
229+ }
230+
231+ if !borrowedStringArguments. isEmpty {
232+ for argument in borrowedStringArguments. reversed ( ) {
233+ if argument. isOptional {
234+ guard argument. forwardedParameterNames. count == 3 else {
235+ throw BridgeJSCoreError (
236+ " Optional borrowed string argument must have 3 lowered values: \( argument. expression) "
237+ )
238+ }
239+ callExpr =
240+ " _swift_js_with_optional_borrowed_utf8( \( argument. expression) ) { \( argument. forwardedParameterNames [ 0 ] ) , \( argument. forwardedParameterNames [ 1 ] ) , \( argument. forwardedParameterNames [ 2 ] ) in \( callExpr) } "
241+ } else {
242+ guard argument. forwardedParameterNames. count == 2 else {
243+ throw BridgeJSCoreError (
244+ " Borrowed string argument must have 2 lowered values: \( argument. expression) "
245+ )
246+ }
247+ callExpr =
248+ " _swift_js_with_borrowed_utf8( \( argument. expression) ) { \( argument. forwardedParameterNames [ 0 ] ) , \( argument. forwardedParameterNames [ 1 ] ) in \( callExpr) } "
249+ }
175250 }
176- body. write ( " } " )
177- } else {
178- body. write ( " \( assign) \( callExpr) " )
179251 }
252+ body. write ( " \( assign) \( callExpr) " )
180253
181254 // Add exception check for ImportTS context
182255 if context == . importTS {
@@ -724,7 +797,7 @@ extension BridgeType {
724797 static let int = LoweringParameterInfo ( loweredParameters: [ ( " value " , . i32) ] )
725798 static let float = LoweringParameterInfo ( loweredParameters: [ ( " value " , . f32) ] )
726799 static let double = LoweringParameterInfo ( loweredParameters: [ ( " value " , . f64) ] )
727- static let string = LoweringParameterInfo ( loweredParameters: [ ( " value " , . i32) ] )
800+ static let string = LoweringParameterInfo ( loweredParameters: [ ( " bytes " , . i32 ) , ( " length " , . i32) ] )
728801 static let jsObject = LoweringParameterInfo ( loweredParameters: [ ( " value " , . i32) ] )
729802 static let jsValue = LoweringParameterInfo ( loweredParameters: [
730803 ( " kind " , . i32) ,
@@ -761,6 +834,9 @@ extension BridgeType {
761834 return LoweringParameterInfo ( loweredParameters: [ ( " value " , . i32) ] )
762835 }
763836 case . rawValueEnum( _, let rawType) :
837+ if rawType == . string {
838+ return . string
839+ }
764840 let wasmType = rawType. wasmCoreType ?? . i32
765841 return LoweringParameterInfo ( loweredParameters: [ ( " value " , wasmType) ] )
766842 case . associatedValueEnum:
0 commit comments