Skip to content

Commit fded40d

Browse files
committed
BridgeJS: Add reusable intrinsics for stack-based types
1 parent d8b0e17 commit fded40d

File tree

15 files changed

+661
-1163
lines changed

15 files changed

+661
-1163
lines changed

Benchmarks/Sources/Generated/BridgeJS.swift

Lines changed: 65 additions & 231 deletions
Large diffs are not rendered by default.

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 67 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -798,60 +798,56 @@ struct StackCodegen {
798798
/// - Returns: An ExprSyntax representing the lift expression
799799
func liftExpression(for type: BridgeType) -> ExprSyntax {
800800
switch type {
801-
case .string:
802-
return "String.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
803-
case .int, .uint:
804-
return "Int.bridgeJSLiftParameter(_swift_js_pop_i32())"
805-
case .bool:
806-
return "Bool.bridgeJSLiftParameter(_swift_js_pop_i32())"
807-
case .float:
808-
return "Float.bridgeJSLiftParameter(_swift_js_pop_f32())"
809-
case .double:
810-
return "Double.bridgeJSLiftParameter(_swift_js_pop_f64())"
811-
case .jsObject:
812-
return "JSObject.bridgeJSLiftParameter(_swift_js_pop_i32())"
813-
case .swiftHeapObject(let className):
814-
return "\(raw: className).bridgeJSLiftParameter(_swift_js_pop_pointer())"
801+
case .string, .int, .uint, .bool, .float, .double,
802+
.jsObject, .swiftStruct, .swiftHeapObject:
803+
return "\(raw: type.swiftType).bridgeJSLiftParameter()"
815804
case .unsafePointer:
816805
return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_pointer())"
817806
case .swiftProtocol(let protocolName):
818-
// Protocols use their Any wrapper type for lifting
819-
let wrapperName = "Any\(protocolName)"
820-
return "\(raw: wrapperName).bridgeJSLiftParameter(_swift_js_pop_i32())"
821-
case .caseEnum(let enumName):
822-
return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_i32())"
823-
case .rawValueEnum(let enumName, let rawType):
807+
return "Any\(raw: protocolName).bridgeJSLiftParameter(_swift_js_pop_i32())"
808+
case .caseEnum:
809+
return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_i32())"
810+
case .rawValueEnum(_, let rawType):
824811
switch rawType {
825812
case .string:
826813
return
827-
"\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
814+
"\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
828815
case .float:
829-
return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_f32())"
816+
return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_f32())"
830817
case .double:
831-
return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_f64())"
818+
return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_f64())"
832819
case .bool, .int, .int32, .int64, .uint, .uint32, .uint64:
833-
return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_i32())"
820+
return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_i32())"
834821
}
835-
case .associatedValueEnum(let enumName):
836-
return "\(raw: enumName).bridgeJSLiftParameter(_swift_js_pop_i32())"
837-
case .swiftStruct(let structName):
838-
return "\(raw: structName).bridgeJSLiftParameter()"
822+
case .associatedValueEnum:
823+
return "\(raw: type.swiftType).bridgeJSLiftParameter(_swift_js_pop_i32())"
839824
case .optional(let wrappedType):
840825
return liftOptionalExpression(wrappedType: wrappedType)
841-
case .void:
842-
// Void shouldn't be lifted, but return a placeholder
843-
return "()"
844-
case .namespaceEnum:
845-
// Namespace enums are not passed as values
846-
return "()"
847-
case .closure:
848-
return "JSObject.bridgeJSLiftParameter(_swift_js_pop_i32())"
849826
case .array(let elementType):
850827
return liftArrayExpression(elementType: elementType)
828+
case .closure:
829+
return "JSObject.bridgeJSLiftParameter()"
830+
case .void, .namespaceEnum:
831+
return "()"
851832
}
852833
}
853834

854835
func liftArrayExpression(elementType: BridgeType) -> ExprSyntax {
836+
switch elementType {
837+
case .int, .uint, .float, .double, .string, .bool,
838+
.jsObject, .swiftStruct, .caseEnum, .swiftHeapObject,
839+
.unsafePointer, .rawValueEnum, .associatedValueEnum:
840+
return "[\(raw: elementType.swiftType)].bridgeJSLiftParameter()"
841+
case .swiftProtocol(let protocolName):
842+
return "[Any\(raw: protocolName)].bridgeJSLiftParameter()"
843+
case .optional, .array, .closure:
844+
return liftArrayExpressionInline(elementType: elementType)
845+
case .void, .namespaceEnum:
846+
fatalError("Invalid array element type: \(elementType)")
847+
}
848+
}
849+
850+
private func liftArrayExpressionInline(elementType: BridgeType) -> ExprSyntax {
855851
let elementLift = liftExpression(for: elementType)
856852
let swiftTypeName = elementType.swiftType
857853
return """
@@ -870,45 +866,9 @@ struct StackCodegen {
870866

871867
private func liftOptionalExpression(wrappedType: BridgeType) -> ExprSyntax {
872868
switch wrappedType {
873-
case .string:
874-
return
875-
"Optional<String>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())"
876-
case .int, .uint:
877-
return "Optional<Int>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
878-
case .bool:
879-
return "Optional<Bool>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
880-
case .float:
881-
return "Optional<Float>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f32())"
882-
case .double:
883-
return "Optional<Double>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f64())"
884-
case .caseEnum(let enumName):
885-
return
886-
"Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
887-
case .rawValueEnum(let enumName, let rawType):
888-
switch rawType {
889-
case .string:
890-
return
891-
"Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32(), _swift_js_pop_i32())"
892-
case .float:
893-
return
894-
"Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f32())"
895-
case .double:
896-
return
897-
"Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_f64())"
898-
case .bool, .int, .int32, .int64, .uint, .uint32, .uint64:
899-
return
900-
"Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
901-
}
902-
case .swiftStruct(let nestedName):
903-
return "Optional<\(raw: nestedName)>.bridgeJSLiftParameter(_swift_js_pop_i32())"
904-
case .swiftHeapObject(let className):
905-
return
906-
"Optional<\(raw: className)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_pointer())"
907-
case .associatedValueEnum(let enumName):
908-
return
909-
"Optional<\(raw: enumName)>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
910-
case .jsObject:
911-
return "Optional<JSObject>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
869+
case .string, .int, .uint, .bool, .float, .double, .jsObject,
870+
.swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum:
871+
return "Optional<\(raw: wrappedType.swiftType)>.bridgeJSLiftParameter()"
912872
case .array(let elementType):
913873
let arrayLift = liftArrayExpression(elementType: elementType)
914874
let swiftTypeName = elementType.swiftType
@@ -922,9 +882,8 @@ struct StackCodegen {
922882
}
923883
}()
924884
"""
925-
default:
926-
// Fallback for other optional types
927-
return "Optional<Int>.bridgeJSLiftParameter(_swift_js_pop_i32(), _swift_js_pop_i32())"
885+
case .void, .namespaceEnum, .closure, .optional, .unsafePointer, .swiftProtocol:
886+
fatalError("Invalid optional wrapped type: \(wrappedType)")
928887
}
929888
}
930889

@@ -999,6 +958,29 @@ struct StackCodegen {
999958
elementType: BridgeType,
1000959
accessor: String,
1001960
varPrefix: String
961+
) -> [CodeBlockItemSyntax] {
962+
switch elementType {
963+
case .int, .uint, .float, .double, .string, .bool,
964+
.jsObject, .swiftStruct, .caseEnum, .swiftHeapObject,
965+
.unsafePointer, .rawValueEnum, .associatedValueEnum:
966+
return ["\(raw: accessor).bridgeJSLowerReturn()"]
967+
case .swiftProtocol(let protocolName):
968+
return ["\(raw: accessor).map { $0 as! Any\(raw: protocolName) }.bridgeJSLowerReturn()"]
969+
case .optional, .array, .closure:
970+
return lowerArrayStatementsInline(
971+
elementType: elementType,
972+
accessor: accessor,
973+
varPrefix: varPrefix
974+
)
975+
case .void, .namespaceEnum:
976+
fatalError("Invalid array element type: \(elementType)")
977+
}
978+
}
979+
980+
private func lowerArrayStatementsInline(
981+
elementType: BridgeType,
982+
accessor: String,
983+
varPrefix: String
1002984
) -> [CodeBlockItemSyntax] {
1003985
var statements: [CodeBlockItemSyntax] = []
1004986
let elementVarName = "__bjs_elem_\(varPrefix)"
@@ -1150,7 +1132,13 @@ struct EnumCodegen {
11501132
}
11511133

11521134
private func renderRawValueEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax {
1153-
return "extension \(raw: enumDef.swiftCallName): _BridgedSwiftEnumNoPayload {}"
1135+
let typeName = enumDef.swiftCallName
1136+
// The stack type methods (bridgeJSLiftParameter() and bridgeJSLowerStackReturn())
1137+
// are provided by conditional extensions in BridgeJSIntrinsics.swift.
1138+
// We only need to declare the protocol conformance here.
1139+
return """
1140+
extension \(raw: typeName): _BridgedSwiftEnumNoPayload {}
1141+
"""
11541142
}
11551143

11561144
private func renderAssociatedValueEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax {

Plugins/BridgeJS/Sources/TS2Swift/JavaScript/src/processor.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,14 @@ export class TypeProcessor {
399399
this.swiftLines.push(` case ${this.renderIdentifier(name)} = "${raw.replaceAll("\"", "\\\\\"")}"`);
400400
}
401401
this.swiftLines.push("}");
402-
this.swiftLines.push(`extension ${swiftEnumName}: _BridgedSwiftEnumNoPayload {}`);
402+
this.swiftLines.push(`extension ${swiftEnumName}: _BridgedSwiftEnumNoPayload {`);
403+
this.swiftLines.push(` @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self {`);
404+
this.swiftLines.push(` Self(rawValue: String.bridgeJSLiftParameter())!`);
405+
this.swiftLines.push(` }`);
406+
this.swiftLines.push(` @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() {`);
407+
this.swiftLines.push(` rawValue.bridgeJSLowerStackReturn()`);
408+
this.swiftLines.push(` }`);
409+
this.swiftLines.push(`}`);
403410
this.swiftLines.push("");
404411
return;
405412
}
@@ -410,7 +417,14 @@ export class TypeProcessor {
410417
this.swiftLines.push(` case ${this.renderIdentifier(name)} = ${raw}`);
411418
}
412419
this.swiftLines.push("}");
413-
this.swiftLines.push(`extension ${swiftEnumName}: _BridgedSwiftEnumNoPayload {}`);
420+
this.swiftLines.push(`extension ${swiftEnumName}: _BridgedSwiftEnumNoPayload {`);
421+
this.swiftLines.push(` @_spi(BridgeJS) public static func bridgeJSLiftParameter() -> Self {`);
422+
this.swiftLines.push(` Self(rawValue: Int.bridgeJSLiftParameter())!`);
423+
this.swiftLines.push(` }`);
424+
this.swiftLines.push(` @_spi(BridgeJS) public consuming func bridgeJSLowerStackReturn() {`);
425+
this.swiftLines.push(` rawValue.bridgeJSLowerStackReturn()`);
426+
this.swiftLines.push(` }`);
427+
this.swiftLines.push(`}`);
414428
this.swiftLines.push("");
415429
return;
416430
}

0 commit comments

Comments
 (0)