Skip to content

Commit 0bb690a

Browse files
committed
BridgeJS: Support generic functions at the Swift and JavaScript boundary
1 parent d58d2c6 commit 0bb690a

15 files changed

Lines changed: 1639 additions & 60 deletions

File tree

Plugins/BridgeJS/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ graph LR
9898
| `Dictionary<K, V>` | `Record<K, V>` | - | [#495](https://github.com/swiftwasm/JavaScriptKit/issues/495) |
9999
| `Set<T>` | `Set<T>` | - | [#397](https://github.com/swiftwasm/JavaScriptKit/issues/397) |
100100
| `Foundation.URL` | `string` | - | [#496](https://github.com/swiftwasm/JavaScriptKit/issues/496) |
101-
| Generics | - | - | [#398](https://github.com/swiftwasm/JavaScriptKit/issues/398) |
101+
| Generic function or method (`T`, `[T]`, `T?`, `[String: T]`) | `<T>(value: T, type: BridgeType<T>)` | Depends on `T` | |
102102

103103
### Import-specific (TypeScript -> Swift)
104104

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 344 additions & 3 deletions
Large diffs are not rendered by default.

Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ public struct ImportTS {
143143
}
144144

145145
func lowerParameter(param: Parameter) throws {
146+
if let genericPush = param.type.genericStackPushStatement(value: param.name) {
147+
stackLoweringStmts.insert(genericPush, at: 0)
148+
return
149+
}
150+
146151
let loweringInfo = try param.type.loweringParameterInfo(context: context)
147152

148153
switch param.type {
@@ -241,6 +246,18 @@ public struct ImportTS {
241246
abiParameterForwardings.insert(contentsOf: ["resolveRef", "rejectRef"], at: 0)
242247
}
243248

249+
private func appendTypeIDParameter(index: Int, genericParameterName: String) {
250+
let abiParamName = ABINameGenerator.genericTypeIdParameterName(index: index)
251+
abiParameterSignatures.append((abiParamName, .i32))
252+
abiParameterForwardings.append("\(genericParameterName).bridgeJSTypeID")
253+
}
254+
255+
func appendTypeIDParameters(_ genericParameterNames: [String]) {
256+
for (index, name) in genericParameterNames.enumerated() {
257+
appendTypeIDParameter(index: index, genericParameterName: name)
258+
}
259+
}
260+
244261
func call() throws {
245262
for stmt in stackLoweringStmts {
246263
body.write(stmt.description)
@@ -297,14 +314,18 @@ public struct ImportTS {
297314
body.write("return \(returnType.swiftType).bridgeJSLiftReturnFromSideChannel()")
298315
} else {
299316
let liftExpr: String
300-
switch returnType {
301-
case .closure(let signature, _):
302-
liftExpr = "_BJS_Closure_\(signature.mangleName).bridgeJSLift(ret)"
303-
default:
304-
if liftingInfo.valueToLift != nil {
305-
liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn(ret)"
306-
} else {
307-
liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn()"
317+
if let genericPop = returnType.genericStackPopExpression {
318+
liftExpr = genericPop
319+
} else {
320+
switch returnType {
321+
case .closure(let signature, _):
322+
liftExpr = "_BJS_Closure_\(signature.mangleName).bridgeJSLift(ret)"
323+
default:
324+
if liftingInfo.valueToLift != nil {
325+
liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn(ret)"
326+
} else {
327+
liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn()"
328+
}
308329
}
309330
}
310331
body.write("return \(liftExpr)")
@@ -363,7 +384,8 @@ public struct ImportTS {
363384
name: String,
364385
parameters: [Parameter],
365386
returnType: BridgeType,
366-
effects: Effects
387+
effects: Effects,
388+
genericParameters: [String] = []
367389
) -> DeclSyntax {
368390
let printer = CodeFragmentPrinter()
369391
let signature = SwiftSignatureBuilder.buildFunctionSignature(
@@ -372,7 +394,12 @@ public struct ImportTS {
372394
effects: effects,
373395
useWildcardLabels: true
374396
)
375-
printer.write("func \(name.backtickIfNeeded())\(signature) {")
397+
let genericClause =
398+
genericParameters.isEmpty
399+
? ""
400+
: "<" + genericParameters.map { "\($0): _BridgedSwiftGenericBridgeable" }.joined(separator: ", ")
401+
+ ">"
402+
printer.write("func \(name.backtickIfNeeded())\(genericClause)\(signature) {")
376403
printer.indent {
377404
printer.write(lines: body.lines)
378405
}
@@ -432,6 +459,7 @@ public struct ImportTS {
432459
for param in function.parameters {
433460
try builder.lowerParameter(param: param)
434461
}
462+
builder.appendTypeIDParameters(function.genericParameterNames)
435463
try builder.call()
436464
try builder.liftReturnValue()
437465
topLevelDecls.append(builder.renderImportDecl())
@@ -440,7 +468,8 @@ public struct ImportTS {
440468
name: Self.thunkName(function: function),
441469
parameters: function.parameters,
442470
returnType: function.returnType,
443-
effects: function.effects
471+
effects: function.effects,
472+
genericParameters: function.genericParameterNames
444473
)
445474
.with(\.leadingTrivia, Self.renderDocumentation(documentation: function.documentation))
446475
]
@@ -461,6 +490,7 @@ public struct ImportTS {
461490
for param in method.parameters {
462491
try builder.lowerParameter(param: param)
463492
}
493+
builder.appendTypeIDParameters(method.genericParameterNames)
464494
try builder.call()
465495
try builder.liftReturnValue()
466496
topLevelDecls.append(builder.renderImportDecl())
@@ -469,7 +499,8 @@ public struct ImportTS {
469499
name: Self.thunkName(type: type, method: method),
470500
parameters: [selfParameter] + method.parameters,
471501
returnType: method.returnType,
472-
effects: method.effects
502+
effects: method.effects,
503+
genericParameters: method.genericParameterNames
473504
)
474505
]
475506
}
@@ -485,6 +516,7 @@ public struct ImportTS {
485516
for param in method.parameters {
486517
try builder.lowerParameter(param: param)
487518
}
519+
builder.appendTypeIDParameters(method.genericParameterNames)
488520
try builder.call()
489521
try builder.liftReturnValue()
490522
topLevelDecls.append(builder.renderImportDecl())
@@ -493,7 +525,8 @@ public struct ImportTS {
493525
name: Self.thunkName(type: type, method: method),
494526
parameters: method.parameters,
495527
returnType: method.returnType,
496-
effects: method.effects
528+
effects: method.effects,
529+
genericParameters: method.genericParameterNames
497530
)
498531
]
499532
}
@@ -959,6 +992,8 @@ extension BridgeType {
959992
return LoweringParameterInfo(loweredParameters: [])
960993
case .alias:
961994
preconditionFailure("`.alias` must be resolved by `.unaliased` before reaching loweringParameterInfo")
995+
case .generic:
996+
return LoweringParameterInfo(loweredParameters: [])
962997
}
963998
}
964999

@@ -1033,6 +1068,8 @@ extension BridgeType {
10331068
return LiftingReturnInfo(valueToLift: nil)
10341069
case .alias:
10351070
preconditionFailure("`.alias` must be resolved by `.unaliased` before reaching liftingReturnInfo")
1071+
case .generic:
1072+
return LiftingReturnInfo(valueToLift: nil)
10361073
}
10371074
}
10381075
}

0 commit comments

Comments
 (0)