diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index 02c623918..a6a73b8f7 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -936,12 +936,7 @@ extension BridgeType { let wasmType = rawType.wasmCoreType ?? .i32 return LoweringParameterInfo(loweredParameters: [("value", wasmType)]) case .associatedValueEnum: - switch context { - case .importTS: - throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .exportSwift: - return LoweringParameterInfo(loweredParameters: [("caseId", .i32)]) - } + return LoweringParameterInfo(loweredParameters: [("caseId", .i32)]) case .swiftStruct: switch context { case .importTS: @@ -1011,12 +1006,7 @@ extension BridgeType { let wasmType = rawType.wasmCoreType ?? .i32 return LiftingReturnInfo(valueToLift: wasmType) case .associatedValueEnum: - switch context { - case .importTS: - throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") - case .exportSwift: - return LiftingReturnInfo(valueToLift: .i32) - } + return LiftingReturnInfo(valueToLift: .i32) case .swiftStruct: switch context { case .importTS: diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index aed01da5a..ac2144bbc 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -1422,27 +1422,19 @@ struct IntrinsicJSFragment: Sendable { return try .optionalLiftParameter(wrappedType: wrappedType, kind: kind, context: context) case .rawValueEnum(_, .string): return .stringLiftParameter case .associatedValueEnum(let fullName): - switch context { - case .importTS: - throw BridgeJSLinkError( - message: - "Associated value enums are not supported to be passed as parameters to imported JS functions: \(fullName)" - ) - case .exportSwift: - let base = fullName.components(separatedBy: ".").last ?? fullName - return IntrinsicJSFragment( - parameters: ["caseId"], - printCode: { arguments, context in - let (scope, printer) = (context.scope, context.printer) - let caseId = arguments[0] - let resultVar = scope.variable("enumValue") - printer.write( - "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId));" - ) - return [resultVar] - } - ) - } + let base = fullName.components(separatedBy: ".").last ?? fullName + return IntrinsicJSFragment( + parameters: ["caseId"], + printCode: { arguments, context in + let (scope, printer) = (context.scope, context.printer) + let caseId = arguments[0] + let resultVar = scope.variable("enumValue") + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId));" + ) + return [resultVar] + } + ) case .swiftStruct(let fullName): switch context { case .importTS: @@ -1502,15 +1494,7 @@ struct IntrinsicJSFragment: Sendable { return try .optionalLowerReturn(wrappedType: wrappedType, kind: kind) case .rawValueEnum(_, .string): return .stringLowerReturn case .associatedValueEnum(let fullName): - switch context { - case .importTS: - throw BridgeJSLinkError( - message: - "Associated value enums are not supported to be returned from imported JS functions: \(fullName)" - ) - case .exportSwift: - return associatedValueLowerReturn(fullName: fullName) - } + return associatedValueLowerReturn(fullName: fullName) case .swiftStruct(let fullName): switch context { case .importTS: diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index f1e2e80fe..830132481 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -1611,10 +1611,10 @@ extension BridgeType { /// Whether a value of this type can be passed to a generated `Promise_resolve_` /// settlement helper, i.e. lowered through the imported-parameter ABI. Every `async` /// exported return settles through `_bjs_makePromise`; the few types that cannot be lowered - /// (associated-value enums, protocols, namespace enums, and their compositions) are diagnosed. + /// (protocols, namespace enums, and their compositions) are diagnosed. public var isAsyncResolvable: Bool { switch self { - case .associatedValueEnum, .swiftProtocol, .namespaceEnum: + case .swiftProtocol, .namespaceEnum: return false case .nullable(let wrapped, _): return wrapped.isAsyncResolvable diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift index 82747f74e..ae12b6566 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift @@ -309,15 +309,14 @@ import Testing @Test func asyncReturnOfUnsupportedTypeIsDiagnosed() throws { - // An associated-value enum can be neither lowered through the imported-parameter ABI - // nor settled via `_bjs_makePromise`, so an async return of one must be diagnosed. + // Protocol existentials still can't be lowered through the imported-parameter ABI, so + // an async return of one must still be diagnosed. let source = """ - @JS enum Payload { - case text(String) - case number(Int) + @JS protocol PayloadDelegate { + func notify() } - @JS func loadPayload() async -> Payload { - .number(1) + @JS func loadPayload() async -> PayloadDelegate { + fatalError() } """ let swiftAPI = SwiftToSkeleton( diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/AsyncAssociatedValueEnum.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/AsyncAssociatedValueEnum.swift new file mode 100644 index 000000000..662e01fce --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/AsyncAssociatedValueEnum.swift @@ -0,0 +1,13 @@ +@JS enum AsyncPayloadResult { + case success(String) + case failure(Int) + case idle +} + +@JS func asyncRoundTripAssociatedValueEnum(_ value: AsyncPayloadResult) async -> AsyncPayloadResult { + return value +} + +@JS func asyncRoundTripOptionalAssociatedValueEnum(_ value: AsyncPayloadResult?) async -> AsyncPayloadResult? { + return value +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValueImport.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValueImport.swift new file mode 100644 index 000000000..aa404b72c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValueImport.swift @@ -0,0 +1,14 @@ +@JS enum PayloadSignal { + case start(String) + case stop(Int) + case idle +} + +// Associated-value enums bridge as their `Int32` case ID plus stack payload in imported +// function parameters and return values. +@JSClass struct PayloadSignalControls { + @JSFunction func send(_ signal: PayloadSignal) throws(JSException) + @JSFunction func current() throws(JSException) -> PayloadSignal + @JSFunction static func roundTrip(_ signal: PayloadSignal) throws(JSException) -> PayloadSignal + @JSFunction func roundTripOptional(_ signal: PayloadSignal?) throws(JSException) -> PayloadSignal? +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.json new file mode 100644 index 000000000..6b0d70453 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.json @@ -0,0 +1,129 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "AsyncPayloadResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AsyncPayloadResult", + "tsFullPath" : "AsyncPayloadResult" + } + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_asyncRoundTripAssociatedValueEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripAssociatedValueEnum", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalAssociatedValueEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripOptionalAssociatedValueEnum", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.swift new file mode 100644 index 000000000..7ceb8cfe3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncAssociatedValueEnum.swift @@ -0,0 +1,116 @@ +extension AsyncPayloadResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AsyncPayloadResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown AsyncPayloadResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .idle: + return Int32(2) + } + } +} + +@_expose(wasm, "bjs_asyncRoundTripAssociatedValueEnum") +@_cdecl("bjs_asyncRoundTripAssociatedValueEnum") +public func _bjs_asyncRoundTripAssociatedValueEnum(_ value: Int32) -> Int32 { + #if arch(wasm32) + let _tmp_value = AsyncPayloadResult.bridgeJSLiftParameter(value) + return _bjs_makePromise(resolve: Promise_resolve_18AsyncPayloadResultO, reject: Promise_reject) { + return await asyncRoundTripAssociatedValueEnum(_: _tmp_value) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripOptionalAssociatedValueEnum") +@_cdecl("bjs_asyncRoundTripOptionalAssociatedValueEnum") +public func _bjs_asyncRoundTripOptionalAssociatedValueEnum(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 { + #if arch(wasm32) + let _tmp_value = Optional.bridgeJSLiftParameter(valueIsSome, valueCaseId) + return _bjs_makePromise(resolve: Promise_resolve_Sq18AsyncPayloadResultO, reject: Promise_reject) { + return await asyncRoundTripOptionalAssociatedValueEnum(_: _tmp_value) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@JSFunction func Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_reject_TestModule") +fileprivate func promise_reject_TestModule_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void +#else +fileprivate func promise_reject_TestModule_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_reject_TestModule(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void { + return promise_reject_TestModule_extern(promise, valueKind, valuePayload1, valuePayload2) +} + +func _$Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueKind, valuePayload1, valuePayload2) = value.bridgeJSLowerParameter() + promise_reject_TestModule(promiseValue, valueKind, valuePayload1, valuePayload2) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_18AsyncPayloadResultO") +fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_TestModule_18AsyncPayloadResultO_extern(promise, value) +} + +func _$Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueCaseId = value.bridgeJSLowerParameter() + promise_resolve_TestModule_18AsyncPayloadResultO(promiseValue, valueCaseId) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sq18AsyncPayloadResultO") +fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void +#else +fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + return promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(promise, valueIsSome, valueCaseId) +} + +func _$Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueIsSome, valueCaseId) = value.bridgeJSLowerParameter() + promise_resolve_TestModule_Sq18AsyncPayloadResultO(promiseValue, valueIsSome, valueCaseId) + if let error = _swift_js_take_exception() { throw error } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.json new file mode 100644 index 000000000..23cb1b0f0 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.json @@ -0,0 +1,194 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "start" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "stop" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "PayloadSignal", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "PayloadSignal", + "tsFullPath" : "PayloadSignal" + } + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + + ] + }, + "imported" : { + "children" : [ + { + "functions" : [ + + ], + "types" : [ + { + "accessLevel" : "internal", + "getters" : [ + + ], + "methods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "send", + "parameters" : [ + { + "name" : "signal", + "type" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "current", + "parameters" : [ + + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "roundTripOptional", + "parameters" : [ + { + "name" : "signal", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "PayloadSignalControls", + "setters" : [ + + ], + "staticMethods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "roundTrip", + "parameters" : [ + { + "name" : "signal", + "type" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "PayloadSignal" + } + } + } + ] + } + ] + } + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.swift new file mode 100644 index 000000000..5e1db5c72 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumAssociatedValueImport.swift @@ -0,0 +1,112 @@ +extension PayloadSignal: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> PayloadSignal { + switch caseId { + case 0: + return .start(String.bridgeJSStackPop()) + case 1: + return .stop(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown PayloadSignal case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .start(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .stop(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .idle: + return Int32(2) + } + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PayloadSignalControls_roundTrip_static") +fileprivate func bjs_PayloadSignalControls_roundTrip_static_extern(_ signal: Int32) -> Int32 +#else +fileprivate func bjs_PayloadSignalControls_roundTrip_static_extern(_ signal: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_PayloadSignalControls_roundTrip_static(_ signal: Int32) -> Int32 { + return bjs_PayloadSignalControls_roundTrip_static_extern(signal) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PayloadSignalControls_send") +fileprivate func bjs_PayloadSignalControls_send_extern(_ self: Int32, _ signal: Int32) -> Void +#else +fileprivate func bjs_PayloadSignalControls_send_extern(_ self: Int32, _ signal: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_PayloadSignalControls_send(_ self: Int32, _ signal: Int32) -> Void { + return bjs_PayloadSignalControls_send_extern(self, signal) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PayloadSignalControls_current") +fileprivate func bjs_PayloadSignalControls_current_extern(_ self: Int32) -> Int32 +#else +fileprivate func bjs_PayloadSignalControls_current_extern(_ self: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_PayloadSignalControls_current(_ self: Int32) -> Int32 { + return bjs_PayloadSignalControls_current_extern(self) +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_PayloadSignalControls_roundTripOptional") +fileprivate func bjs_PayloadSignalControls_roundTripOptional_extern(_ self: Int32, _ signalIsSome: Int32, _ signalCaseId: Int32) -> Int32 +#else +fileprivate func bjs_PayloadSignalControls_roundTripOptional_extern(_ self: Int32, _ signalIsSome: Int32, _ signalCaseId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_PayloadSignalControls_roundTripOptional(_ self: Int32, _ signalIsSome: Int32, _ signalCaseId: Int32) -> Int32 { + return bjs_PayloadSignalControls_roundTripOptional_extern(self, signalIsSome, signalCaseId) +} + +func _$PayloadSignalControls_roundTrip(_ signal: PayloadSignal) throws(JSException) -> PayloadSignal { + let signalCaseId = signal.bridgeJSLowerParameter() + let ret = bjs_PayloadSignalControls_roundTrip_static(signalCaseId) + if let error = _swift_js_take_exception() { + throw error + } + return PayloadSignal.bridgeJSLiftReturn(ret) +} + +func _$PayloadSignalControls_send(_ self: JSObject, _ signal: PayloadSignal) throws(JSException) -> Void { + let selfValue = self.bridgeJSLowerParameter() + let signalCaseId = signal.bridgeJSLowerParameter() + bjs_PayloadSignalControls_send(selfValue, signalCaseId) + if let error = _swift_js_take_exception() { + throw error + } +} + +func _$PayloadSignalControls_current(_ self: JSObject) throws(JSException) -> PayloadSignal { + let selfValue = self.bridgeJSLowerParameter() + let ret = bjs_PayloadSignalControls_current(selfValue) + if let error = _swift_js_take_exception() { + throw error + } + return PayloadSignal.bridgeJSLiftReturn(ret) +} + +func _$PayloadSignalControls_roundTripOptional(_ self: JSObject, _ signal: Optional) throws(JSException) -> Optional { + let selfValue = self.bridgeJSLowerParameter() + let (signalIsSome, signalCaseId) = signal.bridgeJSLowerParameter() + let ret = bjs_PayloadSignalControls_roundTripOptional(selfValue, signalIsSome, signalCaseId) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.d.ts new file mode 100644 index 000000000..d25336ef7 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.d.ts @@ -0,0 +1,33 @@ +// 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 AsyncPayloadResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Idle: 2; + }; +}; + +export type AsyncPayloadResultTag = + { tag: typeof AsyncPayloadResultValues.Tag.Success; param0: string } | { tag: typeof AsyncPayloadResultValues.Tag.Failure; param0: number } | { tag: typeof AsyncPayloadResultValues.Tag.Idle } + +export type AsyncPayloadResultObject = typeof AsyncPayloadResultValues; + +export type Exports = { + asyncRoundTripAssociatedValueEnum(value: AsyncPayloadResultTag): Promise; + asyncRoundTripOptionalAssociatedValueEnum(value: AsyncPayloadResultTag | null): Promise; + AsyncPayloadResult: AsyncPayloadResultObject +} +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/AsyncAssociatedValueEnum.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js new file mode 100644 index 000000000..69e4a4928 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js @@ -0,0 +1,414 @@ +// 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 AsyncPayloadResultValues = { + Tag: { + Success: 0, + Failure: 1, + Idle: 2, + }, +}; +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + let decodeString; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let strStack = []; + let i32Stack = []; + let i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + function __bjs_jsValueLower(value) { + let kind; + let payload1; + let payload2; + if (value === null) { + kind = 4; + payload1 = 0; + payload2 = 0; + } else { + switch (typeof value) { + case "boolean": + kind = 0; + payload1 = value ? 1 : 0; + payload2 = 0; + break; + case "number": + kind = 2; + payload1 = 0; + payload2 = value; + break; + case "string": + kind = 1; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + case "undefined": + kind = 5; + payload1 = 0; + payload2 = 0; + break; + case "object": + kind = 3; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + case "function": + kind = 3; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + case "symbol": + kind = 7; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + case "bigint": + kind = 8; + payload1 = swift.memory.retain(value); + payload2 = 0; + break; + default: + throw new TypeError("Unsupported JSValue type"); + } + } + return [kind, payload1, payload2]; + } + function __bjs_jsValueLift(kind, payload1, payload2) { + let jsValue; + switch (kind) { + case 0: + jsValue = payload1 !== 0; + break; + case 1: + jsValue = swift.memory.getObject(payload1); + break; + case 2: + jsValue = payload2; + break; + case 3: + jsValue = swift.memory.getObject(payload1); + break; + case 4: + jsValue = null; + break; + case 5: + jsValue = undefined; + break; + case 7: + jsValue = swift.memory.getObject(payload1); + break; + case 8: + jsValue = swift.memory.getObject(payload1); + break; + default: + throw new TypeError("Unsupported JSValue kind " + kind); + } + return jsValue; + } + + const __bjs_createAsyncPayloadResultValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case AsyncPayloadResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return AsyncPayloadResultValues.Tag.Success; + } + case AsyncPayloadResultValues.Tag.Failure: { + i32Stack.push((value.param0 | 0)); + return AsyncPayloadResultValues.Tag.Failure; + } + case AsyncPayloadResultValues.Tag.Idle: { + return AsyncPayloadResultValues.Tag.Idle; + } + default: throw new Error("Unknown AsyncPayloadResultValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case AsyncPayloadResultValues.Tag.Success: { + const string = strStack.pop(); + return { tag: AsyncPayloadResultValues.Tag.Success, param0: string }; + } + case AsyncPayloadResultValues.Tag.Failure: { + const int = i32Stack.pop(); + return { tag: AsyncPayloadResultValues.Tag.Failure, param0: int }; + } + case AsyncPayloadResultValues.Tag.Idle: return { tag: AsyncPayloadResultValues.Tag.Idle }; + default: throw new Error("Unknown AsyncPayloadResultValues tag returned from Swift: " + String(tag)); + } + } + }); + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + tmpRetString = decodeString(ptr, len); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + swift.memory.release(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + return swift.memory.retain(decodeString(ptr, len)); + } + 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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const value = decodeString(ptr, len); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + bjs["promise_resolve_TestModule_18AsyncPayloadResultO"] = function(promise, value) { + try { + const enumValue = enumHelpers.AsyncPayloadResult.lift(value); + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(enumValue); + } catch (error) { + setException(error); + } + } + bjs["promise_resolve_TestModule_Sq18AsyncPayloadResultO"] = function(promise, valueIsSome, valueCaseId) { + try { + let optResult; + if (valueIsSome) { + const enumValue = enumHelpers.AsyncPayloadResult.lift(valueCaseId); + optResult = enumValue; + } else { + optResult = null; + } + swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(optResult); + } catch (error) { + setException(error); + } + } + bjs["promise_reject_TestModule"] = function(promise, valueKind, valuePayload1, valuePayload2) { + try { + const jsValue = __bjs_jsValueLift(valueKind, valuePayload1, valuePayload2); + swift.memory.getObject(promise)[__bjs_promiseSettlers].reject(jsValue); + } catch (error) { + setException(error); + } + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = decodeString(ptr, len); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const AsyncPayloadResultHelpers = __bjs_createAsyncPayloadResultValuesHelpers(); + enumHelpers.AsyncPayloadResult = AsyncPayloadResultHelpers; + + const exports = { + asyncRoundTripAssociatedValueEnum: function bjs_asyncRoundTripAssociatedValueEnum(value) { + const valueCaseId = enumHelpers.AsyncPayloadResult.lower(value); + const ret = instance.exports.bjs_asyncRoundTripAssociatedValueEnum(valueCaseId); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + asyncRoundTripOptionalAssociatedValueEnum: function bjs_asyncRoundTripOptionalAssociatedValueEnum(value) { + const isSome = value != null; + let result; + if (isSome) { + const valueCaseId = enumHelpers.AsyncPayloadResult.lower(value); + result = valueCaseId; + } else { + result = 0; + } + const ret = instance.exports.bjs_asyncRoundTripOptionalAssociatedValueEnum(+isSome, result); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + }, + AsyncPayloadResult: AsyncPayloadResultValues, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.d.ts new file mode 100644 index 000000000..d29256af4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.d.ts @@ -0,0 +1,39 @@ +// 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 PayloadSignalValues: { + readonly Tag: { + readonly Start: 0; + readonly Stop: 1; + readonly Idle: 2; + }; +}; + +export type PayloadSignalTag = + { tag: typeof PayloadSignalValues.Tag.Start; param0: string } | { tag: typeof PayloadSignalValues.Tag.Stop; param0: number } | { tag: typeof PayloadSignalValues.Tag.Idle } + +export type PayloadSignalObject = typeof PayloadSignalValues; + +export interface PayloadSignalControls { + send(signal: PayloadSignalTag): void; + current(): PayloadSignalTag; + roundTripOptional(signal: PayloadSignalTag | null): PayloadSignalTag | null; +} +export type Exports = { + PayloadSignal: PayloadSignalObject +} +export type Imports = { + PayloadSignalControls: { + roundTrip(signal: PayloadSignalTag): PayloadSignalTag; + } +} +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/EnumAssociatedValueImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js new file mode 100644 index 000000000..1688dc94d --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js @@ -0,0 +1,323 @@ +// 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 PayloadSignalValues = { + Tag: { + Start: 0, + Stop: 1, + Idle: 2, + }, +}; +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + let decodeString; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let strStack = []; + let i32Stack = []; + let i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createPayloadSignalValuesHelpers = () => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case PayloadSignalValues.Tag.Start: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + return PayloadSignalValues.Tag.Start; + } + case PayloadSignalValues.Tag.Stop: { + i32Stack.push((value.param0 | 0)); + return PayloadSignalValues.Tag.Stop; + } + case PayloadSignalValues.Tag.Idle: { + return PayloadSignalValues.Tag.Idle; + } + default: throw new Error("Unknown PayloadSignalValues tag: " + String(enumTag)); + } + }, + lift: (tag) => { + tag = tag | 0; + switch (tag) { + case PayloadSignalValues.Tag.Start: { + const string = strStack.pop(); + return { tag: PayloadSignalValues.Tag.Start, param0: string }; + } + case PayloadSignalValues.Tag.Stop: { + const int = i32Stack.pop(); + return { tag: PayloadSignalValues.Tag.Stop, param0: int }; + } + case PayloadSignalValues.Tag.Idle: return { tag: PayloadSignalValues.Tag.Idle }; + default: throw new Error("Unknown PayloadSignalValues tag returned from Swift: " + String(tag)); + } + } + }); + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + tmpRetString = decodeString(ptr, len); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + swift.memory.release(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + return swift.memory.retain(decodeString(ptr, len)); + } + 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_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const value = decodeString(ptr, len); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = decodeString(ptr, len); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; + TestModule["bjs_PayloadSignalControls_roundTrip_static"] = function bjs_PayloadSignalControls_roundTrip_static(signal) { + try { + const enumValue = enumHelpers.PayloadSignal.lift(signal); + let ret = imports.PayloadSignalControls.roundTrip(enumValue); + const caseId = enumHelpers.PayloadSignal.lower(ret); + return caseId; + } catch (error) { + setException(error); + } + } + TestModule["bjs_PayloadSignalControls_send"] = function bjs_PayloadSignalControls_send(self, signal) { + try { + const enumValue = enumHelpers.PayloadSignal.lift(signal); + swift.memory.getObject(self).send(enumValue); + } catch (error) { + setException(error); + } + } + TestModule["bjs_PayloadSignalControls_current"] = function bjs_PayloadSignalControls_current(self) { + try { + let ret = swift.memory.getObject(self).current(); + const caseId = enumHelpers.PayloadSignal.lower(ret); + return caseId; + } catch (error) { + setException(error); + } + } + TestModule["bjs_PayloadSignalControls_roundTripOptional"] = function bjs_PayloadSignalControls_roundTripOptional(self, signalIsSome, signalCaseId) { + try { + let optResult; + if (signalIsSome) { + const enumValue = enumHelpers.PayloadSignal.lift(signalCaseId); + optResult = enumValue; + } else { + optResult = null; + } + let ret = swift.memory.getObject(self).roundTripOptional(optResult); + const isSome = ret != null; + if (isSome) { + const caseId = enumHelpers.PayloadSignal.lower(ret); + return caseId; + } else { + return -1; + } + } catch (error) { + setException(error); + } + } + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const PayloadSignalHelpers = __bjs_createPayloadSignalValuesHelpers(); + enumHelpers.PayloadSignal = PayloadSignalHelpers; + + const exports = { + PayloadSignal: PayloadSignalValues, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/AsyncImportTests.swift b/Tests/BridgeJSRuntimeTests/AsyncImportTests.swift index 041f251f4..a092d111c 100644 --- a/Tests/BridgeJSRuntimeTests/AsyncImportTests.swift +++ b/Tests/BridgeJSRuntimeTests/AsyncImportTests.swift @@ -1,6 +1,12 @@ import Testing import JavaScriptKit +@JS enum AsyncImportedPayloadResult: Equatable { + case success(String) + case failure(Int) + case idle +} + @JSClass struct AsyncImportImports { @JSFunction static func jsAsyncRoundTripVoid() async throws(JSException) @JSFunction static func jsAsyncRoundTripNumber(_ v: Double) async throws(JSException) -> Double @@ -12,6 +18,12 @@ import JavaScriptKit @JSFunction static func jsAsyncRoundTripIntArray(_ values: [Double]) async throws(JSException) -> [Double] @JSFunction static func jsAsyncRoundTripStringArray(_ values: [String]) async throws(JSException) -> [String] @JSFunction static func jsAsyncRoundTripFeatureFlag(_ v: FeatureFlag) async throws(JSException) -> FeatureFlag + @JSFunction static func jsAsyncRoundTripAssociatedValueEnum( + _ v: AsyncImportedPayloadResult + ) async throws(JSException) -> AsyncImportedPayloadResult + @JSFunction static func jsAsyncRoundTripOptionalAssociatedValueEnum( + _ v: AsyncImportedPayloadResult? + ) async throws(JSException) -> AsyncImportedPayloadResult? } @Suite struct AsyncImportTests { @@ -69,6 +81,29 @@ import JavaScriptKit try #expect(await AsyncImportImports.jsAsyncRoundTripFeatureFlag(v) == v) } + @Test func asyncRoundTripAssociatedValueEnum() async throws { + let values: [AsyncImportedPayloadResult] = [ + .success("ok"), + .failure(7), + .idle, + ] + for value in values { + try #expect(await AsyncImportImports.jsAsyncRoundTripAssociatedValueEnum(value) == value) + } + } + + @Test func asyncRoundTripOptionalAssociatedValueEnum() async throws { + let values: [AsyncImportedPayloadResult?] = [ + .some(.success("ok")), + .some(.failure(7)), + .some(.idle), + nil, + ] + for value in values { + try #expect(await AsyncImportImports.jsAsyncRoundTripOptionalAssociatedValueEnum(value) == value) + } + } + // MARK: - Structured return type @Test func fetchWeatherData() async throws { diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 79a931930..f64b78510 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -330,6 +330,16 @@ extension StaticCalculator { @JS func asyncRoundTripOptionalFileSize(_ v: FileSize?) async -> FileSize? { v } +@JS enum AsyncPayloadResult: Equatable { + case success(String) + case failure(Int) + case idle +} + +@JS func asyncRoundTripAssociatedValueEnum(_ v: AsyncPayloadResult) async -> AsyncPayloadResult { v } + +@JS func asyncRoundTripOptionalAssociatedValueEnum(_ v: AsyncPayloadResult?) async -> AsyncPayloadResult? { v } + @JS func setHttpStatus(_ status: HttpStatus) -> HttpStatus { return status } diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 497fa3355..b11f32b9d 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -1924,6 +1924,67 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11 #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(_ callback: Int32, _ param0: Int32) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(_ callback: Int32, _ param0: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y(_ callback: Int32, _ param0: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(callback, param0) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y { + static func bridgeJSLift(_ callbackId: Int32) -> (sending AsyncImportedPayloadResult) -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let param0CaseId = param0.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y(callbackValue, param0CaseId) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (sending AsyncImportedPayloadResult) -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (sending AsyncImportedPayloadResult) -> Void) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss26AsyncImportedPayloadResultO_y(_ boxPtr: UnsafeMutableRawPointer, _ param0: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(sending AsyncImportedPayloadResult) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(AsyncImportedPayloadResult.bridgeJSLiftParameter(param0)) + #else + fatalError("Only available on WebAssembly") + #endif +} + #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss7JSValueV_y") fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss7JSValueV_y_extern(_ callback: Int32, _ param0Kind: Int32, _ param0Payload1: Int32, _ param0Payload2: Float64) -> Void @@ -2352,6 +2413,67 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSd #endif } +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y") +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void +#else +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y(_ callback: Int32, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(callback, param0IsSome, param0CaseId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y") +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 +#else +fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y(_ boxPtr: UnsafeMutableRawPointer, _ file: UnsafePointer, _ line: UInt32) -> Int32 { + return make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y_extern(boxPtr, file, line) +} + +private enum _BJS_Closure_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y { + static func bridgeJSLift(_ callbackId: Int32) -> (sending Optional) -> Void { + let callback = JSObject.bridgeJSLiftParameter(callbackId) + return { [callback] param0 in + #if arch(wasm32) + let callbackValue = callback.bridgeJSLowerParameter() + let (param0IsSome, param0CaseId) = param0.bridgeJSLowerParameter() + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y(callbackValue, param0IsSome, param0CaseId) + #else + fatalError("Only available on WebAssembly") + #endif + } + } +} + +extension JSTypedClosure where Signature == (sending Optional) -> Void { + init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping (sending Optional) -> Void) { + self.init( + makeClosure: make_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y, + body: body, + fileID: fileID, + line: line + ) + } +} + +@_expose(wasm, "invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y") +@_cdecl("invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y") +public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq26AsyncImportedPayloadResultO_y(_ boxPtr: UnsafeMutableRawPointer, _ param0IsSome: Int32, _ param0CaseId: Int32) -> Void { + #if arch(wasm32) + let closure = Unmanaged<_BridgeJSTypedClosureBox<(sending Optional) -> Void>>.fromOpaque(boxPtr).takeUnretainedValue().closure + closure(Optional.bridgeJSLiftParameter(param0IsSome, param0CaseId)) + #else + fatalError("Only available on WebAssembly") + #endif +} + #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y") fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void @@ -3816,6 +3938,34 @@ public func _bjs_ArraySupportExports_static_multiOptionalArraySecond() -> Void { #endif } +extension AsyncImportedPayloadResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AsyncImportedPayloadResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown AsyncImportedPayloadResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .idle: + return Int32(2) + } + } +} + @_expose(wasm, "bjs_DefaultArgumentExports_static_testStringDefault") @_cdecl("bjs_DefaultArgumentExports_static_testStringDefault") public func _bjs_DefaultArgumentExports_static_testStringDefault(_ messageBytes: Int32, _ messageLength: Int32) -> Void { @@ -4127,6 +4277,34 @@ extension TSDirection: _BridgedSwiftCaseEnum { extension TSTheme: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { } +extension AsyncPayloadResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AsyncPayloadResult { + switch caseId { + case 0: + return .success(String.bridgeJSStackPop()) + case 1: + return .failure(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown AsyncPayloadResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .success(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .failure(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .idle: + return Int32(2) + } + } +} + @_expose(wasm, "bjs_Utils_StringUtils_static_uppercase") @_cdecl("bjs_Utils_StringUtils_static_uppercase") public func _bjs_Utils_StringUtils_static_uppercase(_ textBytes: Int32, _ textLength: Int32) -> Void { @@ -4870,6 +5048,34 @@ extension LightColor: _BridgedSwiftCaseEnum { } } +extension ImportedPayloadSignal: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> ImportedPayloadSignal { + switch caseId { + case 0: + return .start(String.bridgeJSStackPop()) + case 1: + return .stop(Int.bridgeJSStackPop()) + case 2: + return .idle + default: + fatalError("Unknown ImportedPayloadSignal case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 { + switch self { + case .start(let param0): + param0.bridgeJSStackPush() + return Int32(0) + case .stop(let param0): + param0.bridgeJSStackPush() + return Int32(1) + case .idle: + return Int32(2) + } + } +} + @_expose(wasm, "bjs_IntegerTypesSupportExports_static_roundTripInt") @_cdecl("bjs_IntegerTypesSupportExports_static_roundTripInt") public func _bjs_IntegerTypesSupportExports_static_roundTripInt(_ v: Int32) -> Int32 { @@ -7529,6 +7735,32 @@ public func _bjs_asyncRoundTripOptionalFileSize(_ vIsSome: Int32, _ vValue: Int6 #endif } +@_expose(wasm, "bjs_asyncRoundTripAssociatedValueEnum") +@_cdecl("bjs_asyncRoundTripAssociatedValueEnum") +public func _bjs_asyncRoundTripAssociatedValueEnum(_ v: Int32) -> Int32 { + #if arch(wasm32) + let _tmp_v = AsyncPayloadResult.bridgeJSLiftParameter(v) + return _bjs_makePromise(resolve: Promise_resolve_18AsyncPayloadResultO, reject: Promise_reject) { + return await asyncRoundTripAssociatedValueEnum(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_asyncRoundTripOptionalAssociatedValueEnum") +@_cdecl("bjs_asyncRoundTripOptionalAssociatedValueEnum") +public func _bjs_asyncRoundTripOptionalAssociatedValueEnum(_ vIsSome: Int32, _ vCaseId: Int32) -> Int32 { + #if arch(wasm32) + let _tmp_v = Optional.bridgeJSLiftParameter(vIsSome, vCaseId) + return _bjs_makePromise(resolve: Promise_resolve_Sq18AsyncPayloadResultO, reject: Promise_reject) { + return await asyncRoundTripOptionalAssociatedValueEnum(_: _tmp_v) + } + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setHttpStatus") @_cdecl("bjs_setHttpStatus") public func _bjs_setHttpStatus(_ status: Int32) -> Int32 { @@ -11783,6 +12015,48 @@ func _$Promise_resolve_Sq8FileSizeO(_ promise: JSObject, _ value: Optional Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO(_ promise: Int32, _ value: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO_extern(promise, value) +} + +func _$Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let valueCaseId = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_18AsyncPayloadResultO(promiseValue, valueCaseId) + if let error = _swift_js_take_exception() { throw error } +} + +@JSFunction func Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional) throws(JSException) + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO") +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void +#else +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO_extern(promise, valueIsSome, valueCaseId) +} + +func _$Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { + let promiseValue = promise.bridgeJSLowerParameter() + let (valueIsSome, valueCaseId) = value.bridgeJSLowerParameter() + promise_resolve_BridgeJSRuntimeTests_Sq18AsyncPayloadResultO(promiseValue, valueIsSome, valueCaseId) + if let error = _swift_js_take_exception() { throw error } +} + @JSFunction func Promise_resolve_11PublicPointV(_ promise: JSObject, _ value: PublicPoint) throws(JSException) #if arch(wasm32) @@ -12407,6 +12681,30 @@ fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_exter return bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_extern(resolveRef, rejectRef, vBytes, vLength) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static") +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ v: Int32) -> Void +#else +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ v: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static(_ resolveRef: Int32, _ rejectRef: Int32, _ v: Int32) -> Void { + return bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static_extern(resolveRef, rejectRef, v) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static") +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vCaseId: Int32) -> Void +#else +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vCaseId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vCaseId: Int32) -> Void { + return bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static_extern(resolveRef, rejectRef, vIsSome, vCaseId) +} + func _$AsyncImportImports_jsAsyncRoundTripVoid() async throws(JSException) -> Void { try await _bjs_awaitPromise(makeResolveClosure: { JSTypedClosure<() -> Void>($0) @@ -12528,6 +12826,30 @@ func _$AsyncImportImports_jsAsyncRoundTripFeatureFlag(_ v: FeatureFlag) async th return resolved } +func _$AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum(_ v: AsyncImportedPayloadResult) async throws(JSException) -> AsyncImportedPayloadResult { + let resolved = try await _bjs_awaitPromise(makeResolveClosure: { + JSTypedClosure<(sending AsyncImportedPayloadResult) -> Void>($0) + }, makeRejectClosure: { + JSTypedClosure<(sending JSValue) -> Void>($0) + }) { resolveRef, rejectRef in + let vCaseId = v.bridgeJSLowerParameter() + bjs_AsyncImportImports_jsAsyncRoundTripAssociatedValueEnum_static(resolveRef, rejectRef, vCaseId) + } + return resolved +} + +func _$AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum(_ v: Optional) async throws(JSException) -> Optional { + let resolved = try await _bjs_awaitPromise(makeResolveClosure: { + JSTypedClosure<(sending Optional) -> Void>($0) + }, makeRejectClosure: { + JSTypedClosure<(sending JSValue) -> Void>($0) + }) { resolveRef, rejectRef in + let (vIsSome, vCaseId) = v.bridgeJSLowerParameter() + bjs_AsyncImportImports_jsAsyncRoundTripOptionalAssociatedValueEnum_static(resolveRef, rejectRef, vIsSome, vCaseId) + } + return resolved +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyVoid_static") fileprivate func bjs_ClosureSupportImports_jsApplyVoid_static_extern(_ callback: Int32) -> Void @@ -14065,6 +14387,48 @@ func _$jsRoundTripLightColor(_ value: LightColor) throws(JSException) -> LightCo return LightColor.bridgeJSLiftReturn(ret) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripImportedPayloadSignal") +fileprivate func bjs_jsRoundTripImportedPayloadSignal_extern(_ value: Int32) -> Int32 +#else +fileprivate func bjs_jsRoundTripImportedPayloadSignal_extern(_ value: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_jsRoundTripImportedPayloadSignal(_ value: Int32) -> Int32 { + return bjs_jsRoundTripImportedPayloadSignal_extern(value) +} + +func _$jsRoundTripImportedPayloadSignal(_ value: ImportedPayloadSignal) throws(JSException) -> ImportedPayloadSignal { + let valueCaseId = value.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripImportedPayloadSignal(valueCaseId) + if let error = _swift_js_take_exception() { + throw error + } + return ImportedPayloadSignal.bridgeJSLiftReturn(ret) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripOptionalImportedPayloadSignal") +fileprivate func bjs_jsRoundTripOptionalImportedPayloadSignal_extern(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 +#else +fileprivate func bjs_jsRoundTripOptionalImportedPayloadSignal_extern(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_jsRoundTripOptionalImportedPayloadSignal(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 { + return bjs_jsRoundTripOptionalImportedPayloadSignal_extern(valueIsSome, valueCaseId) +} + +func _$jsRoundTripOptionalImportedPayloadSignal(_ value: Optional) throws(JSException) -> Optional { + let (valueIsSome, valueCaseId) = value.bridgeJSLowerParameter() + let ret = bjs_jsRoundTripOptionalImportedPayloadSignal(valueIsSome, valueCaseId) + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturn(ret) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsTranslatePoint") fileprivate func bjs_jsTranslatePoint_extern(_ point: Int32, _ dx: Int32, _ dy: Int32) -> Int32 diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index d77883980..477198bee 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -6550,6 +6550,53 @@ "swiftCallName" : "ArraySupportExports", "tsFullPath" : "ArraySupportExports" }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "AsyncImportedPayloadResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AsyncImportedPayloadResult", + "tsFullPath" : "AsyncImportedPayloadResult" + }, { "cases" : [ @@ -7715,6 +7762,53 @@ "swiftCallName" : "TSTheme", "tsFullPath" : "TSTheme" }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "AsyncPayloadResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "AsyncPayloadResult", + "tsFullPath" : "AsyncPayloadResult" + }, { "cases" : [ @@ -9326,6 +9420,53 @@ "swiftCallName" : "LightColor", "tsFullPath" : "LightColor" }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "start" + }, + { + "associatedValues" : [ + { + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "stop" + }, + { + "associatedValues" : [ + + ], + "name" : "idle" + } + ], + "emitStyle" : "const", + "name" : "ImportedPayloadSignal", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "ImportedPayloadSignal", + "tsFullPath" : "ImportedPayloadSignal" + }, { "cases" : [ @@ -12967,6 +13108,66 @@ } } }, + { + "abiName" : "bjs_asyncRoundTripAssociatedValueEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripAssociatedValueEnum", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + } + }, + { + "abiName" : "bjs_asyncRoundTripOptionalAssociatedValueEnum", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : false + }, + "name" : "asyncRoundTripOptionalAssociatedValueEnum", + "parameters" : [ + { + "label" : "_", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncPayloadResult" + } + }, + "_1" : "null" + } + } + }, { "abiName" : "bjs_setHttpStatus", "effects" : { @@ -18425,6 +18626,64 @@ "_1" : "String" } } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsAsyncRoundTripAssociatedValueEnum", + "parameters" : [ + { + "name" : "v", + "type" : { + "associatedValueEnum" : { + "_0" : "AsyncImportedPayloadResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "AsyncImportedPayloadResult" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : true, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsAsyncRoundTripOptionalAssociatedValueEnum", + "parameters" : [ + { + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncImportedPayloadResult" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "AsyncImportedPayloadResult" + } + }, + "_1" : "null" + } + } } ] } @@ -20389,6 +20648,64 @@ "_0" : "LightColor" } } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripImportedPayloadSignal", + "parameters" : [ + { + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "ImportedPayloadSignal" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "ImportedPayloadSignal" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsRoundTripOptionalImportedPayloadSignal", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ImportedPayloadSignal" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ImportedPayloadSignal" + } + }, + "_1" : "null" + } + } } ], "types" : [ diff --git a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift index 2bb9158b9..9cf77ed9d 100644 --- a/Tests/BridgeJSRuntimeTests/ImportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ImportAPITests.swift @@ -7,7 +7,19 @@ import JavaScriptKit case green } +@JS enum ImportedPayloadSignal: Equatable { + case start(String) + case stop(Int) + case idle +} + @JSFunction func jsRoundTripLightColor(_ value: LightColor) throws(JSException) -> LightColor +@JSFunction func jsRoundTripImportedPayloadSignal( + _ value: ImportedPayloadSignal +) throws(JSException) -> ImportedPayloadSignal +@JSFunction func jsRoundTripOptionalImportedPayloadSignal( + _ value: ImportedPayloadSignal? +) throws(JSException) -> ImportedPayloadSignal? class ImportAPITests: XCTestCase { func testRoundTripVoid() throws { @@ -80,6 +92,29 @@ class ImportAPITests: XCTestCase { } } + func testRoundTripAssociatedValueEnum() throws { + let values: [ImportedPayloadSignal] = [ + .start("go"), + .stop(42), + .idle, + ] + for value in values { + try XCTAssertEqual(jsRoundTripImportedPayloadSignal(value), value) + } + } + + func testRoundTripOptionalAssociatedValueEnum() throws { + let values: [ImportedPayloadSignal?] = [ + .some(.start("go")), + .some(.stop(42)), + .some(.idle), + nil, + ] + for value in values { + try XCTAssertEqual(jsRoundTripOptionalImportedPayloadSignal(value), value) + } + } + func ensureThrows(_ f: (Bool) throws(JSException) -> T) throws { do { _ = try f(true) diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/AsyncImportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/AsyncImportTests.mjs index eca2b209c..5d508fe07 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/AsyncImportTests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/AsyncImportTests.mjs @@ -1,7 +1,7 @@ // @ts-check import assert from 'node:assert'; -import { ThemeValues, DirectionValues, FileSizeValues } from '../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; +import { ThemeValues, DirectionValues, FileSizeValues, AsyncPayloadResultValues } from '../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; /** * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["AsyncImportImports"]} @@ -38,6 +38,12 @@ export function getImports(importsContext) { jsAsyncRoundTripFeatureFlag: (v) => { return Promise.resolve(v); }, + jsAsyncRoundTripAssociatedValueEnum: (v) => { + return Promise.resolve(v); + }, + jsAsyncRoundTripOptionalAssociatedValueEnum: (v) => { + return Promise.resolve(v); + }, }; } @@ -119,4 +125,15 @@ export async function runAsyncWorksTests(exports) { assert.equal(await exports.asyncRoundTripFileSize(FileSizeValues.Large), FileSizeValues.Large); assert.equal(await exports.asyncRoundTripOptionalFileSize(FileSizeValues.Tiny), FileSizeValues.Tiny); assert.equal(await exports.asyncRoundTripOptionalFileSize(null), null); + + const asyncPayloadSuccess = { tag: AsyncPayloadResultValues.Tag.Success, param0: "ok" }; + const asyncPayloadFailure = { tag: AsyncPayloadResultValues.Tag.Failure, param0: 7 }; + const asyncPayloadIdle = { tag: AsyncPayloadResultValues.Tag.Idle }; + assert.deepEqual(await exports.asyncRoundTripAssociatedValueEnum(asyncPayloadSuccess), asyncPayloadSuccess); + assert.deepEqual(await exports.asyncRoundTripAssociatedValueEnum(asyncPayloadFailure), asyncPayloadFailure); + assert.deepEqual(await exports.asyncRoundTripAssociatedValueEnum(asyncPayloadIdle), asyncPayloadIdle); + assert.deepEqual(await exports.asyncRoundTripOptionalAssociatedValueEnum(asyncPayloadSuccess), asyncPayloadSuccess); + assert.deepEqual(await exports.asyncRoundTripOptionalAssociatedValueEnum(asyncPayloadFailure), asyncPayloadFailure); + assert.deepEqual(await exports.asyncRoundTripOptionalAssociatedValueEnum(asyncPayloadIdle), asyncPayloadIdle); + assert.equal(await exports.asyncRoundTripOptionalAssociatedValueEnum(null), null); } diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 0f83da53c..bf3073c62 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -91,6 +91,12 @@ export async function setupOptions(options, context) { "jsRoundTripLightColor": (value) => { return value; }, + "jsRoundTripImportedPayloadSignal": (value) => { + return value; + }, + "jsRoundTripOptionalImportedPayloadSignal": (value) => { + return value; + }, "jsEchoJSValue": (v) => { return v; },