Skip to content

Commit 7311617

Browse files
BridgeJS: Unify closure JS glue lift/lower
1 parent cb45962 commit 7311617

File tree

4 files changed

+249
-1019
lines changed

4 files changed

+249
-1019
lines changed

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 29 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -716,71 +716,25 @@ public struct BridgeJSLink {
716716
signature: ClosureSignature,
717717
functionName: String
718718
) throws -> [String] {
719-
let printer = CodeFragmentPrinter()
720-
let context = IntrinsicJSFragment.PrintCodeContext(
721-
scope: JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry),
722-
printer: printer,
723-
cleanupCode: CodeFragmentPrinter()
724-
)
719+
let thunkBuilder = ImportedThunkBuilder(context: .exportSwift, intrinsicRegistry: intrinsicRegistry)
720+
thunkBuilder.parameterNames.append("callbackId")
721+
thunkBuilder.body.write("const callback = \(JSGlueVariableScope.reservedSwift).memory.getObject(callbackId);")
725722

726-
// Build parameter list for invoke function
727-
var invokeParams: [String] = ["callbackId"]
728723
for (index, paramType) in signature.parameters.enumerated() {
729-
if case .nullable = paramType {
730-
invokeParams.append("param\(index)IsSome")
731-
invokeParams.append("param\(index)Value")
732-
} else {
733-
invokeParams.append("param\(index)Id")
734-
}
724+
let paramName = "param\(index)"
725+
try thunkBuilder.liftParameter(param: Parameter(label: nil, name: paramName, type: paramType))
735726
}
736727

737-
printer.nextLine()
738-
printer.write("bjs[\"\(functionName)\"] = function(\(invokeParams.joined(separator: ", "))) {")
739-
try printer.indent {
740-
printer.write("try {")
741-
try printer.indent {
742-
printer.write("const callback = \(JSGlueVariableScope.reservedSwift).memory.getObject(callbackId);")
728+
let returnExpr = try thunkBuilder.call(calleeExpr: "callback", returnType: signature.returnType)
743729

744-
for (index, paramType) in signature.parameters.enumerated() {
745-
let fragment = try IntrinsicJSFragment.closureLiftParameter(type: paramType)
746-
let args: [String]
747-
if case .nullable = paramType {
748-
args = ["param\(index)IsSome", "param\(index)Value", "param\(index)"]
749-
} else {
750-
args = ["param\(index)Id", "param\(index)"]
751-
}
752-
_ = try fragment.printCode(args, context)
753-
}
754-
755-
let callbackParams = signature.parameters.indices.map { "param\($0)" }.joined(separator: ", ")
756-
printer.write("const result = callback(\(callbackParams));")
757-
758-
// Type check if needed (for example, formatName requires string return)
759-
switch signature.returnType {
760-
case .string:
761-
printer.write("if (typeof result !== \"string\") {")
762-
printer.indent {
763-
printer.write("throw new TypeError(\"Callback must return a string\");")
764-
}
765-
printer.write("}")
766-
default:
767-
break
768-
}
769-
770-
let returnFragment = try IntrinsicJSFragment.closureLowerReturn(type: signature.returnType)
771-
_ = try returnFragment.printCode(["result"], context)
772-
}
773-
printer.write("} catch (error) {")
774-
try printer.indent {
775-
printer.write("\(JSGlueVariableScope.reservedSetException)?.(error);")
776-
let errorFragment = IntrinsicJSFragment.closureErrorReturn(type: signature.returnType)
777-
_ = try errorFragment.printCode([], context)
778-
}
779-
printer.write("}")
780-
}
781-
printer.write("};")
730+
var functionLines = thunkBuilder.renderFunction(
731+
name: nil,
732+
returnExpr: returnExpr,
733+
returnType: signature.returnType
734+
)
735+
functionLines[0] = "bjs[\"\(functionName)\"] = " + functionLines[0]
782736

783-
return printer.lines
737+
return functionLines
784738
}
785739

786740
/// Generates a lower_closure_* function that wraps a Swift closure for JavaScript
@@ -789,46 +743,27 @@ public struct BridgeJSLink {
789743
functionName: String
790744
) throws -> [String] {
791745
let printer = CodeFragmentPrinter()
792-
let context = IntrinsicJSFragment.PrintCodeContext(
793-
scope: JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry),
794-
printer: printer,
795-
cleanupCode: CodeFragmentPrinter()
746+
let builder = ExportedThunkBuilder(
747+
effects: Effects(isAsync: false, isThrows: true),
748+
hasDirectAccessToSwiftClass: false,
749+
intrinsicRegistry: intrinsicRegistry
796750
)
751+
builder.parameterForwardings.append("boxPtr")
797752

798753
printer.write(
799754
"const \(functionName) = function(\(signature.parameters.indices.map { "param\($0)" }.joined(separator: ", "))) {"
800755
)
801756
try printer.indent {
802-
var invokeArgs: [String] = ["boxPtr"]
803-
757+
// Lower parameters using shared thunk builder
804758
for (index, paramType) in signature.parameters.enumerated() {
805759
let paramName = "param\(index)"
806-
let fragment = try IntrinsicJSFragment.lowerParameter(type: paramType)
807-
let lowered = try fragment.printCode([paramName], context)
808-
invokeArgs.append(contentsOf: lowered)
760+
try builder.lowerParameter(param: Parameter(label: nil, name: paramName, type: paramType))
809761
}
810762

811-
// Call the Swift invoke function
812763
let invokeCall =
813-
"\(JSGlueVariableScope.reservedInstance).exports.invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)(\(invokeArgs.joined(separator: ", ")))"
814-
let invokeResultName = "invokeResult"
815-
printer.write("const \(invokeResultName) = \(invokeCall);")
816-
817-
printer.write("if (\(JSGlueVariableScope.reservedStorageToReturnException)) {")
818-
printer.indent {
819-
printer.write(
820-
"const error = \(JSGlueVariableScope.reservedSwift).memory.getObject(\(JSGlueVariableScope.reservedStorageToReturnException));"
821-
)
822-
printer.write(
823-
"\(JSGlueVariableScope.reservedSwift).memory.release(\(JSGlueVariableScope.reservedStorageToReturnException));"
824-
)
825-
printer.write("\(JSGlueVariableScope.reservedStorageToReturnException) = undefined;")
826-
printer.write("throw error;")
827-
}
828-
printer.write("}")
829-
830-
let returnFragment = try IntrinsicJSFragment.closureLiftReturn(type: signature.returnType)
831-
_ = try returnFragment.printCode([invokeResultName], context)
764+
"invoke_swift_closure_\(signature.moduleName)_\(signature.mangleName)"
765+
let returnExpr = try builder.call(abiName: invokeCall, returnType: signature.returnType)
766+
builder.renderFunctionBody(into: printer, returnExpr: returnExpr)
832767
}
833768
printer.write("};")
834769

@@ -1291,15 +1226,16 @@ public struct BridgeJSLink {
12911226
let scope: JSGlueVariableScope
12921227
let context: IntrinsicJSFragment.PrintCodeContext
12931228

1294-
init(effects: Effects, intrinsicRegistry: JSIntrinsicRegistry) {
1229+
init(effects: Effects, hasDirectAccessToSwiftClass: Bool = true, intrinsicRegistry: JSIntrinsicRegistry) {
12951230
self.effects = effects
12961231
self.scope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry)
12971232
self.body = CodeFragmentPrinter()
12981233
self.cleanupCode = CodeFragmentPrinter()
12991234
self.context = IntrinsicJSFragment.PrintCodeContext(
13001235
scope: scope,
13011236
printer: body,
1302-
cleanupCode: cleanupCode
1237+
cleanupCode: cleanupCode,
1238+
hasDirectAccessToSwiftClass: hasDirectAccessToSwiftClass
13031239
)
13041240
}
13051241

@@ -2221,13 +2157,13 @@ extension BridgeJSLink {
22212157
}
22222158

22232159
func renderFunction(
2224-
name: String,
2160+
name: String?,
22252161
returnExpr: String?,
22262162
returnType: BridgeType
22272163
) -> [String] {
22282164
let printer = CodeFragmentPrinter()
22292165

2230-
printer.write("function \(name)(\(parameterNames.joined(separator: ", "))) {")
2166+
printer.write("function\(name.map { " \($0)" } ?? "")(\(parameterNames.joined(separator: ", "))) {")
22312167
printer.indent {
22322168
printer.write("try {")
22332169
printer.indent {
@@ -2259,7 +2195,7 @@ extension BridgeJSLink {
22592195
return try call(name: name, fromObjectExpr: "imports", returnType: returnType)
22602196
}
22612197

2262-
private func call(calleeExpr: String, returnType: BridgeType) throws -> String? {
2198+
func call(calleeExpr: String, returnType: BridgeType) throws -> String? {
22632199
let callExpr = "\(calleeExpr)(\(parameterForwardings.joined(separator: ", ")))"
22642200
return try self.call(callExpr: callExpr, returnType: returnType)
22652201
}

0 commit comments

Comments
 (0)