Skip to content

Commit f75e365

Browse files
BridgeJS: Fix Array<@jsclass struct> support on imported interfaces
1 parent 9bf1c59 commit f75e365

File tree

8 files changed

+235
-11
lines changed

8 files changed

+235
-11
lines changed

Sources/JavaScriptKit/BridgeJSIntrinsics.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -510,12 +510,13 @@ extension _JSBridgedClass {
510510
@_spi(BridgeJS) public static func bridgeJSLiftParameter(_ id: Int32) -> Self {
511511
Self(unsafelyWrapping: JSObject.bridgeJSLiftParameter(id))
512512
}
513-
@_spi(BridgeJS) public static func bridgeJSStackPop() -> Self {
514-
bridgeJSLiftParameter(_swift_js_pop_i32())
515-
}
516513
@_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Int32 { jsObject.bridgeJSLowerReturn() }
517-
@_spi(BridgeJS) public consuming func bridgeJSStackPush() {
518-
_swift_js_push_i32(bridgeJSLowerReturn())
514+
515+
public static func bridgeJSStackPop() -> Self {
516+
Self(unsafelyWrapping: JSObject.bridgeJSStackPop())
517+
}
518+
public consuming func bridgeJSStackPush() {
519+
jsObject.bridgeJSStackPush()
519520
}
520521
}
521522

Sources/JavaScriptKit/JSBridgedType.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extension JSBridgedType {
1616
/// A protocol that Swift classes that are exposed to JavaScript via `@JS class` conform to.
1717
///
1818
/// The conformance is automatically synthesized by `@JSClass` for BridgeJS-generated declarations.
19-
public protocol _JSBridgedClass {
19+
public protocol _JSBridgedClass: Equatable, _BridgedSwiftStackType {
2020
/// The JavaScript object wrapped by this instance.
2121
/// You may assume that `jsObject instanceof Self.constructor == true`
2222
var jsObject: JSObject { get }
@@ -26,6 +26,12 @@ public protocol _JSBridgedClass {
2626
init(unsafelyWrapping jsObject: JSObject)
2727
}
2828

29+
extension _JSBridgedClass {
30+
public static func == (lhs: Self, rhs: Self) -> Bool {
31+
lhs.jsObject == rhs.jsObject
32+
}
33+
}
34+
2935
/// Conform to this protocol when your Swift class wraps a JavaScript class.
3036
public protocol JSBridgedClass: JSBridgedType, _JSBridgedClass {
3137
/// The constructor function for the JavaScript class

Tests/BridgeJSRuntimeTests/ArraySupportTests.swift

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import XCTest
22
import JavaScriptKit
33

4+
@JSClass struct ArrayElementObject {
5+
@JSGetter var id: String
6+
7+
@JSFunction init(id: String) throws(JSException)
8+
}
9+
410
@JSClass struct ArraySupportImports {
511
@JSFunction static func jsIntArrayLength(_ items: [Int]) throws(JSException) -> Int
612

@@ -10,7 +16,15 @@ import JavaScriptKit
1016
@JSFunction static func jsRoundTripBoolArray(_ values: [Bool]) throws(JSException) -> [Bool]
1117

1218
@JSFunction static func jsRoundTripJSValueArray(_ v: [JSValue]) throws(JSException) -> [JSValue]
13-
@JSFunction static func jsRoundTripOptionalJSValueArray(_ v: Optional<[JSValue]>) throws(JSException) -> Optional<[JSValue]>
19+
@JSFunction static func jsRoundTripOptionalJSValueArray(
20+
_ v: Optional<[JSValue]>
21+
) throws(JSException) -> Optional<[JSValue]>
22+
23+
@JSFunction static func jsRoundTripJSObjectArray(_ values: [JSObject]) throws(JSException) -> [JSObject]
24+
25+
@JSFunction static func jsRoundTripJSClassArray(
26+
_ values: [ArrayElementObject]
27+
) throws(JSException) -> [ArrayElementObject]
1428

1529
@JSFunction static func jsSumNumberArray(_ values: [Double]) throws(JSException) -> Double
1630
@JSFunction static func jsCreateNumberArray() throws(JSException) -> [Double]
@@ -85,4 +99,21 @@ final class ArraySupportTests: XCTestCase {
8599
let result = try ArraySupportImports.jsRoundTripOptionalJSValueArray(values)
86100
XCTAssertEqual(result, values)
87101
}
102+
103+
func testRoundTripJSObjectArray() throws {
104+
let values: [JSObject] = [.global, JSObject(), ["a": 1, "b": 2]]
105+
let result = try ArraySupportImports.jsRoundTripJSObjectArray(values)
106+
XCTAssertEqual(result, values)
107+
}
108+
109+
func testRoundTripJSClassArray() throws {
110+
let values = try [ArrayElementObject(id: "1"), ArrayElementObject(id: "2"), ArrayElementObject(id: "3")]
111+
let result = try ArraySupportImports.jsRoundTripJSClassArray(values)
112+
XCTAssertEqual(result, values)
113+
XCTAssertEqual(try result[0].id, "1")
114+
XCTAssertEqual(try result[1].id, "2")
115+
XCTAssertEqual(try result[2].id, "3")
116+
117+
XCTAssertEqual(try ArraySupportImports.jsRoundTripJSClassArray([]), [])
118+
}
88119
}

Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9229,6 +9229,48 @@ fileprivate func _bjs_LeakCheck_wrap_extern(_ pointer: UnsafeMutableRawPointer)
92299229
return _bjs_LeakCheck_wrap_extern(pointer)
92309230
}
92319231

9232+
#if arch(wasm32)
9233+
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayElementObject_init")
9234+
fileprivate func bjs_ArrayElementObject_init_extern(_ id: Int32) -> Int32
9235+
#else
9236+
fileprivate func bjs_ArrayElementObject_init_extern(_ id: Int32) -> Int32 {
9237+
fatalError("Only available on WebAssembly")
9238+
}
9239+
#endif
9240+
@inline(never) fileprivate func bjs_ArrayElementObject_init(_ id: Int32) -> Int32 {
9241+
return bjs_ArrayElementObject_init_extern(id)
9242+
}
9243+
9244+
#if arch(wasm32)
9245+
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayElementObject_id_get")
9246+
fileprivate func bjs_ArrayElementObject_id_get_extern(_ self: Int32) -> Int32
9247+
#else
9248+
fileprivate func bjs_ArrayElementObject_id_get_extern(_ self: Int32) -> Int32 {
9249+
fatalError("Only available on WebAssembly")
9250+
}
9251+
#endif
9252+
@inline(never) fileprivate func bjs_ArrayElementObject_id_get(_ self: Int32) -> Int32 {
9253+
return bjs_ArrayElementObject_id_get_extern(self)
9254+
}
9255+
9256+
func _$ArrayElementObject_init(_ id: String) throws(JSException) -> JSObject {
9257+
let idValue = id.bridgeJSLowerParameter()
9258+
let ret = bjs_ArrayElementObject_init(idValue)
9259+
if let error = _swift_js_take_exception() {
9260+
throw error
9261+
}
9262+
return JSObject.bridgeJSLiftReturn(ret)
9263+
}
9264+
9265+
func _$ArrayElementObject_id_get(_ self: JSObject) throws(JSException) -> String {
9266+
let selfValue = self.bridgeJSLowerParameter()
9267+
let ret = bjs_ArrayElementObject_id_get(selfValue)
9268+
if let error = _swift_js_take_exception() {
9269+
throw error
9270+
}
9271+
return String.bridgeJSLiftReturn(ret)
9272+
}
9273+
92329274
#if arch(wasm32)
92339275
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArraySupportImports_jsIntArrayLength_static")
92349276
fileprivate func bjs_ArraySupportImports_jsIntArrayLength_static_extern() -> Int32
@@ -9313,6 +9355,30 @@ fileprivate func bjs_ArraySupportImports_jsRoundTripOptionalJSValueArray_static_
93139355
return bjs_ArraySupportImports_jsRoundTripOptionalJSValueArray_static_extern(v)
93149356
}
93159357

9358+
#if arch(wasm32)
9359+
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArraySupportImports_jsRoundTripJSObjectArray_static")
9360+
fileprivate func bjs_ArraySupportImports_jsRoundTripJSObjectArray_static_extern() -> Void
9361+
#else
9362+
fileprivate func bjs_ArraySupportImports_jsRoundTripJSObjectArray_static_extern() -> Void {
9363+
fatalError("Only available on WebAssembly")
9364+
}
9365+
#endif
9366+
@inline(never) fileprivate func bjs_ArraySupportImports_jsRoundTripJSObjectArray_static() -> Void {
9367+
return bjs_ArraySupportImports_jsRoundTripJSObjectArray_static_extern()
9368+
}
9369+
9370+
#if arch(wasm32)
9371+
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArraySupportImports_jsRoundTripJSClassArray_static")
9372+
fileprivate func bjs_ArraySupportImports_jsRoundTripJSClassArray_static_extern() -> Void
9373+
#else
9374+
fileprivate func bjs_ArraySupportImports_jsRoundTripJSClassArray_static_extern() -> Void {
9375+
fatalError("Only available on WebAssembly")
9376+
}
9377+
#endif
9378+
@inline(never) fileprivate func bjs_ArraySupportImports_jsRoundTripJSClassArray_static() -> Void {
9379+
return bjs_ArraySupportImports_jsRoundTripJSClassArray_static_extern()
9380+
}
9381+
93169382
#if arch(wasm32)
93179383
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArraySupportImports_jsSumNumberArray_static")
93189384
fileprivate func bjs_ArraySupportImports_jsSumNumberArray_static_extern() -> Float64
@@ -9400,6 +9466,24 @@ func _$ArraySupportImports_jsRoundTripOptionalJSValueArray(_ v: Optional<[JSValu
94009466
return Optional<[JSValue]>.bridgeJSLiftReturn()
94019467
}
94029468

9469+
func _$ArraySupportImports_jsRoundTripJSObjectArray(_ values: [JSObject]) throws(JSException) -> [JSObject] {
9470+
let _ = values.bridgeJSLowerParameter()
9471+
bjs_ArraySupportImports_jsRoundTripJSObjectArray_static()
9472+
if let error = _swift_js_take_exception() {
9473+
throw error
9474+
}
9475+
return [JSObject].bridgeJSLiftReturn()
9476+
}
9477+
9478+
func _$ArraySupportImports_jsRoundTripJSClassArray(_ values: [ArrayElementObject]) throws(JSException) -> [ArrayElementObject] {
9479+
let _ = values.bridgeJSLowerParameter()
9480+
bjs_ArraySupportImports_jsRoundTripJSClassArray_static()
9481+
if let error = _swift_js_take_exception() {
9482+
throw error
9483+
}
9484+
return [ArrayElementObject].bridgeJSLiftReturn()
9485+
}
9486+
94039487
func _$ArraySupportImports_jsSumNumberArray(_ values: [Double]) throws(JSException) -> Double {
94049488
let _ = values.bridgeJSLowerParameter()
94059489
let ret = bjs_ArraySupportImports_jsSumNumberArray_static()

Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13379,6 +13379,40 @@
1337913379

1338013380
],
1338113381
"types" : [
13382+
{
13383+
"constructor" : {
13384+
"parameters" : [
13385+
{
13386+
"name" : "id",
13387+
"type" : {
13388+
"string" : {
13389+
13390+
}
13391+
}
13392+
}
13393+
]
13394+
},
13395+
"getters" : [
13396+
{
13397+
"name" : "id",
13398+
"type" : {
13399+
"string" : {
13400+
13401+
}
13402+
}
13403+
}
13404+
],
13405+
"methods" : [
13406+
13407+
],
13408+
"name" : "ArrayElementObject",
13409+
"setters" : [
13410+
13411+
],
13412+
"staticMethods" : [
13413+
13414+
]
13415+
},
1338213416
{
1338313417
"getters" : [
1338413418

@@ -13579,6 +13613,58 @@
1357913613
}
1358013614
}
1358113615
},
13616+
{
13617+
"name" : "jsRoundTripJSObjectArray",
13618+
"parameters" : [
13619+
{
13620+
"name" : "values",
13621+
"type" : {
13622+
"array" : {
13623+
"_0" : {
13624+
"jsObject" : {
13625+
13626+
}
13627+
}
13628+
}
13629+
}
13630+
}
13631+
],
13632+
"returnType" : {
13633+
"array" : {
13634+
"_0" : {
13635+
"jsObject" : {
13636+
13637+
}
13638+
}
13639+
}
13640+
}
13641+
},
13642+
{
13643+
"name" : "jsRoundTripJSClassArray",
13644+
"parameters" : [
13645+
{
13646+
"name" : "values",
13647+
"type" : {
13648+
"array" : {
13649+
"_0" : {
13650+
"jsObject" : {
13651+
"_0" : "ArrayElementObject"
13652+
}
13653+
}
13654+
}
13655+
}
13656+
}
13657+
],
13658+
"returnType" : {
13659+
"array" : {
13660+
"_0" : {
13661+
"jsObject" : {
13662+
"_0" : "ArrayElementObject"
13663+
}
13664+
}
13665+
}
13666+
}
13667+
},
1358213668
{
1358313669
"name" : "jsSumNumberArray",
1358413670
"parameters" : [

Tests/BridgeJSRuntimeTests/JSClassSupportTests.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ import JavaScriptKit
1313
}
1414

1515
@JSClass struct JSClassSupportImports {
16-
@JSFunction static func makeJSClassWithArrayMembers(_ numbers: [Int], _ labels: [String]) throws(JSException) -> JSClassWithArrayMembers
16+
@JSFunction static func makeJSClassWithArrayMembers(
17+
_ numbers: [Int],
18+
_ labels: [String]
19+
) throws(JSException) -> JSClassWithArrayMembers
1720
}
1821

1922
final class JSClassSupportTests: XCTestCase {
@@ -35,4 +38,4 @@ final class JSClassSupportTests: XCTestCase {
3538
XCTAssertEqual(try host.firstLabel([]), "gamma")
3639
XCTAssertEqual(try host.firstLabel(["zeta"]), "zeta")
3740
}
38-
}
41+
}

Tests/BridgeJSRuntimeTests/JavaScript/ArraySupportTests.mjs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
// @ts-check
22

3+
export class ArrayElementObject {
4+
constructor(id) {
5+
this.id = id;
6+
}
7+
}
8+
39
/**
410
* @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["ArraySupportImports"]}
511
*/
@@ -31,6 +37,12 @@ export function getImports(importsContext) {
3137
},
3238
jsCreateNumberArray: function () {
3339
return [1, 2, 3, 4, 5];
34-
}
40+
},
41+
jsRoundTripJSObjectArray: (values) => {
42+
return values;
43+
},
44+
jsRoundTripJSClassArray: (values) => {
45+
return values;
46+
},
3547
};
3648
}

Tests/prelude.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { runJsOptionalSupportTests } from './BridgeJSRuntimeTests/JavaScript/Opt
88
import { getImports as getClosureSupportImports } from './BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs';
99
import { getImports as getSwiftClassSupportImports } from './BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs';
1010
import { getImports as getOptionalSupportImports } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs';
11-
import { getImports as getArraySupportImports } from './BridgeJSRuntimeTests/JavaScript/ArraySupportTests.mjs';
11+
import { getImports as getArraySupportImports, ArrayElementObject } from './BridgeJSRuntimeTests/JavaScript/ArraySupportTests.mjs';
1212
import { getImports as getJSClassSupportImports, JSClassWithArrayMembers } from './BridgeJSRuntimeTests/JavaScript/JSClassSupportTests.mjs';
1313

1414
/** @type {import('../.build/plugins/PackageToJS/outputs/PackageTests/test.d.ts').SetupOptionsFn} */
@@ -112,6 +112,7 @@ export async function setupOptions(options, context) {
112112
"$jsWeirdFunction": () => {
113113
return 42;
114114
},
115+
ArrayElementObject,
115116
JSClassWithArrayMembers,
116117
JsGreeter: class {
117118
/**

0 commit comments

Comments
 (0)