Skip to content

Commit 085ad29

Browse files
committed
BridgeJS: Include namespace prefix in ABI names for namespace-nested classes and structs
1 parent 33c03e9 commit 085ad29

30 files changed

+831
-493
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,9 @@ public class ExportSwift {
389389
case .enumStatic(let enumDef):
390390
return enumDef.name
391391
case .classStatic(let klass), .classInstance(let klass):
392-
return klass.name
392+
return klass.abiName
393393
case .structStatic(let structDef):
394-
return structDef.name
394+
return structDef.abiName
395395
}
396396
}
397397

@@ -642,7 +642,7 @@ public class ExportSwift {
642642

643643
do {
644644
let funcDecl = SwiftCodePattern.buildExposedFunctionDecl(
645-
abiName: "bjs_\(klass.name)_deinit",
645+
abiName: "bjs_\(klass.abiName)_deinit",
646646
signature: SwiftSignatureBuilder.buildABIFunctionSignature(
647647
abiParameters: [("pointer", .pointer)],
648648
returnType: nil
@@ -675,8 +675,8 @@ public class ExportSwift {
675675
/// fileprivate func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32
676676
/// ```
677677
func renderConvertibleToJSValueExtension(klass: ExportedClass) -> [DeclSyntax] {
678-
let wrapFunctionName = "_bjs_\(klass.name)_wrap"
679-
let externFunctionName = "bjs_\(klass.name)_wrap"
678+
let wrapFunctionName = "_bjs_\(klass.abiName)_wrap"
679+
let externFunctionName = "bjs_\(klass.abiName)_wrap"
680680

681681
// If the class has an explicit access control, we need to add it to the extension declaration.
682682
let accessControl = klass.explicitAccessControl.map { "\($0) " } ?? ""
@@ -1076,10 +1076,10 @@ struct StructCodegen {
10761076
func renderStructHelpers(_ structDef: ExportedStruct) -> [DeclSyntax] {
10771077
let typeName = structDef.swiftCallName
10781078

1079-
let lowerExternName = "swift_js_struct_lower_\(structDef.name)"
1080-
let liftExternName = "swift_js_struct_lift_\(structDef.name)"
1081-
let lowerFunctionName = "_bjs_struct_lower_\(structDef.name)"
1082-
let liftFunctionName = "_bjs_struct_lift_\(structDef.name)"
1079+
let lowerExternName = "swift_js_struct_lower_\(structDef.abiName)"
1080+
let liftExternName = "swift_js_struct_lift_\(structDef.abiName)"
1081+
let lowerFunctionName = "_bjs_struct_lower_\(structDef.abiName)"
1082+
let liftFunctionName = "_bjs_struct_lift_\(structDef.abiName)"
10831083

10841084
let printer = CodeFragmentPrinter()
10851085
printer.write("extension \(typeName): _BridgedSwiftStruct {")

Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,9 +1060,10 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
10601060
switch state {
10611061
case .topLevel:
10621062
staticContext = nil
1063-
case .classBody(let className, _):
1063+
case .classBody(_, let classKey):
10641064
if isStatic {
1065-
staticContext = .className(className)
1065+
let classAbiName = exportedClassByName[classKey]?.abiName ?? "unknown"
1066+
staticContext = .className(classAbiName)
10661067
} else {
10671068
staticContext = nil
10681069
}
@@ -1077,20 +1078,21 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
10771078
staticContext = isNamespaceEnum ? .namespaceEnum(swiftCallName) : .enumName(enumName)
10781079
case .protocolBody(_, _):
10791080
return nil
1080-
case .structBody(let structName, _):
1081+
case .structBody(_, let structKey):
10811082
if isStatic {
1082-
staticContext = .structName(structName)
1083+
let structAbiName = exportedStructByName[structKey]?.abiName ?? "unknown"
1084+
staticContext = .structName(structAbiName)
10831085
} else {
10841086
staticContext = nil
10851087
}
10861088
}
10871089

10881090
let classNameForABI: String?
10891091
switch state {
1090-
case .classBody(let className, _):
1091-
classNameForABI = className
1092-
case .structBody(let structName, _):
1093-
classNameForABI = structName
1092+
case .classBody(_, let classKey):
1093+
classNameForABI = exportedClassByName[classKey]?.abiName
1094+
case .structBody(_, let structKey):
1095+
classNameForABI = exportedStructByName[structKey]?.abiName
10941096
default:
10951097
classNameForABI = nil
10961098
}
@@ -1179,7 +1181,7 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
11791181
guard let jsAttribute = node.attributes.firstJSAttribute else { return .skipChildren }
11801182

11811183
switch state {
1182-
case .classBody(let className, let classKey):
1184+
case .classBody(_, let classKey):
11831185
if extractNamespace(from: jsAttribute) != nil {
11841186
diagnose(
11851187
node: jsAttribute,
@@ -1194,14 +1196,15 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
11941196
return .skipChildren
11951197
}
11961198

1199+
let classAbiName = exportedClassByName[classKey]?.abiName ?? "unknown"
11971200
let constructor = ExportedConstructor(
1198-
abiName: "bjs_\(className)_init",
1201+
abiName: "bjs_\(classAbiName)_init",
11991202
parameters: parameters,
12001203
effects: effects
12011204
)
12021205
exportedClassByName[classKey]?.constructor = constructor
12031206

1204-
case .structBody(let structName, let structKey):
1207+
case .structBody(_, let structKey):
12051208
if extractNamespace(from: jsAttribute) != nil {
12061209
diagnose(
12071210
node: jsAttribute,
@@ -1216,8 +1219,9 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
12161219
return .skipChildren
12171220
}
12181221

1222+
let structAbiName = exportedStructByName[structKey]?.abiName ?? "unknown"
12191223
let constructor = ExportedConstructor(
1220-
abiName: "bjs_\(structName)_init",
1224+
abiName: "bjs_\(structAbiName)_init",
12211225
parameters: parameters,
12221226
effects: effects
12231227
)
@@ -1263,8 +1267,13 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
12631267
let staticContext: StaticContext?
12641268

12651269
switch state {
1266-
case .classBody(let className, _):
1267-
staticContext = isStatic ? .className(className) : nil
1270+
case .classBody(_, let classKey):
1271+
if isStatic {
1272+
let classAbiName = exportedClassByName[classKey]?.abiName ?? "unknown"
1273+
staticContext = .className(classAbiName)
1274+
} else {
1275+
staticContext = nil
1276+
}
12681277
case .enumBody(let enumName, let enumKey):
12691278
if !isStatic {
12701279
diagnose(node: node, message: "Only static properties are supported in enums")
@@ -1280,9 +1289,10 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
12801289
return .skipChildren
12811290
case .protocolBody(let protocolName, let protocolKey):
12821291
return visitProtocolProperty(node: node, protocolName: protocolName, protocolKey: protocolKey)
1283-
case .structBody(let structName, _):
1292+
case .structBody(_, let structKey):
12841293
if isStatic {
1285-
staticContext = .structName(structName)
1294+
let structAbiName = exportedStructByName[structKey]?.abiName ?? "unknown"
1295+
staticContext = .structName(structAbiName)
12861296
} else {
12871297
diagnose(node: node, message: "@JS var must be static in structs (instance fields don't need @JS)")
12881298
return .skipChildren

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,15 +447,15 @@ public struct BridgeJSLink {
447447
printer.write("}")
448448
if !allStructs.isEmpty {
449449
for structDef in allStructs {
450-
printer.write("bjs[\"swift_js_struct_lower_\(structDef.name)\"] = function(objectId) {")
450+
printer.write("bjs[\"swift_js_struct_lower_\(structDef.abiName)\"] = function(objectId) {")
451451
printer.indent {
452452
printer.write(
453453
"\(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lower(\(JSGlueVariableScope.reservedSwift).memory.getObject(objectId));"
454454
)
455455
}
456456
printer.write("}")
457457

458-
printer.write("bjs[\"swift_js_struct_lift_\(structDef.name)\"] = function() {")
458+
printer.write("bjs[\"swift_js_struct_lift_\(structDef.abiName)\"] = function() {")
459459
printer.indent {
460460
printer.write(
461461
"const value = \(JSGlueVariableScope.reservedStructHelpers).\(structDef.name).lift();"
@@ -1155,7 +1155,7 @@ public struct BridgeJSLink {
11551155
wrapperLines.append("}")
11561156

11571157
for klass in classes.sorted(by: { $0.name < $1.name }) {
1158-
let wrapperFunctionName = "bjs_\(klass.name)_wrap"
1158+
let wrapperFunctionName = "bjs_\(klass.abiName)_wrap"
11591159
let namespacePath = (klass.namespace ?? []).map { ".\($0)" }.joined()
11601160
let exportsPath =
11611161
namespacePath.isEmpty ? "_exports['\(klass.name)']" : "_exports\(namespacePath).\(klass.name)"
@@ -1967,7 +1967,7 @@ extension BridgeJSLink {
19671967
jsPrinter.write("static __construct(ptr) {")
19681968
jsPrinter.indent {
19691969
jsPrinter.write(
1970-
"return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_\(klass.name)_deinit, \(klass.name).prototype);"
1970+
"return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_\(klass.abiName)_deinit, \(klass.name).prototype);"
19711971
)
19721972
}
19731973
jsPrinter.write("}")
@@ -2069,7 +2069,7 @@ extension BridgeJSLink {
20692069
for property in klass.properties {
20702070
try renderClassProperty(
20712071
property: property,
2072-
className: klass.name,
2072+
className: klass.abiName,
20732073
isStatic: property.isStatic,
20742074
jsPrinter: jsPrinter,
20752075
dtsPrinter: property.isStatic ? dtsExportEntryPrinter : dtsTypePrinter

Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,13 @@ public struct ExportedStruct: Codable, Equatable, Sendable {
421421
public var methods: [ExportedFunction]
422422
public let namespace: [String]?
423423

424+
public var abiName: String {
425+
if let namespace = namespace, !namespace.isEmpty {
426+
return (namespace + [name]).joined(separator: "_")
427+
}
428+
return name
429+
}
430+
424431
public init(
425432
name: String,
426433
swiftCallName: String,
@@ -628,6 +635,13 @@ public struct ExportedClass: Codable {
628635
public var properties: [ExportedProperty]
629636
public var namespace: [String]?
630637

638+
public var abiName: String {
639+
if let namespace = namespace, !namespace.isEmpty {
640+
return (namespace + [name]).joined(separator: "_")
641+
}
642+
return name
643+
}
644+
631645
public init(
632646
name: String,
633647
swiftCallName: String,

Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumNamespace.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ enum Internal {
5353
}
5454
}
5555

56+
@JS enum Formatting {
57+
@JS class Converter {
58+
@JS init() {}
59+
60+
@JS func format(value: Int) -> String {
61+
return "formatted_\(value)"
62+
}
63+
}
64+
}
65+
5666
@JS(namespace: "Services.Graph")
5767
enum GraphOperations {
5868
@JS static func createGraph(rootId: Int) -> Int {

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumNamespace.Global.json

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"classes" : [
44
{
55
"constructor" : {
6-
"abiName" : "bjs_Converter_init",
6+
"abiName" : "bjs_Utils_Converter_init",
77
"effects" : {
88
"isAsync" : false,
99
"isStatic" : false,
@@ -15,7 +15,7 @@
1515
},
1616
"methods" : [
1717
{
18-
"abiName" : "bjs_Converter_toString",
18+
"abiName" : "bjs_Utils_Converter_toString",
1919
"effects" : {
2020
"isAsync" : false,
2121
"isStatic" : false,
@@ -54,7 +54,7 @@
5454
},
5555
{
5656
"constructor" : {
57-
"abiName" : "bjs_HTTPServer_init",
57+
"abiName" : "bjs_Networking_API_HTTPServer_init",
5858
"effects" : {
5959
"isAsync" : false,
6060
"isStatic" : false,
@@ -66,7 +66,7 @@
6666
},
6767
"methods" : [
6868
{
69-
"abiName" : "bjs_HTTPServer_call",
69+
"abiName" : "bjs_Networking_API_HTTPServer_call",
7070
"effects" : {
7171
"isAsync" : false,
7272
"isStatic" : false,
@@ -107,7 +107,7 @@
107107
},
108108
{
109109
"constructor" : {
110-
"abiName" : "bjs_TestServer_init",
110+
"abiName" : "bjs_Networking_APIV2_Internal_TestServer_init",
111111
"effects" : {
112112
"isAsync" : false,
113113
"isStatic" : false,
@@ -119,7 +119,7 @@
119119
},
120120
"methods" : [
121121
{
122-
"abiName" : "bjs_TestServer_call",
122+
"abiName" : "bjs_Networking_APIV2_Internal_TestServer_call",
123123
"effects" : {
124124
"isAsync" : false,
125125
"isStatic" : false,
@@ -159,6 +159,57 @@
159159

160160
],
161161
"swiftCallName" : "Internal.TestServer"
162+
},
163+
{
164+
"constructor" : {
165+
"abiName" : "bjs_Formatting_Converter_init",
166+
"effects" : {
167+
"isAsync" : false,
168+
"isStatic" : false,
169+
"isThrows" : false
170+
},
171+
"parameters" : [
172+
173+
]
174+
},
175+
"methods" : [
176+
{
177+
"abiName" : "bjs_Formatting_Converter_format",
178+
"effects" : {
179+
"isAsync" : false,
180+
"isStatic" : false,
181+
"isThrows" : false
182+
},
183+
"name" : "format",
184+
"namespace" : [
185+
"Formatting"
186+
],
187+
"parameters" : [
188+
{
189+
"label" : "value",
190+
"name" : "value",
191+
"type" : {
192+
"int" : {
193+
194+
}
195+
}
196+
}
197+
],
198+
"returnType" : {
199+
"string" : {
200+
201+
}
202+
}
203+
}
204+
],
205+
"name" : "Converter",
206+
"namespace" : [
207+
"Formatting"
208+
],
209+
"properties" : [
210+
211+
],
212+
"swiftCallName" : "Formatting.Converter"
162213
}
163214
],
164215
"enums" : [
@@ -405,6 +456,21 @@
405456
{
406457
"cases" : [
407458

459+
],
460+
"emitStyle" : "const",
461+
"name" : "Formatting",
462+
"staticMethods" : [
463+
464+
],
465+
"staticProperties" : [
466+
467+
],
468+
"swiftCallName" : "Formatting",
469+
"tsFullPath" : "Formatting"
470+
},
471+
{
472+
"cases" : [
473+
408474
],
409475
"emitStyle" : "const",
410476
"name" : "GraphOperations",

0 commit comments

Comments
 (0)