Skip to content

Commit 7aae4b8

Browse files
Added JS null/undefined optional coverage and strict TS config for generation:
- Created `tsconfig.json` with strict/null-checking to ensure unions survive into BridgeJS generation. - Extended runtime JS prelude and `bridge-js.d.ts` with optional number round-trips, regenerated bindings via `Utilities/bridge-js-generate.sh`, and added Swift runtime tests in `Tests/BridgeJSRuntimeTests/ImportAPITests.swift` to exercise `T | null` → `Optional` and `T | undefined` → `JSUndefinedOr`. - Regenerated BridgeJS runtime artifacts under `Tests/BridgeJSRuntimeTests/Generated/` and related outputs. Tests executed: - `swift test --package-path ./Plugins/BridgeJS` - `SWIFT_SDK_ID=DEVELOPMENT-SNAPSHOT-2025-11-03-a-wasm32-unknown-wasip1 make unittest`
1 parent 40e944c commit 7aae4b8

File tree

7 files changed

+128
-0
lines changed

7 files changed

+128
-0
lines changed

Tests/BridgeJSRuntimeTests/Generated/BridgeJS.Macros.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
@JSFunction func jsRoundTripString(_ v: String) throws (JSException) -> String
1616

17+
@JSFunction func jsRoundTripOptionalNumberNull(_ v: Optional<Double>) throws (JSException) -> Optional<Double>
18+
19+
@JSFunction func jsRoundTripOptionalNumberUndefined(_ v: JSUndefinedOr<Double>) throws (JSException) -> JSUndefinedOr<Double>
20+
1721
@JSFunction func jsThrowOrVoid(_ shouldThrow: Bool) throws (JSException) -> Void
1822

1923
@JSFunction func jsThrowOrNumber(_ shouldThrow: Bool) throws (JSException) -> Double

Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7648,6 +7648,42 @@ func _$jsRoundTripString(_ v: String) throws(JSException) -> String {
76487648
return String.bridgeJSLiftReturn(ret)
76497649
}
76507650

7651+
#if arch(wasm32)
7652+
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripOptionalNumberNull")
7653+
fileprivate func bjs_jsRoundTripOptionalNumberNull(_ vIsSome: Int32, _ vValue: Float64) -> Void
7654+
#else
7655+
fileprivate func bjs_jsRoundTripOptionalNumberNull(_ vIsSome: Int32, _ vValue: Float64) -> Void {
7656+
fatalError("Only available on WebAssembly")
7657+
}
7658+
#endif
7659+
7660+
func _$jsRoundTripOptionalNumberNull(_ v: Optional<Double>) throws(JSException) -> Optional<Double> {
7661+
let (vIsSome, vValue) = v.bridgeJSLowerParameter()
7662+
bjs_jsRoundTripOptionalNumberNull(vIsSome, vValue)
7663+
if let error = _swift_js_take_exception() {
7664+
throw error
7665+
}
7666+
return Optional<Double>.bridgeJSLiftReturnFromSideChannel()
7667+
}
7668+
7669+
#if arch(wasm32)
7670+
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripOptionalNumberUndefined")
7671+
fileprivate func bjs_jsRoundTripOptionalNumberUndefined(_ vIsDefined: Int32, _ vValue: Float64) -> Void
7672+
#else
7673+
fileprivate func bjs_jsRoundTripOptionalNumberUndefined(_ vIsDefined: Int32, _ vValue: Float64) -> Void {
7674+
fatalError("Only available on WebAssembly")
7675+
}
7676+
#endif
7677+
7678+
func _$jsRoundTripOptionalNumberUndefined(_ v: JSUndefinedOr<Double>) throws(JSException) -> JSUndefinedOr<Double> {
7679+
let (vIsDefined, vValue) = v.bridgeJSLowerParameter()
7680+
bjs_jsRoundTripOptionalNumberUndefined(vIsDefined, vValue)
7681+
if let error = _swift_js_take_exception() {
7682+
throw error
7683+
}
7684+
return JSUndefinedOr<Double>.bridgeJSLiftReturnFromSideChannel()
7685+
}
7686+
76517687
#if arch(wasm32)
76527688
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsThrowOrVoid")
76537689
fileprivate func bjs_jsThrowOrVoid(_ shouldThrow: Int32) -> Void

Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11475,6 +11475,58 @@
1147511475
}
1147611476
}
1147711477
},
11478+
{
11479+
"name" : "jsRoundTripOptionalNumberNull",
11480+
"parameters" : [
11481+
{
11482+
"name" : "v",
11483+
"type" : {
11484+
"optional" : {
11485+
"_0" : {
11486+
"double" : {
11487+
11488+
}
11489+
}
11490+
}
11491+
}
11492+
}
11493+
],
11494+
"returnType" : {
11495+
"optional" : {
11496+
"_0" : {
11497+
"double" : {
11498+
11499+
}
11500+
}
11501+
}
11502+
}
11503+
},
11504+
{
11505+
"name" : "jsRoundTripOptionalNumberUndefined",
11506+
"parameters" : [
11507+
{
11508+
"name" : "v",
11509+
"type" : {
11510+
"undefinedOr" : {
11511+
"_0" : {
11512+
"double" : {
11513+
11514+
}
11515+
}
11516+
}
11517+
}
11518+
}
11519+
],
11520+
"returnType" : {
11521+
"undefinedOr" : {
11522+
"_0" : {
11523+
"double" : {
11524+
11525+
}
11526+
}
11527+
}
11528+
}
11529+
},
1147811530
{
1147911531
"name" : "jsThrowOrVoid",
1148011532
"parameters" : [

Tests/BridgeJSRuntimeTests/ImportAPITests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,26 @@ class ImportAPITests: XCTestCase {
3535
}
3636
}
3737

38+
func testRoundTripOptionalNumberNull() throws {
39+
try XCTAssertEqual(jsRoundTripOptionalNumberNull(42), 42)
40+
try XCTAssertNil(jsRoundTripOptionalNumberNull(nil))
41+
}
42+
43+
func testRoundTripOptionalNumberUndefined() throws {
44+
let some = try jsRoundTripOptionalNumberUndefined(.value(42))
45+
switch some {
46+
case .value(let value):
47+
XCTAssertEqual(value, 42)
48+
case .undefined:
49+
XCTFail("Expected defined value")
50+
}
51+
52+
let undefined = try jsRoundTripOptionalNumberUndefined(.undefinedValue)
53+
if case .value = undefined {
54+
XCTFail("Expected undefined")
55+
}
56+
}
57+
3858
func testRoundTripFeatureFlag() throws {
3959
for v in [FeatureFlag.foo, .bar] {
4060
try XCTAssertEqual(jsRoundTripFeatureFlag(v), v)

Tests/BridgeJSRuntimeTests/bridge-js.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ export function jsRoundTripVoid(): void
22
export function jsRoundTripNumber(v: number): number
33
export function jsRoundTripBool(v: boolean): boolean
44
export function jsRoundTripString(v: string): string
5+
export function jsRoundTripOptionalNumberNull(v: number | null): number | null
6+
export function jsRoundTripOptionalNumberUndefined(v: number | undefined): number | undefined
57
export function jsThrowOrVoid(shouldThrow: boolean): void
68
export function jsThrowOrNumber(shouldThrow: boolean): number
79
export function jsThrowOrBool(shouldThrow: boolean): boolean

Tests/prelude.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ export async function setupOptions(options, context) {
2525
"jsRoundTripString": (v) => {
2626
return v;
2727
},
28+
"jsRoundTripOptionalNumberNull": (v) => {
29+
return v ?? null;
30+
},
31+
"jsRoundTripOptionalNumberUndefined": (v) => {
32+
return v === undefined ? undefined : v;
33+
},
2834
"jsThrowOrVoid": (shouldThrow) => {
2935
if (shouldThrow) {
3036
throw new Error("TestError");

tsconfig.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"compilerOptions": {
3+
"strict": true,
4+
"noEmit": true,
5+
"lib": ["es2020", "DOM"],
6+
"skipLibCheck": true
7+
}
8+
}

0 commit comments

Comments
 (0)