diff --git a/Benchmarks/Sources/Benchmarks.swift b/Benchmarks/Sources/Benchmarks.swift index 55b9f3eb..b05075eb 100644 --- a/Benchmarks/Sources/Benchmarks.swift +++ b/Benchmarks/Sources/Benchmarks.swift @@ -18,6 +18,99 @@ class Benchmark { } } +@JS enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} + +@JS class EnumRoundtrip { + @JS init() {} + + @JS func take(_ value: APIResult) {} + @JS func makeSuccess() -> APIResult { + return .success("Hello, world") + } + @JS func makeFailure() -> APIResult { + return .failure(42) + } + @JS func makeFlag() -> APIResult { + return .flag(true) + } + @JS func makeRate() -> APIResult { + return .rate(0.5) + } + @JS func makePrecise() -> APIResult { + return .precise(0.5) + } + @JS func makeInfo() -> APIResult { + return .info + } + + @JS func roundtrip(_ result: APIResult) -> APIResult { + return result + } +} + +@JS +enum ComplexResult { + case success(String) + case error(String, Int) + case location(Double, Double, String) + case status(Bool, Int, String) + case coordinates(Double, Double, Double) + case comprehensive(Bool, Bool, Int, Int, Double, Double, String, String, String) + case info +} + +@JS class ComplexResultRoundtrip { + @JS init() {} + + @JS func take(_ value: ComplexResult) {} + + @JS func makeSuccess() -> ComplexResult { + return .success("Hello, world") + } + + @JS func makeError() -> ComplexResult { + return .error("Network timeout", 503) + } + + @JS func makeLocation() -> ComplexResult { + return .location(37.7749, -122.4194, "San Francisco") + } + + @JS func makeStatus() -> ComplexResult { + return .status(true, 200, "OK") + } + + @JS func makeCoordinates() -> ComplexResult { + return .coordinates(10.5, 20.3, 30.7) + } + + @JS func makeComprehensive() -> ComplexResult { + return .comprehensive(true, false, 42, 100, 3.14, 2.718, "Hello", "World", "Test") + } + + @JS func makeInfo() -> ComplexResult { + return .info + } + + @JS func roundtrip(_ result: ComplexResult) -> ComplexResult { + return result + } +} +@JS class StringRoundtrip { + @JS init() {} + @JS func take(_ value: String) {} + @JS func make() -> String { + return "Hello, world" + } +} + @JS func run() { let call = Benchmark("Call") diff --git a/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift b/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift index ee86def7..2d9f61b9 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift @@ -6,6 +6,136 @@ @_spi(BridgeJS) import JavaScriptKit +private extension APIResult { + static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 2: + return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 3: + return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())) + case 4: + return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + case 5: + return .info + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .failure(let param0): + _swift_js_push_tag(Int32(1)) + _swift_js_push_int(Int32(param0)) + case .flag(let param0): + _swift_js_push_tag(Int32(2)) + _swift_js_push_int(param0 ? 1 : 0) + case .rate(let param0): + _swift_js_push_tag(Int32(3)) + _swift_js_push_f32(param0) + case .precise(let param0): + _swift_js_push_tag(Int32(4)) + _swift_js_push_f64(param0) + case .info: + _swift_js_push_tag(Int32(5)) + } + } +} + +private extension ComplexResult { + static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .error(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 2: + return .location(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 3: + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 4: + return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + case 5: + return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 6: + return .info + default: + fatalError("Unknown ComplexResult case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .error(let param0, let param1): + _swift_js_push_tag(Int32(1)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_int(Int32(param1)) + case .location(let param0, let param1, let param2): + _swift_js_push_tag(Int32(2)) + _swift_js_push_f64(param0) + _swift_js_push_f64(param1) + var __bjs_param2 = param2 + __bjs_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .status(let param0, let param1, let param2): + _swift_js_push_tag(Int32(3)) + _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_int(Int32(param1)) + var __bjs_param2 = param2 + __bjs_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .coordinates(let param0, let param1, let param2): + _swift_js_push_tag(Int32(4)) + _swift_js_push_f64(param0) + _swift_js_push_f64(param1) + _swift_js_push_f64(param2) + case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): + _swift_js_push_tag(Int32(5)) + _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_int(param1 ? 1 : 0) + _swift_js_push_int(Int32(param2)) + _swift_js_push_int(Int32(param3)) + _swift_js_push_f64(param4) + _swift_js_push_f64(param5) + var __bjs_param6 = param6 + __bjs_param6.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + var __bjs_param7 = param7 + __bjs_param7.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + var __bjs_param8 = param8 + __bjs_param8.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .info: + _swift_js_push_tag(Int32(6)) + } + } +} + @_expose(wasm, "bjs_run") @_cdecl("bjs_run") public func _bjs_run() -> Void { @@ -14,4 +144,303 @@ public func _bjs_run() -> Void { #else fatalError("Only available on WebAssembly") #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_init") +@_cdecl("bjs_EnumRoundtrip_init") +public func _bjs_EnumRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = EnumRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_take") +@_cdecl("bjs_EnumRoundtrip_take") +public func _bjs_EnumRoundtrip_take(_self: UnsafeMutableRawPointer, value: Int32) -> Void { + #if arch(wasm32) + EnumRoundtrip.bridgeJSLiftParameter(_self).take(_: APIResult.bridgeJSLiftParameter(value)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeSuccess") +@_cdecl("bjs_EnumRoundtrip_makeSuccess") +public func _bjs_EnumRoundtrip_makeSuccess(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeSuccess() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeFailure") +@_cdecl("bjs_EnumRoundtrip_makeFailure") +public func _bjs_EnumRoundtrip_makeFailure(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeFailure() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeFlag") +@_cdecl("bjs_EnumRoundtrip_makeFlag") +public func _bjs_EnumRoundtrip_makeFlag(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeFlag() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeRate") +@_cdecl("bjs_EnumRoundtrip_makeRate") +public func _bjs_EnumRoundtrip_makeRate(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeRate() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makePrecise") +@_cdecl("bjs_EnumRoundtrip_makePrecise") +public func _bjs_EnumRoundtrip_makePrecise(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makePrecise() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_makeInfo") +@_cdecl("bjs_EnumRoundtrip_makeInfo") +public func _bjs_EnumRoundtrip_makeInfo(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).makeInfo() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_roundtrip") +@_cdecl("bjs_EnumRoundtrip_roundtrip") +public func _bjs_EnumRoundtrip_roundtrip(_self: UnsafeMutableRawPointer, result: Int32) -> Void { + #if arch(wasm32) + let ret = EnumRoundtrip.bridgeJSLiftParameter(_self).roundtrip(_: APIResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_EnumRoundtrip_deinit") +@_cdecl("bjs_EnumRoundtrip_deinit") +public func _bjs_EnumRoundtrip_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension EnumRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "Benchmarks", name: "bjs_EnumRoundtrip_wrap") + func _bjs_EnumRoundtrip_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_EnumRoundtrip_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_EnumRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_init") +@_cdecl("bjs_ComplexResultRoundtrip_init") +public func _bjs_ComplexResultRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = ComplexResultRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_take") +@_cdecl("bjs_ComplexResultRoundtrip_take") +public func _bjs_ComplexResultRoundtrip_take(_self: UnsafeMutableRawPointer, value: Int32) -> Void { + #if arch(wasm32) + ComplexResultRoundtrip.bridgeJSLiftParameter(_self).take(_: ComplexResult.bridgeJSLiftParameter(value)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeSuccess") +@_cdecl("bjs_ComplexResultRoundtrip_makeSuccess") +public func _bjs_ComplexResultRoundtrip_makeSuccess(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeSuccess() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeError") +@_cdecl("bjs_ComplexResultRoundtrip_makeError") +public func _bjs_ComplexResultRoundtrip_makeError(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeError() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeLocation") +@_cdecl("bjs_ComplexResultRoundtrip_makeLocation") +public func _bjs_ComplexResultRoundtrip_makeLocation(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeLocation() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeStatus") +@_cdecl("bjs_ComplexResultRoundtrip_makeStatus") +public func _bjs_ComplexResultRoundtrip_makeStatus(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeStatus() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeCoordinates") +@_cdecl("bjs_ComplexResultRoundtrip_makeCoordinates") +public func _bjs_ComplexResultRoundtrip_makeCoordinates(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeCoordinates() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeComprehensive") +@_cdecl("bjs_ComplexResultRoundtrip_makeComprehensive") +public func _bjs_ComplexResultRoundtrip_makeComprehensive(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeComprehensive() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_makeInfo") +@_cdecl("bjs_ComplexResultRoundtrip_makeInfo") +public func _bjs_ComplexResultRoundtrip_makeInfo(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).makeInfo() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_roundtrip") +@_cdecl("bjs_ComplexResultRoundtrip_roundtrip") +public func _bjs_ComplexResultRoundtrip_roundtrip(_self: UnsafeMutableRawPointer, result: Int32) -> Void { + #if arch(wasm32) + let ret = ComplexResultRoundtrip.bridgeJSLiftParameter(_self).roundtrip(_: ComplexResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_ComplexResultRoundtrip_deinit") +@_cdecl("bjs_ComplexResultRoundtrip_deinit") +public func _bjs_ComplexResultRoundtrip_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension ComplexResultRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "Benchmarks", name: "bjs_ComplexResultRoundtrip_wrap") + func _bjs_ComplexResultRoundtrip_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_ComplexResultRoundtrip_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_ComplexResultRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +@_expose(wasm, "bjs_StringRoundtrip_init") +@_cdecl("bjs_StringRoundtrip_init") +public func _bjs_StringRoundtrip_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = StringRoundtrip() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringRoundtrip_take") +@_cdecl("bjs_StringRoundtrip_take") +public func _bjs_StringRoundtrip_take(_self: UnsafeMutableRawPointer, valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + StringRoundtrip.bridgeJSLiftParameter(_self).take(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringRoundtrip_make") +@_cdecl("bjs_StringRoundtrip_make") +public func _bjs_StringRoundtrip_make(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = StringRoundtrip.bridgeJSLiftParameter(_self).make() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringRoundtrip_deinit") +@_cdecl("bjs_StringRoundtrip_deinit") +public func _bjs_StringRoundtrip_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension StringRoundtrip: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "Benchmarks", name: "bjs_StringRoundtrip_wrap") + func _bjs_StringRoundtrip_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_StringRoundtrip_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_StringRoundtrip_wrap(Unmanaged.passRetained(self).toOpaque())))) + } } \ No newline at end of file diff --git a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json index b00ec9ab..cfd7c19e 100644 --- a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json +++ b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json @@ -1,9 +1,671 @@ { "classes" : [ + { + "constructor" : { + "abiName" : "bjs_EnumRoundtrip_init", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_EnumRoundtrip_take", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "take", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeSuccess", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeSuccess", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeFailure", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeFailure", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeFlag", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeFlag", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeRate", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeRate", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makePrecise", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makePrecise", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_makeInfo", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeInfo", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_EnumRoundtrip_roundtrip", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "name" : "EnumRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "EnumRoundtrip" + }, + { + "constructor" : { + "abiName" : "bjs_ComplexResultRoundtrip_init", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_ComplexResultRoundtrip_take", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "take", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeSuccess", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeSuccess", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeError", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeError", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeLocation", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeLocation", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeStatus", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeStatus", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeCoordinates", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeCoordinates", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeComprehensive", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeComprehensive", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_makeInfo", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "makeInfo", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_ComplexResultRoundtrip_roundtrip", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "name" : "ComplexResultRoundtrip", + "properties" : [ + + ], + "swiftCallName" : "ComplexResultRoundtrip" + }, + { + "constructor" : { + "abiName" : "bjs_StringRoundtrip_init", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_StringRoundtrip_take", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "take", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_StringRoundtrip_make", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "make", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "StringRoundtrip", + "properties" : [ + ], + "swiftCallName" : "StringRoundtrip" + } ], "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + } + ], + "name" : "flag" + }, + { + "associatedValues" : [ + { + "type" : { + "float" : { + + } + } + } + ], + "name" : "rate" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "precise" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "swiftCallName" : "APIResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "error" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "location" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "coordinates" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "comprehensive" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "ComplexResult", + "swiftCallName" : "ComplexResult" + } ], "functions" : [ { diff --git a/Benchmarks/run.js b/Benchmarks/run.js index 17b19214..d4747311 100644 --- a/Benchmarks/run.js +++ b/Benchmarks/run.js @@ -3,6 +3,7 @@ import { defaultNodeSetup } from "./.build/plugins/PackageToJS/outputs/Package/p import fs from 'fs'; import path from 'path'; import { parseArgs } from "util"; +import { APIResult, ComplexResult } from "./.build/plugins/PackageToJS/outputs/Package/bridge-js.js"; /** * Update progress bar on the current line @@ -288,6 +289,171 @@ async function singleRun(results, nameFilter) { }) }); exports.run(); + + const enumRoundtrip = new exports.EnumRoundtrip(); + const iterations = 100_000; + benchmarkRunner("EnumRoundtrip/takeEnum success", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Success, param0: "Hello, world" }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum failure", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Failure, param0: 42 }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum flag", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Flag, param0: true }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum rate", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Rate, param0: 0.5 }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum precise", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Precise, param0: 0.5 }) + } + }) + benchmarkRunner("EnumRoundtrip/takeEnum info", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.take({ tag: APIResult.Tag.Info }) + } + }) + benchmarkRunner("EnumRoundtrip/makeSuccess", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeSuccess() + } + }) + benchmarkRunner("EnumRoundtrip/makeFailure", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeFailure() + } + }) + benchmarkRunner("EnumRoundtrip/makeFlag", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeFlag() + } + }) + benchmarkRunner("EnumRoundtrip/makeRate", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeRate() + } + }) + benchmarkRunner("EnumRoundtrip/makePrecise", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makePrecise() + } + }) + benchmarkRunner("EnumRoundtrip/makeInfo", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.makeInfo() + } + }) + + benchmarkRunner("EnumRoundtrip/roundtrip", () => { + for (let i = 0; i < iterations; i++) { + enumRoundtrip.roundtrip({ tag: APIResult.Tag.Success, param0: "Hello, world" }) + } + }) + + const complexResultRoundtrip = new exports.ComplexResultRoundtrip(); + + benchmarkRunner("ComplexResultRoundtrip/takeEnum success", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Success, param0: "Operation completed" }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum error", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Error, param0: "Network timeout", param1: 503 }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum location", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Location, param0: 37.7749, param1: -122.4194, param2: "San Francisco" }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum status", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Status, param0: true, param1: 200, param2: "OK" }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum coordinates", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Coordinates, param0: 10.5, param1: 20.3, param2: 30.7 }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum comprehensive", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ + tag: ComplexResult.Tag.Comprehensive, + param0: true, param1: false, param2: 42, param3: 100, + param4: 3.14, param5: 2.718, param6: "Hello", param7: "World", param8: "Test" + }) + } + }) + benchmarkRunner("ComplexResultRoundtrip/takeEnum info", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.take({ tag: ComplexResult.Tag.Info }) + } + }) + + benchmarkRunner("ComplexResultRoundtrip/makeSuccess", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeSuccess() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeError", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeError() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeLocation", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeLocation() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeStatus", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeStatus() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeCoordinates", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeCoordinates() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeComprehensive", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeComprehensive() + } + }) + benchmarkRunner("ComplexResultRoundtrip/makeInfo", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.makeInfo() + } + }) + + benchmarkRunner("ComplexResultRoundtrip/roundtrip", () => { + for (let i = 0; i < iterations; i++) { + complexResultRoundtrip.roundtrip({ tag: ComplexResult.Tag.Success, param0: "Hello, world" }) + } + }) + + const stringRoundtrip = new exports.StringRoundtrip(); + benchmarkRunner("StringRoundtrip/takeString", () => { + for (let i = 0; i < iterations; i++) { + stringRoundtrip.take("Hello, world") + } + }) + benchmarkRunner("StringRoundtrip/makeString", () => { + for (let i = 0; i < iterations; i++) { + stringRoundtrip.make() + } + }) } /** diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 117158df..a8a50acf 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -25,6 +25,7 @@ public class ExportSwift { private var exportedClasses: [ExportedClass] = [] private var exportedEnums: [ExportedEnum] = [] private var typeDeclResolver: TypeDeclResolver = TypeDeclResolver() + private let enumCodegen: EnumCodegen = EnumCodegen() public init(progress: ProgressReporting, moduleName: String) { self.progress = progress @@ -524,6 +525,31 @@ public class ExportSwift { ) } + if currentEnum.cases.contains(where: { !$0.associatedValues.isEmpty }) { + if case .tsEnum = emitStyle { + diagnose( + node: jsAttribute, + message: "TypeScript enum style is not supported for associated value enums", + hint: "Use enumStyle: .const in order to map associated-value enums" + ) + } + for enumCase in currentEnum.cases { + for associatedValue in enumCase.associatedValues { + switch associatedValue.type { + case .string, .int, .float, .double, .bool: + break + default: + diagnose( + node: node, + message: "Unsupported associated value type: \(associatedValue.type.swiftType)", + hint: + "Only primitive types (String, Int, Float, Double, Bool) are supported in associated-value enums" + ) + } + } + } + } + let swiftCallName = ExportSwift.computeSwiftCallName(for: node, itemName: enumName) let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( for: node, @@ -753,10 +779,15 @@ public class ExportSwift { decls.append(Self.prelude) for enumDef in exportedEnums { - if enumDef.enumType == .simple { - decls.append(renderCaseEnumHelpers(enumDef)) - } else { + switch enumDef.enumType { + case .simple: + decls.append(enumCodegen.renderCaseEnumHelpers(enumDef)) + case .rawValue: decls.append("extension \(raw: enumDef.swiftCallName): _BridgedSwiftEnumNoPayload {}") + case .associatedValue: + decls.append(enumCodegen.renderAssociatedValueEnumHelpers(enumDef)) + case .namespace: + () } } @@ -770,45 +801,6 @@ public class ExportSwift { return decls.map { $0.formatted(using: format).description }.joined(separator: "\n\n") } - func renderCaseEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { - let typeName = enumDef.swiftCallName - var initCases: [String] = [] - var valueCases: [String] = [] - for (index, c) in enumDef.cases.enumerated() { - initCases.append("case \(index): self = .\(c.name)") - valueCases.append("case .\(c.name): return \(index)") - } - let initSwitch = (["switch bridgeJSRawValue {"] + initCases + ["default: return nil", "}"]).joined( - separator: "\n" - ) - let valueSwitch = (["switch self {"] + valueCases + ["}"]).joined(separator: "\n") - - return """ - extension \(raw: typeName) { - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { - return bridgeJSRawValue - } - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> \(raw: typeName) { - return \(raw: typeName)(bridgeJSRawValue: value)! - } - @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> \(raw: typeName) { - return \(raw: typeName)(bridgeJSRawValue: value)! - } - @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { - return bridgeJSRawValue - } - - private init?(bridgeJSRawValue: Int32) { - \(raw: initSwitch) - } - - private var bridgeJSRawValue: Int32 { - \(raw: valueSwitch) - } - } - """ - } - class ExportedThunkBuilder { var body: [CodeBlockItemSyntax] = [] var liftedParameterExprs: [ExprSyntax] = [] @@ -1006,6 +998,146 @@ public class ExportSwift { } } + private struct EnumCodegen { + func renderCaseEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { + let typeName = enumDef.swiftCallName + var initCases: [String] = [] + var valueCases: [String] = [] + for (index, enumCase) in enumDef.cases.enumerated() { + initCases.append("case \(index): self = .\(enumCase.name)") + valueCases.append("case .\(enumCase.name): return \(index)") + } + let initSwitch = (["switch bridgeJSRawValue {"] + initCases + ["default: return nil", "}"]).joined( + separator: "\n" + ) + let valueSwitch = (["switch self {"] + valueCases + ["}"]).joined(separator: "\n") + + return """ + extension \(raw: typeName) { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> \(raw: typeName) { + return \(raw: typeName)(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> \(raw: typeName) { + return \(raw: typeName)(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { + \(raw: initSwitch) + } + + private var bridgeJSRawValue: Int32 { + \(raw: valueSwitch) + } + } + """ + } + + func renderAssociatedValueEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { + let typeName = enumDef.swiftCallName + return """ + private extension \(raw: typeName) { + static func bridgeJSLiftParameter(_ caseId: Int32) -> \(raw: typeName) { + switch caseId { + \(raw: generateStackLiftSwitchCases(enumDef: enumDef).joined(separator: "\n")) + default: fatalError("Unknown \(raw: typeName) case ID: \\(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + \(raw: generateReturnSwitchCases(enumDef: enumDef).joined(separator: "\n")) + } + } + } + """ + } + + private func generateStackLiftSwitchCases(enumDef: ExportedEnum) -> [String] { + var cases: [String] = [] + for (caseIndex, enumCase) in enumDef.cases.enumerated() { + if enumCase.associatedValues.isEmpty { + cases.append("case \(caseIndex): return .\(enumCase.name)") + } else { + var lines: [String] = [] + lines.append("case \(caseIndex):") + let argList = enumCase.associatedValues.map { associatedValue in + let paramName: String + if let label = associatedValue.label { + paramName = "\(label): " + } else { + paramName = "" + } + switch associatedValue.type { + case .string: + return + "\(paramName)String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + case .int: + return "\(paramName)Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + case .bool: + return "\(paramName)Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + case .float: + return "\(paramName)Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())" + case .double: + return "\(paramName)Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())" + default: + return "\(paramName)Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())" + } + } + lines.append("return .\(enumCase.name)(\(argList.joined(separator: ", ")))") + cases.append(lines.joined(separator: "\n")) + } + } + return cases + } + + private func generateReturnSwitchCases(enumDef: ExportedEnum) -> [String] { + var cases: [String] = [] + for (caseIndex, enumCase) in enumDef.cases.enumerated() { + if enumCase.associatedValues.isEmpty { + cases.append("case .\(enumCase.name):") + cases.append("_swift_js_push_tag(Int32(\(caseIndex)))") + } else { + var bodyLines: [String] = [] + bodyLines.append("_swift_js_push_tag(Int32(\(caseIndex)))") + for (index, associatedValue) in enumCase.associatedValues.enumerated() { + let paramName = associatedValue.label ?? "param\(index)" + switch associatedValue.type { + case .string: + bodyLines.append("var __bjs_\(paramName) = \(paramName)") + bodyLines.append("__bjs_\(paramName).withUTF8 { ptr in") + bodyLines.append("_swift_js_push_string(ptr.baseAddress, Int32(ptr.count))") + bodyLines.append("}") + case .int: + bodyLines.append("_swift_js_push_int(Int32(\(paramName)))") + case .bool: + bodyLines.append("_swift_js_push_int(\(paramName) ? 1 : 0)") + case .float: + bodyLines.append("_swift_js_push_f32(\(paramName))") + case .double: + bodyLines.append("_swift_js_push_f64(\(paramName))") + default: + bodyLines.append( + "preconditionFailure(\"BridgeJS: unsupported associated value type in generated code\")" + ) + } + } + let pattern = enumCase.associatedValues.enumerated() + .map { index, associatedValue in "let \(associatedValue.label ?? "param\(index)")" } + .joined(separator: ", ") + cases.append("case .\(enumCase.name)(\(pattern)):") + cases.append(contentsOf: bodyLines) + } + } + return cases + } + } + func renderSingleExportedFunction(function: ExportedFunction) throws -> DeclSyntax { let builder = ExportedThunkBuilder(effects: function.effects) for param in function.parameters { @@ -1264,6 +1396,9 @@ extension BridgeType { static let swiftHeapObject = LiftingIntrinsicInfo(parameters: [("value", .pointer)]) static let void = LiftingIntrinsicInfo(parameters: []) static let caseEnum = LiftingIntrinsicInfo(parameters: [("value", .i32)]) + static let associatedValueEnum = LiftingIntrinsicInfo(parameters: [ + ("caseId", .i32) + ]) } func liftParameterInfo() throws -> LiftingIntrinsicInfo { @@ -1291,7 +1426,7 @@ extension BridgeType { case .uint64: return .int } case .associatedValueEnum: - throw BridgeJSCoreError("Associated value enums are not supported to pass as parameters") + return .associatedValueEnum case .namespaceEnum: throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") } @@ -1310,6 +1445,7 @@ extension BridgeType { static let void = LoweringIntrinsicInfo(returnType: nil) static let caseEnum = LoweringIntrinsicInfo(returnType: .i32) static let rawValueEnum = LoweringIntrinsicInfo(returnType: .i32) + static let associatedValueEnum = LoweringIntrinsicInfo(returnType: nil) } func loweringReturnInfo() throws -> LoweringIntrinsicInfo { @@ -1337,7 +1473,7 @@ extension BridgeType { case .uint64: return .int } case .associatedValueEnum: - throw BridgeJSCoreError("Associated value enums are not supported to pass as parameters") + return .associatedValueEnum case .namespaceEnum: throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters") } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 360a6274..494351db 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -65,6 +65,9 @@ struct BridgeJSLink { } """ + let sharedEnumHelpersJs = """ + """ + func link() throws -> (outputJs: String, outputDts: String) { var exportsLines: [String] = [] var classLines: [String] = [] @@ -73,8 +76,6 @@ struct BridgeJSLink { var namespacedFunctions: [ExportedFunction] = [] var namespacedClasses: [ExportedClass] = [] var namespacedEnums: [ExportedEnum] = [] - var enumConstantLines: [String] = [] - var dtsEnumLines: [String] = [] var topLevelEnumLines: [String] = [] var topLevelDtsEnumLines: [String] = [] @@ -123,12 +124,15 @@ struct BridgeJSLink { namespacedEnums.append(enumDefinition) } case .associatedValue: - enumConstantLines.append(contentsOf: jsEnum) - exportsLines.append("\(enumDefinition.name),") + var exportedJsEnum = jsEnum + if !exportedJsEnum.isEmpty && exportedJsEnum[0].hasPrefix("const ") { + exportedJsEnum[0] = "export " + exportedJsEnum[0] + } + topLevelEnumLines.append(contentsOf: exportedJsEnum) + topLevelDtsEnumLines.append(contentsOf: dtsEnum) if enumDefinition.namespace != nil { namespacedEnums.append(enumDefinition) } - dtsEnumLines.append(contentsOf: dtsEnum) } } } @@ -161,7 +165,7 @@ struct BridgeJSLink { importObjectBuilders.append(importObjectBuilder) } - let hasNamespacedItems = !namespacedFunctions.isEmpty || !namespacedClasses.isEmpty || !namespacedEnums.isEmpty + let hasNamespacedItems = !namespacedFunctions.isEmpty || !namespacedClasses.isEmpty let namespaceBuilder = NamespaceBuilder() let namespaceDeclarationsLines = namespaceBuilder.namespaceDeclarations( @@ -173,21 +177,15 @@ struct BridgeJSLink { let exportsSection: String if hasNamespacedItems { - let namespacedEnumsForExports = namespacedEnums.filter { $0.enumType == .associatedValue } let namespaceSetupCode = namespaceBuilder.renderGlobalNamespace( namespacedFunctions: namespacedFunctions, - namespacedClasses: namespacedClasses, - namespacedEnums: namespacedEnumsForExports + namespacedClasses: namespacedClasses ) .map { $0.indent(count: 12) }.joined(separator: "\n") - let enumSection = - enumConstantLines.isEmpty - ? "" : enumConstantLines.map { $0.indent(count: 12) }.joined(separator: "\n") + "\n" - exportsSection = """ \(classLines.map { $0.indent(count: 12) }.joined(separator: "\n")) - \(enumSection)\("const exports = {".indent(count: 12)) + \("const exports = {".indent(count: 12)) \(exportsLines.map { $0.indent(count: 16) }.joined(separator: "\n")) \("};".indent(count: 12)) @@ -197,27 +195,31 @@ struct BridgeJSLink { }, """ } else { - let enumSection = - enumConstantLines.isEmpty - ? "" : enumConstantLines.map { $0.indent(count: 12) }.joined(separator: "\n") + "\n" - exportsSection = """ \(classLines.map { $0.indent(count: 12) }.joined(separator: "\n")) - \(enumSection)\("return {".indent(count: 12)) + \("return {".indent(count: 12)) \(exportsLines.map { $0.indent(count: 16) }.joined(separator: "\n")) \("};".indent(count: 12)) }, """ } + let hasAssociatedValueEnums = exportedSkeletons.contains { skeleton in + skeleton.enums.contains { $0.enumType == .associatedValue } + } + let sharedEnumHelpersSection = hasAssociatedValueEnums ? sharedEnumHelpersJs : "" let topLevelEnumsSection = topLevelEnumLines.isEmpty ? "" : topLevelEnumLines.joined(separator: "\n") + "\n\n" - let topLevelNamespaceCode = namespaceBuilder.renderTopLevelEnumNamespaceAssignments( namespacedEnums: namespacedEnums ) let namespaceAssignmentsSection = topLevelNamespaceCode.isEmpty ? "" : topLevelNamespaceCode.joined(separator: "\n") + "\n\n" + let enumHelpers = renderEnumHelperAssignments() + let enumHelpersSection = + enumHelpers.isEmpty ? "" : "\n\n" + enumHelpers.map { $0.indent(count: 12) }.joined(separator: "\n") + let enumHelpersDeclaration = hasAssociatedValueEnums ? "const enumHelpers = {};\n" : "\n" + let outputJs = """ // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, // DO NOT EDIT. @@ -225,16 +227,24 @@ struct BridgeJSLink { // To update this file, just rebuild your project or run // `swift package bridge-js`. - \(topLevelEnumsSection)\(namespaceAssignmentsSection)export async function createInstantiator(options, \(JSGlueVariableScope.reservedSwift)) { + \(sharedEnumHelpersSection)\(topLevelEnumsSection)\(namespaceAssignmentsSection)export async function createInstantiator(options, \(JSGlueVariableScope.reservedSwift)) { let \(JSGlueVariableScope.reservedInstance); let \(JSGlueVariableScope.reservedMemory); let \(JSGlueVariableScope.reservedSetException); const \(JSGlueVariableScope.reservedTextDecoder) = new TextDecoder("utf-8"); const \(JSGlueVariableScope.reservedTextEncoder) = new TextEncoder("utf-8"); - let \(JSGlueVariableScope.reservedStorageToReturnString); let \(JSGlueVariableScope.reservedStorageToReturnBytes); let \(JSGlueVariableScope.reservedStorageToReturnException); + let \(JSGlueVariableScope.reservedTmpRetTag); + let \(JSGlueVariableScope.reservedTmpRetStrings) = []; + let \(JSGlueVariableScope.reservedTmpRetInts) = []; + let \(JSGlueVariableScope.reservedTmpRetF32s) = []; + let \(JSGlueVariableScope.reservedTmpRetF64s) = []; + let \(JSGlueVariableScope.reservedTmpParamInts) = []; + let \(JSGlueVariableScope.reservedTmpParamF32s) = []; + let \(JSGlueVariableScope.reservedTmpParamF64s) = []; + \(enumHelpersDeclaration) return { /** * @param {WebAssembly.Imports} importObject @@ -248,13 +258,13 @@ struct BridgeJSLink { \(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { - const source = \(JSGlueVariableScope.reservedSwift).memory.getObject(sourceId); + const source = \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).getObject(sourceId); const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, bytesPtr); bytes.set(source); } bjs["swift_js_make_js_string"] = function(ptr, len) { const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len)\(sharedMemory ? ".slice()" : ""); - return \(JSGlueVariableScope.reservedSwift).memory.retain(\(JSGlueVariableScope.reservedTextDecoder).decode(bytes)); + return \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retain(\(JSGlueVariableScope.reservedTextDecoder).decode(bytes)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len); @@ -262,20 +272,47 @@ struct BridgeJSLink { \(JSGlueVariableScope.reservedStorageToReturnBytes) = undefined; } bjs["swift_js_throw"] = function(id) { - \(JSGlueVariableScope.reservedStorageToReturnException) = \(JSGlueVariableScope.reservedSwift).memory.retainByRef(id); + \(JSGlueVariableScope.reservedStorageToReturnException) = \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retainByRef(id); } bjs["swift_js_retain"] = function(id) { - return \(JSGlueVariableScope.reservedSwift).memory.retainByRef(id); + return \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retainByRef(id); } bjs["swift_js_release"] = function(id) { \(JSGlueVariableScope.reservedSwift).memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + \(JSGlueVariableScope.reservedTmpRetTag) = tag; + } + bjs["swift_js_push_int"] = function(v) { + \(JSGlueVariableScope.reservedTmpRetInts).push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + \(JSGlueVariableScope.reservedTmpRetF32s).push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + \(JSGlueVariableScope.reservedTmpRetF64s).push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len)\(sharedMemory ? ".slice()" : ""); + const value = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes); + \(JSGlueVariableScope.reservedTmpRetStrings).push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return \(JSGlueVariableScope.reservedTmpParamInts).pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return \(JSGlueVariableScope.reservedTmpParamF32s).pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return \(JSGlueVariableScope.reservedTmpParamF64s).pop(); + } \(renderSwiftClassWrappers().map { $0.indent(count: 12) }.joined(separator: "\n")) \(importObjectBuilders.flatMap { $0.importedLines }.map { $0.indent(count: 12) }.joined(separator: "\n")) }, setInstance: (i) => { \(JSGlueVariableScope.reservedInstance) = i; \(JSGlueVariableScope.reservedMemory) = \(JSGlueVariableScope.reservedInstance).exports.memory; + \(enumHelpersSection) \(JSGlueVariableScope.reservedSetException) = (error) => { \(JSGlueVariableScope.reservedInstance).exports._swift_js_exception.value = \(JSGlueVariableScope.reservedSwift).memory.retain(error) } @@ -291,7 +328,6 @@ struct BridgeJSLink { var dtsLines: [String] = [] dtsLines.append(contentsOf: namespaceDeclarationsLines) dtsLines.append(contentsOf: dtsClassLines) - dtsLines.append(contentsOf: dtsEnumLines) dtsLines.append(contentsOf: generateImportedTypeDefinitions()) dtsLines.append("export type Exports = {") dtsLines.append(contentsOf: dtsExportLines.map { $0.indent(count: 4) }) @@ -321,6 +357,23 @@ struct BridgeJSLink { return (outputJs, outputDts) } + private func renderEnumHelperAssignments() -> [String] { + var lines: [String] = [] + + for skeleton in exportedSkeletons { + for enumDef in skeleton.enums where enumDef.enumType == .associatedValue { + let base = enumDef.name + lines.append( + "const \(base)Helpers = __bjs_create\(base)Helpers()(\(JSGlueVariableScope.reservedTmpParamInts), \(JSGlueVariableScope.reservedTmpParamF32s), \(JSGlueVariableScope.reservedTmpParamF64s), \(JSGlueVariableScope.reservedTextEncoder), \(JSGlueVariableScope.reservedSwift));" + ) + lines.append("enumHelpers.\(base) = \(base)Helpers;") + lines.append("") + } + } + + return lines + } + private func renderSwiftClassWrappers() -> [String] { var wrapperLines: [String] = [] var modulesByName: [String: [ExportedClass]] = [:] @@ -612,10 +665,210 @@ struct BridgeJSLink { dtsLines.append("") } } - case .associatedValue: - jsLines.append("// TODO: Implement \(enumDefinition.enumType) enum: \(enumDefinition.name)") - dtsLines.append("// TODO: Implement \(enumDefinition.enumType) enum: \(enumDefinition.name)") + do { + jsLines.append("const \(enumDefinition.name) = {") + jsLines.append("Tag: {".indent(count: 4)) + for (caseIndex, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + jsLines.append("\(caseName): \(caseIndex),".indent(count: 8)) + } + jsLines.append("}".indent(count: 4)) + jsLines.append("};") + jsLines.append("") + jsLines.append("const __bjs_create\(enumDefinition.name)Helpers = () => {") + jsLines.append( + "return (\(JSGlueVariableScope.reservedTmpParamInts), \(JSGlueVariableScope.reservedTmpParamF32s), \(JSGlueVariableScope.reservedTmpParamF64s), textEncoder, swift) => ({" + .indent(count: 4) + ) + + jsLines.append("lower: (value) => {".indent(count: 8)) + jsLines.append("const enumTag = value.tag;".indent(count: 12)) + jsLines.append("switch (enumTag) {".indent(count: 12)) + enumDefinition.cases.forEach { enumCase in + let caseName = enumCase.name.capitalizedFirstLetter + if enumCase.associatedValues.isEmpty { + jsLines.append("case \(enumDefinition.name).Tag.\(caseName): {".indent(count: 16)) + jsLines.append("const cleanup = undefined;".indent(count: 20)) + jsLines.append( + "return { caseId: \(enumDefinition.name).Tag.\(caseName), cleanup };" + .indent(count: 20) + ) + jsLines.append("}".indent(count: 16)) + } else { + jsLines.append("case \(enumDefinition.name).Tag.\(caseName): {".indent(count: 16)) + var pushLines: [String] = [] + var releaseIds: [String] = [] + let reversedValues = enumCase.associatedValues.enumerated().reversed() + for (associatedValueIndex, associatedValue) in reversedValues { + let prop = associatedValue.label ?? "param\(associatedValueIndex)" + switch associatedValue.type { + case .string: + let bytesVar = "bytes_\(associatedValueIndex)" + let idVar = "bytesId_\(associatedValueIndex)" + pushLines.append( + "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(value.\(prop));" + ) + pushLines.append( + "const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" + ) + pushLines.append( + "\(JSGlueVariableScope.reservedTmpParamInts).push(\(bytesVar).length);" + ) + pushLines.append("\(JSGlueVariableScope.reservedTmpParamInts).push(\(idVar));") + releaseIds.append(idVar) + case .bool: + pushLines.append( + "\(JSGlueVariableScope.reservedTmpParamInts).push(value.\(prop) ? 1 : 0);" + ) + case .int: + pushLines.append( + "\(JSGlueVariableScope.reservedTmpParamInts).push((value.\(prop) | 0));" + ) + case .float: + pushLines.append( + "\(JSGlueVariableScope.reservedTmpParamF32s).push(Math.fround(value.\(prop)));" + ) + case .double: + pushLines.append("\(JSGlueVariableScope.reservedTmpParamF64s).push(value.\(prop));") + default: + pushLines.append("\(JSGlueVariableScope.reservedTmpParamInts).push(0);") + } + } + jsLines.append(contentsOf: pushLines.map { $0.indent(count: 20) }) + if releaseIds.isEmpty { + jsLines.append("const cleanup = undefined;".indent(count: 20)) + } else { + jsLines.append("const cleanup = () => {".indent(count: 20)) + for id in releaseIds { + jsLines.append( + "\(JSGlueVariableScope.reservedSwift).memory.release(\(id));".indent(count: 24) + ) + } + jsLines.append("};".indent(count: 20)) + } + jsLines.append( + "return { caseId: \(enumDefinition.name).Tag.\(caseName), cleanup };" + .indent(count: 20) + ) + jsLines.append("}".indent(count: 16)) + } + } + jsLines.append( + "default: throw new Error(\"Unknown \(enumDefinition.name) tag: \" + String(enumTag));".indent( + count: 16 + ) + ) + jsLines.append("}".indent(count: 12)) + jsLines.append("},".indent(count: 8)) + + jsLines.append( + "raise: (\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s)) => {" + .indent( + count: 8 + ) + ) + jsLines.append("const tag = tmpRetTag | 0;".indent(count: 12)) + jsLines.append("switch (tag) {".indent(count: 12)) + enumDefinition.cases.forEach { enumCase in + let caseName = enumCase.name.capitalizedFirstLetter + if enumCase.associatedValues.isEmpty { + jsLines.append( + "case \(enumDefinition.name).Tag.\(caseName): return { tag: \(enumDefinition.name).Tag.\(caseName) };" + .indent(count: 16) + ) + } else { + var locals: [String] = [] + var fieldPairs: [String] = [] + for (associatedValueIndex, associatedValue) in enumCase.associatedValues.enumerated().reversed() + { + let prop = associatedValue.label ?? "param\(associatedValueIndex)" + switch associatedValue.type { + case .string: + let strVar = "string_\(associatedValueIndex)" + locals.append("const \(strVar) = tmpRetStrings.pop();") + fieldPairs.append("\(prop): \(strVar)") + case .bool: + let bVar = "bool_\(associatedValueIndex)" + locals.append("const \(bVar) = tmpRetInts.pop();") + fieldPairs.append("\(prop): \(bVar)") + case .int: + let iVar = "int_\(associatedValueIndex)" + locals.append("const \(iVar) = tmpRetInts.pop();") + fieldPairs.append("\(prop): \(iVar)") + case .float: + let fVar = "f32_\(associatedValueIndex)" + locals.append("const \(fVar) = tmpRetF32s.pop();") + fieldPairs.append("\(prop): \(fVar)") + case .double: + let dVar = "f64_\(associatedValueIndex)" + locals.append("const \(dVar) = tmpRetF64s.pop();") + fieldPairs.append("\(prop): \(dVar)") + default: + fieldPairs.append("\(prop): undefined") + } + } + jsLines.append("case \(enumDefinition.name).Tag.\(caseName): {".indent(count: 16)) + jsLines.append(contentsOf: locals.map { $0.indent(count: 20) }) + jsLines.append( + "return { tag: \(enumDefinition.name).Tag.\(caseName), \(fieldPairs.reversed().joined(separator: ", ")) };" + .indent(count: 20) + ) + jsLines.append("}".indent(count: 16)) + } + } + jsLines.append( + "default: throw new Error(\"Unknown \(enumDefinition.name) tag returned from Swift: \" + String(tag));" + .indent( + count: 16 + ) + ) + jsLines.append("}".indent(count: 12)) + jsLines.append("}".indent(count: 8)) + jsLines.append("});".indent(count: 4)) + jsLines.append("};") + + if enumDefinition.namespace == nil { + dtsLines.append("export const \(enumDefinition.name): {") + dtsLines.append("readonly Tag: {".indent(count: 4)) + for (index, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + dtsLines.append("readonly \(caseName): \(index);".indent(count: 8)) + } + dtsLines.append("};".indent(count: 4)) + dtsLines.append("};") + dtsLines.append("") + var unionParts: [String] = [] + for enumCase in enumDefinition.cases { + if enumCase.associatedValues.isEmpty { + unionParts.append( + "{ tag: typeof \(enumDefinition.name).Tag.\(enumCase.name.capitalizedFirstLetter) }" + ) + } else { + var fields: [String] = [ + "tag: typeof \(enumDefinition.name).Tag.\(enumCase.name.capitalizedFirstLetter)" + ] + for (associatedValueIndex, associatedValue) in enumCase.associatedValues + .enumerated() + { + let prop = associatedValue.label ?? "param\(associatedValueIndex)" + let ts: String + switch associatedValue.type { + case .string: ts = "string" + case .bool: ts = "boolean" + case .int, .float, .double: ts = "number" + default: ts = "never" + } + fields.append("\(prop): \(ts)") + } + unionParts.append("{ \(fields.joined(separator: "; ")) }") + } + } + dtsLines.append("export type \(enumDefinition.name) =") + dtsLines.append(" " + unionParts.joined(separator: " | ")) + dtsLines.append("") + } + } case .namespace: break } @@ -992,8 +1245,7 @@ struct BridgeJSLink { /// - Returns: Array of JavaScript code lines that set up the global namespace structure func renderGlobalNamespace( namespacedFunctions: [ExportedFunction], - namespacedClasses: [ExportedClass], - namespacedEnums: [ExportedEnum] + namespacedClasses: [ExportedClass] ) -> [String] { var lines: [String] = [] var uniqueNamespaces: [String] = [] @@ -1007,15 +1259,10 @@ struct BridgeJSLink { namespacedClasses .compactMap { $0.namespace } ) - let enumNamespacePaths: Set<[String]> = Set( - namespacedEnums - .compactMap { $0.namespace } - ) let allNamespacePaths = functionNamespacePaths .union(classNamespacePaths) - .union(enumNamespacePaths) allNamespacePaths.forEach { namespacePath in namespacePath.makeIterator().enumerated().forEach { (index, _) in @@ -1037,11 +1284,6 @@ struct BridgeJSLink { lines.append("globalThis.\(namespacePath).\(klass.name) = exports.\(klass.name);") } - namespacedEnums.forEach { enumDefinition in - let namespacePath: String = enumDefinition.namespace?.joined(separator: ".") ?? "" - lines.append("globalThis.\(namespacePath).\(enumDefinition.name) = exports.\(enumDefinition.name);") - } - namespacedFunctions.forEach { function in let namespacePath: String = function.namespace?.joined(separator: ".") ?? "" lines.append("globalThis.\(namespacePath).\(function.name) = exports.\(function.name);") @@ -1051,15 +1293,13 @@ struct BridgeJSLink { } func renderTopLevelEnumNamespaceAssignments(namespacedEnums: [ExportedEnum]) -> [String] { - let topLevelNamespacedEnums = namespacedEnums.filter { $0.enumType == .simple || $0.enumType == .rawValue } - - guard !topLevelNamespacedEnums.isEmpty else { return [] } + guard !namespacedEnums.isEmpty else { return [] } var lines: [String] = [] var uniqueNamespaces: [String] = [] var seen = Set() - for enumDef in topLevelNamespacedEnums { + for enumDef in namespacedEnums { guard let namespacePath = enumDef.namespace else { continue } namespacePath.enumerated().forEach { (index, _) in let path = namespacePath[0...index].joined(separator: ".") @@ -1080,7 +1320,7 @@ struct BridgeJSLink { lines.append("") } - for enumDef in topLevelNamespacedEnums { + for enumDef in namespacedEnums { let namespacePath = enumDef.namespace?.joined(separator: ".") ?? "" lines.append("globalThis.\(namespacePath).\(enumDef.name) = \(enumDef.name);") } @@ -1291,7 +1531,53 @@ struct BridgeJSLink { .indent(count: identBaseSize * contentDepth) ) } - case .associatedValue, .namespace: + case .associatedValue: + dtsLines.append( + "const \(enumDefinition.name): {".indent(count: identBaseSize * contentDepth) + ) + dtsLines.append("readonly Tag: {".indent(count: identBaseSize * (contentDepth + 1))) + for (caseIndex, enumCase) in enumDefinition.cases.enumerated() { + let caseName = enumCase.name.capitalizedFirstLetter + dtsLines.append( + "readonly \(caseName): \(caseIndex);".indent( + count: identBaseSize * (contentDepth + 2) + ) + ) + } + dtsLines.append("};".indent(count: identBaseSize * (contentDepth + 1))) + dtsLines.append("};".indent(count: identBaseSize * contentDepth)) + + var unionParts: [String] = [] + for enumCase in enumDefinition.cases { + if enumCase.associatedValues.isEmpty { + unionParts.append( + "{ tag: typeof \(enumDefinition.name).Tag.\(enumCase.name.capitalizedFirstLetter) }" + ) + } else { + var fields: [String] = [ + "tag: typeof \(enumDefinition.name).Tag.\(enumCase.name.capitalizedFirstLetter)" + ] + for (associatedValueIndex, associatedValue) in enumCase.associatedValues + .enumerated() + { + let prop = associatedValue.label ?? "param\(associatedValueIndex)" + let ts: String + switch associatedValue.type { + case .string: ts = "string" + case .bool: ts = "boolean" + case .int, .float, .double: ts = "number" + default: ts = "never" + } + fields.append("\(prop): \(ts)") + } + unionParts.append("{ \(fields.joined(separator: "; ")) }") + } + } + dtsLines.append("type \(enumDefinition.name) =".indent(count: identBaseSize * contentDepth)) + dtsLines.append( + " " + unionParts.joined(separator: " | ").indent(count: identBaseSize * contentDepth) + ) + case .namespace: continue } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index ae74844f..f559e62f 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -15,6 +15,14 @@ final class JSGlueVariableScope { static let reservedStorageToReturnException = "tmpRetException" static let reservedTextEncoder = "textEncoder" static let reservedTextDecoder = "textDecoder" + static let reservedTmpRetTag = "tmpRetTag" + static let reservedTmpRetStrings = "tmpRetStrings" + static let reservedTmpRetInts = "tmpRetInts" + static let reservedTmpRetF32s = "tmpRetF32s" + static let reservedTmpRetF64s = "tmpRetF64s" + static let reservedTmpParamInts = "tmpParamInts" + static let reservedTmpParamF32s = "tmpParamF32s" + static let reservedTmpParamF64s = "tmpParamF64s" private var variables: Set = [ reservedSwift, @@ -24,6 +32,14 @@ final class JSGlueVariableScope { reservedStorageToReturnException, reservedTextEncoder, reservedTextDecoder, + reservedTmpRetTag, + reservedTmpRetStrings, + reservedTmpRetInts, + reservedTmpRetF32s, + reservedTmpRetF64s, + reservedTmpParamInts, + reservedTmpParamF32s, + reservedTmpParamF64s, ] /// Returns a unique variable name in the scope based on the given name hint. @@ -194,6 +210,35 @@ struct IntrinsicJSFragment: Sendable { ) } + static func associatedEnumLowerParameter(enumBase: String) -> IntrinsicJSFragment { + IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let caseIdName = "\(value)CaseId" + let cleanupName = "\(value)Cleanup" + printer.write( + "const { caseId: \(caseIdName), cleanup: \(cleanupName) } = enumHelpers.\(enumBase).lower(\(value));" + ) + cleanup.write("if (\(cleanupName)) { \(cleanupName)(); }") + return [caseIdName] + } + ) + } + + static func associatedEnumLiftReturn(enumBase: String) -> IntrinsicJSFragment { + IntrinsicJSFragment( + parameters: [], + printCode: { _, scope, printer, _ in + let retName = scope.variable("ret") + printer.write( + "const \(retName) = enumHelpers.\(enumBase).raise(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + ) + return [retName] + } + ) + } + // MARK: - ExportSwift /// Returns a fragment that lowers a JS value to Wasm core values for parameters @@ -211,10 +256,9 @@ struct IntrinsicJSFragment: Sendable { case .string: return .stringLowerParameter default: return .identity } - case .associatedValueEnum(let string): - throw BridgeJSLinkError( - message: "Associated value enums are not supported to be passed as parameters: \(string)" - ) + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return .associatedEnumLowerParameter(enumBase: base) case .namespaceEnum(let string): throw BridgeJSLinkError(message: "Namespace enums are not supported to be passed as parameters: \(string)") } @@ -236,10 +280,9 @@ struct IntrinsicJSFragment: Sendable { case .bool: return .boolLiftReturn default: return .identity } - case .associatedValueEnum(let string): - throw BridgeJSLinkError( - message: "Associated value enums are not supported to be returned from functions: \(string)" - ) + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + return .associatedEnumLiftReturn(enumBase: base) case .namespaceEnum(let string): throw BridgeJSLinkError( message: "Namespace enums are not supported to be returned from functions: \(string)" diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumAssociatedValue.swift new file mode 100644 index 00000000..419800d6 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumAssociatedValue.swift @@ -0,0 +1,46 @@ +@JS +enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} + +@JS func handle(result: APIResult) +@JS func getResult() -> APIResult +@JS func roundtripAPIResult(result: APIResult) -> APIResult { + return result +} + +@JS +enum ComplexResult { + case success(String) + case error(String, Int) + case status(Bool, Int, String) + case coordinates(Double, Double, Double) + case comprehensive(Bool, Bool, Int, Int, Double, Double, String, String, String) + case info +} + +@JS func handleComplex(result: ComplexResult) +@JS func getComplexResult() -> ComplexResult +@JS func roundtripComplexResult(_ result: ComplexResult) -> ComplexResult { + return result +} + +@JS +enum Utilities { + @JS enum Result { + case success(String) + case failure(String, Int) + case status(Bool, Int, String) + } +} + +@JS(namespace: "API") +@JS enum NetworkingResult { + case success(String) + case failure(String, Int) +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js index c122f179..ef8b096f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkArray"] = function bjs_checkArray(a) { @@ -76,6 +111,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js index 97c1e215..45744231 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,12 +58,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js index 0b07aedd..56b27ffb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_asyncReturnVoid"] = function bjs_asyncReturnVoid() { @@ -120,6 +155,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts new file mode 100644 index 00000000..18d8a763 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts @@ -0,0 +1,77 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +export const APIResult: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Flag: 2; + readonly Rate: 3; + readonly Precise: 4; + readonly Info: 5; + }; +}; + +export type APIResult = + { tag: typeof APIResult.Tag.Success; param0: string } | { tag: typeof APIResult.Tag.Failure; param0: number } | { tag: typeof APIResult.Tag.Flag; param0: boolean } | { tag: typeof APIResult.Tag.Rate; param0: number } | { tag: typeof APIResult.Tag.Precise; param0: number } | { tag: typeof APIResult.Tag.Info } + +export const ComplexResult: { + readonly Tag: { + readonly Success: 0; + readonly Error: 1; + readonly Status: 2; + readonly Coordinates: 3; + readonly Comprehensive: 4; + readonly Info: 5; + }; +}; + +export type ComplexResult = + { tag: typeof ComplexResult.Tag.Success; param0: string } | { tag: typeof ComplexResult.Tag.Error; param0: string; param1: number } | { tag: typeof ComplexResult.Tag.Status; param0: boolean; param1: number; param2: string } | { tag: typeof ComplexResult.Tag.Coordinates; param0: number; param1: number; param2: number } | { tag: typeof ComplexResult.Tag.Comprehensive; param0: boolean; param1: boolean; param2: number; param3: number; param4: number; param5: number; param6: string; param7: string; param8: string } | { tag: typeof ComplexResult.Tag.Info } + +export {}; + +declare global { + namespace API { + const NetworkingResult: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + }; + }; + type NetworkingResult = + { tag: typeof NetworkingResult.Tag.Success; param0: string } | { tag: typeof NetworkingResult.Tag.Failure; param0: string; param1: number } + } + namespace Utilities { + const Result: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Status: 2; + }; + }; + type Result = + { tag: typeof Result.Tag.Success; param0: string } | { tag: typeof Result.Tag.Failure; param0: string; param1: number } | { tag: typeof Result.Tag.Status; param0: boolean; param1: number; param2: string } + } +} + +export type Exports = { + handle(result: APIResult): void; + getResult(): APIResult; + roundtripAPIResult(result: APIResult): APIResult; + handleComplex(result: ComplexResult): void; + getComplexResult(): ComplexResult; + roundtripComplexResult(result: ComplexResult): ComplexResult; +} +export type Imports = { +} +export function createInstantiator(options: { + imports: Imports; +}, swift: any): Promise<{ + addImports: (importObject: WebAssembly.Imports) => void; + setInstance: (instance: WebAssembly.Instance) => void; + createExports: (instance: WebAssembly.Instance) => Exports; +}>; \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js new file mode 100644 index 00000000..7a189d19 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js @@ -0,0 +1,502 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +export const APIResult = { + Tag: { + Success: 0, + Failure: 1, + Flag: 2, + Rate: 3, + Precise: 4, + Info: 5, + } +}; + +const __bjs_createAPIResultHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResult.Tag.Success: { + const bytes_0 = textEncoder.encode(value.param0); + const bytesId_0 = swift.memory.retain(bytes_0); + tmpParamInts.push(bytes_0.length); + tmpParamInts.push(bytesId_0); + const cleanup = () => { + swift.memory.release(bytesId_0); + }; + return { caseId: APIResult.Tag.Success, cleanup }; + } + case APIResult.Tag.Failure: { + tmpParamInts.push((value.param0 | 0)); + const cleanup = undefined; + return { caseId: APIResult.Tag.Failure, cleanup }; + } + case APIResult.Tag.Flag: { + tmpParamInts.push(value.param0 ? 1 : 0); + const cleanup = undefined; + return { caseId: APIResult.Tag.Flag, cleanup }; + } + case APIResult.Tag.Rate: { + tmpParamF32s.push(Math.fround(value.param0)); + const cleanup = undefined; + return { caseId: APIResult.Tag.Rate, cleanup }; + } + case APIResult.Tag.Precise: { + tmpParamF64s.push(value.param0); + const cleanup = undefined; + return { caseId: APIResult.Tag.Precise, cleanup }; + } + case APIResult.Tag.Info: { + const cleanup = undefined; + return { caseId: APIResult.Tag.Info, cleanup }; + } + default: throw new Error("Unknown APIResult tag: " + String(enumTag)); + } + }, + raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + const tag = tmpRetTag | 0; + switch (tag) { + case APIResult.Tag.Success: { + const string_0 = tmpRetStrings.pop(); + return { tag: APIResult.Tag.Success, param0: string_0 }; + } + case APIResult.Tag.Failure: { + const int_0 = tmpRetInts.pop(); + return { tag: APIResult.Tag.Failure, param0: int_0 }; + } + case APIResult.Tag.Flag: { + const bool_0 = tmpRetInts.pop(); + return { tag: APIResult.Tag.Flag, param0: bool_0 }; + } + case APIResult.Tag.Rate: { + const f32_0 = tmpRetF32s.pop(); + return { tag: APIResult.Tag.Rate, param0: f32_0 }; + } + case APIResult.Tag.Precise: { + const f64_0 = tmpRetF64s.pop(); + return { tag: APIResult.Tag.Precise, param0: f64_0 }; + } + case APIResult.Tag.Info: return { tag: APIResult.Tag.Info }; + default: throw new Error("Unknown APIResult tag returned from Swift: " + String(tag)); + } + } + }); +}; +export const ComplexResult = { + Tag: { + Success: 0, + Error: 1, + Status: 2, + Coordinates: 3, + Comprehensive: 4, + Info: 5, + } +}; + +const __bjs_createComplexResultHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case ComplexResult.Tag.Success: { + const bytes_0 = textEncoder.encode(value.param0); + const bytesId_0 = swift.memory.retain(bytes_0); + tmpParamInts.push(bytes_0.length); + tmpParamInts.push(bytesId_0); + const cleanup = () => { + swift.memory.release(bytesId_0); + }; + return { caseId: ComplexResult.Tag.Success, cleanup }; + } + case ComplexResult.Tag.Error: { + tmpParamInts.push((value.param1 | 0)); + const bytes_0 = textEncoder.encode(value.param0); + const bytesId_0 = swift.memory.retain(bytes_0); + tmpParamInts.push(bytes_0.length); + tmpParamInts.push(bytesId_0); + const cleanup = () => { + swift.memory.release(bytesId_0); + }; + return { caseId: ComplexResult.Tag.Error, cleanup }; + } + case ComplexResult.Tag.Status: { + const bytes_2 = textEncoder.encode(value.param2); + const bytesId_2 = swift.memory.retain(bytes_2); + tmpParamInts.push(bytes_2.length); + tmpParamInts.push(bytesId_2); + tmpParamInts.push((value.param1 | 0)); + tmpParamInts.push(value.param0 ? 1 : 0); + const cleanup = () => { + swift.memory.release(bytesId_2); + }; + return { caseId: ComplexResult.Tag.Status, cleanup }; + } + case ComplexResult.Tag.Coordinates: { + tmpParamF64s.push(value.param2); + tmpParamF64s.push(value.param1); + tmpParamF64s.push(value.param0); + const cleanup = undefined; + return { caseId: ComplexResult.Tag.Coordinates, cleanup }; + } + case ComplexResult.Tag.Comprehensive: { + const bytes_8 = textEncoder.encode(value.param8); + const bytesId_8 = swift.memory.retain(bytes_8); + tmpParamInts.push(bytes_8.length); + tmpParamInts.push(bytesId_8); + const bytes_7 = textEncoder.encode(value.param7); + const bytesId_7 = swift.memory.retain(bytes_7); + tmpParamInts.push(bytes_7.length); + tmpParamInts.push(bytesId_7); + const bytes_6 = textEncoder.encode(value.param6); + const bytesId_6 = swift.memory.retain(bytes_6); + tmpParamInts.push(bytes_6.length); + tmpParamInts.push(bytesId_6); + tmpParamF64s.push(value.param5); + tmpParamF64s.push(value.param4); + tmpParamInts.push((value.param3 | 0)); + tmpParamInts.push((value.param2 | 0)); + tmpParamInts.push(value.param1 ? 1 : 0); + tmpParamInts.push(value.param0 ? 1 : 0); + const cleanup = () => { + swift.memory.release(bytesId_8); + swift.memory.release(bytesId_7); + swift.memory.release(bytesId_6); + }; + return { caseId: ComplexResult.Tag.Comprehensive, cleanup }; + } + case ComplexResult.Tag.Info: { + const cleanup = undefined; + return { caseId: ComplexResult.Tag.Info, cleanup }; + } + default: throw new Error("Unknown ComplexResult tag: " + String(enumTag)); + } + }, + raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + const tag = tmpRetTag | 0; + switch (tag) { + case ComplexResult.Tag.Success: { + const string_0 = tmpRetStrings.pop(); + return { tag: ComplexResult.Tag.Success, param0: string_0 }; + } + case ComplexResult.Tag.Error: { + const int_1 = tmpRetInts.pop(); + const string_0 = tmpRetStrings.pop(); + return { tag: ComplexResult.Tag.Error, param0: string_0, param1: int_1 }; + } + case ComplexResult.Tag.Status: { + const string_2 = tmpRetStrings.pop(); + const int_1 = tmpRetInts.pop(); + const bool_0 = tmpRetInts.pop(); + return { tag: ComplexResult.Tag.Status, param0: bool_0, param1: int_1, param2: string_2 }; + } + case ComplexResult.Tag.Coordinates: { + const f64_2 = tmpRetF64s.pop(); + const f64_1 = tmpRetF64s.pop(); + const f64_0 = tmpRetF64s.pop(); + return { tag: ComplexResult.Tag.Coordinates, param0: f64_0, param1: f64_1, param2: f64_2 }; + } + case ComplexResult.Tag.Comprehensive: { + const string_8 = tmpRetStrings.pop(); + const string_7 = tmpRetStrings.pop(); + const string_6 = tmpRetStrings.pop(); + const f64_5 = tmpRetF64s.pop(); + const f64_4 = tmpRetF64s.pop(); + const int_3 = tmpRetInts.pop(); + const int_2 = tmpRetInts.pop(); + const bool_1 = tmpRetInts.pop(); + const bool_0 = tmpRetInts.pop(); + return { tag: ComplexResult.Tag.Comprehensive, param0: bool_0, param1: bool_1, param2: int_2, param3: int_3, param4: f64_4, param5: f64_5, param6: string_6, param7: string_7, param8: string_8 }; + } + case ComplexResult.Tag.Info: return { tag: ComplexResult.Tag.Info }; + default: throw new Error("Unknown ComplexResult tag returned from Swift: " + String(tag)); + } + } + }); +}; +export const Result = { + Tag: { + Success: 0, + Failure: 1, + Status: 2, + } +}; + +const __bjs_createResultHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case Result.Tag.Success: { + const bytes_0 = textEncoder.encode(value.param0); + const bytesId_0 = swift.memory.retain(bytes_0); + tmpParamInts.push(bytes_0.length); + tmpParamInts.push(bytesId_0); + const cleanup = () => { + swift.memory.release(bytesId_0); + }; + return { caseId: Result.Tag.Success, cleanup }; + } + case Result.Tag.Failure: { + tmpParamInts.push((value.param1 | 0)); + const bytes_0 = textEncoder.encode(value.param0); + const bytesId_0 = swift.memory.retain(bytes_0); + tmpParamInts.push(bytes_0.length); + tmpParamInts.push(bytesId_0); + const cleanup = () => { + swift.memory.release(bytesId_0); + }; + return { caseId: Result.Tag.Failure, cleanup }; + } + case Result.Tag.Status: { + const bytes_2 = textEncoder.encode(value.param2); + const bytesId_2 = swift.memory.retain(bytes_2); + tmpParamInts.push(bytes_2.length); + tmpParamInts.push(bytesId_2); + tmpParamInts.push((value.param1 | 0)); + tmpParamInts.push(value.param0 ? 1 : 0); + const cleanup = () => { + swift.memory.release(bytesId_2); + }; + return { caseId: Result.Tag.Status, cleanup }; + } + default: throw new Error("Unknown Result tag: " + String(enumTag)); + } + }, + raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + const tag = tmpRetTag | 0; + switch (tag) { + case Result.Tag.Success: { + const string_0 = tmpRetStrings.pop(); + return { tag: Result.Tag.Success, param0: string_0 }; + } + case Result.Tag.Failure: { + const int_1 = tmpRetInts.pop(); + const string_0 = tmpRetStrings.pop(); + return { tag: Result.Tag.Failure, param0: string_0, param1: int_1 }; + } + case Result.Tag.Status: { + const string_2 = tmpRetStrings.pop(); + const int_1 = tmpRetInts.pop(); + const bool_0 = tmpRetInts.pop(); + return { tag: Result.Tag.Status, param0: bool_0, param1: int_1, param2: string_2 }; + } + default: throw new Error("Unknown Result tag returned from Swift: " + String(tag)); + } + } + }); +}; +export const NetworkingResult = { + Tag: { + Success: 0, + Failure: 1, + } +}; + +const __bjs_createNetworkingResultHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case NetworkingResult.Tag.Success: { + const bytes_0 = textEncoder.encode(value.param0); + const bytesId_0 = swift.memory.retain(bytes_0); + tmpParamInts.push(bytes_0.length); + tmpParamInts.push(bytesId_0); + const cleanup = () => { + swift.memory.release(bytesId_0); + }; + return { caseId: NetworkingResult.Tag.Success, cleanup }; + } + case NetworkingResult.Tag.Failure: { + tmpParamInts.push((value.param1 | 0)); + const bytes_0 = textEncoder.encode(value.param0); + const bytesId_0 = swift.memory.retain(bytes_0); + tmpParamInts.push(bytes_0.length); + tmpParamInts.push(bytesId_0); + const cleanup = () => { + swift.memory.release(bytesId_0); + }; + return { caseId: NetworkingResult.Tag.Failure, cleanup }; + } + default: throw new Error("Unknown NetworkingResult tag: " + String(enumTag)); + } + }, + raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + const tag = tmpRetTag | 0; + switch (tag) { + case NetworkingResult.Tag.Success: { + const string_0 = tmpRetStrings.pop(); + return { tag: NetworkingResult.Tag.Success, param0: string_0 }; + } + case NetworkingResult.Tag.Failure: { + const int_1 = tmpRetInts.pop(); + const string_0 = tmpRetStrings.pop(); + return { tag: NetworkingResult.Tag.Failure, param0: string_0, param1: int_1 }; + } + default: throw new Error("Unknown NetworkingResult tag returned from Swift: " + String(tag)); + } + } + }); +}; + +if (typeof globalThis.Utilities === 'undefined') { + globalThis.Utilities = {}; +} +if (typeof globalThis.API === 'undefined') { + globalThis.API = {}; +} + +globalThis.Utilities.Result = Result; +globalThis.API.NetworkingResult = NetworkingResult; + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + const enumHelpers = {}; + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + const bjs = {}; + importObject["bjs"] = bjs; + const imports = options.getImports(importsContext); + bjs["swift_js_return_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + return swift.memory.retain(textDecoder.decode(bytes)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr, len); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } + + + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + + const APIResultHelpers = __bjs_createAPIResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + enumHelpers.APIResult = APIResultHelpers; + + const ComplexResultHelpers = __bjs_createComplexResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + enumHelpers.ComplexResult = ComplexResultHelpers; + + const ResultHelpers = __bjs_createResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + enumHelpers.Result = ResultHelpers; + + const NetworkingResultHelpers = __bjs_createNetworkingResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + enumHelpers.NetworkingResult = NetworkingResultHelpers; + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + + return { + handle: function bjs_handle(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result); + instance.exports.bjs_handle(resultCaseId); + if (resultCleanup) { resultCleanup(); } + }, + getResult: function bjs_getResult() { + instance.exports.bjs_getResult(); + const ret = enumHelpers.APIResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + return ret; + }, + roundtripAPIResult: function bjs_roundtripAPIResult(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result); + instance.exports.bjs_roundtripAPIResult(resultCaseId); + const ret = enumHelpers.APIResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + if (resultCleanup) { resultCleanup(); } + return ret; + }, + handleComplex: function bjs_handleComplex(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.ComplexResult.lower(result); + instance.exports.bjs_handleComplex(resultCaseId); + if (resultCleanup) { resultCleanup(); } + }, + getComplexResult: function bjs_getComplexResult() { + instance.exports.bjs_getComplexResult(); + const ret = enumHelpers.ComplexResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + return ret; + }, + roundtripComplexResult: function bjs_roundtripComplexResult(result) { + const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.ComplexResult.lower(result); + instance.exports.bjs_roundtripComplexResult(resultCaseId); + const ret = enumHelpers.ComplexResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + if (resultCleanup) { resultCleanup(); } + return ret; + }, + }; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js index b5bc1145..acb5877a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js @@ -35,10 +35,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -74,12 +83,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js index 677e02c9..9db3b5f4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js @@ -57,10 +57,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -96,6 +105,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; @@ -117,6 +152,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js index 2be034b4..8419a835 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js @@ -86,10 +86,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -125,12 +134,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js index f81c7e47..4b6e9fc8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_returnAnimatable"] = function bjs_returnAnimatable() { @@ -82,6 +117,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js index 6b5211e0..318afa1d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_createArrayBuffer"] = function bjs_createArrayBuffer() { @@ -152,6 +187,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js index d9a13b5e..8fe1102c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_createDatabaseConnection"] = function bjs_createDatabaseConnection(config) { @@ -186,6 +221,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js index 6915a61a..ca477bdf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; @@ -70,6 +105,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js index 4873fc33..c56a487d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,12 +58,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js index b0dbaa19..fb10cc4e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_check"] = function bjs_check(a, b) { @@ -62,6 +97,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js index 594dc9d5..d8f0949d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,12 +58,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js index a61149cd..d839dd03 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkNumber"] = function bjs_checkNumber() { @@ -73,6 +108,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js index ffc1eab6..3b91c039 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; @@ -62,6 +97,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js index ea47fb55..78b1dd66 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,12 +58,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js index 16ed1081..70f2a3d5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkString"] = function bjs_checkString(a) { @@ -73,6 +108,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js index f98cea55..9b7359e9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,12 +58,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js index 3220ae7b..315e6bf8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkString"] = function bjs_checkString() { @@ -64,6 +99,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js index fb995d24..ed64ec10 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; @@ -70,6 +105,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js index c7671805..812a53cd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_createTS2Skeleton"] = function bjs_createTS2Skeleton() { @@ -124,6 +159,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js index b2089962..15b6eaa7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,12 +58,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js index 2eb9dee5..7f285863 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkSimple"] = function bjs_checkSimple(a) { @@ -62,6 +97,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js index 48d15c7e..47828d7a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_Greeter_init"] = function bjs_Greeter_init(name) { @@ -110,6 +145,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js index c200c077..ef2ef687 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,12 +58,39 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } }, setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js index ca497688..c102415e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js @@ -10,10 +10,19 @@ export async function createInstantiator(options, swift) { let setException; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); - let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { /** * @param {WebAssembly.Imports} importObject @@ -49,6 +58,32 @@ export async function createInstantiator(options, swift) { bjs["swift_js_release"] = function(id) { swift.memory.release(id); } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_check"] = function bjs_check() { @@ -62,6 +97,7 @@ export async function createInstantiator(options, swift) { setInstance: (i) => { instance = i; memory = instance.exports.memory; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json new file mode 100644 index 00000000..37f4b61f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json @@ -0,0 +1,483 @@ +{ + "classes" : [ + + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + } + ], + "name" : "flag" + }, + { + "associatedValues" : [ + { + "type" : { + "float" : { + + } + } + } + ], + "name" : "rate" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "precise" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "swiftCallName" : "APIResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "error" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "coordinates" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "comprehensive" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "ComplexResult", + "swiftCallName" : "ComplexResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "Result", + "namespace" : [ + "Utilities" + ], + "swiftCallName" : "Utilities.Result" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "NetworkingResult", + "namespace" : [ + "API" + ], + "swiftCallName" : "NetworkingResult" + } + ], + "functions" : [ + { + "abiName" : "bjs_handle", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "handle", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "getResult", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_roundtripAPIResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundtripAPIResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + }, + { + "abiName" : "bjs_handleComplex", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "handleComplex", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_getComplexResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "getComplexResult", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + }, + { + "abiName" : "bjs_roundtripComplexResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundtripComplexResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + ], + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift new file mode 100644 index 00000000..410c569d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift @@ -0,0 +1,263 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +@_spi(BridgeJS) import JavaScriptKit + +private extension APIResult { + static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 2: + return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 3: + return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())) + case 4: + return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + case 5: + return .info + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .failure(let param0): + _swift_js_push_tag(Int32(1)) + _swift_js_push_int(Int32(param0)) + case .flag(let param0): + _swift_js_push_tag(Int32(2)) + _swift_js_push_int(param0 ? 1 : 0) + case .rate(let param0): + _swift_js_push_tag(Int32(3)) + _swift_js_push_f32(param0) + case .precise(let param0): + _swift_js_push_tag(Int32(4)) + _swift_js_push_f64(param0) + case .info: + _swift_js_push_tag(Int32(5)) + } + } +} + +private extension ComplexResult { + static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .error(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 2: + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 3: + return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + case 4: + return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 5: + return .info + default: + fatalError("Unknown ComplexResult case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .error(let param0, let param1): + _swift_js_push_tag(Int32(1)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_int(Int32(param1)) + case .status(let param0, let param1, let param2): + _swift_js_push_tag(Int32(2)) + _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_int(Int32(param1)) + var __bjs_param2 = param2 + __bjs_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .coordinates(let param0, let param1, let param2): + _swift_js_push_tag(Int32(3)) + _swift_js_push_f64(param0) + _swift_js_push_f64(param1) + _swift_js_push_f64(param2) + case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): + _swift_js_push_tag(Int32(4)) + _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_int(param1 ? 1 : 0) + _swift_js_push_int(Int32(param2)) + _swift_js_push_int(Int32(param3)) + _swift_js_push_f64(param4) + _swift_js_push_f64(param5) + var __bjs_param6 = param6 + __bjs_param6.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + var __bjs_param7 = param7 + __bjs_param7.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + var __bjs_param8 = param8 + __bjs_param8.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .info: + _swift_js_push_tag(Int32(5)) + } + } +} + +private extension Utilities.Result { + static func bridgeJSLiftParameter(_ caseId: Int32) -> Utilities.Result { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 2: + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + default: + fatalError("Unknown Utilities.Result case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .failure(let param0, let param1): + _swift_js_push_tag(Int32(1)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_int(Int32(param1)) + case .status(let param0, let param1, let param2): + _swift_js_push_tag(Int32(2)) + _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_int(Int32(param1)) + var __bjs_param2 = param2 + __bjs_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + } + } +} + +private extension NetworkingResult { + static func bridgeJSLiftParameter(_ caseId: Int32) -> NetworkingResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + default: + fatalError("Unknown NetworkingResult case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .failure(let param0, let param1): + _swift_js_push_tag(Int32(1)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_int(Int32(param1)) + } + } +} + +@_expose(wasm, "bjs_handle") +@_cdecl("bjs_handle") +public func _bjs_handle(result: Int32) -> Void { + #if arch(wasm32) + handle(result: APIResult.bridgeJSLiftParameter(result)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getResult") +@_cdecl("bjs_getResult") +public func _bjs_getResult() -> Void { + #if arch(wasm32) + let ret = getResult() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripAPIResult") +@_cdecl("bjs_roundtripAPIResult") +public func _bjs_roundtripAPIResult(result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripAPIResult(result: APIResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_handleComplex") +@_cdecl("bjs_handleComplex") +public func _bjs_handleComplex(result: Int32) -> Void { + #if arch(wasm32) + handleComplex(result: ComplexResult.bridgeJSLiftParameter(result)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getComplexResult") +@_cdecl("bjs_getComplexResult") +public func _bjs_getComplexResult() -> Void { + #if arch(wasm32) + let ret = getComplexResult() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripComplexResult") +@_cdecl("bjs_roundtripComplexResult") +public func _bjs_roundtripComplexResult(result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripComplexResult(_: ComplexResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift index bb0fbe43..23120ea7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift @@ -6,9 +6,6 @@ @_spi(BridgeJS) import JavaScriptKit -extension Utils: _BridgedSwiftEnumNoPayload { -} - extension Networking.API.Method { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue diff --git a/Sources/JavaScriptKit/BridgeJSInstrincics.swift b/Sources/JavaScriptKit/BridgeJSInstrincics.swift index 56b87fa5..31f56a2a 100644 --- a/Sources/JavaScriptKit/BridgeJSInstrincics.swift +++ b/Sources/JavaScriptKit/BridgeJSInstrincics.swift @@ -338,3 +338,86 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo rawValue.bridgeJSLowerReturn() } } + +// MARK: Wasm externs used by generated enum glue + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_init_memory") +@_spi(BridgeJS) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) +#else +@_spi(BridgeJS) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_tag") +@_spi(BridgeJS) public func _swift_js_push_tag(_ tag: Int32) +#else +@_spi(BridgeJS) public func _swift_js_push_tag(_ tag: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_string") +@_spi(BridgeJS) public func _swift_js_push_string(_ ptr: UnsafePointer?, _ len: Int32) +#else +@_spi(BridgeJS) public func _swift_js_push_string(_ ptr: UnsafePointer?, _ len: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_int") +@_spi(BridgeJS) public func _swift_js_push_int(_ value: Int32) +#else +@_spi(BridgeJS) public func _swift_js_return_int(_ value: Int32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_f32") +@_spi(BridgeJS) public func _swift_js_push_f32(_ value: Float32) +#else +@_spi(BridgeJS) public func _swift_js_push_f32(_ value: Float32) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_push_f64") +@_spi(BridgeJS) public func _swift_js_push_f64(_ value: Float64) +#else +@_spi(BridgeJS) public func _swift_js_push_f64(_ value: Float64) { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_pop_param_int32") +@_spi(BridgeJS) public func _swift_js_pop_param_int32() -> Int32 +#else +@_spi(BridgeJS) public func _swift_js_pop_param_int32() { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_pop_param_f32") +@_spi(BridgeJS) public func _swift_js_pop_param_f32() -> Float32 +#else +@_spi(BridgeJS) public func _swift_js_pop_param_f32() { + _onlyAvailableOnWasm() +} +#endif + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_pop_param_f64") +@_spi(BridgeJS) public func _swift_js_pop_param_f64() -> Float64 +#else +@_spi(BridgeJS) public func _swift_js_pop_param_f64() { + _onlyAvailableOnWasm() +} +#endif diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md index e4bc1d7f..9c0f9971 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md @@ -405,4 +405,138 @@ enum Helper { #### Associated Value Enums -Associated value enums are not currently supported, but are planned for future releases. +Associated value enums are supported and allow you to pass data along with each enum case. BridgeJS generates TypeScript discriminated union types. Associated values are encoded into a binary format for efficient transfer between JavaScript and WebAssembly + +**Swift Definition:** + +```swift +@JS +enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} + +@JS +enum ComplexResult { + case success(String) + case error(String, Int) + case status(Bool, Int, String) + case coordinates(Double, Double, Double) + case comprehensive(Bool, Bool, Int, Int, Double, Double, String, String, String) + case info +} + +@JS func handle(result: APIResult) +@JS func getResult() -> APIResult +``` + +**Generated TypeScript Declaration:** + +```typescript +export const APIResult: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Flag: 2; + readonly Rate: 3; + readonly Precise: 4; + readonly Info: 5; + }; +}; + +export type APIResult = + { tag: typeof APIResult.Tag.Success; param0: string } | + { tag: typeof APIResult.Tag.Failure; param0: number } | + { tag: typeof APIResult.Tag.Flag; param0: boolean } | + { tag: typeof APIResult.Tag.Rate; param0: number } | + { tag: typeof APIResult.Tag.Precise; param0: number } | + { tag: typeof APIResult.Tag.Info } + +export const ComplexResult: { + readonly Tag: { + readonly Success: 0; + readonly Error: 1; + readonly Status: 2; + readonly Coordinates: 3; + readonly Comprehensive: 4; + readonly Info: 5; + }; +}; + +export type ComplexResult = + { tag: typeof ComplexResult.Tag.Success; param0: string } | + { tag: typeof ComplexResult.Tag.Error; param0: string; param1: number } | + { tag: typeof ComplexResult.Tag.Status; param0: boolean; param1: number; param2: string } | + { tag: typeof ComplexResult.Tag.Coordinates; param0: number; param1: number; param2: number } | + { tag: typeof ComplexResult.Tag.Comprehensive; param0: boolean; param1: boolean; param2: number; param3: number; param4: number; param5: number; param6: string; param7: string; param8: string } | + { tag: typeof ComplexResult.Tag.Info } +``` + +**Usage in TypeScript:** + +```typescript +const successResult: APIResult = { + tag: exports.APIResult.Tag.Success, + param0: "Operation completed successfully" +}; + +const errorResult: ComplexResult = { + tag: exports.ComplexResult.Tag.Error, + param0: "Network timeout", + param1: 503 +}; + +const statusResult: ComplexResult = { + tag: exports.ComplexResult.Tag.Status, + param0: true, + param1: 200, + param2: "OK" +}; + +exports.handle(successResult); +exports.handle(errorResult); + +const result: APIResult = exports.getResult(); + +// Pattern matching with discriminated unions +function processResult(result: APIResult) { + switch (result.tag) { + case exports.APIResult.Tag.Success: + console.log("Success:", result.param0); // TypeScript knows param0 is string + break; + case exports.APIResult.Tag.Failure: + console.log("Failure code:", result.param0); // TypeScript knows param0 is number + break; + case exports.APIResult.Tag.Flag: + console.log("Flag value:", result.param0); // TypeScript knows param0 is boolean + break; + case exports.APIResult.Tag.Info: + console.log("Info case has no associated data"); + break; + // TypeScript will warn about missing cases + } +} +``` + +**Supported Features:** + +| Swift Feature | Status | +|:--------------|:-------| +| Associated values: `String` | ✅ | +| Associated values: `Int` | ✅ | +| Associated values: `Bool` | ✅ | +| Associated values: `Float` | ✅ | +| Associated values: `Double` | ✅ | +| Associated values: Custom classes/structs | ❌ | +| Associated values: Other enums | ❌ | +| Associated values: Arrays/Collections | ❌ | +| Associated values: Optionals | ❌ | +| Use as exported function parameters | ✅ | +| Use as exported function return values | ✅ | +| Use as imported function parameters | ❌ | +| Use as imported function return values | ❌ | +| Namespace support | ✅ | diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index ff42f3c7..b00aa67b 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -277,15 +277,15 @@ enum Internal { } } -@JS func echoNetworkingAPIMethod(_ method: Networking.API.Method) -> Networking.API.Method { +@JS func roundtripNetworkingAPIMethod(_ method: Networking.API.Method) -> Networking.API.Method { return method } -@JS func echoConfigurationLogLevel(_ level: Configuration.LogLevel) -> Configuration.LogLevel { +@JS func roundtripConfigurationLogLevel(_ level: Configuration.LogLevel) -> Configuration.LogLevel { return level } -@JS func echoConfigurationPort(_ port: Configuration.Port) -> Configuration.Port { +@JS func roundtripConfigurationPort(_ port: Configuration.Port) -> Configuration.Port { return port } @@ -298,10 +298,143 @@ enum Internal { } } -@JS func echoInternalSupportedMethod(_ method: Internal.SupportedMethod) -> Internal.SupportedMethod { +@JS func roundtripInternalSupportedMethod(_ method: Internal.SupportedMethod) -> Internal.SupportedMethod { return method } +@JS enum APIResult { + case success(String) + case failure(Int) + case flag(Bool) + case rate(Float) + case precise(Double) + case info +} + +@JS func roundtripAPIResult(result: APIResult) -> APIResult { + return result +} + +@JS func makeAPIResultSuccess(_ value: String) -> APIResult { + return .success(value) +} + +@JS func makeAPIResultFailure(_ value: Int) -> APIResult { + return .failure(value) +} + +@JS func makeAPIResultInfo() -> APIResult { + return .info +} + +@JS func makeAPIResultFlag(_ value: Bool) -> APIResult { + return .flag(value) +} + +@JS func makeAPIResultRate(_ value: Float) -> APIResult { + return .rate(value) +} + +@JS func makeAPIResultPrecise(_ value: Double) -> APIResult { + return .precise(value) +} + +@JS +enum ComplexResult { + case success(String) + case error(String, Int) + case location(Double, Double, String) + case status(Bool, Int, String) + case coordinates(Double, Double, Double) + case comprehensive(Bool, Bool, Int, Int, Double, Double, String, String, String) + case info +} + +@JS func roundtripComplexResult(_ result: ComplexResult) -> ComplexResult { + return result +} + +@JS func makeComplexResultSuccess(_ value: String) -> ComplexResult { + return .success(value) +} + +@JS func makeComplexResultError(_ message: String, _ code: Int) -> ComplexResult { + return .error(message, code) +} + +@JS func makeComplexResultLocation(_ lat: Double, _ lng: Double, _ name: String) -> ComplexResult { + return .location(lat, lng, name) +} + +@JS func makeComplexResultStatus(_ active: Bool, _ code: Int, _ message: String) -> ComplexResult { + return .status(active, code, message) +} + +@JS func makeComplexResultCoordinates(_ x: Double, _ y: Double, _ z: Double) -> ComplexResult { + return .coordinates(x, y, z) +} + +@JS func makeComplexResultComprehensive( + _ flag1: Bool, + _ flag2: Bool, + _ count1: Int, + _ count2: Int, + _ value1: Double, + _ value2: Double, + _ text1: String, + _ text2: String, + _ text3: String +) -> ComplexResult { + return .comprehensive(flag1, flag2, count1, count2, value1, value2, text1, text2, text3) +} + +@JS func makeComplexResultInfo() -> ComplexResult { + return .info +} + +@JS enum Utilities { + @JS enum Result { + case success(String) + case failure(String, Int) + case status(Bool, Int, String) + } +} + +@JS enum API { + @JS enum NetworkingResult { + case success(String) + case failure(String, Int) + } +} + +@JS func makeUtilitiesResultSuccess(_ message: String) -> Utilities.Result { + return .success(message) +} + +@JS func makeUtilitiesResultFailure(_ error: String, _ code: Int) -> Utilities.Result { + return .failure(error, code) +} + +@JS func makeUtilitiesResultStatus(_ active: Bool, _ code: Int, _ message: String) -> Utilities.Result { + return .status(active, code, message) +} + +@JS func makeAPINetworkingResultSuccess(_ message: String) -> API.NetworkingResult { + return .success(message) +} + +@JS func makeAPINetworkingResultFailure(_ error: String, _ code: Int) -> API.NetworkingResult { + return .failure(error, code) +} + +@JS func roundtripUtilitiesResult(_ result: Utilities.Result) -> Utilities.Result { + return result +} + +@JS func roundtripAPINetworkingResult(_ result: API.NetworkingResult) -> API.NetworkingResult { + return result +} + // MARK: - Property Tests // Simple class for SwiftHeapObject property testing diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift index 2c70c647..5ae4e055 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift @@ -140,9 +140,6 @@ extension TSDirection { extension TSTheme: _BridgedSwiftEnumNoPayload { } -extension Utils: _BridgedSwiftEnumNoPayload { -} - extension Networking.API.Method { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue @@ -227,6 +224,208 @@ extension Internal.SupportedMethod { } } +private extension APIResult { + static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 2: + return .flag(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 3: + return .rate(Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())) + case 4: + return .precise(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + case 5: + return .info + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .failure(let param0): + _swift_js_push_tag(Int32(1)) + _swift_js_push_int(Int32(param0)) + case .flag(let param0): + _swift_js_push_tag(Int32(2)) + _swift_js_push_int(param0 ? 1 : 0) + case .rate(let param0): + _swift_js_push_tag(Int32(3)) + _swift_js_push_f32(param0) + case .precise(let param0): + _swift_js_push_tag(Int32(4)) + _swift_js_push_f64(param0) + case .info: + _swift_js_push_tag(Int32(5)) + } + } +} + +private extension ComplexResult { + static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .error(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 2: + return .location(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 3: + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 4: + return .coordinates(Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())) + case 5: + return .comprehensive(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 6: + return .info + default: + fatalError("Unknown ComplexResult case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .error(let param0, let param1): + _swift_js_push_tag(Int32(1)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_int(Int32(param1)) + case .location(let param0, let param1, let param2): + _swift_js_push_tag(Int32(2)) + _swift_js_push_f64(param0) + _swift_js_push_f64(param1) + var __bjs_param2 = param2 + __bjs_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .status(let param0, let param1, let param2): + _swift_js_push_tag(Int32(3)) + _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_int(Int32(param1)) + var __bjs_param2 = param2 + __bjs_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .coordinates(let param0, let param1, let param2): + _swift_js_push_tag(Int32(4)) + _swift_js_push_f64(param0) + _swift_js_push_f64(param1) + _swift_js_push_f64(param2) + case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8): + _swift_js_push_tag(Int32(5)) + _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_int(param1 ? 1 : 0) + _swift_js_push_int(Int32(param2)) + _swift_js_push_int(Int32(param3)) + _swift_js_push_f64(param4) + _swift_js_push_f64(param5) + var __bjs_param6 = param6 + __bjs_param6.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + var __bjs_param7 = param7 + __bjs_param7.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + var __bjs_param8 = param8 + __bjs_param8.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .info: + _swift_js_push_tag(Int32(6)) + } + } +} + +private extension Utilities.Result { + static func bridgeJSLiftParameter(_ caseId: Int32) -> Utilities.Result { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + case 2: + return .status(Bool.bridgeJSLiftParameter(_swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()), String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + default: + fatalError("Unknown Utilities.Result case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .failure(let param0, let param1): + _swift_js_push_tag(Int32(1)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_int(Int32(param1)) + case .status(let param0, let param1, let param2): + _swift_js_push_tag(Int32(2)) + _swift_js_push_int(param0 ? 1 : 0) + _swift_js_push_int(Int32(param1)) + var __bjs_param2 = param2 + __bjs_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + } + } +} + +private extension API.NetworkingResult { + static func bridgeJSLiftParameter(_ caseId: Int32) -> API.NetworkingResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + default: + fatalError("Unknown API.NetworkingResult case ID: \(caseId)") + } + } + + func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .failure(let param0, let param1): + _swift_js_push_tag(Int32(1)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + _swift_js_push_int(Int32(param1)) + } + } +} + @_expose(wasm, "bjs_roundTripVoid") @_cdecl("bjs_roundTripVoid") public func _bjs_roundTripVoid() -> Void { @@ -814,33 +1013,33 @@ public func _bjs_getTSTheme() -> Void { #endif } -@_expose(wasm, "bjs_echoNetworkingAPIMethod") -@_cdecl("bjs_echoNetworkingAPIMethod") -public func _bjs_echoNetworkingAPIMethod(method: Int32) -> Int32 { +@_expose(wasm, "bjs_roundtripNetworkingAPIMethod") +@_cdecl("bjs_roundtripNetworkingAPIMethod") +public func _bjs_roundtripNetworkingAPIMethod(method: Int32) -> Int32 { #if arch(wasm32) - let ret = echoNetworkingAPIMethod(_: Networking.API.Method.bridgeJSLiftParameter(method)) + let ret = roundtripNetworkingAPIMethod(_: Networking.API.Method.bridgeJSLiftParameter(method)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_echoConfigurationLogLevel") -@_cdecl("bjs_echoConfigurationLogLevel") -public func _bjs_echoConfigurationLogLevel(levelBytes: Int32, levelLength: Int32) -> Void { +@_expose(wasm, "bjs_roundtripConfigurationLogLevel") +@_cdecl("bjs_roundtripConfigurationLogLevel") +public func _bjs_roundtripConfigurationLogLevel(levelBytes: Int32, levelLength: Int32) -> Void { #if arch(wasm32) - let ret = echoConfigurationLogLevel(_: Configuration.LogLevel.bridgeJSLiftParameter(levelBytes, levelLength)) + let ret = roundtripConfigurationLogLevel(_: Configuration.LogLevel.bridgeJSLiftParameter(levelBytes, levelLength)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") #endif } -@_expose(wasm, "bjs_echoConfigurationPort") -@_cdecl("bjs_echoConfigurationPort") -public func _bjs_echoConfigurationPort(port: Int32) -> Int32 { +@_expose(wasm, "bjs_roundtripConfigurationPort") +@_cdecl("bjs_roundtripConfigurationPort") +public func _bjs_roundtripConfigurationPort(port: Int32) -> Int32 { #if arch(wasm32) - let ret = echoConfigurationPort(_: Configuration.Port.bridgeJSLiftParameter(port)) + let ret = roundtripConfigurationPort(_: Configuration.Port.bridgeJSLiftParameter(port)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") @@ -858,11 +1057,253 @@ public func _bjs_processConfigurationLogLevel(levelBytes: Int32, levelLength: In #endif } -@_expose(wasm, "bjs_echoInternalSupportedMethod") -@_cdecl("bjs_echoInternalSupportedMethod") -public func _bjs_echoInternalSupportedMethod(method: Int32) -> Int32 { +@_expose(wasm, "bjs_roundtripInternalSupportedMethod") +@_cdecl("bjs_roundtripInternalSupportedMethod") +public func _bjs_roundtripInternalSupportedMethod(method: Int32) -> Int32 { + #if arch(wasm32) + let ret = roundtripInternalSupportedMethod(_: Internal.SupportedMethod.bridgeJSLiftParameter(method)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripAPIResult") +@_cdecl("bjs_roundtripAPIResult") +public func _bjs_roundtripAPIResult(result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripAPIResult(result: APIResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultSuccess") +@_cdecl("bjs_makeAPIResultSuccess") +public func _bjs_makeAPIResultSuccess(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPIResultSuccess(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultFailure") +@_cdecl("bjs_makeAPIResultFailure") +public func _bjs_makeAPIResultFailure(value: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPIResultFailure(_: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultInfo") +@_cdecl("bjs_makeAPIResultInfo") +public func _bjs_makeAPIResultInfo() -> Void { + #if arch(wasm32) + let ret = makeAPIResultInfo() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultFlag") +@_cdecl("bjs_makeAPIResultFlag") +public func _bjs_makeAPIResultFlag(value: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPIResultFlag(_: Bool.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultRate") +@_cdecl("bjs_makeAPIResultRate") +public func _bjs_makeAPIResultRate(value: Float32) -> Void { + #if arch(wasm32) + let ret = makeAPIResultRate(_: Float.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPIResultPrecise") +@_cdecl("bjs_makeAPIResultPrecise") +public func _bjs_makeAPIResultPrecise(value: Float64) -> Void { + #if arch(wasm32) + let ret = makeAPIResultPrecise(_: Double.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripComplexResult") +@_cdecl("bjs_roundtripComplexResult") +public func _bjs_roundtripComplexResult(result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripComplexResult(_: ComplexResult.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultSuccess") +@_cdecl("bjs_makeComplexResultSuccess") +public func _bjs_makeComplexResultSuccess(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultSuccess(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultError") +@_cdecl("bjs_makeComplexResultError") +public func _bjs_makeComplexResultError(messageBytes: Int32, messageLength: Int32, code: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultError(_: String.bridgeJSLiftParameter(messageBytes, messageLength), _: Int.bridgeJSLiftParameter(code)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultLocation") +@_cdecl("bjs_makeComplexResultLocation") +public func _bjs_makeComplexResultLocation(lat: Float64, lng: Float64, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultLocation(_: Double.bridgeJSLiftParameter(lat), _: Double.bridgeJSLiftParameter(lng), _: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultStatus") +@_cdecl("bjs_makeComplexResultStatus") +public func _bjs_makeComplexResultStatus(active: Int32, code: Int32, messageBytes: Int32, messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultStatus(_: Bool.bridgeJSLiftParameter(active), _: Int.bridgeJSLiftParameter(code), _: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultCoordinates") +@_cdecl("bjs_makeComplexResultCoordinates") +public func _bjs_makeComplexResultCoordinates(x: Float64, y: Float64, z: Float64) -> Void { + #if arch(wasm32) + let ret = makeComplexResultCoordinates(_: Double.bridgeJSLiftParameter(x), _: Double.bridgeJSLiftParameter(y), _: Double.bridgeJSLiftParameter(z)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultComprehensive") +@_cdecl("bjs_makeComplexResultComprehensive") +public func _bjs_makeComplexResultComprehensive(flag1: Int32, flag2: Int32, count1: Int32, count2: Int32, value1: Float64, value2: Float64, text1Bytes: Int32, text1Length: Int32, text2Bytes: Int32, text2Length: Int32, text3Bytes: Int32, text3Length: Int32) -> Void { + #if arch(wasm32) + let ret = makeComplexResultComprehensive(_: Bool.bridgeJSLiftParameter(flag1), _: Bool.bridgeJSLiftParameter(flag2), _: Int.bridgeJSLiftParameter(count1), _: Int.bridgeJSLiftParameter(count2), _: Double.bridgeJSLiftParameter(value1), _: Double.bridgeJSLiftParameter(value2), _: String.bridgeJSLiftParameter(text1Bytes, text1Length), _: String.bridgeJSLiftParameter(text2Bytes, text2Length), _: String.bridgeJSLiftParameter(text3Bytes, text3Length)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeComplexResultInfo") +@_cdecl("bjs_makeComplexResultInfo") +public func _bjs_makeComplexResultInfo() -> Void { + #if arch(wasm32) + let ret = makeComplexResultInfo() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeUtilitiesResultSuccess") +@_cdecl("bjs_makeUtilitiesResultSuccess") +public func _bjs_makeUtilitiesResultSuccess(messageBytes: Int32, messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeUtilitiesResultSuccess(_: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeUtilitiesResultFailure") +@_cdecl("bjs_makeUtilitiesResultFailure") +public func _bjs_makeUtilitiesResultFailure(errorBytes: Int32, errorLength: Int32, code: Int32) -> Void { + #if arch(wasm32) + let ret = makeUtilitiesResultFailure(_: String.bridgeJSLiftParameter(errorBytes, errorLength), _: Int.bridgeJSLiftParameter(code)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeUtilitiesResultStatus") +@_cdecl("bjs_makeUtilitiesResultStatus") +public func _bjs_makeUtilitiesResultStatus(active: Int32, code: Int32, messageBytes: Int32, messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeUtilitiesResultStatus(_: Bool.bridgeJSLiftParameter(active), _: Int.bridgeJSLiftParameter(code), _: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPINetworkingResultSuccess") +@_cdecl("bjs_makeAPINetworkingResultSuccess") +public func _bjs_makeAPINetworkingResultSuccess(messageBytes: Int32, messageLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPINetworkingResultSuccess(_: String.bridgeJSLiftParameter(messageBytes, messageLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeAPINetworkingResultFailure") +@_cdecl("bjs_makeAPINetworkingResultFailure") +public func _bjs_makeAPINetworkingResultFailure(errorBytes: Int32, errorLength: Int32, code: Int32) -> Void { + #if arch(wasm32) + let ret = makeAPINetworkingResultFailure(_: String.bridgeJSLiftParameter(errorBytes, errorLength), _: Int.bridgeJSLiftParameter(code)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripUtilitiesResult") +@_cdecl("bjs_roundtripUtilitiesResult") +public func _bjs_roundtripUtilitiesResult(result: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripUtilitiesResult(_: Utilities.Result.bridgeJSLiftParameter(result)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripAPINetworkingResult") +@_cdecl("bjs_roundtripAPINetworkingResult") +public func _bjs_roundtripAPINetworkingResult(result: Int32) -> Void { #if arch(wasm32) - let ret = echoInternalSupportedMethod(_: Internal.SupportedMethod.bridgeJSLiftParameter(method)) + let ret = roundtripAPINetworkingResult(_: API.NetworkingResult.bridgeJSLiftParameter(result)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json index 8e65a50d..5609a0f2 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json @@ -913,16 +913,707 @@ "Internal" ], "swiftCallName" : "Internal.SupportedMethod" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + } + ], + "name" : "flag" + }, + { + "associatedValues" : [ + { + "type" : { + "float" : { + + } + } + } + ], + "name" : "rate" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "precise" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "swiftCallName" : "APIResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "error" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "location" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + }, + { + "associatedValues" : [ + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + } + ], + "name" : "coordinates" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "double" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "comprehensive" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "ComplexResult", + "swiftCallName" : "ComplexResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "Result", + "namespace" : [ + "Utilities" + ], + "swiftCallName" : "Utilities.Result" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "NetworkingResult", + "namespace" : [ + "API" + ], + "swiftCallName" : "API.NetworkingResult" } ], "functions" : [ { - "abiName" : "bjs_roundTripVoid", + "abiName" : "bjs_roundTripVoid", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripVoid", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_roundTripInt", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripInt", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_roundTripFloat", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripFloat", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "float" : { + + } + } + } + ], + "returnType" : { + "float" : { + + } + } + }, + { + "abiName" : "bjs_roundTripDouble", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripDouble", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "double" : { + + } + } + } + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_roundTripBool", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripBool", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_roundTripString", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripString", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_roundTripSwiftHeapObject", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripSwiftHeapObject", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_roundTripJSObject", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripJSObject", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_throwsSwiftError", + "effects" : { + "isAsync" : false, + "isThrows" : true + }, + "name" : "throwsSwiftError", + "parameters" : [ + { + "label" : "shouldThrow", + "name" : "shouldThrow", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithIntResult", + "effects" : { + "isAsync" : false, + "isThrows" : true + }, + "name" : "throwsWithIntResult", + "parameters" : [ + + ], + "returnType" : { + "int" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithStringResult", + "effects" : { + "isAsync" : false, + "isThrows" : true + }, + "name" : "throwsWithStringResult", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithBoolResult", + "effects" : { + "isAsync" : false, + "isThrows" : true + }, + "name" : "throwsWithBoolResult", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithFloatResult", + "effects" : { + "isAsync" : false, + "isThrows" : true + }, + "name" : "throwsWithFloatResult", + "parameters" : [ + + ], + "returnType" : { + "float" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithDoubleResult", + "effects" : { + "isAsync" : false, + "isThrows" : true + }, + "name" : "throwsWithDoubleResult", + "parameters" : [ + + ], + "returnType" : { + "double" : { + + } + } + }, + { + "abiName" : "bjs_throwsWithSwiftHeapObjectResult", + "effects" : { + "isAsync" : false, + "isThrows" : true + }, + "name" : "throwsWithSwiftHeapObjectResult", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_throwsWithJSObjectResult", "effects" : { "isAsync" : false, + "isThrows" : true + }, + "name" : "throwsWithJSObjectResult", + "parameters" : [ + + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripVoid", + "effects" : { + "isAsync" : true, "isThrows" : false }, - "name" : "roundTripVoid", + "name" : "asyncRoundTripVoid", "parameters" : [ ], @@ -933,12 +1624,12 @@ } }, { - "abiName" : "bjs_roundTripInt", + "abiName" : "bjs_asyncRoundTripInt", "effects" : { - "isAsync" : false, + "isAsync" : true, "isThrows" : false }, - "name" : "roundTripInt", + "name" : "asyncRoundTripInt", "parameters" : [ { "label" : "v", @@ -957,12 +1648,12 @@ } }, { - "abiName" : "bjs_roundTripFloat", + "abiName" : "bjs_asyncRoundTripFloat", "effects" : { - "isAsync" : false, + "isAsync" : true, "isThrows" : false }, - "name" : "roundTripFloat", + "name" : "asyncRoundTripFloat", "parameters" : [ { "label" : "v", @@ -981,12 +1672,12 @@ } }, { - "abiName" : "bjs_roundTripDouble", + "abiName" : "bjs_asyncRoundTripDouble", "effects" : { - "isAsync" : false, + "isAsync" : true, "isThrows" : false }, - "name" : "roundTripDouble", + "name" : "asyncRoundTripDouble", "parameters" : [ { "label" : "v", @@ -1005,91 +1696,238 @@ } }, { - "abiName" : "bjs_roundTripBool", + "abiName" : "bjs_asyncRoundTripBool", + "effects" : { + "isAsync" : true, + "isThrows" : false + }, + "name" : "asyncRoundTripBool", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripString", + "effects" : { + "isAsync" : true, + "isThrows" : false + }, + "name" : "asyncRoundTripString", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_asyncRoundTripSwiftHeapObject", + "effects" : { + "isAsync" : true, + "isThrows" : false + }, + "name" : "asyncRoundTripSwiftHeapObject", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripJSObject", + "effects" : { + "isAsync" : true, + "isThrows" : false + }, + "name" : "asyncRoundTripJSObject", + "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "jsObject" : { + + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_takeGreeter", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "takeGreeter", + "parameters" : [ + { + "label" : "g", + "name" : "g", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_createCalculator", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "createCalculator", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Calculator" + } + } + }, + { + "abiName" : "bjs_useCalculator", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "roundTripBool", + "name" : "useCalculator", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "calc", + "name" : "calc", "type" : { - "bool" : { + "swiftHeapObject" : { + "_0" : "Calculator" + } + } + }, + { + "label" : "x", + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "int" : { } } } ], "returnType" : { - "bool" : { + "int" : { } } }, { - "abiName" : "bjs_roundTripString", + "abiName" : "bjs_testGreeterToJSValue", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "roundTripString", + "name" : "testGreeterToJSValue", "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "string" : { - } - } - } ], "returnType" : { - "string" : { + "jsObject" : { } } }, { - "abiName" : "bjs_roundTripSwiftHeapObject", + "abiName" : "bjs_testCalculatorToJSValue", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "roundTripSwiftHeapObject", + "name" : "testCalculatorToJSValue", "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - } + ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "jsObject" : { + } } }, { - "abiName" : "bjs_roundTripJSObject", + "abiName" : "bjs_testSwiftClassAsJSValue", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "roundTripJSObject", + "name" : "testSwiftClassAsJSValue", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "greeter", + "name" : "greeter", "type" : { - "jsObject" : { - + "swiftHeapObject" : { + "_0" : "Greeter" } } } @@ -1101,854 +1939,1070 @@ } }, { - "abiName" : "bjs_throwsSwiftError", + "abiName" : "bjs_setDirection", "effects" : { "isAsync" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsSwiftError", + "name" : "setDirection", "parameters" : [ { - "label" : "shouldThrow", - "name" : "shouldThrow", + "label" : "_", + "name" : "direction", "type" : { - "bool" : { - + "caseEnum" : { + "_0" : "Direction" } } } ], "returnType" : { - "void" : { - + "caseEnum" : { + "_0" : "Direction" } } }, { - "abiName" : "bjs_throwsWithIntResult", + "abiName" : "bjs_getDirection", "effects" : { "isAsync" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithIntResult", + "name" : "getDirection", "parameters" : [ ], "returnType" : { - "int" : { - + "caseEnum" : { + "_0" : "Direction" } } }, { - "abiName" : "bjs_throwsWithStringResult", + "abiName" : "bjs_processDirection", "effects" : { "isAsync" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithStringResult", + "name" : "processDirection", "parameters" : [ - + { + "label" : "_", + "name" : "input", + "type" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } ], "returnType" : { - "string" : { - + "caseEnum" : { + "_0" : "Status" } } }, { - "abiName" : "bjs_throwsWithBoolResult", + "abiName" : "bjs_setTheme", "effects" : { "isAsync" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithBoolResult", + "name" : "setTheme", "parameters" : [ - + { + "label" : "_", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } ], "returnType" : { - "bool" : { - + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" } } }, { - "abiName" : "bjs_throwsWithFloatResult", + "abiName" : "bjs_getTheme", "effects" : { "isAsync" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithFloatResult", + "name" : "getTheme", "parameters" : [ ], "returnType" : { - "float" : { - + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" } } }, { - "abiName" : "bjs_throwsWithDoubleResult", + "abiName" : "bjs_setHttpStatus", "effects" : { "isAsync" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithDoubleResult", + "name" : "setHttpStatus", "parameters" : [ - + { + "label" : "_", + "name" : "status", + "type" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } ], "returnType" : { - "double" : { - + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" } } }, { - "abiName" : "bjs_throwsWithSwiftHeapObjectResult", + "abiName" : "bjs_getHttpStatus", "effects" : { "isAsync" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithSwiftHeapObjectResult", + "name" : "getHttpStatus", "parameters" : [ ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" } } }, { - "abiName" : "bjs_throwsWithJSObjectResult", + "abiName" : "bjs_processTheme", "effects" : { "isAsync" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithJSObjectResult", + "name" : "processTheme", "parameters" : [ - + { + "label" : "_", + "name" : "theme", + "type" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } ], "returnType" : { - "jsObject" : { - + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" } } }, { - "abiName" : "bjs_asyncRoundTripVoid", + "abiName" : "bjs_setTSDirection", "effects" : { - "isAsync" : true, + "isAsync" : false, "isThrows" : false }, - "name" : "asyncRoundTripVoid", + "name" : "setTSDirection", "parameters" : [ - + { + "label" : "_", + "name" : "direction", + "type" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + } ], "returnType" : { - "void" : { - + "caseEnum" : { + "_0" : "TSDirection" } } }, { - "abiName" : "bjs_asyncRoundTripInt", + "abiName" : "bjs_getTSDirection", "effects" : { - "isAsync" : true, + "isAsync" : false, "isThrows" : false }, - "name" : "asyncRoundTripInt", + "name" : "getTSDirection", "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "int" : { - } - } - } ], "returnType" : { - "int" : { - + "caseEnum" : { + "_0" : "TSDirection" } } }, { - "abiName" : "bjs_asyncRoundTripFloat", + "abiName" : "bjs_setTSTheme", "effects" : { - "isAsync" : true, + "isAsync" : false, "isThrows" : false }, - "name" : "asyncRoundTripFloat", + "name" : "setTSTheme", "parameters" : [ - { - "label" : "v", - "name" : "v", + { + "label" : "_", + "name" : "theme", "type" : { - "float" : { - + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" } } } ], "returnType" : { - "float" : { - + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" } } }, { - "abiName" : "bjs_asyncRoundTripDouble", + "abiName" : "bjs_getTSTheme", "effects" : { - "isAsync" : true, + "isAsync" : false, "isThrows" : false }, - "name" : "asyncRoundTripDouble", + "name" : "getTSTheme", "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "double" : { - } - } - } ], "returnType" : { - "double" : { - + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" } } }, { - "abiName" : "bjs_asyncRoundTripBool", + "abiName" : "bjs_roundtripNetworkingAPIMethod", "effects" : { - "isAsync" : true, + "isAsync" : false, "isThrows" : false }, - "name" : "asyncRoundTripBool", + "name" : "roundtripNetworkingAPIMethod", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "method", "type" : { - "bool" : { - + "caseEnum" : { + "_0" : "Networking.API.Method" } } } ], "returnType" : { - "bool" : { - + "caseEnum" : { + "_0" : "Networking.API.Method" } } }, { - "abiName" : "bjs_asyncRoundTripString", + "abiName" : "bjs_roundtripConfigurationLogLevel", "effects" : { - "isAsync" : true, + "isAsync" : false, "isThrows" : false }, - "name" : "asyncRoundTripString", + "name" : "roundtripConfigurationLogLevel", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "level", "type" : { - "string" : { - + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" } } } ], "returnType" : { - "string" : { - + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" } } }, { - "abiName" : "bjs_asyncRoundTripSwiftHeapObject", + "abiName" : "bjs_roundtripConfigurationPort", "effects" : { - "isAsync" : true, + "isAsync" : false, "isThrows" : false }, - "name" : "asyncRoundTripSwiftHeapObject", + "name" : "roundtripConfigurationPort", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "port", "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" } } } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" } } }, { - "abiName" : "bjs_asyncRoundTripJSObject", + "abiName" : "bjs_processConfigurationLogLevel", "effects" : { - "isAsync" : true, + "isAsync" : false, "isThrows" : false }, - "name" : "asyncRoundTripJSObject", + "name" : "processConfigurationLogLevel", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "level", "type" : { - "jsObject" : { - + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" } } } ], "returnType" : { - "jsObject" : { - + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" } } }, { - "abiName" : "bjs_takeGreeter", + "abiName" : "bjs_roundtripInternalSupportedMethod", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "takeGreeter", + "name" : "roundtripInternalSupportedMethod", "parameters" : [ { - "label" : "g", - "name" : "g", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - }, - { - "label" : "name", - "name" : "name", + "label" : "_", + "name" : "method", "type" : { - "string" : { - + "caseEnum" : { + "_0" : "Internal.SupportedMethod" } } } ], "returnType" : { - "void" : { - + "caseEnum" : { + "_0" : "Internal.SupportedMethod" } } }, { - "abiName" : "bjs_createCalculator", + "abiName" : "bjs_roundtripAPIResult", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "createCalculator", + "name" : "roundtripAPIResult", "parameters" : [ - + { + "label" : "result", + "name" : "result", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Calculator" + "associatedValueEnum" : { + "_0" : "APIResult" } } }, { - "abiName" : "bjs_useCalculator", + "abiName" : "bjs_makeAPIResultSuccess", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "useCalculator", + "name" : "makeAPIResultSuccess", "parameters" : [ { - "label" : "calc", - "name" : "calc", - "type" : { - "swiftHeapObject" : { - "_0" : "Calculator" - } - } - }, - { - "label" : "x", - "name" : "x", - "type" : { - "int" : { - - } - } - }, - { - "label" : "y", - "name" : "y", + "label" : "_", + "name" : "value", "type" : { - "int" : { + "string" : { } } } ], "returnType" : { - "int" : { - + "associatedValueEnum" : { + "_0" : "APIResult" } } }, { - "abiName" : "bjs_testGreeterToJSValue", + "abiName" : "bjs_makeAPIResultFailure", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "testGreeterToJSValue", + "name" : "makeAPIResultFailure", "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "int" : { + } + } + } ], "returnType" : { - "jsObject" : { - + "associatedValueEnum" : { + "_0" : "APIResult" } } }, { - "abiName" : "bjs_testCalculatorToJSValue", + "abiName" : "bjs_makeAPIResultInfo", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "testCalculatorToJSValue", + "name" : "makeAPIResultInfo", "parameters" : [ ], "returnType" : { - "jsObject" : { - + "associatedValueEnum" : { + "_0" : "APIResult" } } }, { - "abiName" : "bjs_testSwiftClassAsJSValue", + "abiName" : "bjs_makeAPIResultFlag", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "testSwiftClassAsJSValue", + "name" : "makeAPIResultFlag", "parameters" : [ { - "label" : "greeter", - "name" : "greeter", + "label" : "_", + "name" : "value", "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "bool" : { + } } } ], "returnType" : { - "jsObject" : { - + "associatedValueEnum" : { + "_0" : "APIResult" } } }, { - "abiName" : "bjs_setDirection", + "abiName" : "bjs_makeAPIResultRate", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "setDirection", + "name" : "makeAPIResultRate", "parameters" : [ { "label" : "_", - "name" : "direction", + "name" : "value", "type" : { - "caseEnum" : { - "_0" : "Direction" + "float" : { + } } } ], "returnType" : { - "caseEnum" : { - "_0" : "Direction" + "associatedValueEnum" : { + "_0" : "APIResult" } } }, { - "abiName" : "bjs_getDirection", + "abiName" : "bjs_makeAPIResultPrecise", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "getDirection", + "name" : "makeAPIResultPrecise", "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "double" : { + } + } + } ], "returnType" : { - "caseEnum" : { - "_0" : "Direction" + "associatedValueEnum" : { + "_0" : "APIResult" } } }, { - "abiName" : "bjs_processDirection", + "abiName" : "bjs_roundtripComplexResult", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "processDirection", + "name" : "roundtripComplexResult", "parameters" : [ { "label" : "_", - "name" : "input", + "name" : "result", "type" : { - "caseEnum" : { - "_0" : "Direction" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } } ], "returnType" : { - "caseEnum" : { - "_0" : "Status" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_setTheme", + "abiName" : "bjs_makeComplexResultSuccess", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "setTheme", + "name" : "makeComplexResultSuccess", "parameters" : [ { "label" : "_", - "name" : "theme", + "name" : "value", "type" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "string" : { + } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_getTheme", + "abiName" : "bjs_makeComplexResultError", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "getTheme", + "name" : "makeComplexResultError", "parameters" : [ + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + + } + } + } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_setHttpStatus", + "abiName" : "bjs_makeComplexResultLocation", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "setHttpStatus", + "name" : "makeComplexResultLocation", "parameters" : [ { "label" : "_", - "name" : "status", + "name" : "lat", "type" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "lng", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "name", + "type" : { + "string" : { + } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_getHttpStatus", + "abiName" : "bjs_makeComplexResultStatus", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "getHttpStatus", + "name" : "makeComplexResultStatus", "parameters" : [ + { + "label" : "_", + "name" : "active", + "type" : { + "bool" : { + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + + } + } + }, + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + + } + } + } ], "returnType" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_processTheme", + "abiName" : "bjs_makeComplexResultCoordinates", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "processTheme", + "name" : "makeComplexResultCoordinates", "parameters" : [ { "label" : "_", - "name" : "theme", + "name" : "x", "type" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "y", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "z", + "type" : { + "double" : { + } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_setTSDirection", + "abiName" : "bjs_makeComplexResultComprehensive", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "setTSDirection", + "name" : "makeComplexResultComprehensive", "parameters" : [ { "label" : "_", - "name" : "direction", + "name" : "flag1", "type" : { - "caseEnum" : { - "_0" : "TSDirection" + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "flag2", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "count1", + "type" : { + "int" : { + + } + } + }, + { + "label" : "_", + "name" : "count2", + "type" : { + "int" : { + + } + } + }, + { + "label" : "_", + "name" : "value1", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "value2", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "text1", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "text2", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "text3", + "type" : { + "string" : { + } } } ], "returnType" : { - "caseEnum" : { - "_0" : "TSDirection" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_getTSDirection", + "abiName" : "bjs_makeComplexResultInfo", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "getTSDirection", + "name" : "makeComplexResultInfo", "parameters" : [ ], "returnType" : { - "caseEnum" : { - "_0" : "TSDirection" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_setTSTheme", + "abiName" : "bjs_makeUtilitiesResultSuccess", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "setTSTheme", + "name" : "makeUtilitiesResultSuccess", "parameters" : [ { "label" : "_", - "name" : "theme", + "name" : "message", "type" : { - "rawValueEnum" : { - "_0" : "TSTheme", - "_1" : "String" + "string" : { + } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "TSTheme", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } }, { - "abiName" : "bjs_getTSTheme", + "abiName" : "bjs_makeUtilitiesResultFailure", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "getTSTheme", + "name" : "makeUtilitiesResultFailure", "parameters" : [ + { + "label" : "_", + "name" : "error", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + } + } + } ], "returnType" : { - "rawValueEnum" : { - "_0" : "TSTheme", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } }, { - "abiName" : "bjs_echoNetworkingAPIMethod", + "abiName" : "bjs_makeUtilitiesResultStatus", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "echoNetworkingAPIMethod", + "name" : "makeUtilitiesResultStatus", "parameters" : [ { "label" : "_", - "name" : "method", + "name" : "active", "type" : { - "caseEnum" : { - "_0" : "Networking.API.Method" + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + + } + } + }, + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + } } } ], "returnType" : { - "caseEnum" : { - "_0" : "Networking.API.Method" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } }, { - "abiName" : "bjs_echoConfigurationLogLevel", + "abiName" : "bjs_makeAPINetworkingResultSuccess", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "echoConfigurationLogLevel", + "name" : "makeAPINetworkingResultSuccess", "parameters" : [ { "label" : "_", - "name" : "level", + "name" : "message", "type" : { - "rawValueEnum" : { - "_0" : "Configuration.LogLevel", - "_1" : "String" + "string" : { + } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Configuration.LogLevel", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" } } }, { - "abiName" : "bjs_echoConfigurationPort", + "abiName" : "bjs_makeAPINetworkingResultFailure", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "echoConfigurationPort", + "name" : "makeAPINetworkingResultFailure", "parameters" : [ { "label" : "_", - "name" : "port", + "name" : "error", "type" : { - "rawValueEnum" : { - "_0" : "Configuration.Port", - "_1" : "Int" + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "int" : { + } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Configuration.Port", - "_1" : "Int" + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" } } }, { - "abiName" : "bjs_processConfigurationLogLevel", + "abiName" : "bjs_roundtripUtilitiesResult", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "processConfigurationLogLevel", + "name" : "roundtripUtilitiesResult", "parameters" : [ { "label" : "_", - "name" : "level", + "name" : "result", "type" : { - "rawValueEnum" : { - "_0" : "Configuration.LogLevel", - "_1" : "String" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Configuration.Port", - "_1" : "Int" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } }, { - "abiName" : "bjs_echoInternalSupportedMethod", + "abiName" : "bjs_roundtripAPINetworkingResult", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "echoInternalSupportedMethod", + "name" : "roundtripAPINetworkingResult", "parameters" : [ { "label" : "_", - "name" : "method", + "name" : "result", "type" : { - "caseEnum" : { - "_0" : "Internal.SupportedMethod" + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" } } } ], "returnType" : { - "caseEnum" : { - "_0" : "Internal.SupportedMethod" + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" } } }, diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 8094a465..5ce68b5c 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -1,7 +1,7 @@ // @ts-check -import { - Direction, Status, Theme, HttpStatus, TSDirection, TSTheme +import { + Direction, Status, Theme, HttpStatus, TSDirection, TSTheme, APIResult, ComplexResult } from '../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; /** @type {import('../.build/plugins/PackageToJS/outputs/PackageTests/test.d.ts').SetupOptionsFn} */ @@ -354,14 +354,14 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(globalThis.Networking.APIV2.Internal.SupportedMethod.Get, 0); assert.equal(globalThis.Networking.APIV2.Internal.SupportedMethod.Post, 1); - assert.equal(exports.echoNetworkingAPIMethod(globalThis.Networking.API.Method.Get), globalThis.Networking.API.Method.Get); - assert.equal(exports.echoConfigurationLogLevel(globalThis.Configuration.LogLevel.Debug), globalThis.Configuration.LogLevel.Debug); - assert.equal(exports.echoConfigurationPort(globalThis.Configuration.Port.Http), globalThis.Configuration.Port.Http); + assert.equal(exports.roundtripNetworkingAPIMethod(globalThis.Networking.API.Method.Get), globalThis.Networking.API.Method.Get); + assert.equal(exports.roundtripConfigurationLogLevel(globalThis.Configuration.LogLevel.Debug), globalThis.Configuration.LogLevel.Debug); + assert.equal(exports.roundtripConfigurationPort(globalThis.Configuration.Port.Http), globalThis.Configuration.Port.Http); assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevel.Debug), globalThis.Configuration.Port.Development); assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevel.Info), globalThis.Configuration.Port.Http); assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevel.Warning), globalThis.Configuration.Port.Https); assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevel.Error), globalThis.Configuration.Port.Development); - assert.equal(exports.echoInternalSupportedMethod(globalThis.Networking.APIV2.Internal.SupportedMethod.Get), globalThis.Networking.APIV2.Internal.SupportedMethod.Get); + assert.equal(exports.roundtripInternalSupportedMethod(globalThis.Networking.APIV2.Internal.SupportedMethod.Get), globalThis.Networking.APIV2.Internal.SupportedMethod.Get); const converter = new exports.Converter(); assert.equal(converter.toString(42), "42"); @@ -389,6 +389,80 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { const globalTestServer = new globalThis.Networking.APIV2.Internal.TestServer(); globalTestServer.call(globalThis.Networking.APIV2.Internal.SupportedMethod.Post); globalTestServer.release(); + + const s1 = { tag: APIResult.Tag.Success, param0: "Cześć 🙋‍♂️" }; + const f1 = { tag: APIResult.Tag.Failure, param0: 42 }; + const i1 = { tag: APIResult.Tag.Info }; + + assert.deepEqual(exports.roundtripAPIResult(s1), s1); + assert.deepEqual(exports.roundtripAPIResult(f1), f1); + assert.deepEqual(exports.roundtripAPIResult(i1), i1); + + assert.deepEqual(exports.makeAPIResultSuccess("Test"), { tag: APIResult.Tag.Success, param0: "Test" }); + assert.deepEqual(exports.makeAPIResultSuccess("ok"), { tag: APIResult.Tag.Success, param0: "ok" }); + assert.deepEqual(exports.makeAPIResultFailure(123), { tag: APIResult.Tag.Failure, param0: 123 }); + assert.deepEqual(exports.makeAPIResultInfo(), { tag: APIResult.Tag.Info }); + + const bTrue = { tag: APIResult.Tag.Flag, param0: true }; + const bFalse = { tag: APIResult.Tag.Flag, param0: false }; + assert.deepEqual(exports.makeAPIResultFlag(true), bTrue); + assert.deepEqual(exports.makeAPIResultFlag(false), bFalse); + + const rVal = 3.25; + const r1 = { tag: APIResult.Tag.Rate, param0: rVal }; + assert.deepEqual(exports.roundtripAPIResult(r1), r1); + assert.deepEqual(exports.makeAPIResultRate(rVal), r1); + + const pVal = 3.141592653589793; + const p1 = { tag: APIResult.Tag.Precise, param0: pVal }; + assert.deepEqual(exports.roundtripAPIResult(p1), p1); + assert.deepEqual(exports.makeAPIResultPrecise(pVal), p1); + + const cs1 = { tag: ComplexResult.Tag.Success, param0: "All good!" }; + const ce1 = { tag: ComplexResult.Tag.Error, param0: "Network error", param1: 503 }; + const cl1 = { tag: ComplexResult.Tag.Location, param0: 37.7749, param1: -122.4194, param2: "San Francisco" }; + const cst1 = { tag: ComplexResult.Tag.Status, param0: true, param1: 200, param2: "OK" }; + const cc1 = { tag: ComplexResult.Tag.Coordinates, param0: 10.5, param1: 20.3, param2: 30.7 }; + const ccomp1 = { tag: ComplexResult.Tag.Comprehensive, param0: true, param1: false, param2: 42, param3: 100, param4: 3.14, param5: 2.718, param6: "Hello", param7: "World", param8: "Test" }; + const ci1 = { tag: ComplexResult.Tag.Info }; + + assert.deepEqual(exports.roundtripComplexResult(cs1), cs1); + assert.deepEqual(exports.roundtripComplexResult(ce1), ce1); + assert.deepEqual(exports.roundtripComplexResult(cl1), cl1); + assert.deepEqual(exports.roundtripComplexResult(cst1), cst1); + assert.deepEqual(exports.roundtripComplexResult(cc1), cc1); + assert.deepEqual(exports.roundtripComplexResult(ccomp1), ccomp1); + assert.deepEqual(exports.roundtripComplexResult(ci1), ci1); + + assert.deepEqual(exports.makeComplexResultSuccess("Great!"), { tag: ComplexResult.Tag.Success, param0: "Great!" }); + assert.deepEqual(exports.makeComplexResultError("Timeout", 408), { tag: ComplexResult.Tag.Error, param0: "Timeout", param1: 408 }); + assert.deepEqual(exports.makeComplexResultLocation(40.7128, -74.0060, "New York"), { tag: ComplexResult.Tag.Location, param0: 40.7128, param1: -74.0060, param2: "New York" }); + assert.deepEqual(exports.makeComplexResultStatus(false, 500, "Internal Server Error"), { tag: ComplexResult.Tag.Status, param0: false, param1: 500, param2: "Internal Server Error" }); + assert.deepEqual(exports.makeComplexResultCoordinates(1.1, 2.2, 3.3), { tag: ComplexResult.Tag.Coordinates, param0: 1.1, param1: 2.2, param2: 3.3 }); + assert.deepEqual(exports.makeComplexResultComprehensive(true, false, 10, 20, 1.5, 2.5, "First", "Second", "Third"), { tag: ComplexResult.Tag.Comprehensive, param0: true, param1: false, param2: 10, param3: 20, param4: 1.5, param5: 2.5, param6: "First", param7: "Second", param8: "Third" }); + assert.deepEqual(exports.makeComplexResultInfo(), { tag: ComplexResult.Tag.Info }); + + const urSuccess = { tag: globalThis.Utilities.Result.Tag.Success, param0: "Utility operation completed" }; + const urFailure = { tag: globalThis.Utilities.Result.Tag.Failure, param0: "Utility error occurred", param1: 500 }; + const urStatus = { tag: globalThis.Utilities.Result.Tag.Status, param0: true, param1: 200, param2: "Utility status OK" }; + + assert.deepEqual(exports.roundtripUtilitiesResult(urSuccess), urSuccess); + assert.deepEqual(exports.roundtripUtilitiesResult(urFailure), urFailure); + assert.deepEqual(exports.roundtripUtilitiesResult(urStatus), urStatus); + + assert.deepEqual(exports.makeUtilitiesResultSuccess("Test"), { tag: globalThis.Utilities.Result.Tag.Success, param0: "Test" }); + assert.deepEqual(exports.makeUtilitiesResultSuccess("ok"), { tag: globalThis.Utilities.Result.Tag.Success, param0: "ok" }); + assert.deepEqual(exports.makeUtilitiesResultFailure("Error", 123), { tag: globalThis.Utilities.Result.Tag.Failure, param0: "Error", param1: 123 }); + assert.deepEqual(exports.makeUtilitiesResultStatus(true, 200, "OK"), { tag: globalThis.Utilities.Result.Tag.Status, param0: true, param1: 200, param2: "OK" }); + + const nrSuccess = { tag: globalThis.API.NetworkingResult.Tag.Success, param0: "Network request successful" }; + const nrFailure = { tag: globalThis.API.NetworkingResult.Tag.Failure, param0: "Network timeout", param1: 408 }; + + assert.deepEqual(exports.roundtripAPINetworkingResult(nrSuccess), nrSuccess); + assert.deepEqual(exports.roundtripAPINetworkingResult(nrFailure), nrFailure); + + assert.deepEqual(exports.makeAPINetworkingResultSuccess("Connected"), { tag: globalThis.API.NetworkingResult.Tag.Success, param0: "Connected" }); + assert.deepEqual(exports.makeAPINetworkingResultFailure("Timeout", 408), { tag: globalThis.API.NetworkingResult.Tag.Failure, param0: "Timeout", param1: 408 }); } /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */ @@ -487,4 +561,4 @@ function setupTestGlobals(global) { sym: Symbol("s"), bi: BigInt(3) }; -} +} \ No newline at end of file