Skip to content

Commit 177be43

Browse files
BridgeJS: Complete protocol-based lift/lower for ImportTS and _JSBridgedClass
Add _JSBridgedClass protocol with lift/lower operations for JavaScript objects imported into Swift. Update ImportTS code generation to use new protocol-based bridgeJS* methods. Update all generated ImportTS Swift files and test snapshots to use the new bridgeJS* method calls instead of legacy functions.
1 parent e546582 commit 177be43

File tree

17 files changed

+208
-241
lines changed

17 files changed

+208
-241
lines changed

Benchmarks/Sources/Generated/BridgeJS.ImportTS.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func benchmarkHelperNoopWithNumber(_ n: Double) throws(JSException) -> Void {
3030
fatalError("Only available on WebAssembly")
3131
}
3232
#endif
33-
bjs_benchmarkHelperNoopWithNumber(n)
33+
bjs_benchmarkHelperNoopWithNumber(n.bridgeJSLowerParameter())
3434
if let error = _swift_js_take_exception() {
3535
throw error
3636
}

Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.ImportTS.swift

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,14 @@ func createTS2Skeleton() throws(JSException) -> TS2Skeleton {
1919
if let error = _swift_js_take_exception() {
2020
throw error
2121
}
22-
return TS2Skeleton(takingThis: ret)
22+
return TS2Skeleton.bridgeJSLiftReturn(ret)
2323
}
2424

25-
struct TS2Skeleton {
26-
let this: JSObject
25+
struct TS2Skeleton: _JSBridgedClass {
26+
let jsObject: JSObject
2727

28-
init(this: JSObject) {
29-
self.this = this
30-
}
31-
32-
init(takingThis this: Int32) {
33-
self.this = JSObject(id: UInt32(bitPattern: this))
28+
init(unsafelyWrapping jsObject: JSObject) {
29+
self.jsObject = jsObject
3430
}
3531

3632
func convert(_ ts: String) throws(JSException) -> String {
@@ -42,7 +38,7 @@ struct TS2Skeleton {
4238
fatalError("Only available on WebAssembly")
4339
}
4440
#endif
45-
let ret = bjs_TS2Skeleton_convert(self.this.bridgeJSLowerParameter(), ts.bridgeJSLowerParameter())
41+
let ret = bjs_TS2Skeleton_convert(self.bridgeJSLowerParameter(), ts.bridgeJSLowerParameter())
4642
if let error = _swift_js_take_exception() {
4743
throw error
4844
}

Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift

Lines changed: 84 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -68,70 +68,19 @@ public struct ImportTS {
6868
}
6969

7070
func lowerParameter(param: Parameter) throws {
71-
switch param.type {
72-
case .bool:
73-
abiParameterForwardings.append(
74-
LabeledExprSyntax(
75-
label: param.label,
76-
expression: ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()")
77-
)
78-
)
79-
abiParameterSignatures.append((param.name, .i32))
80-
case .int:
81-
abiParameterForwardings.append(
82-
LabeledExprSyntax(
83-
label: param.label,
84-
expression: ExprSyntax("\(raw: param.name)")
85-
)
86-
)
87-
abiParameterSignatures.append((param.name, .i32))
88-
case .float:
89-
abiParameterForwardings.append(
90-
LabeledExprSyntax(
91-
label: param.label,
92-
expression: ExprSyntax("\(raw: param.name)")
93-
)
94-
)
95-
abiParameterSignatures.append((param.name, .f32))
96-
case .double:
97-
abiParameterForwardings.append(
98-
LabeledExprSyntax(
99-
label: param.label,
100-
expression: ExprSyntax("\(raw: param.name)")
101-
)
102-
)
103-
abiParameterSignatures.append((param.name, .f64))
104-
case .string:
105-
abiParameterForwardings.append(
106-
LabeledExprSyntax(
107-
label: param.label,
108-
expression: ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()")
109-
)
110-
)
111-
abiParameterSignatures.append((param.name, .i32))
112-
case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum:
113-
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
114-
case .jsObject(_?):
115-
abiParameterSignatures.append((param.name, .i32))
116-
abiParameterForwardings.append(
117-
LabeledExprSyntax(
118-
label: param.label,
119-
expression: ExprSyntax("\(raw: param.name).this.bridgeJSLowerParameter()")
120-
)
121-
)
122-
case .jsObject(nil):
123-
abiParameterForwardings.append(
124-
LabeledExprSyntax(
125-
label: param.label,
126-
expression: ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()")
127-
)
71+
let loweringInfo = try param.type.loweringParameterInfo()
72+
assert(
73+
loweringInfo.loweredParameters.count == 1,
74+
"For now, we require a single parameter to be lowered to a single Wasm core type"
75+
)
76+
let (_, type) = loweringInfo.loweredParameters[0]
77+
abiParameterForwardings.append(
78+
LabeledExprSyntax(
79+
label: param.label,
80+
expression: ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()")
12881
)
129-
abiParameterSignatures.append((param.name, .i32))
130-
case .swiftHeapObject(_):
131-
throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures")
132-
case .void:
133-
break
134-
}
82+
)
83+
abiParameterSignatures.append((param.name, type))
13584
}
13685

13786
func call(returnType: BridgeType) {
@@ -146,44 +95,20 @@ public struct ImportTS {
14695
}
14796

14897
func liftReturnValue(returnType: BridgeType) throws {
149-
switch returnType {
150-
case .bool:
151-
abiReturnType = .i32
152-
body.append("return \(raw: returnType.swiftType).bridgeJSLiftReturn(ret)")
153-
case .int:
154-
abiReturnType = .i32
155-
body.append("return \(raw: returnType.swiftType)(ret)")
156-
case .float:
157-
abiReturnType = .f32
158-
body.append("return \(raw: returnType.swiftType)(ret)")
159-
case .double:
160-
abiReturnType = .f64
161-
body.append("return \(raw: returnType.swiftType)(ret)")
162-
case .string:
163-
abiReturnType = .i32
164-
body.append("return \(raw: returnType.swiftType).bridgeJSLiftReturn(ret)")
165-
case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum:
166-
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
167-
case .jsObject(let name):
168-
abiReturnType = .i32
169-
if let name = name {
170-
body.append("return \(raw: name)(takingThis: ret)")
171-
} else {
172-
body.append("return JSObject.bridgeJSLiftReturn(ret)")
173-
}
174-
case .swiftHeapObject(_):
175-
throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures")
176-
case .void:
177-
break
98+
let liftingInfo = try returnType.liftingReturnInfo()
99+
abiReturnType = liftingInfo.valueToLift
100+
if returnType == .void {
101+
return
178102
}
103+
body.append("return \(raw: returnType.swiftType).bridgeJSLiftReturn(ret)")
179104
}
180105

181106
func assignThis(returnType: BridgeType) {
182107
guard case .jsObject = returnType else {
183108
preconditionFailure("assignThis can only be called with a jsObject return type")
184109
}
185110
abiReturnType = .i32
186-
body.append("self.this = JSObject(id: UInt32(bitPattern: ret))")
111+
body.append("self.jsObject = JSObject(id: UInt32(bitPattern: ret))")
187112
}
188113

189114
func renderImportDecl() -> DeclSyntax {
@@ -410,25 +335,22 @@ public struct ImportTS {
410335
let classDecl = try StructDeclSyntax(
411336
leadingTrivia: Self.renderDocumentation(documentation: type.documentation),
412337
name: .identifier(name),
338+
inheritanceClause: InheritanceClauseSyntax(
339+
inheritedTypesBuilder: {
340+
InheritedTypeSyntax(type: TypeSyntax("_JSBridgedClass"))
341+
}
342+
),
413343
memberBlockBuilder: {
414344
DeclSyntax(
415345
"""
416-
let this: JSObject
346+
let jsObject: JSObject
417347
"""
418348
).with(\.trailingTrivia, .newlines(2))
419349

420350
DeclSyntax(
421351
"""
422-
init(this: JSObject) {
423-
self.this = this
424-
}
425-
"""
426-
).with(\.trailingTrivia, .newlines(2))
427-
428-
DeclSyntax(
429-
"""
430-
init(takingThis this: Int32) {
431-
self.this = JSObject(id: UInt32(bitPattern: this))
352+
init(unsafelyWrapping jsObject: JSObject) {
353+
self.jsObject = jsObject
432354
}
433355
"""
434356
).with(\.trailingTrivia, .newlines(2))
@@ -483,3 +405,61 @@ public struct ImportTS {
483405
)
484406
}
485407
}
408+
409+
extension BridgeType {
410+
struct LoweringParameterInfo {
411+
let loweredParameters: [(name: String, type: WasmCoreType)]
412+
413+
static let bool = LoweringParameterInfo(loweredParameters: [("value", .i32)])
414+
static let int = LoweringParameterInfo(loweredParameters: [("value", .i32)])
415+
static let float = LoweringParameterInfo(loweredParameters: [("value", .f32)])
416+
static let double = LoweringParameterInfo(loweredParameters: [("value", .f64)])
417+
static let string = LoweringParameterInfo(loweredParameters: [("value", .i32)])
418+
static let jsObject = LoweringParameterInfo(loweredParameters: [("value", .i32)])
419+
static let void = LoweringParameterInfo(loweredParameters: [])
420+
}
421+
422+
func loweringParameterInfo() throws -> LoweringParameterInfo {
423+
switch self {
424+
case .bool: return .bool
425+
case .int: return .int
426+
case .float: return .float
427+
case .double: return .double
428+
case .string: return .string
429+
case .jsObject: return .jsObject
430+
case .void: return .void
431+
case .swiftHeapObject:
432+
throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures")
433+
case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum:
434+
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
435+
}
436+
}
437+
438+
struct LiftingReturnInfo {
439+
let valueToLift: WasmCoreType?
440+
441+
static let bool = LiftingReturnInfo(valueToLift: .i32)
442+
static let int = LiftingReturnInfo(valueToLift: .i32)
443+
static let float = LiftingReturnInfo(valueToLift: .f32)
444+
static let double = LiftingReturnInfo(valueToLift: .f64)
445+
static let string = LiftingReturnInfo(valueToLift: .i32)
446+
static let jsObject = LiftingReturnInfo(valueToLift: .i32)
447+
static let void = LiftingReturnInfo(valueToLift: nil)
448+
}
449+
450+
func liftingReturnInfo() throws -> LiftingReturnInfo {
451+
switch self {
452+
case .bool: return .bool
453+
case .int: return .int
454+
case .float: return .float
455+
case .double: return .double
456+
case .string: return .string
457+
case .jsObject: return .jsObject
458+
case .void: return .void
459+
case .swiftHeapObject:
460+
throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures")
461+
case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum:
462+
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
463+
}
464+
}
465+
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/ArrayParameter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func checkArrayWithLength(_ a: JSObject, _ b: Double) throws(JSException) -> Voi
3030
fatalError("Only available on WebAssembly")
3131
}
3232
#endif
33-
bjs_checkArrayWithLength(a.bridgeJSLowerParameter(), b)
33+
bjs_checkArrayWithLength(a.bridgeJSLowerParameter(), b.bridgeJSLowerParameter())
3434
if let error = _swift_js_take_exception() {
3535
throw error
3636
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Async.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func asyncReturnVoid() throws(JSException) -> JSPromise {
1919
if let error = _swift_js_take_exception() {
2020
throw error
2121
}
22-
return JSPromise(takingThis: ret)
22+
return JSPromise.bridgeJSLiftReturn(ret)
2323
}
2424

2525
func asyncRoundTripInt(_ v: Double) throws(JSException) -> JSPromise {
@@ -31,11 +31,11 @@ func asyncRoundTripInt(_ v: Double) throws(JSException) -> JSPromise {
3131
fatalError("Only available on WebAssembly")
3232
}
3333
#endif
34-
let ret = bjs_asyncRoundTripInt(v)
34+
let ret = bjs_asyncRoundTripInt(v.bridgeJSLowerParameter())
3535
if let error = _swift_js_take_exception() {
3636
throw error
3737
}
38-
return JSPromise(takingThis: ret)
38+
return JSPromise.bridgeJSLiftReturn(ret)
3939
}
4040

4141
func asyncRoundTripString(_ v: String) throws(JSException) -> JSPromise {
@@ -51,7 +51,7 @@ func asyncRoundTripString(_ v: String) throws(JSException) -> JSPromise {
5151
if let error = _swift_js_take_exception() {
5252
throw error
5353
}
54-
return JSPromise(takingThis: ret)
54+
return JSPromise.bridgeJSLiftReturn(ret)
5555
}
5656

5757
func asyncRoundTripBool(_ v: Bool) throws(JSException) -> JSPromise {
@@ -67,7 +67,7 @@ func asyncRoundTripBool(_ v: Bool) throws(JSException) -> JSPromise {
6767
if let error = _swift_js_take_exception() {
6868
throw error
6969
}
70-
return JSPromise(takingThis: ret)
70+
return JSPromise.bridgeJSLiftReturn(ret)
7171
}
7272

7373
func asyncRoundTripFloat(_ v: Double) throws(JSException) -> JSPromise {
@@ -79,11 +79,11 @@ func asyncRoundTripFloat(_ v: Double) throws(JSException) -> JSPromise {
7979
fatalError("Only available on WebAssembly")
8080
}
8181
#endif
82-
let ret = bjs_asyncRoundTripFloat(v)
82+
let ret = bjs_asyncRoundTripFloat(v.bridgeJSLowerParameter())
8383
if let error = _swift_js_take_exception() {
8484
throw error
8585
}
86-
return JSPromise(takingThis: ret)
86+
return JSPromise.bridgeJSLiftReturn(ret)
8787
}
8888

8989
func asyncRoundTripDouble(_ v: Double) throws(JSException) -> JSPromise {
@@ -95,11 +95,11 @@ func asyncRoundTripDouble(_ v: Double) throws(JSException) -> JSPromise {
9595
fatalError("Only available on WebAssembly")
9696
}
9797
#endif
98-
let ret = bjs_asyncRoundTripDouble(v)
98+
let ret = bjs_asyncRoundTripDouble(v.bridgeJSLowerParameter())
9999
if let error = _swift_js_take_exception() {
100100
throw error
101101
}
102-
return JSPromise(takingThis: ret)
102+
return JSPromise.bridgeJSLiftReturn(ret)
103103
}
104104

105105
func asyncRoundTripJSObject(_ v: JSObject) throws(JSException) -> JSPromise {
@@ -115,5 +115,5 @@ func asyncRoundTripJSObject(_ v: JSObject) throws(JSException) -> JSPromise {
115115
if let error = _swift_js_take_exception() {
116116
throw error
117117
}
118-
return JSPromise(takingThis: ret)
118+
return JSPromise.bridgeJSLiftReturn(ret)
119119
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ImportTSTests/Interface.swift

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,14 @@ func returnAnimatable() throws(JSException) -> Animatable {
1919
if let error = _swift_js_take_exception() {
2020
throw error
2121
}
22-
return Animatable(takingThis: ret)
22+
return Animatable.bridgeJSLiftReturn(ret)
2323
}
2424

25-
struct Animatable {
26-
let this: JSObject
25+
struct Animatable: _BridgedJSClass {
26+
let jsObject: JSObject
2727

28-
init(this: JSObject) {
29-
self.this = this
30-
}
31-
32-
init(takingThis this: Int32) {
33-
self.this = JSObject(id: UInt32(bitPattern: this))
28+
init(unsafelyWrapping jsObject: JSObject) {
29+
self.jsObject = jsObject
3430
}
3531

3632
func animate(_ keyframes: JSObject, _ options: JSObject) throws(JSException) -> JSObject {
@@ -42,7 +38,7 @@ struct Animatable {
4238
fatalError("Only available on WebAssembly")
4339
}
4440
#endif
45-
let ret = bjs_Animatable_animate(self.this.bridgeJSLowerParameter(), keyframes.bridgeJSLowerParameter(), options.bridgeJSLowerParameter())
41+
let ret = bjs_Animatable_animate(self.bridgeJSLowerParameter(), keyframes.bridgeJSLowerParameter(), options.bridgeJSLowerParameter())
4642
if let error = _swift_js_take_exception() {
4743
throw error
4844
}
@@ -58,7 +54,7 @@ struct Animatable {
5854
fatalError("Only available on WebAssembly")
5955
}
6056
#endif
61-
let ret = bjs_Animatable_getAnimations(self.this.bridgeJSLowerParameter(), options.bridgeJSLowerParameter())
57+
let ret = bjs_Animatable_getAnimations(self.bridgeJSLowerParameter(), options.bridgeJSLowerParameter())
6258
if let error = _swift_js_take_exception() {
6359
throw error
6460
}

0 commit comments

Comments
 (0)