diff --git a/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift b/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift index 2d9f61b9..d02d0fae 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.ExportSwift.swift @@ -6,8 +6,8 @@ @_spi(BridgeJS) import JavaScriptKit -private extension APIResult { - static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) @@ -26,7 +26,7 @@ private extension APIResult { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -52,8 +52,8 @@ private extension APIResult { } } -private extension ComplexResult { - static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { +extension ComplexResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) @@ -74,7 +74,7 @@ private extension ComplexResult { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index a8a50acf..e44178a8 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -143,6 +143,14 @@ public class ExportSwift { ) } + private func diagnoseNestedOptional(node: some SyntaxProtocol, type: String) { + diagnose( + node: node, + message: "Nested optional types are not supported: \(type)", + hint: "Use a single optional like String? instead of String?? or Optional>" + ) + } + override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { switch state { case .topLevel: @@ -183,17 +191,32 @@ public class ExportSwift { var parameters: [Parameter] = [] for param in node.signature.parameterClause.parameters { - guard let type = self.parent.lookupType(for: param.type) else { + let resolvedType = self.parent.lookupType(for: param.type) + + if let type = resolvedType, case .optional(let wrappedType) = type, wrappedType.isOptional { + diagnoseNestedOptional(node: param.type, type: param.type.trimmedDescription) + continue + } + + guard let type = resolvedType else { diagnoseUnsupportedType(node: param.type, type: param.type.trimmedDescription) continue } + let name = param.secondName?.text ?? param.firstName.text let label = param.firstName.text parameters.append(Parameter(label: label, name: name, type: type)) } let returnType: BridgeType if let returnClause = node.signature.returnClause { - guard let type = self.parent.lookupType(for: returnClause.type) else { + let resolvedType = self.parent.lookupType(for: returnClause.type) + + if let type = resolvedType, case .optional(let wrappedType) = type, wrappedType.isOptional { + diagnoseNestedOptional(node: returnClause.type, type: returnClause.type.trimmedDescription) + return nil + } + + guard let type = resolvedType else { diagnoseUnsupportedType(node: returnClause.type, type: returnClause.type.trimmedDescription) return nil } @@ -538,12 +561,24 @@ public class ExportSwift { switch associatedValue.type { case .string, .int, .float, .double, .bool: break + case .optional(let wrappedType): + switch wrappedType { + case .string, .int, .float, .double, .bool: + break + default: + diagnose( + node: node, + message: "Unsupported associated value type: \(associatedValue.type.swiftType)", + hint: + "Only primitive types and optional primitives (String?, Int?, Float?, Double?, Bool?) are supported in associated-value enums" + ) + } 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" + "Only primitive types and optional primitives (String?, Int?, Float?, Double?, Bool?) are supported in associated-value enums" ) } } @@ -712,8 +747,46 @@ public class ExportSwift { } func lookupType(for type: TypeSyntax) -> BridgeType? { - if let primitive = BridgeType(swiftType: type.trimmedDescription) { - return primitive + // T? + if let optionalType = type.as(OptionalTypeSyntax.self) { + let wrappedType = optionalType.wrappedType + if let baseType = lookupType(for: wrappedType) { + return .optional(baseType) + } + } + // Optional + if let identifierType = type.as(IdentifierTypeSyntax.self), + identifierType.name.text == "Optional", + let genericArgs = identifierType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = genericArgs.first?.argument + { + if let baseType = lookupType(for: argType) { + return .optional(baseType) + } + } + // Swift.Optional + if let memberType = type.as(MemberTypeSyntax.self), + let baseType = memberType.baseType.as(IdentifierTypeSyntax.self), + baseType.name.text == "Swift", + memberType.name.text == "Optional", + let genericArgs = memberType.genericArgumentClause?.arguments, + genericArgs.count == 1, + let argType = genericArgs.first?.argument + { + if let wrappedType = lookupType(for: argType) { + return .optional(wrappedType) + } + } + if let aliasDecl = typeDeclResolver.resolveTypeAlias(type) { + if let resolvedType = lookupType(for: aliasDecl.initializer.value) { + return resolvedType + } + } + + let typeName = type.trimmedDescription + if let primitiveType = BridgeType(swiftType: typeName) { + return primitiveType } guard let typeDecl = typeDeclResolver.resolve(type) else { @@ -831,9 +904,18 @@ public class ExportSwift { } else { argumentsToLift = liftingInfo.parameters.map { (name, _) in param.name + name.capitalizedFirstLetter } } + + let typeNameForIntrinsic: String + switch param.type { + case .optional(let wrappedType): + typeNameForIntrinsic = "Optional<\(wrappedType.swiftType)>" + default: + typeNameForIntrinsic = param.type.swiftType + } + liftedParameterExprs.append( ExprSyntax( - "\(raw: param.type.swiftType).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" + "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) ) for (name, type) in zip(argumentsToLift, liftingInfo.parameters.map { $0.type }) { @@ -1013,7 +1095,7 @@ public class ExportSwift { let valueSwitch = (["switch self {"] + valueCases + ["}"]).joined(separator: "\n") return """ - extension \(raw: typeName) { + extension \(raw: typeName): _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -1041,15 +1123,15 @@ public class ExportSwift { func renderAssociatedValueEnumHelpers(_ enumDef: ExportedEnum) -> DeclSyntax { let typeName = enumDef.swiftCallName return """ - private extension \(raw: typeName) { - static func bridgeJSLiftParameter(_ caseId: Int32) -> \(raw: typeName) { + extension \(raw: typeName): _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public 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() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { \(raw: generateReturnSwitchCases(enumDef: enumDef).joined(separator: "\n")) } @@ -1085,6 +1167,26 @@ public class ExportSwift { return "\(paramName)Float.bridgeJSLiftParameter(_swift_js_pop_param_f32())" case .double: return "\(paramName)Double.bridgeJSLiftParameter(_swift_js_pop_param_f64())" + case .optional(let wrappedType): + switch wrappedType { + case .string: + return + "\(paramName)Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + case .int: + return + "\(paramName)Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + case .bool: + return + "\(paramName)Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())" + case .float: + return + "\(paramName)Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_f32())" + case .double: + return + "\(paramName)Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_f64())" + default: + return "" + } default: return "\(paramName)Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())" } @@ -1121,6 +1223,30 @@ public class ExportSwift { bodyLines.append("_swift_js_push_f32(\(paramName))") case .double: bodyLines.append("_swift_js_push_f64(\(paramName))") + case .optional(let wrappedType): + bodyLines.append("let __bjs_isSome_\(paramName) = \(paramName) != nil") + bodyLines.append("if let __bjs_unwrapped_\(paramName) = \(paramName) {") + switch wrappedType { + case .string: + bodyLines.append("var __bjs_str_\(paramName) = __bjs_unwrapped_\(paramName)") + bodyLines.append("__bjs_str_\(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(__bjs_unwrapped_\(paramName)))") + case .bool: + bodyLines.append("_swift_js_push_int(__bjs_unwrapped_\(paramName) ? 1 : 0)") + case .float: + bodyLines.append("_swift_js_push_f32(__bjs_unwrapped_\(paramName))") + case .double: + bodyLines.append("_swift_js_push_f64(__bjs_unwrapped_\(paramName))") + default: + bodyLines.append( + "preconditionFailure(\"BridgeJS: unsupported optional wrapped type in generated code\")" + ) + } + bodyLines.append("}") + bodyLines.append("_swift_js_push_int(__bjs_isSome_\(paramName) ? 1 : 0)") default: bodyLines.append( "preconditionFailure(\"BridgeJS: unsupported associated value type in generated code\")" @@ -1377,6 +1503,7 @@ extension BridgeType { case .jsObject(let name?): return name case .swiftHeapObject(let name): return name case .void: return "Void" + case .optional(let wrappedType): return "Optional<\(wrappedType.swiftType)>" case .caseEnum(let name): return name case .rawValueEnum(let name, _): return name case .associatedValueEnum(let name): return name @@ -1411,6 +1538,10 @@ extension BridgeType { case .jsObject: return .jsObject case .swiftHeapObject: return .swiftHeapObject case .void: return .void + case .optional(let wrappedType): + var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)] + optionalParams.append(contentsOf: try wrappedType.liftParameterInfo().parameters) + return LiftingIntrinsicInfo(parameters: optionalParams) case .caseEnum: return .caseEnum case .rawValueEnum(_, let rawType): switch rawType { @@ -1446,6 +1577,7 @@ extension BridgeType { static let caseEnum = LoweringIntrinsicInfo(returnType: .i32) static let rawValueEnum = LoweringIntrinsicInfo(returnType: .i32) static let associatedValueEnum = LoweringIntrinsicInfo(returnType: nil) + static let optional = LoweringIntrinsicInfo(returnType: nil) } func loweringReturnInfo() throws -> LoweringIntrinsicInfo { @@ -1458,6 +1590,7 @@ extension BridgeType { case .jsObject: return .jsObject case .swiftHeapObject: return .swiftHeapObject case .void: return .void + case .optional: return .optional case .caseEnum: return .caseEnum case .rawValueEnum(_, let rawType): switch rawType { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index 9fc8a62d..abacddd0 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -437,6 +437,8 @@ extension BridgeType { throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures") case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum: throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") + case .optional: + throw BridgeJSCoreError("Optional types are not yet supported in TypeScript imports") } } @@ -465,6 +467,8 @@ extension BridgeType { throw BridgeJSCoreError("swiftHeapObject is not supported in imported signatures") case .caseEnum, .rawValueEnum, .associatedValueEnum, .namespaceEnum: throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports") + case .optional: + throw BridgeJSCoreError("Optional types are not yet supported in TypeScript imports") } } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift index 25200e13..33e36a4a 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/TypeDeclResolver.swift @@ -8,6 +8,7 @@ class TypeDeclResolver { /// `Outer.Inner` type declaration is represented as ["Outer", "Inner"] typealias QualifiedName = [String] private var typeDeclByQualifiedName: [QualifiedName: TypeDecl] = [:] + private var typeAliasByQualifiedName: [QualifiedName: TypeAliasDeclSyntax] = [:] enum Error: Swift.Error { case typeNotFound(QualifiedName) @@ -62,6 +63,13 @@ class TypeDeclResolver { override func visitPost(_ node: EnumDeclSyntax) { visitPostNominalDecl() } + + override func visit(_ node: TypeAliasDeclSyntax) -> SyntaxVisitorContinueKind { + let name = node.name.text + let qualifiedName = scope.map(\.name.text) + [name] + resolver.typeAliasByQualifiedName[qualifiedName] = node + return .skipChildren + } } /// Collects type declarations from a parsed Swift source file @@ -132,6 +140,21 @@ class TypeDeclResolver { return nil } + /// Resolves a type usage node to a type alias declaration + /// + /// - Parameter type: The SwiftSyntax node representing a type appearance in source code. + /// - Returns: The type alias declaration if found, otherwise nil. + func resolveTypeAlias(_ type: TypeSyntax) -> TypeAliasDeclSyntax? { + if let id = type.as(IdentifierTypeSyntax.self) { + let qualifiedName = tryQualify(type: id) + return typeAliasByQualifiedName[qualifiedName] + } + if let components = qualifiedComponents(from: type) { + return typeAliasByQualifiedName[components] + } + return nil + } + private func qualifiedComponents(from type: TypeSyntax) -> QualifiedName? { if let m = type.as(MemberTypeSyntax.self) { guard let base = qualifiedComponents(from: TypeSyntax(m.baseType)) else { return nil } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 7de0ec53..9715014c 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -189,6 +189,11 @@ struct BridgeJSLink { "let \(JSGlueVariableScope.reservedStorageToReturnString);", "let \(JSGlueVariableScope.reservedStorageToReturnBytes);", "let \(JSGlueVariableScope.reservedStorageToReturnException);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);", + "let \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);", "let \(JSGlueVariableScope.reservedTmpRetTag);", "let \(JSGlueVariableScope.reservedTmpRetStrings) = [];", "let \(JSGlueVariableScope.reservedTmpRetInts) = [];", @@ -233,7 +238,6 @@ struct BridgeJSLink { ) } printer.write("}") - printer.write("bjs[\"swift_js_init_memory\"] = function(sourceId, bytesPtr) {") printer.indent { printer.write( @@ -245,7 +249,6 @@ struct BridgeJSLink { printer.write("bytes.set(source);") } printer.write("}") - printer.write("bjs[\"swift_js_make_js_string\"] = function(ptr, len) {") printer.indent { printer.write( @@ -256,7 +259,6 @@ struct BridgeJSLink { ) } printer.write("}") - printer.write("bjs[\"swift_js_init_memory_with_result\"] = function(ptr, len) {") printer.indent { printer.write( @@ -266,7 +268,6 @@ struct BridgeJSLink { printer.write("\(JSGlueVariableScope.reservedStorageToReturnBytes) = undefined;") } printer.write("}") - printer.write("bjs[\"swift_js_throw\"] = function(id) {") printer.indent { printer.write( @@ -274,7 +275,6 @@ struct BridgeJSLink { ) } printer.write("}") - printer.write("bjs[\"swift_js_retain\"] = function(id) {") printer.indent { printer.write( @@ -282,37 +282,31 @@ struct BridgeJSLink { ) } printer.write("}") - printer.write("bjs[\"swift_js_release\"] = function(id) {") printer.indent { printer.write("\(JSGlueVariableScope.reservedSwift).memory.release(id);") } printer.write("}") - printer.write("bjs[\"swift_js_push_tag\"] = function(tag) {") printer.indent { printer.write("\(JSGlueVariableScope.reservedTmpRetTag) = tag;") } printer.write("}") - printer.write("bjs[\"swift_js_push_int\"] = function(v) {") printer.indent { printer.write("\(JSGlueVariableScope.reservedTmpRetInts).push(v | 0);") } printer.write("}") - printer.write("bjs[\"swift_js_push_f32\"] = function(v) {") printer.indent { printer.write("\(JSGlueVariableScope.reservedTmpRetF32s).push(Math.fround(v));") } printer.write("}") - printer.write("bjs[\"swift_js_push_f64\"] = function(v) {") printer.indent { printer.write("\(JSGlueVariableScope.reservedTmpRetF64s).push(v);") } printer.write("}") - printer.write("bjs[\"swift_js_push_string\"] = function(ptr, len) {") printer.indent { printer.write( @@ -322,24 +316,119 @@ struct BridgeJSLink { printer.write("\(JSGlueVariableScope.reservedTmpRetStrings).push(value);") } printer.write("}") - printer.write("bjs[\"swift_js_pop_param_int32\"] = function() {") printer.indent { printer.write("return \(JSGlueVariableScope.reservedTmpParamInts).pop();") } printer.write("}") - printer.write("bjs[\"swift_js_pop_param_f32\"] = function() {") printer.indent { printer.write("return \(JSGlueVariableScope.reservedTmpParamF32s).pop();") } printer.write("}") - printer.write("bjs[\"swift_js_pop_param_f64\"] = function() {") printer.indent { printer.write("return \(JSGlueVariableScope.reservedTmpParamF64s).pop();") } printer.write("}") + printer.write("bjs[\"swift_js_return_optional_bool\"] = function(isSome, value) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = null;") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = value !== 0;") + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_int\"] = function(isSome, value) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = null;") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = value | 0;") + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_float\"] = function(isSome, value) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = null;") + } + printer.write("} else {") + printer.indent { + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = Math.fround(value);" + ) + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_double\"] = function(isSome, value) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = null;") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = value;") + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_string\"] = function(isSome, ptr, len) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = null;") + } + printer.write("} else {") + printer.indent { + printer.write(lines: [ + "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr, len);", + "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedTextDecoder).decode(bytes);", + ]) + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_object\"] = function(isSome, objectId) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = null;") + } + printer.write("} else {") + printer.indent { + printer.write( + "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedSwift).memory.getObject(objectId);" + ) + } + printer.write("}") + } + printer.write("}") + printer.write("bjs[\"swift_js_return_optional_heap_object\"] = function(isSome, pointer) {") + printer.indent { + printer.write("if (isSome === 0) {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = null;") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = pointer;") + } + printer.write("}") + } + printer.write("}") } } return printer @@ -1676,6 +1765,8 @@ extension BridgeType { return name ?? "any" case .swiftHeapObject(let name): return name + case .optional(let wrappedType): + return "\(wrappedType.tsType) | null" case .caseEnum(let name): return name case .rawValueEnum(let name, _): diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 36977aae..ad07774d 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -13,6 +13,11 @@ final class JSGlueVariableScope { static let reservedStorageToReturnString = "tmpRetString" static let reservedStorageToReturnBytes = "tmpRetBytes" static let reservedStorageToReturnException = "tmpRetException" + static let reservedStorageToReturnOptionalBool = "tmpRetOptionalBool" + static let reservedStorageToReturnOptionalInt = "tmpRetOptionalInt" + static let reservedStorageToReturnOptionalFloat = "tmpRetOptionalFloat" + static let reservedStorageToReturnOptionalDouble = "tmpRetOptionalDouble" + static let reservedStorageToReturnOptionalHeapObject = "tmpRetOptionalHeapObject" static let reservedTextEncoder = "textEncoder" static let reservedTextDecoder = "textDecoder" static let reservedTmpRetTag = "tmpRetTag" @@ -30,6 +35,11 @@ final class JSGlueVariableScope { reservedStorageToReturnString, reservedStorageToReturnBytes, reservedStorageToReturnException, + reservedStorageToReturnOptionalBool, + reservedStorageToReturnOptionalInt, + reservedStorageToReturnOptionalFloat, + reservedStorageToReturnOptionalDouble, + reservedStorageToReturnOptionalHeapObject, reservedTextEncoder, reservedTextDecoder, reservedTmpRetTag, @@ -239,6 +249,144 @@ struct IntrinsicJSFragment: Sendable { ) } + static func optionalLowerParameter(wrappedType: BridgeType) throws -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanupCode in + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(value) != null;") + + switch wrappedType { + case .string, .rawValueEnum(_, .string): + let bytesVar = scope.variable("\(value)Bytes") + let idVar = scope.variable("\(value)Id") + + printer.write("let \(idVar), \(bytesVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + printer.write("\(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));") + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") + } + printer.write("}") + cleanupCode.write("if (\(idVar) != undefined) {") + cleanupCode.indent { + cleanupCode.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));") + } + cleanupCode.write("}") + + return ["+\(isSomeVar)", "\(isSomeVar) ? \(idVar) : 0", "\(isSomeVar) ? \(bytesVar).length : 0"] + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let caseIdVar = scope.variable("\(value)CaseId") + let cleanupVar = scope.variable("\(value)Cleanup") + + printer.write("let \(caseIdVar), \(cleanupVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let resultVar = scope.variable("enumResult") + printer.write("const \(resultVar) = enumHelpers.\(base).lower(\(value));") + printer.write("\(caseIdVar) = \(resultVar).caseId;") + printer.write("\(cleanupVar) = \(resultVar).cleanup;") + } + printer.write("}") + cleanupCode.write("if (\(cleanupVar)) { \(cleanupVar)(); }") + + return ["+\(isSomeVar)", "\(isSomeVar) ? \(caseIdVar) : 0"] + default: + switch wrappedType { + case .swiftHeapObject: + return ["+\(isSomeVar)", "\(isSomeVar) ? \(value).pointer : 0"] + default: + return ["+\(isSomeVar)", "\(isSomeVar) ? \(value) : 0"] + } + } + } + ) + } + + static func optionalLiftReturn(wrappedType: BridgeType) -> IntrinsicJSFragment { + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanupCode in + let resultVar = scope.variable("optResult") + switch wrappedType { + case .bool: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = undefined;") + case .int: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") + case .float: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = undefined;") + case .double: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = undefined;") + case .string: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + case .swiftHeapObject(let className): + let pointerVar = scope.variable("pointer") + printer.write( + "const \(pointerVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);" + ) + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;") + printer.write( + "const \(resultVar) = \(pointerVar) === null ? null : \(className).__construct(\(pointerVar));" + ) + case .caseEnum: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") + case .rawValueEnum(_, let rawType): + switch rawType { + case .string: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + case .bool: + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalBool);" + ) + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalBool) = undefined;") + case .float: + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);" + ) + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalFloat) = undefined;") + case .double: + printer.write( + "const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);" + ) + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalDouble) = undefined;") + default: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnOptionalInt);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnOptionalInt) = undefined;") + } + case .associatedValueEnum(let fullName): + let base = fullName.components(separatedBy: ".").last ?? fullName + let isNullVar = scope.variable("isNull") + printer.write("const \(isNullVar) = (\(JSGlueVariableScope.reservedTmpRetTag) === -1);") + printer.write("let \(resultVar);") + printer.write("if (\(isNullVar)) {") + printer.indent { + printer.write("\(resultVar) = null;") + } + printer.write("} else {") + printer.indent { + printer.write( + "\(resultVar) = enumHelpers.\(base).raise(\(JSGlueVariableScope.reservedTmpRetTag), \(JSGlueVariableScope.reservedTmpRetStrings), \(JSGlueVariableScope.reservedTmpRetInts), \(JSGlueVariableScope.reservedTmpRetF32s), \(JSGlueVariableScope.reservedTmpRetF64s));" + ) + } + printer.write("}") + default: + printer.write("const \(resultVar) = \(JSGlueVariableScope.reservedStorageToReturnString);") + printer.write("\(JSGlueVariableScope.reservedStorageToReturnString) = undefined;") + } + return [resultVar] + } + ) + } + // MARK: - ExportSwift /// Returns a fragment that lowers a JS value to Wasm core values for parameters @@ -250,6 +398,8 @@ struct IntrinsicJSFragment: Sendable { case .swiftHeapObject: return .swiftHeapObjectLowerParameter case .void: return .void + case .optional(let wrappedType): + return try .optionalLowerParameter(wrappedType: wrappedType) case .caseEnum: return .identity case .rawValueEnum(_, let rawType): switch rawType { @@ -273,6 +423,7 @@ struct IntrinsicJSFragment: Sendable { case .jsObject: return .jsObjectLiftReturn case .swiftHeapObject(let name): return .swiftHeapObjectLiftReturn(name) case .void: return .void + case .optional(let wrappedType): return .optionalLiftReturn(wrappedType: wrappedType) case .caseEnum: return .identity case .rawValueEnum(_, let rawType): switch rawType { @@ -308,6 +459,10 @@ struct IntrinsicJSFragment: Sendable { throw BridgeJSLinkError( message: "Void can't appear in parameters of imported JS functions" ) + case .optional(let wrappedType): + throw BridgeJSLinkError( + message: "Optional types are not supported for imported JS functions: \(wrappedType)" + ) case .caseEnum: return .identity case .rawValueEnum(_, let rawType): switch rawType { @@ -340,6 +495,10 @@ struct IntrinsicJSFragment: Sendable { message: "Swift heap objects are not supported to be returned from imported JS functions" ) case .void: return .void + case .optional(let wrappedType): + throw BridgeJSLinkError( + message: "Optional types are not supported for imported JS functions: \(wrappedType)" + ) case .caseEnum: return .identity case .rawValueEnum(_, let rawType): switch rawType { @@ -630,6 +789,66 @@ struct IntrinsicJSFragment: Sendable { parameters: ["value"], printCode: { arguments, scope, printer, cleanup in printer.write("\(JSGlueVariableScope.reservedTmpParamF64s).push(\(arguments[0]));") + return [] + } + ) + case .optional(let wrappedType): + return IntrinsicJSFragment( + parameters: ["value"], + printCode: { arguments, scope, printer, cleanup in + let value = arguments[0] + let isSomeVar = scope.variable("isSome") + printer.write("const \(isSomeVar) = \(value) != null;") + + switch wrappedType { + case .string: + let idVar = scope.variable("id") + printer.write("let \(idVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let bytesVar = scope.variable("bytes") + printer.write( + "let \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" + ) + printer.write("\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(bytesVar).length);") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(idVar));") + } + printer.write("} else {") + printer.indent { + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(0);") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(0);") + } + printer.write("}") + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);") + cleanup.write("if(\(idVar)) {") + cleanup.indent { + cleanup.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));") + } + cleanup.write("}") + default: + switch wrappedType { + case .int: + printer.write( + "\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? (\(value) | 0) : 0);" + ) + case .bool: + printer.write( + "\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? (\(value) ? 1 : 0) : 0);" + ) + case .float: + printer.write( + "\(JSGlueVariableScope.reservedTmpParamF32s).push(\(isSomeVar) ? Math.fround(\(value)) : 0.0);" + ) + case .double: + printer.write( + "\(JSGlueVariableScope.reservedTmpParamF64s).push(\(isSomeVar) ? \(value) : 0.0);" + ) + default: () + } + printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);") + } + return [] } ) @@ -690,6 +909,34 @@ struct IntrinsicJSFragment: Sendable { return [dVar] } ) + case .optional(let wrappedType): + return IntrinsicJSFragment( + parameters: [], + printCode: { arguments, scope, printer, cleanup in + let optVar = scope.variable("optional") + let isSomeVar = scope.variable("isSome") + + printer.write("const \(isSomeVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();") + printer.write("let \(optVar);") + printer.write("if (\(isSomeVar)) {") + printer.indent { + let wrappedFragment = associatedValuePopPayload(type: wrappedType) + let wrappedResults = wrappedFragment.printCode([], scope, printer, cleanup) + if let wrappedResult = wrappedResults.first { + printer.write("\(optVar) = \(wrappedResult);") + } else { + printer.write("\(optVar) = undefined;") + } + } + printer.write("} else {") + printer.indent { + printer.write("\(optVar) = null;") + } + printer.write("}") + + return [optVar] + } + ) default: return IntrinsicJSFragment( parameters: [], diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index a0d4bd9f..32df40d1 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -4,6 +4,7 @@ public enum BridgeType: Codable, Equatable, Sendable { case int, float, double, string, bool, jsObject(String?), swiftHeapObject(String), void + indirect case optional(BridgeType) case caseEnum(String) case rawValueEnum(String, SwiftEnumRawType) case associatedValueEnum(String) @@ -336,6 +337,8 @@ extension BridgeType { case .swiftHeapObject: // UnsafeMutableRawPointer is returned as an i32 pointer return .pointer + case .optional(_): + return nil case .caseEnum: return .i32 case .rawValueEnum(_, let rawType): @@ -346,4 +349,10 @@ extension BridgeType { return nil } } + + /// Returns true if this type is optional + public var isOptional: Bool { + if case .optional = self { return true } + return false + } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumAssociatedValue.swift index 419800d6..e099ba85 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumAssociatedValue.swift @@ -13,6 +13,9 @@ enum APIResult { @JS func roundtripAPIResult(result: APIResult) -> APIResult { return result } +@JS func roundTripOptionalAPIResult(result: APIResult?) -> APIResult? { + return result +} @JS enum ComplexResult { @@ -29,6 +32,9 @@ enum ComplexResult { @JS func roundtripComplexResult(_ result: ComplexResult) -> ComplexResult { return result } +@JS func roundTripOptionalComplexResult(result: ComplexResult?) -> ComplexResult? { + return result +} @JS enum Utilities { @@ -39,8 +45,26 @@ enum Utilities { } } +@JS func roundTripOptionalUtilitiesResult(result: Utilities.Result?) -> Utilities.Result? { + return result +} + @JS(namespace: "API") @JS enum NetworkingResult { case success(String) case failure(String, Int) } + +@JS func roundTripOptionalNetworkingResult(result: NetworkingResult?) -> NetworkingResult? { + return result +} + +@JS +enum APIOptionalResult { + case success(String?) + case failure(Int?, Bool?) + case status(Bool?, Int?, String?) +} +@JS func roundTripOptionalAPIOptionalResult(result: APIOptionalResult?) -> APIOptionalResult? { + return result +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumCase.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumCase.swift index 15bdb9f4..c54ee6ae 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumCase.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumCase.swift @@ -14,6 +14,7 @@ @JS func setDirection(_ direction: Direction) @JS func getDirection() -> Direction @JS func processDirection(_ input: Direction) -> Status +@JS func roundTripOptionalDirection(_ input: Direction?) -> Direction? @JS(enumStyle: .tsEnum) enum TSDirection { case north @@ -24,6 +25,7 @@ @JS func setTSDirection(_ direction: TSDirection) @JS func getTSDirection() -> TSDirection +@JS func roundTripOptionalTSDirection(_ input: TSDirection?) -> TSDirection? @JS public enum PublicStatus { case success diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumRawType.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumRawType.swift index 799df164..7e2c17ac 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumRawType.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/EnumRawType.swift @@ -75,42 +75,51 @@ @JS func setTheme(_ theme: Theme) @JS func getTheme() -> Theme +@JS func roundTripOptionalTheme(_ input: Theme?) -> Theme? @JS func setTSTheme(_ theme: TSTheme) @JS func getTSTheme() -> TSTheme +@JS func roundTripOptionalTSTheme(_ input: TSTheme?) -> TSTheme? @JS func setFeatureFlag(_ flag: FeatureFlag) @JS func getFeatureFlag() -> FeatureFlag +@JS func roundTripOptionalFeatureFlag(_ input: FeatureFlag?) -> FeatureFlag? @JS func setHttpStatus(_ status: HttpStatus) @JS func getHttpStatus() -> HttpStatus +@JS func roundTripOptionalHttpStatus(_ input: HttpStatus?) -> HttpStatus? @JS func setTSHttpStatus(_ status: TSHttpStatus) @JS func getTSHttpStatus() -> TSHttpStatus +@JS func roundTripOptionalHttpStatus(_ input: TSHttpStatus?) -> TSHttpStatus? @JS func setPriority(_ priority: Priority) @JS func getPriority() -> Priority +@JS func roundTripOptionalPriority(_ input: Priority?) -> Priority? @JS func setFileSize(_ size: FileSize) @JS func getFileSize() -> FileSize +@JS func roundTripOptionalFileSize(_ input: FileSize?) -> FileSize? @JS func setUserId(_ id: UserId) @JS func getUserId() -> UserId +@JS func roundTripOptionalUserId(_ input: UserId?) -> UserId? @JS func setTokenId(_ token: TokenId) @JS func getTokenId() -> TokenId +@JS func roundTripOptionalTokenId(_ input: TokenId?) -> TokenId? @JS func setSessionId(_ session: SessionId) @JS func getSessionId() -> SessionId +@JS func roundTripOptionalSessionId(_ input: SessionId?) -> SessionId? @JS func setPrecision(_ precision: Precision) @JS func getPrecision() -> Precision +@JS func roundTripOptionalPrecision(_ input: Precision?) -> Precision? @JS func setRatio(_ ratio: Ratio) @JS func getRatio() -> Ratio - -@JS func setFeatureFlag(_ featureFlag: FeatureFlag) -@JS func getFeatureFlag() -> FeatureFlag +@JS func roundTripOptionalRatio(_ input: Ratio?) -> Ratio? @JS func processTheme(_ theme: Theme) -> HttpStatus @JS func convertPriority(_ status: HttpStatus) -> Priority diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Optionals.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Optionals.swift new file mode 100644 index 00000000..d256a875 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/Optionals.swift @@ -0,0 +1,92 @@ +@JS class Greeter { + @JS var name: String? + + @JS init(name: String?) { + self.name = name + } + + @JS func greet() -> String { + return "Hello, " + (self.name ?? "stranger") + "!" + } + + @JS func changeName(name: String?) { + self.name = name + } +} + +@JS +func roundTripOptionalClass(value: Greeter?) -> Greeter? { + return value +} + +@JS +class OptionalPropertyHolder { + @JS var optionalName: String? = nil + @JS var optionalAge: Int? = nil + @JS var optionalGreeter: Greeter? = nil + + @JS init() {} +} + +@JS func testOptionalPropertyRoundtrip(_ holder: OptionalPropertyHolder?) -> OptionalPropertyHolder? + +@JS +func roundTripString(name: String?) -> String? { + return name +} + +@JS +func roundTripInt(value: Int?) -> Int? { + return value +} + +@JS +func roundTripBool(flag: Bool?) -> Bool? { + return flag +} + +@JS +func roundTripFloat(number: Float?) -> Float? { + return number +} + +@JS +func roundTripDouble(precision: Double?) -> Double? { + return precision +} + +@JS func roundTripSyntax(name: Optional) -> Optional { + return name +} + +@JS func roundTripMixSyntax(name: String?) -> Optional { + return name +} + +@JS func roundTripSwiftSyntax(name: Swift.Optional) -> Swift.Optional { + return name +} + +@JS func roundTripMixedSwiftSyntax(name: String?) -> Swift.Optional { + return name +} + +@JS func roundTripWithSpaces(value: Optional) -> Optional { + return value +} + +typealias OptionalAge = Int? + +@JS func roundTripAlias(age: OptionalAge) -> OptionalAge { + return age +} + +typealias OptionalNameAlias = Optional +@JS func roundTripOptionalAlias(name: OptionalNameAlias) -> OptionalNameAlias { + return name +} + +@JS +func testMixedOptionals(firstName: String?, lastName: String?, age: Int?, active: Bool) -> String? { + return nil +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.swift index e6763d4c..c735c56f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringParameter.swift @@ -1 +1,2 @@ @JS func checkString(a: String) {} +@JS func roundtripString(a: String) -> String { return a } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js index 1534a0fb..7295699a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayParameter.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkArray"] = function bjs_checkArray(a) { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js index bdc30973..92f10f94 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js index d1d11903..74fb30c5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_asyncReturnVoid"] = function bjs_asyncReturnVoid() { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts index 18d8a763..4195e9a2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts @@ -32,6 +32,17 @@ export const ComplexResult: { 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 const APIOptionalResult: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + readonly Status: 2; + }; +}; + +export type APIOptionalResult = + { tag: typeof APIOptionalResult.Tag.Success; param0: string | null } | { tag: typeof APIOptionalResult.Tag.Failure; param0: number | null; param1: boolean | null } | { tag: typeof APIOptionalResult.Tag.Status; param0: boolean | null; param1: number | null; param2: string | null } + export {}; declare global { @@ -62,9 +73,14 @@ export type Exports = { handle(result: APIResult): void; getResult(): APIResult; roundtripAPIResult(result: APIResult): APIResult; + roundTripOptionalAPIResult(result: APIResult | null): APIResult | null; handleComplex(result: ComplexResult): void; getComplexResult(): ComplexResult; roundtripComplexResult(result: ComplexResult): ComplexResult; + roundTripOptionalComplexResult(result: ComplexResult | null): ComplexResult | null; + roundTripOptionalUtilitiesResult(result: Utilities.Result | null): Utilities.Result | null; + roundTripOptionalNetworkingResult(result: NetworkingResult | null): NetworkingResult | null; + roundTripOptionalAPIOptionalResult(result: APIOptionalResult | null): APIOptionalResult | null; } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js index 280f0c0a..f7ca2dd8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js @@ -342,6 +342,143 @@ const __bjs_createNetworkingResultHelpers = () => { } }); }; +export const APIOptionalResult = { + Tag: { + Success: 0, + Failure: 1, + Status: 2, + } +}; + +const __bjs_createAPIOptionalResultHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIOptionalResult.Tag.Success: { + const isSome = value.param0 != null; + let id; + if (isSome) { + let bytes = textEncoder.encode(value.param0); + id = swift.memory.retain(bytes); + tmpParamInts.push(bytes.length); + tmpParamInts.push(id); + } else { + tmpParamInts.push(0); + tmpParamInts.push(0); + } + tmpParamInts.push(isSome ? 1 : 0); + const cleanup = () => { + if(id) { + swift.memory.release(id); + } + }; + return { caseId: APIOptionalResult.Tag.Success, cleanup }; + } + case APIOptionalResult.Tag.Failure: { + const isSome = value.param1 != null; + tmpParamInts.push(isSome ? (value.param1 ? 1 : 0) : 0); + tmpParamInts.push(isSome ? 1 : 0); + const isSome1 = value.param0 != null; + tmpParamInts.push(isSome1 ? (value.param0 | 0) : 0); + tmpParamInts.push(isSome1 ? 1 : 0); + const cleanup = undefined; + return { caseId: APIOptionalResult.Tag.Failure, cleanup }; + } + case APIOptionalResult.Tag.Status: { + const isSome = value.param2 != null; + let id; + if (isSome) { + let bytes = textEncoder.encode(value.param2); + id = swift.memory.retain(bytes); + tmpParamInts.push(bytes.length); + tmpParamInts.push(id); + } else { + tmpParamInts.push(0); + tmpParamInts.push(0); + } + tmpParamInts.push(isSome ? 1 : 0); + const isSome1 = value.param1 != null; + tmpParamInts.push(isSome1 ? (value.param1 | 0) : 0); + tmpParamInts.push(isSome1 ? 1 : 0); + const isSome2 = value.param0 != null; + tmpParamInts.push(isSome2 ? (value.param0 ? 1 : 0) : 0); + tmpParamInts.push(isSome2 ? 1 : 0); + const cleanup = () => { + if(id) { + swift.memory.release(id); + } + }; + return { caseId: APIOptionalResult.Tag.Status, cleanup }; + } + default: throw new Error("Unknown APIOptionalResult tag: " + String(enumTag)); + } + }, + raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + const tag = tmpRetTag | 0; + switch (tag) { + case APIOptionalResult.Tag.Success: { + const isSome = tmpRetInts.pop(); + let optional; + if (isSome) { + const string = tmpRetStrings.pop(); + optional = string; + } else { + optional = null; + } + return { tag: APIOptionalResult.Tag.Success, param0: optional }; + } + case APIOptionalResult.Tag.Failure: { + const isSome = tmpRetInts.pop(); + let optional; + if (isSome) { + const bool = tmpRetInts.pop(); + optional = bool; + } else { + optional = null; + } + const isSome1 = tmpRetInts.pop(); + let optional1; + if (isSome1) { + const int = tmpRetInts.pop(); + optional1 = int; + } else { + optional1 = null; + } + return { tag: APIOptionalResult.Tag.Failure, param0: optional1, param1: optional }; + } + case APIOptionalResult.Tag.Status: { + const isSome = tmpRetInts.pop(); + let optional; + if (isSome) { + const string = tmpRetStrings.pop(); + optional = string; + } else { + optional = null; + } + const isSome1 = tmpRetInts.pop(); + let optional1; + if (isSome1) { + const int = tmpRetInts.pop(); + optional1 = int; + } else { + optional1 = null; + } + const isSome2 = tmpRetInts.pop(); + let optional2; + if (isSome2) { + const bool = tmpRetInts.pop(); + optional2 = bool; + } else { + optional2 = null; + } + return { tag: APIOptionalResult.Tag.Status, param0: optional2, param1: optional1, param2: optional }; + } + default: throw new Error("Unknown APIOptionalResult tag returned from Swift: " + String(tag)); + } + } + }); +}; if (typeof globalThis.Utilities === 'undefined') { globalThis.Utilities = {}; } @@ -361,6 +498,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -432,6 +574,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; @@ -449,6 +641,9 @@ export async function createInstantiator(options, swift) { const NetworkingResultHelpers = __bjs_createNetworkingResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); enumHelpers.NetworkingResult = NetworkingResultHelpers; + const APIOptionalResultHelpers = __bjs_createAPIOptionalResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + enumHelpers.APIOptionalResult = APIOptionalResultHelpers; + setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) } @@ -474,6 +669,25 @@ export async function createInstantiator(options, swift) { if (resultCleanup) { resultCleanup(); } return ret; }, + roundTripOptionalAPIResult: function bjs_roundTripOptionalAPIResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.APIResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalAPIResult(+isSome, isSome ? resultCaseId : 0); + const isNull = (tmpRetTag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.APIResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, handleComplex: function bjs_handleComplex(result) { const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.ComplexResult.lower(result); instance.exports.bjs_handleComplex(resultCaseId); @@ -491,6 +705,82 @@ export async function createInstantiator(options, swift) { if (resultCleanup) { resultCleanup(); } return ret; }, + roundTripOptionalComplexResult: function bjs_roundTripOptionalComplexResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.ComplexResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalComplexResult(+isSome, isSome ? resultCaseId : 0); + const isNull = (tmpRetTag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.ComplexResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + roundTripOptionalUtilitiesResult: function bjs_roundTripOptionalUtilitiesResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.Result.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalUtilitiesResult(+isSome, isSome ? resultCaseId : 0); + const isNull = (tmpRetTag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.Result.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + roundTripOptionalNetworkingResult: function bjs_roundTripOptionalNetworkingResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.NetworkingResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalNetworkingResult(+isSome, isSome ? resultCaseId : 0); + const isNull = (tmpRetTag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.NetworkingResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, + roundTripOptionalAPIOptionalResult: function bjs_roundTripOptionalAPIOptionalResult(result) { + const isSome = result != null; + let resultCaseId, resultCleanup; + if (isSome) { + const enumResult = enumHelpers.APIOptionalResult.lower(result); + resultCaseId = enumResult.caseId; + resultCleanup = enumResult.cleanup; + } + instance.exports.bjs_roundTripOptionalAPIOptionalResult(+isSome, isSome ? resultCaseId : 0); + const isNull = (tmpRetTag === -1); + let optResult; + if (isNull) { + optResult = null; + } else { + optResult = enumHelpers.APIOptionalResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + } + if (resultCleanup) { resultCleanup(); } + return optResult; + }, }; }, } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.d.ts index 1375cc36..9a04f59a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.d.ts @@ -35,8 +35,10 @@ export type Exports = { setDirection(direction: Direction): void; getDirection(): Direction; processDirection(input: Direction): Status; + roundTripOptionalDirection(input: Direction | null): Direction | null; setTSDirection(direction: TSDirection): void; getTSDirection(): TSDirection; + roundTripOptionalTSDirection(input: TSDirection | null): TSDirection | null; } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js index 80fb2399..5eb0b420 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js @@ -37,6 +37,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -107,6 +112,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; @@ -131,6 +186,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_processDirection(input); return ret; }, + roundTripOptionalDirection: function bjs_roundTripOptionalDirection(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalDirection(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, setTSDirection: function bjs_setTSDirection(direction) { instance.exports.bjs_setTSDirection(direction); }, @@ -138,6 +200,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getTSDirection(); return ret; }, + roundTripOptionalTSDirection: function bjs_roundTripOptionalTSDirection(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalTSDirection(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, }; }, } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js index c5b50719..0aff338b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js @@ -59,6 +59,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -129,6 +134,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts index 51b020ad..96297187 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts @@ -92,30 +92,40 @@ export type Ratio = typeof Ratio[keyof typeof Ratio]; export type Exports = { setTheme(theme: Theme): void; getTheme(): Theme; + roundTripOptionalTheme(input: Theme | null): Theme | null; setTSTheme(theme: TSTheme): void; getTSTheme(): TSTheme; + roundTripOptionalTSTheme(input: TSTheme | null): TSTheme | null; setFeatureFlag(flag: FeatureFlag): void; getFeatureFlag(): FeatureFlag; + roundTripOptionalFeatureFlag(input: FeatureFlag | null): FeatureFlag | null; setHttpStatus(status: HttpStatus): void; getHttpStatus(): HttpStatus; + roundTripOptionalHttpStatus(input: HttpStatus | null): HttpStatus | null; setTSHttpStatus(status: TSHttpStatus): void; getTSHttpStatus(): TSHttpStatus; + roundTripOptionalHttpStatus(input: TSHttpStatus | null): TSHttpStatus | null; setPriority(priority: Priority): void; getPriority(): Priority; + roundTripOptionalPriority(input: Priority | null): Priority | null; setFileSize(size: FileSize): void; getFileSize(): FileSize; + roundTripOptionalFileSize(input: FileSize | null): FileSize | null; setUserId(id: UserId): void; getUserId(): UserId; + roundTripOptionalUserId(input: UserId | null): UserId | null; setTokenId(token: TokenId): void; getTokenId(): TokenId; + roundTripOptionalTokenId(input: TokenId | null): TokenId | null; setSessionId(session: SessionId): void; getSessionId(): SessionId; + roundTripOptionalSessionId(input: SessionId | null): SessionId | null; setPrecision(precision: Precision): void; getPrecision(): Precision; + roundTripOptionalPrecision(input: Precision | null): Precision | null; setRatio(ratio: Ratio): void; getRatio(): Ratio; - setFeatureFlag(featureFlag: FeatureFlag): void; - getFeatureFlag(): FeatureFlag; + roundTripOptionalRatio(input: Ratio | null): Ratio | null; processTheme(theme: Theme): HttpStatus; convertPriority(status: HttpStatus): Priority; validateSession(session: SessionId): Theme; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js index 6aa897c3..fe1b4258 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js @@ -88,6 +88,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -158,6 +163,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; @@ -183,6 +238,21 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }, + roundTripOptionalTheme: function bjs_roundTripOptionalTheme(input) { + const isSome = input != null; + let inputId, inputBytes; + if (isSome) { + inputBytes = textEncoder.encode(input); + inputId = swift.memory.retain(inputBytes); + } + instance.exports.bjs_roundTripOptionalTheme(+isSome, isSome ? inputId : 0, isSome ? inputBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (inputId != undefined) { + swift.memory.release(inputId); + } + return optResult; + }, setTSTheme: function bjs_setTSTheme(theme) { const themeBytes = textEncoder.encode(theme); const themeId = swift.memory.retain(themeBytes); @@ -195,6 +265,21 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }, + roundTripOptionalTSTheme: function bjs_roundTripOptionalTSTheme(input) { + const isSome = input != null; + let inputId, inputBytes; + if (isSome) { + inputBytes = textEncoder.encode(input); + inputId = swift.memory.retain(inputBytes); + } + instance.exports.bjs_roundTripOptionalTSTheme(+isSome, isSome ? inputId : 0, isSome ? inputBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (inputId != undefined) { + swift.memory.release(inputId); + } + return optResult; + }, setFeatureFlag: function bjs_setFeatureFlag(flag) { instance.exports.bjs_setFeatureFlag(flag); }, @@ -202,6 +287,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getFeatureFlag(); return ret !== 0; }, + roundTripOptionalFeatureFlag: function bjs_roundTripOptionalFeatureFlag(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalFeatureFlag(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalBool; + tmpRetOptionalBool = undefined; + return optResult; + }, setHttpStatus: function bjs_setHttpStatus(status) { instance.exports.bjs_setHttpStatus(status); }, @@ -209,6 +301,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getHttpStatus(); return ret; }, + roundTripOptionalHttpStatus: function bjs_roundTripOptionalHttpStatus(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalHttpStatus(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, setTSHttpStatus: function bjs_setTSHttpStatus(status) { instance.exports.bjs_setTSHttpStatus(status); }, @@ -216,6 +315,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getTSHttpStatus(); return ret; }, + roundTripOptionalHttpStatus: function bjs_roundTripOptionalHttpStatus(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalHttpStatus(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, setPriority: function bjs_setPriority(priority) { instance.exports.bjs_setPriority(priority); }, @@ -223,6 +329,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getPriority(); return ret; }, + roundTripOptionalPriority: function bjs_roundTripOptionalPriority(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalPriority(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, setFileSize: function bjs_setFileSize(size) { instance.exports.bjs_setFileSize(size); }, @@ -230,6 +343,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getFileSize(); return ret; }, + roundTripOptionalFileSize: function bjs_roundTripOptionalFileSize(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalFileSize(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, setUserId: function bjs_setUserId(id) { instance.exports.bjs_setUserId(id); }, @@ -237,6 +357,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getUserId(); return ret; }, + roundTripOptionalUserId: function bjs_roundTripOptionalUserId(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalUserId(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, setTokenId: function bjs_setTokenId(token) { instance.exports.bjs_setTokenId(token); }, @@ -244,6 +371,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getTokenId(); return ret; }, + roundTripOptionalTokenId: function bjs_roundTripOptionalTokenId(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalTokenId(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, setSessionId: function bjs_setSessionId(session) { instance.exports.bjs_setSessionId(session); }, @@ -251,6 +385,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getSessionId(); return ret; }, + roundTripOptionalSessionId: function bjs_roundTripOptionalSessionId(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalSessionId(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, setPrecision: function bjs_setPrecision(precision) { instance.exports.bjs_setPrecision(precision); }, @@ -258,6 +399,13 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getPrecision(); return ret; }, + roundTripOptionalPrecision: function bjs_roundTripOptionalPrecision(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalPrecision(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return optResult; + }, setRatio: function bjs_setRatio(ratio) { instance.exports.bjs_setRatio(ratio); }, @@ -265,12 +413,12 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_getRatio(); return ret; }, - setFeatureFlag: function bjs_setFeatureFlag(featureFlag) { - instance.exports.bjs_setFeatureFlag(featureFlag); - }, - getFeatureFlag: function bjs_getFeatureFlag() { - const ret = instance.exports.bjs_getFeatureFlag(); - return ret !== 0; + roundTripOptionalRatio: function bjs_roundTripOptionalRatio(input) { + const isSome = input != null; + instance.exports.bjs_roundTripOptionalRatio(+isSome, isSome ? input : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return optResult; }, processTheme: function bjs_processTheme(theme) { const themeBytes = textEncoder.encode(theme); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js index a897ccee..cead874b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Interface.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_returnAnimatable"] = function bjs_returnAnimatable() { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js index 670a27d7..f469072f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_createArrayBuffer"] = function bjs_createArrayBuffer() { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js index 1e09d4e3..116933d7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MultipleImportedTypes.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_createDatabaseConnection"] = function bjs_createDatabaseConnection(config) { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js index 23fb7990..4631fb24 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.d.ts new file mode 100644 index 00000000..5f63e9db --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.d.ts @@ -0,0 +1,55 @@ +// 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`. + +/// Represents a Swift heap object like a class instance or an actor instance. +export interface SwiftHeapObject { + /// Release the heap object. + /// + /// Note: Calling this method will release the heap object and it will no longer be accessible. + release(): void; +} +export interface Greeter extends SwiftHeapObject { + greet(): string; + changeName(name: string | null): void; + name: string | null; +} +export interface OptionalPropertyHolder extends SwiftHeapObject { + optionalName: string | null; + optionalAge: number | null; + optionalGreeter: Greeter | null; +} +export type Exports = { + Greeter: { + new(name: string | null): Greeter; + } + OptionalPropertyHolder: { + new(): OptionalPropertyHolder; + } + roundTripOptionalClass(value: Greeter | null): Greeter | null; + testOptionalPropertyRoundtrip(holder: OptionalPropertyHolder | null): OptionalPropertyHolder | null; + roundTripString(name: string | null): string | null; + roundTripInt(value: number | null): number | null; + roundTripBool(flag: boolean | null): boolean | null; + roundTripFloat(number: number | null): number | null; + roundTripDouble(precision: number | null): number | null; + roundTripSyntax(name: string | null): string | null; + roundTripMixSyntax(name: string | null): string | null; + roundTripSwiftSyntax(name: string | null): string | null; + roundTripMixedSwiftSyntax(name: string | null): string | null; + roundTripWithSpaces(value: number | null): number | null; + roundTripAlias(age: number | null): number | null; + roundTripOptionalAlias(name: string | null): string | null; + testMixedOptionals(firstName: string | null, lastName: string | null, age: number | null, active: boolean): string | null; +} +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/Optionals.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.js new file mode 100644 index 00000000..f67a06e8 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.Export.js @@ -0,0 +1,467 @@ +// 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 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 tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + 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(); + } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { + const obj = Greeter.__construct(pointer); + return swift.memory.retain(obj); + }; + importObject["TestModule"]["bjs_OptionalPropertyHolder_wrap"] = function(pointer) { + const obj = OptionalPropertyHolder.__construct(pointer); + return swift.memory.retain(obj); + }; + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + /// Represents a Swift heap object like a class instance or an actor instance. + class SwiftHeapObject { + static __wrap(pointer, deinit, prototype) { + const obj = Object.create(prototype); + obj.pointer = pointer; + obj.hasReleased = false; + obj.deinit = deinit; + obj.registry = new FinalizationRegistry((pointer) => { + deinit(pointer); + }); + obj.registry.register(this, obj.pointer); + return obj; + } + + release() { + this.registry.unregister(this); + this.deinit(this.pointer); + } + } + class Greeter extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Greeter_deinit, Greeter.prototype); + } + + constructor(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + const ret = instance.exports.bjs_Greeter_init(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + if (nameId != undefined) { + swift.memory.release(nameId); + } + return Greeter.__construct(ret); + } + greet() { + instance.exports.bjs_Greeter_greet(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + changeName(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_Greeter_changeName(this.pointer, +isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + if (nameId != undefined) { + swift.memory.release(nameId); + } + } + get name() { + instance.exports.bjs_Greeter_name_get(this.pointer); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + set name(value) { + const isSome = value != null; + let valueId, valueBytes; + if (isSome) { + valueBytes = textEncoder.encode(value); + valueId = swift.memory.retain(valueBytes); + } + instance.exports.bjs_Greeter_name_set(this.pointer, +isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + if (valueId != undefined) { + swift.memory.release(valueId); + } + } + } + class OptionalPropertyHolder extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_OptionalPropertyHolder_deinit, OptionalPropertyHolder.prototype); + } + + constructor() { + const ret = instance.exports.bjs_OptionalPropertyHolder_init(); + return OptionalPropertyHolder.__construct(ret); + } + get optionalName() { + instance.exports.bjs_OptionalPropertyHolder_optionalName_get(this.pointer); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + set optionalName(value) { + const isSome = value != null; + let valueId, valueBytes; + if (isSome) { + valueBytes = textEncoder.encode(value); + valueId = swift.memory.retain(valueBytes); + } + instance.exports.bjs_OptionalPropertyHolder_optionalName_set(this.pointer, +isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + if (valueId != undefined) { + swift.memory.release(valueId); + } + } + get optionalAge() { + instance.exports.bjs_OptionalPropertyHolder_optionalAge_get(this.pointer); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + } + set optionalAge(value) { + const isSome = value != null; + instance.exports.bjs_OptionalPropertyHolder_optionalAge_set(this.pointer, +isSome, isSome ? value : 0); + } + get optionalGreeter() { + instance.exports.bjs_OptionalPropertyHolder_optionalGreeter_get(this.pointer); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : Greeter.__construct(pointer); + return optResult; + } + set optionalGreeter(value) { + const isSome = value != null; + instance.exports.bjs_OptionalPropertyHolder_optionalGreeter_set(this.pointer, +isSome, isSome ? value.pointer : 0); + } + } + return { + Greeter, + OptionalPropertyHolder, + roundTripOptionalClass: function bjs_roundTripOptionalClass(value) { + const isSome = value != null; + instance.exports.bjs_roundTripOptionalClass(+isSome, isSome ? value.pointer : 0); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : Greeter.__construct(pointer); + return optResult; + }, + testOptionalPropertyRoundtrip: function bjs_testOptionalPropertyRoundtrip(holder) { + const isSome = holder != null; + instance.exports.bjs_testOptionalPropertyRoundtrip(+isSome, isSome ? holder.pointer : 0); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : OptionalPropertyHolder.__construct(pointer); + return optResult; + }, + roundTripString: function bjs_roundTripString(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripString(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (nameId != undefined) { + swift.memory.release(nameId); + } + return optResult; + }, + roundTripInt: function bjs_roundTripInt(value) { + const isSome = value != null; + instance.exports.bjs_roundTripInt(+isSome, isSome ? value : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + roundTripBool: function bjs_roundTripBool(flag) { + const isSome = flag != null; + instance.exports.bjs_roundTripBool(+isSome, isSome ? flag : 0); + const optResult = tmpRetOptionalBool; + tmpRetOptionalBool = undefined; + return optResult; + }, + roundTripFloat: function bjs_roundTripFloat(number) { + const isSome = number != null; + instance.exports.bjs_roundTripFloat(+isSome, isSome ? number : 0); + const optResult = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return optResult; + }, + roundTripDouble: function bjs_roundTripDouble(precision) { + const isSome = precision != null; + instance.exports.bjs_roundTripDouble(+isSome, isSome ? precision : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return optResult; + }, + roundTripSyntax: function bjs_roundTripSyntax(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (nameId != undefined) { + swift.memory.release(nameId); + } + return optResult; + }, + roundTripMixSyntax: function bjs_roundTripMixSyntax(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripMixSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (nameId != undefined) { + swift.memory.release(nameId); + } + return optResult; + }, + roundTripSwiftSyntax: function bjs_roundTripSwiftSyntax(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripSwiftSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (nameId != undefined) { + swift.memory.release(nameId); + } + return optResult; + }, + roundTripMixedSwiftSyntax: function bjs_roundTripMixedSwiftSyntax(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripMixedSwiftSyntax(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (nameId != undefined) { + swift.memory.release(nameId); + } + return optResult; + }, + roundTripWithSpaces: function bjs_roundTripWithSpaces(value) { + const isSome = value != null; + instance.exports.bjs_roundTripWithSpaces(+isSome, isSome ? value : 0); + const optResult = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return optResult; + }, + roundTripAlias: function bjs_roundTripAlias(age) { + const isSome = age != null; + instance.exports.bjs_roundTripAlias(+isSome, isSome ? age : 0); + const optResult = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return optResult; + }, + roundTripOptionalAlias: function bjs_roundTripOptionalAlias(name) { + const isSome = name != null; + let nameId, nameBytes; + if (isSome) { + nameBytes = textEncoder.encode(name); + nameId = swift.memory.retain(nameBytes); + } + instance.exports.bjs_roundTripOptionalAlias(+isSome, isSome ? nameId : 0, isSome ? nameBytes.length : 0); + const optResult = tmpRetString; + tmpRetString = undefined; + if (nameId != undefined) { + swift.memory.release(nameId); + } + return optResult; + }, + testMixedOptionals: function bjs_testMixedOptionals(firstName, lastName, age, active) { + const isSome = firstName != null; + let firstNameId, firstNameBytes; + if (isSome) { + firstNameBytes = textEncoder.encode(firstName); + firstNameId = swift.memory.retain(firstNameBytes); + } + const isSome1 = lastName != null; + let lastNameId, lastNameBytes; + if (isSome1) { + lastNameBytes = textEncoder.encode(lastName); + lastNameId = swift.memory.retain(lastNameBytes); + } + const isSome2 = age != null; + instance.exports.bjs_testMixedOptionals(+isSome, isSome ? firstNameId : 0, isSome ? firstNameBytes.length : 0, +isSome1, isSome1 ? lastNameId : 0, isSome1 ? lastNameBytes.length : 0, +isSome2, isSome2 ? age : 0, active); + const optResult = tmpRetString; + tmpRetString = undefined; + if (firstNameId != undefined) { + swift.memory.release(firstNameId); + } + if (lastNameId != undefined) { + swift.memory.release(lastNameId); + } + return optResult; + }, + }; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js index 8aeb3f9b..eea05ba1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js index c6e9c0de..882e633e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_check"] = function bjs_check(a, b) { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js index 5bf2e0fd..7c20fa15 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js index 202fbb55..481cc495 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkNumber"] = function bjs_checkNumber() { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js index 281bed1d..bbfbb0ac 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.d.ts index a83fca6f..22943671 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.d.ts @@ -6,6 +6,7 @@ export type Exports = { checkString(a: string): void; + roundtripString(a: string): string; } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js index cadd112c..b7d4b505 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; @@ -102,6 +157,15 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_checkString(aId, aBytes.length); swift.memory.release(aId); }, + roundtripString: function bjs_roundtripString(a) { + const aBytes = textEncoder.encode(a); + const aId = swift.memory.retain(aBytes); + instance.exports.bjs_roundtripString(aId, aBytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + swift.memory.release(aId); + return ret; + }, }; }, } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js index bed39c8e..bc109fc9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkString"] = function bjs_checkString(a) { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js index 565cd605..08eef7e0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js index 546b20f8..11d30446 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkString"] = function bjs_checkString() { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js index 223c9e7b..0a545a0e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } // Wrapper functions for module: TestModule if (!importObject["TestModule"]) { importObject["TestModule"] = {}; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js index 9a568612..453d5f76 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TS2SkeletonLike.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_createTS2Skeleton"] = function bjs_createTS2Skeleton() { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js index e6512ca4..af17ab14 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js index 9c3b5508..9ba7cf60 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeAlias.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_checkSimple"] = function bjs_checkSimple(a) { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js index fccdccd1..98fb575d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/TypeScriptClass.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_Greeter_init"] = function bjs_Greeter_init(name) { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js index 89515b44..d2716dfa 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Export.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } }, setInstance: (i) => { instance = i; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js index 54f3267a..4b4c75ea 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.Import.js @@ -13,6 +13,11 @@ export async function createInstantiator(options, swift) { let tmpRetString; let tmpRetBytes; let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; let tmpRetTag; let tmpRetStrings = []; let tmpRetInts = []; @@ -83,6 +88,56 @@ export async function createInstantiator(options, swift) { bjs["swift_js_pop_param_f64"] = function() { return tmpParamF64s.pop(); } + 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 { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + 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; + } + } const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; TestModule["bjs_check"] = function bjs_check() { try { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json index 37f4b61f..1f2b15fe 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json @@ -347,6 +347,94 @@ "API" ], "swiftCallName" : "NetworkingResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "APIOptionalResult", + "swiftCallName" : "APIOptionalResult" } ], "functions" : [ @@ -414,6 +502,38 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalAPIResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAPIResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + } + }, { "abiName" : "bjs_handleComplex", "effects" : { @@ -477,6 +597,134 @@ "_0" : "ComplexResult" } } + }, + { + "abiName" : "bjs_roundTripOptionalComplexResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalComplexResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalUtilitiesResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalUtilitiesResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "Utilities.Result" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalNetworkingResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalNetworkingResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "NetworkingResult" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "NetworkingResult" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAPIOptionalResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAPIOptionalResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + } + } + } } ], "moduleName" : "TestModule" diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift index 410c569d..008eeda0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.swift @@ -6,8 +6,8 @@ @_spi(BridgeJS) import JavaScriptKit -private extension APIResult { - static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) @@ -26,7 +26,7 @@ private extension APIResult { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -52,8 +52,8 @@ private extension APIResult { } } -private extension ComplexResult { - static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { +extension ComplexResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) @@ -72,7 +72,7 @@ private extension ComplexResult { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -126,8 +126,8 @@ private extension ComplexResult { } } -private extension Utilities.Result { - static func bridgeJSLiftParameter(_ caseId: Int32) -> Utilities.Result { +extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public 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())) @@ -140,7 +140,7 @@ private extension Utilities.Result { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -167,8 +167,8 @@ private extension Utilities.Result { } } -private extension NetworkingResult { - static func bridgeJSLiftParameter(_ caseId: Int32) -> NetworkingResult { +extension NetworkingResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> NetworkingResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) @@ -179,7 +179,7 @@ private extension NetworkingResult { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -198,6 +198,68 @@ private extension NetworkingResult { } } +extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIOptionalResult { + switch caseId { + case 0: + return .success(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 2: + return .status(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + default: + fatalError("Unknown APIOptionalResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + var __bjs_str_param0 = __bjs_unwrapped_param0 + __bjs_str_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + } + _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + case .failure(let param0, let param1): + _swift_js_push_tag(Int32(1)) + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + _swift_js_push_int(Int32(__bjs_unwrapped_param0)) + } + _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + let __bjs_isSome_param1 = param1 != nil + if let __bjs_unwrapped_param1 = param1 { + _swift_js_push_int(__bjs_unwrapped_param1 ? 1 : 0) + } + _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + case .status(let param0, let param1, let param2): + _swift_js_push_tag(Int32(2)) + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + _swift_js_push_int(__bjs_unwrapped_param0 ? 1 : 0) + } + _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + let __bjs_isSome_param1 = param1 != nil + if let __bjs_unwrapped_param1 = param1 { + _swift_js_push_int(Int32(__bjs_unwrapped_param1)) + } + _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + let __bjs_isSome_param2 = param2 != nil + if let __bjs_unwrapped_param2 = param2 { + var __bjs_str_param2 = __bjs_unwrapped_param2 + __bjs_str_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + } + _swift_js_push_int(__bjs_isSome_param2 ? 1 : 0) + } + } +} + @_expose(wasm, "bjs_handle") @_cdecl("bjs_handle") public func _bjs_handle(result: Int32) -> Void { @@ -230,6 +292,17 @@ public func _bjs_roundtripAPIResult(result: Int32) -> Void { #endif } +@_expose(wasm, "bjs_roundTripOptionalAPIResult") +@_cdecl("bjs_roundTripOptionalAPIResult") +public func _bjs_roundTripOptionalAPIResult(resultIsSome: Int32, resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAPIResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_handleComplex") @_cdecl("bjs_handleComplex") public func _bjs_handleComplex(result: Int32) -> Void { @@ -260,4 +333,48 @@ public func _bjs_roundtripComplexResult(result: Int32) -> Void { #else fatalError("Only available on WebAssembly") #endif +} + +@_expose(wasm, "bjs_roundTripOptionalComplexResult") +@_cdecl("bjs_roundTripOptionalComplexResult") +public func _bjs_roundTripOptionalComplexResult(resultIsSome: Int32, resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalComplexResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalUtilitiesResult") +@_cdecl("bjs_roundTripOptionalUtilitiesResult") +public func _bjs_roundTripOptionalUtilitiesResult(resultIsSome: Int32, resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalUtilitiesResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalNetworkingResult") +@_cdecl("bjs_roundTripOptionalNetworkingResult") +public func _bjs_roundTripOptionalNetworkingResult(resultIsSome: Int32, resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalNetworkingResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAPIOptionalResult") +@_cdecl("bjs_roundTripOptionalAPIOptionalResult") +public func _bjs_roundTripOptionalAPIOptionalResult(resultIsSome: Int32, resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAPIOptionalResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + 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/EnumCase.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.json index b90bd40b..38b26020 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.json @@ -170,6 +170,38 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalDirection", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDirection", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + } + } + } + }, { "abiName" : "bjs_setTSDirection", "effects" : { @@ -209,6 +241,38 @@ "_0" : "TSDirection" } } + }, + { + "abiName" : "bjs_roundTripOptionalTSDirection", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTSDirection", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + } + } } ], "moduleName" : "TestModule" diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.swift index e222a2bb..4a1be41e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.swift @@ -6,7 +6,7 @@ @_spi(BridgeJS) import JavaScriptKit -extension Direction { +extension Direction: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -49,7 +49,7 @@ extension Direction { } } -extension Status { +extension Status: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -88,7 +88,7 @@ extension Status { } } -extension TSDirection { +extension TSDirection: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -131,7 +131,7 @@ extension TSDirection { } } -extension PublicStatus { +extension PublicStatus: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -194,6 +194,17 @@ public func _bjs_processDirection(input: Int32) -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalDirection") +@_cdecl("bjs_roundTripOptionalDirection") +public func _bjs_roundTripOptionalDirection(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalDirection(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setTSDirection") @_cdecl("bjs_setTSDirection") public func _bjs_setTSDirection(direction: Int32) -> Void { @@ -213,4 +224,15 @@ public func _bjs_getTSDirection() -> Int32 { #else fatalError("Only available on WebAssembly") #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTSDirection") +@_cdecl("bjs_roundTripOptionalTSDirection") +public func _bjs_roundTripOptionalTSDirection(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTSDirection(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + 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 23120ea7..daa5577a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.swift @@ -6,7 +6,7 @@ @_spi(BridgeJS) import JavaScriptKit -extension Networking.API.Method { +extension Networking.API.Method: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -55,7 +55,7 @@ extension Configuration.LogLevel: _BridgedSwiftEnumNoPayload { extension Configuration.Port: _BridgedSwiftEnumNoPayload { } -extension Internal.SupportedMethod { +extension Internal.SupportedMethod: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json index 09ce5d6e..c6f17c0a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json @@ -416,6 +416,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalTheme", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTheme", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + }, { "abiName" : "bjs_setTSTheme", "effects" : { @@ -458,6 +492,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalTSTheme", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTSTheme", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + } + } + }, { "abiName" : "bjs_setFeatureFlag", "effects" : { @@ -500,6 +568,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalFeatureFlag", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalFeatureFlag", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "Bool" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FeatureFlag", + "_1" : "Bool" + } + } + } + } + }, { "abiName" : "bjs_setHttpStatus", "effects" : { @@ -542,6 +644,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalHttpStatus", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + } + }, { "abiName" : "bjs_setTSHttpStatus", "effects" : { @@ -584,6 +720,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalHttpStatus", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalHttpStatus", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSHttpStatus", + "_1" : "Int" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSHttpStatus", + "_1" : "Int" + } + } + } + } + }, { "abiName" : "bjs_setPriority", "effects" : { @@ -626,6 +796,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalPriority", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalPriority", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int32" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Priority", + "_1" : "Int32" + } + } + } + } + }, { "abiName" : "bjs_setFileSize", "effects" : { @@ -668,6 +872,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalFileSize", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalFileSize", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" + } + } + } + } + }, { "abiName" : "bjs_setUserId", "effects" : { @@ -710,6 +948,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalUserId", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalUserId", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "UserId", + "_1" : "UInt" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "UserId", + "_1" : "UInt" + } + } + } + } + }, { "abiName" : "bjs_setTokenId", "effects" : { @@ -752,6 +1024,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalTokenId", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTokenId", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TokenId", + "_1" : "UInt32" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TokenId", + "_1" : "UInt32" + } + } + } + } + }, { "abiName" : "bjs_setSessionId", "effects" : { @@ -794,6 +1100,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalSessionId", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalSessionId", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" + } + } + } + } + }, { "abiName" : "bjs_setPrecision", "effects" : { @@ -836,6 +1176,40 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalPrecision", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalPrecision", + "parameters" : [ + { + "label" : "_", + "name" : "input", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Precision", + "_1" : "Float" + } + } + } + } + }, { "abiName" : "bjs_setRatio", "effects" : { @@ -879,44 +1253,36 @@ } }, { - "abiName" : "bjs_setFeatureFlag", + "abiName" : "bjs_roundTripOptionalRatio", "effects" : { "isAsync" : false, "isThrows" : false }, - "name" : "setFeatureFlag", + "name" : "roundTripOptionalRatio", "parameters" : [ { "label" : "_", - "name" : "featureFlag", + "name" : "input", "type" : { - "rawValueEnum" : { - "_0" : "FeatureFlag", - "_1" : "Bool" + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" + } + } } } } ], "returnType" : { - "void" : { - - } - } - }, - { - "abiName" : "bjs_getFeatureFlag", - "effects" : { - "isAsync" : false, - "isThrows" : false - }, - "name" : "getFeatureFlag", - "parameters" : [ - - ], - "returnType" : { - "rawValueEnum" : { - "_0" : "FeatureFlag", - "_1" : "Bool" + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Ratio", + "_1" : "Double" + } + } } } }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.swift index e0a32e84..9e03a665 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.swift @@ -63,6 +63,17 @@ public func _bjs_getTheme() -> Void { #endif } +@_expose(wasm, "bjs_roundTripOptionalTheme") +@_cdecl("bjs_roundTripOptionalTheme") +public func _bjs_roundTripOptionalTheme(inputIsSome: Int32, inputBytes: Int32, inputLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTheme(_: Optional.bridgeJSLiftParameter(inputIsSome, inputBytes, inputLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setTSTheme") @_cdecl("bjs_setTSTheme") public func _bjs_setTSTheme(themeBytes: Int32, themeLength: Int32) -> Void { @@ -84,6 +95,17 @@ public func _bjs_getTSTheme() -> Void { #endif } +@_expose(wasm, "bjs_roundTripOptionalTSTheme") +@_cdecl("bjs_roundTripOptionalTSTheme") +public func _bjs_roundTripOptionalTSTheme(inputIsSome: Int32, inputBytes: Int32, inputLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTSTheme(_: Optional.bridgeJSLiftParameter(inputIsSome, inputBytes, inputLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setFeatureFlag") @_cdecl("bjs_setFeatureFlag") public func _bjs_setFeatureFlag(flag: Int32) -> Void { @@ -105,6 +127,17 @@ public func _bjs_getFeatureFlag() -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalFeatureFlag") +@_cdecl("bjs_roundTripOptionalFeatureFlag") +public func _bjs_roundTripOptionalFeatureFlag(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalFeatureFlag(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setHttpStatus") @_cdecl("bjs_setHttpStatus") public func _bjs_setHttpStatus(status: Int32) -> Void { @@ -126,6 +159,17 @@ public func _bjs_getHttpStatus() -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalHttpStatus") +@_cdecl("bjs_roundTripOptionalHttpStatus") +public func _bjs_roundTripOptionalHttpStatus(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalHttpStatus(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setTSHttpStatus") @_cdecl("bjs_setTSHttpStatus") public func _bjs_setTSHttpStatus(status: Int32) -> Void { @@ -147,6 +191,17 @@ public func _bjs_getTSHttpStatus() -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalHttpStatus") +@_cdecl("bjs_roundTripOptionalHttpStatus") +public func _bjs_roundTripOptionalHttpStatus(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalHttpStatus(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setPriority") @_cdecl("bjs_setPriority") public func _bjs_setPriority(priority: Int32) -> Void { @@ -168,6 +223,17 @@ public func _bjs_getPriority() -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalPriority") +@_cdecl("bjs_roundTripOptionalPriority") +public func _bjs_roundTripOptionalPriority(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalPriority(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setFileSize") @_cdecl("bjs_setFileSize") public func _bjs_setFileSize(size: Int32) -> Void { @@ -189,6 +255,17 @@ public func _bjs_getFileSize() -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalFileSize") +@_cdecl("bjs_roundTripOptionalFileSize") +public func _bjs_roundTripOptionalFileSize(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalFileSize(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setUserId") @_cdecl("bjs_setUserId") public func _bjs_setUserId(id: Int32) -> Void { @@ -210,6 +287,17 @@ public func _bjs_getUserId() -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalUserId") +@_cdecl("bjs_roundTripOptionalUserId") +public func _bjs_roundTripOptionalUserId(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalUserId(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setTokenId") @_cdecl("bjs_setTokenId") public func _bjs_setTokenId(token: Int32) -> Void { @@ -231,6 +319,17 @@ public func _bjs_getTokenId() -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalTokenId") +@_cdecl("bjs_roundTripOptionalTokenId") +public func _bjs_roundTripOptionalTokenId(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTokenId(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setSessionId") @_cdecl("bjs_setSessionId") public func _bjs_setSessionId(session: Int32) -> Void { @@ -252,6 +351,17 @@ public func _bjs_getSessionId() -> Int32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalSessionId") +@_cdecl("bjs_roundTripOptionalSessionId") +public func _bjs_roundTripOptionalSessionId(inputIsSome: Int32, inputValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalSessionId(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setPrecision") @_cdecl("bjs_setPrecision") public func _bjs_setPrecision(precision: Float32) -> Void { @@ -273,6 +383,17 @@ public func _bjs_getPrecision() -> Float32 { #endif } +@_expose(wasm, "bjs_roundTripOptionalPrecision") +@_cdecl("bjs_roundTripOptionalPrecision") +public func _bjs_roundTripOptionalPrecision(inputIsSome: Int32, inputValue: Float32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalPrecision(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_setRatio") @_cdecl("bjs_setRatio") public func _bjs_setRatio(ratio: Float64) -> Void { @@ -294,21 +415,11 @@ public func _bjs_getRatio() -> Float64 { #endif } -@_expose(wasm, "bjs_setFeatureFlag") -@_cdecl("bjs_setFeatureFlag") -public func _bjs_setFeatureFlag(featureFlag: Int32) -> Void { - #if arch(wasm32) - setFeatureFlag(_: FeatureFlag.bridgeJSLiftParameter(featureFlag)) - #else - fatalError("Only available on WebAssembly") - #endif -} - -@_expose(wasm, "bjs_getFeatureFlag") -@_cdecl("bjs_getFeatureFlag") -public func _bjs_getFeatureFlag() -> Int32 { +@_expose(wasm, "bjs_roundTripOptionalRatio") +@_cdecl("bjs_roundTripOptionalRatio") +public func _bjs_roundTripOptionalRatio(inputIsSome: Int32, inputValue: Float64) -> Void { #if arch(wasm32) - let ret = getFeatureFlag() + let ret = roundTripOptionalRatio(_: Optional.bridgeJSLiftParameter(inputIsSome, inputValue)) return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.json new file mode 100644 index 00000000..28ac1150 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.json @@ -0,0 +1,670 @@ +{ + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Greeter_init", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Greeter_greet", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "greet", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_Greeter_changeName", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "changeName", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "Greeter", + "properties" : [ + { + "isReadonly" : false, + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "swiftCallName" : "Greeter" + }, + { + "constructor" : { + "abiName" : "bjs_OptionalPropertyHolder_init", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "OptionalPropertyHolder", + "properties" : [ + { + "isReadonly" : false, + "name" : "optionalName", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "isReadonly" : false, + "name" : "optionalAge", + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "isReadonly" : false, + "name" : "optionalGreeter", + "type" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + ], + "swiftCallName" : "OptionalPropertyHolder" + } + ], + "enums" : [ + + ], + "functions" : [ + { + "abiName" : "bjs_roundTripOptionalClass", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalClass", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + }, + { + "abiName" : "bjs_testOptionalPropertyRoundtrip", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "testOptionalPropertyRoundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "holder", + "type" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "OptionalPropertyHolder" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "OptionalPropertyHolder" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripString", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripString", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripInt", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripInt", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripBool", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripBool", + "parameters" : [ + { + "label" : "flag", + "name" : "flag", + "type" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripFloat", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripFloat", + "parameters" : [ + { + "label" : "number", + "name" : "number", + "type" : { + "optional" : { + "_0" : { + "float" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "float" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripDouble", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripDouble", + "parameters" : [ + { + "label" : "precision", + "name" : "precision", + "type" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripSyntax", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripMixSyntax", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripMixSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripSwiftSyntax", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripSwiftSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripMixedSwiftSyntax", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripMixedSwiftSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripWithSpaces", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripWithSpaces", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripAlias", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripAlias", + "parameters" : [ + { + "label" : "age", + "name" : "age", + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAlias", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAlias", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_testMixedOptionals", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "testMixedOptionals", + "parameters" : [ + { + "label" : "firstName", + "name" : "firstName", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "label" : "lastName", + "name" : "lastName", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "label" : "age", + "name" : "age", + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "label" : "active", + "name" : "active", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.swift new file mode 100644 index 00000000..9cd9e1f6 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.swift @@ -0,0 +1,339 @@ +// 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 + +@_expose(wasm, "bjs_roundTripOptionalClass") +@_cdecl("bjs_roundTripOptionalClass") +public func _bjs_roundTripOptionalClass(valueIsSome: Int32, valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testOptionalPropertyRoundtrip") +@_cdecl("bjs_testOptionalPropertyRoundtrip") +public func _bjs_testOptionalPropertyRoundtrip(holderIsSome: Int32, holderValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = testOptionalPropertyRoundtrip(_: Optional.bridgeJSLiftParameter(holderIsSome, holderValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripString") +@_cdecl("bjs_roundTripString") +public func _bjs_roundTripString(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripString(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripInt") +@_cdecl("bjs_roundTripInt") +public func _bjs_roundTripInt(valueIsSome: Int32, valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripInt(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripBool") +@_cdecl("bjs_roundTripBool") +public func _bjs_roundTripBool(flagIsSome: Int32, flagValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripBool(flag: Optional.bridgeJSLiftParameter(flagIsSome, flagValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripFloat") +@_cdecl("bjs_roundTripFloat") +public func _bjs_roundTripFloat(numberIsSome: Int32, numberValue: Float32) -> Void { + #if arch(wasm32) + let ret = roundTripFloat(number: Optional.bridgeJSLiftParameter(numberIsSome, numberValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripDouble") +@_cdecl("bjs_roundTripDouble") +public func _bjs_roundTripDouble(precisionIsSome: Int32, precisionValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripDouble(precision: Optional.bridgeJSLiftParameter(precisionIsSome, precisionValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripSyntax") +@_cdecl("bjs_roundTripSyntax") +public func _bjs_roundTripSyntax(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripMixSyntax") +@_cdecl("bjs_roundTripMixSyntax") +public func _bjs_roundTripMixSyntax(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripMixSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripSwiftSyntax") +@_cdecl("bjs_roundTripSwiftSyntax") +public func _bjs_roundTripSwiftSyntax(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripSwiftSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripMixedSwiftSyntax") +@_cdecl("bjs_roundTripMixedSwiftSyntax") +public func _bjs_roundTripMixedSwiftSyntax(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripMixedSwiftSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripWithSpaces") +@_cdecl("bjs_roundTripWithSpaces") +public func _bjs_roundTripWithSpaces(valueIsSome: Int32, valueValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripWithSpaces(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripAlias") +@_cdecl("bjs_roundTripAlias") +public func _bjs_roundTripAlias(ageIsSome: Int32, ageValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripAlias(age: Optional.bridgeJSLiftParameter(ageIsSome, ageValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAlias") +@_cdecl("bjs_roundTripOptionalAlias") +public func _bjs_roundTripOptionalAlias(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAlias(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_testMixedOptionals") +@_cdecl("bjs_testMixedOptionals") +public func _bjs_testMixedOptionals(firstNameIsSome: Int32, firstNameBytes: Int32, firstNameLength: Int32, lastNameIsSome: Int32, lastNameBytes: Int32, lastNameLength: Int32, ageIsSome: Int32, ageValue: Int32, active: Int32) -> Void { + #if arch(wasm32) + let ret = testMixedOptionals(firstName: Optional.bridgeJSLiftParameter(firstNameIsSome, firstNameBytes, firstNameLength), lastName: Optional.bridgeJSLiftParameter(lastNameIsSome, lastNameBytes, lastNameLength), age: Optional.bridgeJSLiftParameter(ageIsSome, ageValue), active: Bool.bridgeJSLiftParameter(active)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_init") +@_cdecl("bjs_Greeter_init") +public func _bjs_Greeter_init(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Greeter(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_greet") +@_cdecl("bjs_Greeter_greet") +public func _bjs_Greeter_greet(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).greet() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_changeName") +@_cdecl("bjs_Greeter_changeName") +public func _bjs_Greeter_changeName(_self: UnsafeMutableRawPointer, nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).changeName(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_get") +@_cdecl("bjs_Greeter_name_get") +public func _bjs_Greeter_name_get(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Greeter.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_name_set") +@_cdecl("bjs_Greeter_name_set") +public func _bjs_Greeter_name_set(_self: UnsafeMutableRawPointer, valueIsSome: Int32, valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + Greeter.bridgeJSLiftParameter(_self).name = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Greeter_deinit") +@_cdecl("bjs_Greeter_deinit") +public func _bjs_Greeter_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension Greeter: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "TestModule", name: "bjs_Greeter_wrap") + func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_Greeter_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_Greeter_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_init") +@_cdecl("bjs_OptionalPropertyHolder_init") +public func _bjs_OptionalPropertyHolder_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = OptionalPropertyHolder() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_get") +public func _bjs_OptionalPropertyHolder_optionalName_get(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_set") +public func _bjs_OptionalPropertyHolder_optionalName_set(_self: UnsafeMutableRawPointer, valueIsSome: Int32, valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_get") +public func _bjs_OptionalPropertyHolder_optionalAge_get(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_set") +public func _bjs_OptionalPropertyHolder_optionalAge_set(_self: UnsafeMutableRawPointer, valueIsSome: Int32, valueValue: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_get") +public func _bjs_OptionalPropertyHolder_optionalGreeter_get(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_set") +public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_self: UnsafeMutableRawPointer, valueIsSome: Int32, valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_deinit") +@_cdecl("bjs_OptionalPropertyHolder_deinit") +public func _bjs_OptionalPropertyHolder_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension OptionalPropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "TestModule", name: "bjs_OptionalPropertyHolder_wrap") + func _bjs_OptionalPropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_OptionalPropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_OptionalPropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json index 22df1dc5..24d7641c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json @@ -27,6 +27,30 @@ "returnType" : { "void" : { + } + } + }, + { + "abiName" : "bjs_roundtripString", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundtripString", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift index 723a639c..2a43d7bf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.swift @@ -14,4 +14,15 @@ public func _bjs_checkString(aBytes: Int32, aLength: Int32) -> Void { #else fatalError("Only available on WebAssembly") #endif +} + +@_expose(wasm, "bjs_roundtripString") +@_cdecl("bjs_roundtripString") +public func _bjs_roundtripString(aBytes: Int32, aLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundtripString(a: String.bridgeJSLiftParameter(aBytes, aLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif } \ No newline at end of file diff --git a/Plugins/PackageToJS/Templates/instantiate.js b/Plugins/PackageToJS/Templates/instantiate.js index 9b35efd1..236b7020 100644 --- a/Plugins/PackageToJS/Templates/instantiate.js +++ b/Plugins/PackageToJS/Templates/instantiate.js @@ -39,6 +39,21 @@ async function createInstantiator(options, swift) { swift_js_throw: unexpectedBjsCall, swift_js_retain: unexpectedBjsCall, swift_js_release: unexpectedBjsCall, + swift_js_push_tag: unexpectedBjsCall, + swift_js_push_int: unexpectedBjsCall, + swift_js_push_f32: unexpectedBjsCall, + swift_js_push_f64: unexpectedBjsCall, + swift_js_push_string: unexpectedBjsCall, + swift_js_pop_param_int32: unexpectedBjsCall, + swift_js_pop_param_f32: unexpectedBjsCall, + swift_js_pop_param_f64: unexpectedBjsCall, + swift_js_return_optional_bool: unexpectedBjsCall, + swift_js_return_optional_int: unexpectedBjsCall, + swift_js_return_optional_string: unexpectedBjsCall, + swift_js_return_optional_double: unexpectedBjsCall, + swift_js_return_optional_float: unexpectedBjsCall, + swift_js_return_optional_heap_object: unexpectedBjsCall, + swift_js_return_optional_object: unexpectedBjsCall, } }, /** @param {WebAssembly.Instance} instance */ diff --git a/Sources/JavaScriptKit/BridgeJSInstrincics.swift b/Sources/JavaScriptKit/BridgeJSInstrincics.swift index 31f56a2a..d8ddf8fd 100644 --- a/Sources/JavaScriptKit/BridgeJSInstrincics.swift +++ b/Sources/JavaScriptKit/BridgeJSInstrincics.swift @@ -306,6 +306,22 @@ extension _JSBridgedClass { /// The conformance is automatically synthesized by the BridgeJS code generator. public protocol _BridgedSwiftEnumNoPayload {} +/// A protocol that Swift case enum types (enums without raw values or associated values) conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftCaseEnum { + @_spi(BridgeJS) static func bridgeJSLiftParameter(_ value: Int32) -> Self + @_spi(BridgeJS) consuming func bridgeJSLowerReturn() -> Int32 +} + +/// A protocol that Swift associated value enum types conform to. +/// +/// The conformance is automatically synthesized by the BridgeJS code generator. +public protocol _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) static func bridgeJSLiftParameter(_ caseId: Int32) -> Self + @_spi(BridgeJS) consuming func bridgeJSLowerReturn() -> Void +} + extension _BridgedSwiftEnumNoPayload where Self: RawRepresentable, RawValue == String { // MARK: ImportTS @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Int32 { rawValue.bridgeJSLowerParameter() } @@ -372,7 +388,7 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo @_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) { +@_spi(BridgeJS) public func _swift_js_push_int(_ value: Int32) { _onlyAvailableOnWasm() } #endif @@ -399,7 +415,7 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo @_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() { +@_spi(BridgeJS) public func _swift_js_pop_param_int32() -> Int32 { _onlyAvailableOnWasm() } #endif @@ -408,7 +424,7 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo @_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() { +@_spi(BridgeJS) public func _swift_js_pop_param_f32() -> Float32 { _onlyAvailableOnWasm() } #endif @@ -417,7 +433,585 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo @_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() { +@_spi(BridgeJS) public func _swift_js_pop_param_f64() -> Float64 { _onlyAvailableOnWasm() } #endif + +// MARK: Optional Type Support + +extension Optional where Wrapped == Bool { + // MARK: ImportTS + + @available(*, unavailable, message: "Optional Bool type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available(*, unavailable, message: "Optional Bool type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Int32) -> Bool? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Bool? { + if isSome == 0 { + return nil + } else { + return Bool.bridgeJSLiftParameter(wrappedValue) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_optional_bool") + func _swift_js_return_optional_bool(_ isSome: Int32, _ value: Int32) + #else + /// Sets the optional bool for return value storage + func _swift_js_return_optional_bool(_ isSome: Int32, _ value: Int32) { + _onlyAvailableOnWasm() + } + #endif + + switch consume self { + case .none: + _swift_js_return_optional_bool(0, 0) + case .some(let value): + _swift_js_return_optional_bool(1, value.bridgeJSLowerReturn()) + } + } +} + +/// Optional support for Int +extension Optional where Wrapped == Int { + // MARK: ImportTS + + @available(*, unavailable, message: "Optional Int type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public func bridgeJSLowerParameter() -> Void {} + + @available(*, unavailable, message: "Optional Int type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Int32) -> Int? { return nil } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Int? { + if isSome == 0 { + return nil + } else { + return Int.bridgeJSLiftParameter(wrappedValue) + } + } + + @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_optional_int") + func _swift_js_return_optional_int(_ isSome: Int32, _ value: Int32) + #else + /// Sets the optional int for return value storage + func _swift_js_return_optional_int(_ isSome: Int32, _ value: Int32) { + _onlyAvailableOnWasm() + } + #endif + + switch self { + case .none: + _swift_js_return_optional_int(0, 0) + case .some(let value): + _swift_js_return_optional_int(1, value.bridgeJSLowerReturn()) + } + } +} +extension Optional where Wrapped == String { + // MARK: ImportTS + + @available(*, unavailable, message: "Optional String type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public func bridgeJSLowerParameter() -> Void {} + + @available(*, unavailable, message: "Optional String type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32) -> String? { return nil } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ bytes: Int32, _ count: Int32) -> String? + { + if isSome == 0 { + return nil + } else { + return String.bridgeJSLiftParameter(bytes, count) + } + } + + @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_optional_string") + func _swift_js_return_optional_string(_ isSome: Int32, _ ptr: UnsafePointer?, _ len: Int32) + #else + /// Write an optional string to reserved string storage to be returned to JavaScript + func _swift_js_return_optional_string(_ isSome: Int32, _ ptr: UnsafePointer?, _ len: Int32) { + _onlyAvailableOnWasm() + } + #endif + + switch self { + case .none: + _swift_js_return_optional_string(0, nil, 0) + case .some(var value): + return value.withUTF8 { ptr in + _swift_js_return_optional_string(1, ptr.baseAddress, Int32(ptr.count)) + } + } + } +} +extension Optional where Wrapped == JSObject { + // MARK: ImportTS + + @available(*, unavailable, message: "Optional JSObject type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public func bridgeJSLowerParameter() -> Void {} + + @available(*, unavailable, message: "Optional JSObject type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ objectId: Int32) -> JSObject? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ objectId: Int32) -> JSObject? { + if isSome == 0 { + return nil + } else { + return JSObject.bridgeJSLiftParameter(objectId) + } + } + + @_spi(BridgeJS) public func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_optional_object") + func _swift_js_return_optional_object(_ isSome: Int32, _ objectId: Int32) + #else + /// Write an optional JSObject to reserved storage to be returned to JavaScript + func _swift_js_return_optional_object(_ isSome: Int32, _ objectId: Int32) { + _onlyAvailableOnWasm() + } + #endif + + switch self { + case .none: + _swift_js_return_optional_object(0, 0) + case .some(let value): + let retainedId = value.bridgeJSLowerReturn() + _swift_js_return_optional_object(1, retainedId) + } + } +} + +/// Optional support for Swift heap objects +extension Optional where Wrapped: _BridgedSwiftHeapObject { + // MARK: ImportTS + @available( + *, + unavailable, + message: "Optional Swift heap objects are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Void {} + + @available( + *, + unavailable, + message: "Optional Swift heap objects are not supported to be returned from imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ pointer: UnsafeMutableRawPointer) -> Void { + } + + // MARK: ExportSwift + + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ pointer: UnsafeMutableRawPointer + ) -> Optional { + if isSome == 0 { + return nil + } else { + return Wrapped.bridgeJSLiftParameter(pointer) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_optional_heap_object") + func _swift_js_return_optional_heap_object(_ isSome: Int32, _ pointer: UnsafeMutableRawPointer?) + #else + /// Write an optional Swift heap object to reserved storage to be returned to JavaScript + func _swift_js_return_optional_heap_object(_ isSome: Int32, _ pointer: UnsafeMutableRawPointer?) { + _onlyAvailableOnWasm() + } + #endif + + switch consume self { + case .none: + _swift_js_return_optional_heap_object(0, nil) + case .some(let value): + let retainedPointer = value.bridgeJSLowerReturn() + _swift_js_return_optional_heap_object(1, retainedPointer) + } + } +} +extension Optional where Wrapped == Float { + // MARK: ImportTS + + @available(*, unavailable, message: "Optional Float type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available(*, unavailable, message: "Optional Float type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Float32) -> Float? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float32) -> Float? { + if isSome == 0 { + return nil + } else { + return Float.bridgeJSLiftParameter(wrappedValue) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_optional_float") + func _swift_js_return_optional_float(_ isSome: Int32, _ value: Float32) + #else + /// Sets the optional float for return value storage + func _swift_js_return_optional_float(_ isSome: Int32, _ value: Float32) { + _onlyAvailableOnWasm() + } + #endif + + switch consume self { + case .none: + _swift_js_return_optional_float(0, 0.0) + case .some(let value): + _swift_js_return_optional_float(1, value.bridgeJSLowerReturn()) + } + } +} + +/// Optional support for Double +extension Optional where Wrapped == Double { + // MARK: ImportTS + + @available(*, unavailable, message: "Optional Double type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available(*, unavailable, message: "Optional Double type is not supported to be passed to imported JS functions") + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Float64) -> Double? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float64) -> Double? { + if isSome == 0 { + return nil + } else { + return Double.bridgeJSLiftParameter(wrappedValue) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_optional_double") + func _swift_js_return_optional_double(_ isSome: Int32, _ value: Float64) + #else + /// Sets the optional double for return value storage + func _swift_js_return_optional_double(_ isSome: Int32, _ value: Float64) { + _onlyAvailableOnWasm() + } + #endif + + switch consume self { + case .none: + _swift_js_return_optional_double(0, 0.0) + case .some(let value): + _swift_js_return_optional_double(1, value.bridgeJSLowerReturn()) + } + } +} + +/// Optional support for case enums +extension Optional where Wrapped: _BridgedSwiftCaseEnum { + // MARK: ImportTS + + @available( + *, + unavailable, + message: "Optional case enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available( + *, + unavailable, + message: "Optional case enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + if isSome == 0 { + return nil + } else { + return Wrapped.bridgeJSLiftParameter(wrappedValue) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_return_optional_int") + func _swift_js_return_optional_int(_ isSome: Int32, _ value: Int32) + #else + /// Sets the optional int for return value storage + func _swift_js_return_optional_int(_ isSome: Int32, _ value: Int32) { + _onlyAvailableOnWasm() + } + #endif + + switch consume self { + case .none: + _swift_js_return_optional_int(0, 0) + case .some(let value): + _swift_js_return_optional_int(1, value.bridgeJSLowerReturn()) + } + } +} + +public protocol _BridgedSwiftTypeLoweredIntoVoidType { + // MARK: ExportSwift + consuming func bridgeJSLowerReturn() -> Void +} + +extension Optional where Wrapped: _BridgedSwiftTypeLoweredIntoVoidType { + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + switch consume self { + case .none: + () + case .some(let value): + value.bridgeJSLowerReturn() + } + } +} + +// MARK: Optional Raw Value Enum Support + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == String { + // MARK: ImportTS + + @available( + *, + unavailable, + message: "Optional String raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available( + *, + unavailable, + message: "Optional String raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32) -> Wrapped? { return nil } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ bytes: Int32, + _ count: Int32 + ) -> Wrapped? { + let optionalRawValue = String?.bridgeJSLiftParameter(isSome, bytes, count) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: String? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Int { + // MARK: ImportTS + + @available( + *, + unavailable, + message: "Optional Int raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available( + *, + unavailable, + message: "Optional Int raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + let optionalRawValue = Int?.bridgeJSLiftParameter(isSome, wrappedValue) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: Int? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Bool { + // MARK: ImportTS + + @available( + *, + unavailable, + message: "Optional Bool raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available( + *, + unavailable, + message: "Optional Bool raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Int32) -> Wrapped? { + let optionalRawValue = Bool?.bridgeJSLiftParameter(isSome, wrappedValue) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: Bool? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Float { + // MARK: ImportTS + + @available( + *, + unavailable, + message: "Optional Float raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available( + *, + unavailable, + message: "Optional Float raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Float32) -> Wrapped? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float32) -> Wrapped? { + let optionalRawValue = Float?.bridgeJSLiftParameter(isSome, wrappedValue) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: Float? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +extension Optional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == Double { + // MARK: ImportTS + + @available( + *, + unavailable, + message: "Optional Double raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void {} + + @available( + *, + unavailable, + message: "Optional Double raw value enum types are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ wrappedValue: Float64) -> Wrapped? { + return nil + } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ wrappedValue: Float64) -> Wrapped? { + let optionalRawValue = Double?.bridgeJSLiftParameter(isSome, wrappedValue) + return optionalRawValue.flatMap { Wrapped(rawValue: $0) } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + let optionalRawValue: Double? = self?.rawValue + optionalRawValue.bridgeJSLowerReturn() + } +} + +// MARK: Optional Associated Value Enum Support + +extension Optional where Wrapped: _BridgedSwiftAssociatedValueEnum { + // MARK: ImportTS + @available( + *, + unavailable, + message: "Optional associated value enums are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> Void { + fatalError("Optional associated value enum bridgeJSLowerParameter is not supported for ImportTS") + } + + @available( + *, + unavailable, + message: "Optional associated value enums are not supported to be passed to imported JS functions" + ) + @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ isSome: Int32, _ caseId: Int32) -> Wrapped? { return nil } + + // MARK: ExportSwift + + @_spi(BridgeJS) public static func bridgeJSLiftParameter(_ isSome: Int32, _ caseId: Int32) -> Wrapped? { + if isSome == 0 { + return nil + } else { + return Wrapped.bridgeJSLiftParameter(caseId) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + #if arch(wasm32) + @_extern(wasm, module: "bjs", name: "swift_js_push_tag") + func _swift_js_push_tag(_ tag: Int32) + #else + func _swift_js_push_tag(_ tag: Int32) { + _onlyAvailableOnWasm() + } + #endif + + switch consume self { + case .none: + _swift_js_push_tag(-1) // Use -1 as sentinel for null + case .some(let value): + value.bridgeJSLowerReturn() + } + } +} diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md index 7c512982..c19b8c52 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md @@ -66,4 +66,5 @@ This command will: - - - +- - diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md new file mode 100644 index 00000000..24b04d74 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Optional.md @@ -0,0 +1,127 @@ +# Exporting Swift Optionals to JS + +Learn how to use Swift optionals in functions, classes, and enums exported to JavaScript. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS provides comprehensive support for Swift optionals across all bridged types. When you use `Optional` or `T?` in Swift, it automatically maps to `T | null` in TypeScript/JavaScript. + +Swift optionals are translated to union types with `null` (not `undefined`) because `null` represents an explicit "no value" state that aligns semantically with Swift's `nil`. This design choice ensures consistent null handling across the Swift-JavaScript bridge and avoids the ambiguity that comes with JavaScript's `undefined`. + +> Important: BridgeJS optional support is **Swift → JavaScript only**. TypeScript → Swift optional imports are not currently supported. + +## Supported Optional Syntax + +BridgeJS recognizes all Swift optional syntax variants: + +```swift +// All of these work identically +@JS func test(name: String?) -> String? { return name } +@JS func test(name: Optional) -> Optional { return name } +@JS func test(name: Swift.Optional) -> Swift.Optional { return name } +@JS func test(name: Swift.Optional< String >) -> Swift.Optional< String. > { return name } + +// Type aliases work too +typealias OptionalName = String? +@JS func test(name: OptionalName) -> OptionalName { return name } +``` + +## Optional Parameters + +All parameter types can be made optional, including primitives, objects, and enums: + +```swift +@JS public func processOptionalData( + text: String?, // Optional string + count: Int?, // Optional integer + flag: Bool?, // Optional boolean + rate: Double?, // Optional double + user: User? // Optional Swift class +) -> String +``` + +Generated TypeScript type: + +```typescript +export type Exports = { + processOptionalData( + text: string | null, + count: number | null, + flag: boolean | null, + rate: number | null, + user: User | null + ): string; +} +``` + +## Optional Return Values + +Functions can return optional values of any supported type: + +```swift +@JS public func processText(input: String?) -> String? +``` + +Generated TypeScript type: + +```typescript +export type Exports = { + processText( + input: string | null + ): string | null; +} +``` + +## Optionals in classes + +Class properties can be optional with proper getter/setter support. +Constructors can accept optional parameters. + +```swift +@JS public class UserProfile { + @JS public var name: String? + @JS public var email: String? + @JS public var age: Int? + @JS public var avatar: User? + + @JS public init(name: String?) + @JS public func updateProfile(email: String?, age: Int?) +} + +``` + +Generated TypeScript definition: + +```typescript +export interface UserProfile extends SwiftHeapObject { + name: string | null; + email: string | null; + age: number | null; + avatar: User | null; + + updateProfile(email: string | null, age: number | null): void; +} +export type UserProfile = { + UserProfile: { + new(name: string | null): UserProfile; + } +} +``` + +## Supported Features + +| Swift Optional Feature | Status | +|:----------------------|:-------| +| Optional primitive parameters: `Int?`, `String?`, etc. | ✅ | +| Optional primitive return values | ✅ | +| Optional object parameters: `MyClass?`, `JSObject?` | ✅ | +| Optional object return values | ✅ | +| Optional enum type parameters and returns | ✅ | +| Optional properties within associated value enum cases | ✅ | +| Optional properties in classes | ✅ | +| Optional constructor parameters | ✅ | +| Type aliases for optionals | ✅ | +| All optional syntax: `T?`, `Optional`, `Swift.Optional` | ✅ | +| Nested optionals: `T??` | ❌ | \ No newline at end of file diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md index 71b92573..668fe21b 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Supported-Types.md @@ -11,8 +11,8 @@ Use this page as a quick reference for how common TypeScript types appear in Swi | `boolean` | `Bool` | | TODO | `Array` | | TODO | `Dictionary` | -| TODO | `Optional` | | `T \| undefined` | TODO | +| `T \| null` | `Optional` | | `Promise` | `JSPromise` | | `any` / `unknown` / `object` | `JSObject` | | Other types | `JSObject` | diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index b00aa67b..7e2b586e 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -435,6 +435,104 @@ enum ComplexResult { return result } +// MARK: - Optionals + +@JS func roundTripOptionalString(name: String?) -> String? { + return name +} + +@JS func roundTripOptionalInt(value: Int?) -> Int? { + return value +} + +@JS func roundTripOptionalBool(flag: Bool?) -> Bool? { + return flag +} + +@JS func roundTripOptionalFloat(number: Float?) -> Float? { + return number +} + +@JS func roundTripOptionalDouble(precision: Double?) -> Double? { + return precision +} + +@JS func roundTripOptionalSyntax(name: Optional) -> Optional { + return name +} + +@JS func roundTripOptionalMixSyntax(name: String?) -> Optional { + return name +} + +@JS func roundTripOptionalSwiftSyntax(name: Swift.Optional) -> Swift.Optional { + return name +} + +@JS func roundTripOptionalWithSpaces(value: Optional) -> Optional { + return value +} + +typealias OptionalAge = Int? +@JS func roundTripOptionalTypeAlias(age: OptionalAge) -> OptionalAge { + return age +} + +@JS func roundTripOptionalStatus(value: Status?) -> Status? { + return value +} + +@JS func roundTripOptionalTheme(value: Theme?) -> Theme? { + return value +} + +@JS func roundTripOptionalHttpStatus(value: HttpStatus?) -> HttpStatus? { + return value +} + +@JS func roundTripOptionalTSDirection(value: TSDirection?) -> TSDirection? { + return value +} + +@JS func roundTripOptionalTSTheme(value: TSTheme?) -> TSTheme? { + return value +} + +@JS func roundTripOptionalNetworkingAPIMethod(_ method: Networking.API.Method?) -> Networking.API.Method? { + return method +} + +@JS func roundTripOptionalAPIResult(value: APIResult?) -> APIResult? { + return value +} + +@JS func roundTripOptionalComplexResult(_ result: ComplexResult?) -> ComplexResult? { + return result +} + +@JS func roundTripOptionalClass(value: Greeter?) -> Greeter? { + return value +} +@JS class OptionalPropertyHolder { + @JS var optionalName: String? + @JS var optionalAge: Int? = nil + @JS var optionalGreeter: Greeter? = nil + + @JS init(optionalName: String?) { + self.optionalName = optionalName + } +} + +@JS +enum APIOptionalResult { + case success(String?) + case failure(Int?, Bool?) + case status(Bool?, Int?, String?) +} +@JS func roundTripOptionalAPIOptionalResult(result: APIOptionalResult?) -> APIOptionalResult? { + 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 5ae4e055..b629cda4 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift @@ -6,7 +6,7 @@ @_spi(BridgeJS) import JavaScriptKit -extension Direction { +extension Direction: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -49,7 +49,7 @@ extension Direction { } } -extension Status { +extension Status: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -94,7 +94,7 @@ extension Theme: _BridgedSwiftEnumNoPayload { extension HttpStatus: _BridgedSwiftEnumNoPayload { } -extension TSDirection { +extension TSDirection: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -140,7 +140,7 @@ extension TSDirection { extension TSTheme: _BridgedSwiftEnumNoPayload { } -extension Networking.API.Method { +extension Networking.API.Method: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -189,7 +189,7 @@ extension Configuration.LogLevel: _BridgedSwiftEnumNoPayload { extension Configuration.Port: _BridgedSwiftEnumNoPayload { } -extension Internal.SupportedMethod { +extension Internal.SupportedMethod: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue } @@ -224,8 +224,8 @@ extension Internal.SupportedMethod { } } -private extension APIResult { - static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) @@ -244,7 +244,7 @@ private extension APIResult { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -270,8 +270,8 @@ private extension APIResult { } } -private extension ComplexResult { - static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { +extension ComplexResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> ComplexResult { switch caseId { case 0: return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) @@ -292,7 +292,7 @@ private extension ComplexResult { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -354,8 +354,8 @@ private extension ComplexResult { } } -private extension Utilities.Result { - static func bridgeJSLiftParameter(_ caseId: Int32) -> Utilities.Result { +extension Utilities.Result: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public 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())) @@ -368,7 +368,7 @@ private extension Utilities.Result { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -395,8 +395,8 @@ private extension Utilities.Result { } } -private extension API.NetworkingResult { - static func bridgeJSLiftParameter(_ caseId: Int32) -> API.NetworkingResult { +extension API.NetworkingResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public 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())) @@ -407,7 +407,7 @@ private extension API.NetworkingResult { } } - func bridgeJSLowerReturn() { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { switch self { case .success(let param0): _swift_js_push_tag(Int32(0)) @@ -426,6 +426,68 @@ private extension API.NetworkingResult { } } +extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIOptionalResult { + switch caseId { + case 0: + return .success(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 2: + return .status(Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32()), Optional.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + default: + fatalError("Unknown APIOptionalResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + var __bjs_str_param0 = __bjs_unwrapped_param0 + __bjs_str_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + } + _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + case .failure(let param0, let param1): + _swift_js_push_tag(Int32(1)) + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + _swift_js_push_int(Int32(__bjs_unwrapped_param0)) + } + _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + let __bjs_isSome_param1 = param1 != nil + if let __bjs_unwrapped_param1 = param1 { + _swift_js_push_int(__bjs_unwrapped_param1 ? 1 : 0) + } + _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + case .status(let param0, let param1, let param2): + _swift_js_push_tag(Int32(2)) + let __bjs_isSome_param0 = param0 != nil + if let __bjs_unwrapped_param0 = param0 { + _swift_js_push_int(__bjs_unwrapped_param0 ? 1 : 0) + } + _swift_js_push_int(__bjs_isSome_param0 ? 1 : 0) + let __bjs_isSome_param1 = param1 != nil + if let __bjs_unwrapped_param1 = param1 { + _swift_js_push_int(Int32(__bjs_unwrapped_param1)) + } + _swift_js_push_int(__bjs_isSome_param1 ? 1 : 0) + let __bjs_isSome_param2 = param2 != nil + if let __bjs_unwrapped_param2 = param2 { + var __bjs_str_param2 = __bjs_unwrapped_param2 + __bjs_str_param2.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + } + _swift_js_push_int(__bjs_isSome_param2 ? 1 : 0) + } + } +} + @_expose(wasm, "bjs_roundTripVoid") @_cdecl("bjs_roundTripVoid") public func _bjs_roundTripVoid() -> Void { @@ -1310,6 +1372,226 @@ public func _bjs_roundtripAPINetworkingResult(result: Int32) -> Void { #endif } +@_expose(wasm, "bjs_roundTripOptionalString") +@_cdecl("bjs_roundTripOptionalString") +public func _bjs_roundTripOptionalString(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalString(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalInt") +@_cdecl("bjs_roundTripOptionalInt") +public func _bjs_roundTripOptionalInt(valueIsSome: Int32, valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalInt(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalBool") +@_cdecl("bjs_roundTripOptionalBool") +public func _bjs_roundTripOptionalBool(flagIsSome: Int32, flagValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalBool(flag: Optional.bridgeJSLiftParameter(flagIsSome, flagValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalFloat") +@_cdecl("bjs_roundTripOptionalFloat") +public func _bjs_roundTripOptionalFloat(numberIsSome: Int32, numberValue: Float32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalFloat(number: Optional.bridgeJSLiftParameter(numberIsSome, numberValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalDouble") +@_cdecl("bjs_roundTripOptionalDouble") +public func _bjs_roundTripOptionalDouble(precisionIsSome: Int32, precisionValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalDouble(precision: Optional.bridgeJSLiftParameter(precisionIsSome, precisionValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalSyntax") +@_cdecl("bjs_roundTripOptionalSyntax") +public func _bjs_roundTripOptionalSyntax(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalMixSyntax") +@_cdecl("bjs_roundTripOptionalMixSyntax") +public func _bjs_roundTripOptionalMixSyntax(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalMixSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalSwiftSyntax") +@_cdecl("bjs_roundTripOptionalSwiftSyntax") +public func _bjs_roundTripOptionalSwiftSyntax(nameIsSome: Int32, nameBytes: Int32, nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalSwiftSyntax(name: Optional.bridgeJSLiftParameter(nameIsSome, nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalWithSpaces") +@_cdecl("bjs_roundTripOptionalWithSpaces") +public func _bjs_roundTripOptionalWithSpaces(valueIsSome: Int32, valueValue: Float64) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalWithSpaces(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTypeAlias") +@_cdecl("bjs_roundTripOptionalTypeAlias") +public func _bjs_roundTripOptionalTypeAlias(ageIsSome: Int32, ageValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTypeAlias(age: Optional.bridgeJSLiftParameter(ageIsSome, ageValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalStatus") +@_cdecl("bjs_roundTripOptionalStatus") +public func _bjs_roundTripOptionalStatus(valueIsSome: Int32, valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalStatus(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTheme") +@_cdecl("bjs_roundTripOptionalTheme") +public func _bjs_roundTripOptionalTheme(valueIsSome: Int32, valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTheme(value: Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalHttpStatus") +@_cdecl("bjs_roundTripOptionalHttpStatus") +public func _bjs_roundTripOptionalHttpStatus(valueIsSome: Int32, valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalHttpStatus(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTSDirection") +@_cdecl("bjs_roundTripOptionalTSDirection") +public func _bjs_roundTripOptionalTSDirection(valueIsSome: Int32, valueValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTSDirection(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalTSTheme") +@_cdecl("bjs_roundTripOptionalTSTheme") +public func _bjs_roundTripOptionalTSTheme(valueIsSome: Int32, valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalTSTheme(value: Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalNetworkingAPIMethod") +@_cdecl("bjs_roundTripOptionalNetworkingAPIMethod") +public func _bjs_roundTripOptionalNetworkingAPIMethod(methodIsSome: Int32, methodValue: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalNetworkingAPIMethod(_: Optional.bridgeJSLiftParameter(methodIsSome, methodValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAPIResult") +@_cdecl("bjs_roundTripOptionalAPIResult") +public func _bjs_roundTripOptionalAPIResult(valueIsSome: Int32, valueCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAPIResult(value: Optional.bridgeJSLiftParameter(valueIsSome, valueCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalComplexResult") +@_cdecl("bjs_roundTripOptionalComplexResult") +public func _bjs_roundTripOptionalComplexResult(resultIsSome: Int32, resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalComplexResult(_: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalClass") +@_cdecl("bjs_roundTripOptionalClass") +public func _bjs_roundTripOptionalClass(valueIsSome: Int32, valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalClass(value: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripOptionalAPIOptionalResult") +@_cdecl("bjs_roundTripOptionalAPIOptionalResult") +public func _bjs_roundTripOptionalAPIOptionalResult(resultIsSome: Int32, resultCaseId: Int32) -> Void { + #if arch(wasm32) + let ret = roundTripOptionalAPIOptionalResult(result: Optional.bridgeJSLiftParameter(resultIsSome, resultCaseId)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_createPropertyHolder") @_cdecl("bjs_createPropertyHolder") public func _bjs_createPropertyHolder(intValue: Int32, floatValue: Float32, doubleValue: Float64, boolValue: Int32, stringValueBytes: Int32, stringValueLength: Int32, jsObject: Int32) -> UnsafeMutableRawPointer { @@ -1663,6 +1945,100 @@ extension Internal.TestServer: ConvertibleToJSValue, _BridgedSwiftHeapObject { } } +@_expose(wasm, "bjs_OptionalPropertyHolder_init") +@_cdecl("bjs_OptionalPropertyHolder_init") +public func _bjs_OptionalPropertyHolder_init(optionalNameIsSome: Int32, optionalNameBytes: Int32, optionalNameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = OptionalPropertyHolder(optionalName: Optional.bridgeJSLiftParameter(optionalNameIsSome, optionalNameBytes, optionalNameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_get") +public func _bjs_OptionalPropertyHolder_optionalName_get(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalName_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalName_set") +public func _bjs_OptionalPropertyHolder_optionalName_set(_self: UnsafeMutableRawPointer, valueIsSome: Int32, valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalName = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_get") +public func _bjs_OptionalPropertyHolder_optionalAge_get(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalAge_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalAge_set") +public func _bjs_OptionalPropertyHolder_optionalAge_set(_self: UnsafeMutableRawPointer, valueIsSome: Int32, valueValue: Int32) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalAge = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_get") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_get") +public func _bjs_OptionalPropertyHolder_optionalGreeter_get(_self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_optionalGreeter_set") +@_cdecl("bjs_OptionalPropertyHolder_optionalGreeter_set") +public func _bjs_OptionalPropertyHolder_optionalGreeter_set(_self: UnsafeMutableRawPointer, valueIsSome: Int32, valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + OptionalPropertyHolder.bridgeJSLiftParameter(_self).optionalGreeter = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_OptionalPropertyHolder_deinit") +@_cdecl("bjs_OptionalPropertyHolder_deinit") +public func _bjs_OptionalPropertyHolder_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension OptionalPropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalPropertyHolder_wrap") + func _bjs_OptionalPropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_OptionalPropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_OptionalPropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + @_expose(wasm, "bjs_SimplePropertyHolder_init") @_cdecl("bjs_SimplePropertyHolder_init") public func _bjs_SimplePropertyHolder_init(value: Int32) -> UnsafeMutableRawPointer { diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json index 5609a0f2..def3e68d 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json @@ -324,6 +324,76 @@ ], "swiftCallName" : "Internal.TestServer" }, + { + "constructor" : { + "abiName" : "bjs_OptionalPropertyHolder_init", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "optionalName", + "name" : "optionalName", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "OptionalPropertyHolder", + "properties" : [ + { + "isReadonly" : false, + "name" : "optionalName", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "isReadonly" : false, + "name" : "optionalAge", + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "isReadonly" : false, + "name" : "optionalGreeter", + "type" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + ], + "swiftCallName" : "OptionalPropertyHolder" + }, { "constructor" : { "abiName" : "bjs_SimplePropertyHolder_init", @@ -1284,6 +1354,94 @@ "API" ], "swiftCallName" : "API.NetworkingResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "APIOptionalResult", + "swiftCallName" : "APIOptionalResult" } ], "functions" : [ @@ -3006,6 +3164,652 @@ } } }, + { + "abiName" : "bjs_roundTripOptionalString", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalString", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalInt", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalInt", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalBool", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalBool", + "parameters" : [ + { + "label" : "flag", + "name" : "flag", + "type" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalFloat", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalFloat", + "parameters" : [ + { + "label" : "number", + "name" : "number", + "type" : { + "optional" : { + "_0" : { + "float" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "float" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalDouble", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalDouble", + "parameters" : [ + { + "label" : "precision", + "name" : "precision", + "type" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalSyntax", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalMixSyntax", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalMixSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalSwiftSyntax", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalSwiftSyntax", + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalWithSpaces", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalWithSpaces", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "double" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTypeAlias", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTypeAlias", + "parameters" : [ + { + "label" : "age", + "name" : "age", + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalStatus", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalStatus", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Status" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTheme", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTheme", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalHttpStatus", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalHttpStatus", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTSDirection", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTSDirection", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalTSTheme", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalTSTheme", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalNetworkingAPIMethod", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalNetworkingAPIMethod", + "parameters" : [ + { + "label" : "_", + "name" : "method", + "type" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "caseEnum" : { + "_0" : "Networking.API.Method" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAPIResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAPIResult", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalComplexResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalComplexResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "ComplexResult" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalClass", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalClass", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + }, + { + "abiName" : "bjs_roundTripOptionalAPIOptionalResult", + "effects" : { + "isAsync" : false, + "isThrows" : false + }, + "name" : "roundTripOptionalAPIOptionalResult", + "parameters" : [ + { + "label" : "result", + "name" : "result", + "type" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + } + } + } + } + ], + "returnType" : { + "optional" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIOptionalResult" + } + } + } + } + }, { "abiName" : "bjs_createPropertyHolder", "effects" : { diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 5ce68b5c..039c721e 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -1,7 +1,7 @@ // @ts-check import { - Direction, Status, Theme, HttpStatus, TSDirection, TSTheme, APIResult, ComplexResult + Direction, Status, Theme, HttpStatus, TSDirection, TSTheme, APIResult, ComplexResult, APIOptionalResult } from '../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; /** @type {import('../.build/plugins/PackageToJS/outputs/PackageTests/test.d.ts').SetupOptionsFn} */ @@ -229,26 +229,26 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(ph.lazyValue, "computed lazily"); ph.lazyValue = "modified lazy"; assert.equal(ph.lazyValue, "modified lazy"); - + // Test computed read-write property assert.equal(ph.computedReadWrite, "Value: 456"); ph.computedReadWrite = "Value: 777"; assert.equal(ph.intValue, 777); // Should have parsed and set intValue assert.equal(ph.computedReadWrite, "Value: 777"); - + // Test computed readonly property assert.equal(ph.computedReadonly, 1554); // intValue * 2 = 777 * 2 - + // Test property with observers // Sync observedProperty to match current intValue, then reset counters for clean test ph.observedProperty = 777; // Sync with current intValue after computed property changed it exports.resetObserverCounts(); // Reset counters to start fresh test - + // Set property from JavaScript and verify observers are called ph.observedProperty = 100; assert.equal(ph.observedProperty, 100); let afterSetStats = exports.getObserverStats(); - + // Verify willSet and didSet were called // The stats should show: willSet:1,didSet:1,willSetOld:777,willSetNew:100,didSetOld:777,didSetNew:100 assert(afterSetStats.includes("willSet:1"), `willSet should be called once, got: ${afterSetStats}`); @@ -257,12 +257,12 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert(afterSetStats.includes("willSetNew:100"), `willSet should see new value 100, got: ${afterSetStats}`); assert(afterSetStats.includes("didSetOld:777"), `didSet should see old value 777, got: ${afterSetStats}`); assert(afterSetStats.includes("didSetNew:100"), `didSet should see new value 100, got: ${afterSetStats}`); - + // Set property to a different value and verify observers are called again ph.observedProperty = 200; assert.equal(ph.observedProperty, 200); let afterSecondSetStats = exports.getObserverStats(); - + // Now should be: willSet:2,didSet:2,willSetOld:100,willSetNew:200,didSetOld:100,didSetNew:200 assert(afterSecondSetStats.includes("willSet:2"), `willSet should be called twice, got: ${afterSecondSetStats}`); assert(afterSecondSetStats.includes("didSet:2"), `didSet should be called twice, got: ${afterSecondSetStats}`); @@ -463,6 +463,94 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { 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 }); + + assert.equal(exports.roundTripOptionalString(null), null); + assert.equal(exports.roundTripOptionalInt(null), null); + assert.equal(exports.roundTripOptionalBool(null), null); + assert.equal(exports.roundTripOptionalFloat(null), null); + assert.equal(exports.roundTripOptionalDouble(null), null); + + assert.equal(exports.roundTripOptionalString("Hello"), "Hello"); + assert.equal(exports.roundTripOptionalInt(42), 42); + assert.equal(exports.roundTripOptionalBool(true), true); + assert.equal(exports.roundTripOptionalFloat(3.141592502593994), 3.141592502593994); // Float32 precision + assert.equal(exports.roundTripOptionalDouble(2.718), 2.718); + + assert.equal(exports.roundTripOptionalSyntax(null), null); + assert.equal(exports.roundTripOptionalSyntax("Test"), "Test"); + assert.equal(exports.roundTripOptionalMixSyntax(null), null); + assert.equal(exports.roundTripOptionalMixSyntax("Mix"), "Mix"); + assert.equal(exports.roundTripOptionalSwiftSyntax(null), null); + assert.equal(exports.roundTripOptionalSwiftSyntax("Swift"), "Swift"); + assert.equal(exports.roundTripOptionalWithSpaces(null), null); + assert.equal(exports.roundTripOptionalWithSpaces(1.618), 1.618); + assert.equal(exports.roundTripOptionalTypeAlias(null), null); + assert.equal(exports.roundTripOptionalTypeAlias(25), 25); + assert.equal(exports.roundTripOptionalStatus(Status.Success), Status.Success); + assert.equal(exports.roundTripOptionalTheme(Theme.Light), Theme.Light); + assert.equal(exports.roundTripOptionalHttpStatus(HttpStatus.Ok), HttpStatus.Ok); + assert.equal(exports.roundTripOptionalTSDirection(TSDirection.North), TSDirection.North); + assert.equal(exports.roundTripOptionalTSTheme(TSTheme.Light), TSTheme.Light); + assert.equal(exports.roundTripOptionalNetworkingAPIMethod(globalThis.Networking.API.Method.Get), globalThis.Networking.API.Method.Get); + assert.deepEqual(exports.roundTripOptionalAPIResult(p1), p1); + assert.deepEqual(exports.roundTripOptionalComplexResult(cl1), cl1); + + const optionalGreeter = new exports.Greeter("Schrödinger"); + const optionalGreeter2 = exports.roundTripOptionalClass(optionalGreeter); + assert.equal(optionalGreeter2?.greet() ?? "", "Hello, Schrödinger!"); + assert.equal(optionalGreeter2?.name ?? "", "Schrödinger"); + assert.equal(optionalGreeter2?.prefix ?? "", "Hello"); + assert.equal(exports.roundTripOptionalClass(null), null); + optionalGreeter.release(); + optionalGreeter2?.release(); + + const optionalsHolder = new exports.OptionalPropertyHolder(null); + + assert.equal(optionalsHolder.optionalName, null); + assert.equal(optionalsHolder.optionalAge, null); + assert.equal(optionalsHolder.optionalGreeter, null); + + optionalsHolder.optionalName = "Alice"; + optionalsHolder.optionalAge = 25; + assert.equal(optionalsHolder.optionalName, "Alice"); + assert.equal(optionalsHolder.optionalAge, 25); + + const testPropertyGreeter = new exports.Greeter("Bob"); + optionalsHolder.optionalGreeter = testPropertyGreeter; + assert.equal(optionalsHolder.optionalGreeter.greet(), "Hello, Bob!"); + assert.equal(optionalsHolder.optionalGreeter.name, "Bob"); + + optionalsHolder.optionalName = null; + optionalsHolder.optionalAge = null; + optionalsHolder.optionalGreeter = null; + assert.equal(optionalsHolder.optionalName, null); + assert.equal(optionalsHolder.optionalAge, null); + assert.equal(optionalsHolder.optionalGreeter, null); + testPropertyGreeter.release(); + optionalsHolder.release(); + + const aor1 = { tag: APIOptionalResult.Tag.Success, param0: "hello world" }; + const aor2 = { tag: APIOptionalResult.Tag.Success, param0: null }; + const aor3 = { tag: APIOptionalResult.Tag.Failure, param0: 404, param1: true }; + const aor4 = { tag: APIOptionalResult.Tag.Failure, param0: 404, param1: null }; + const aor5 = { tag: APIOptionalResult.Tag.Failure, param0: null, param1: null }; + const aor6 = { tag: APIOptionalResult.Tag.Status, param0: true, param1: 200, param2: "OK" }; + const aor7 = { tag: APIOptionalResult.Tag.Status, param0: true, param1: null, param2: "Partial" }; + const aor8 = { tag: APIOptionalResult.Tag.Status, param0: null, param1: null, param2: "Zero" }; + const aor9 = { tag: APIOptionalResult.Tag.Status, param0: false, param1: 500, param2: null }; + const aor10 = { tag: APIOptionalResult.Tag.Status, param0: null, param1: 0, param2: "Zero" }; + + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor1), aor1); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor2), aor2); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor3), aor3); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor4), aor4); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor5), aor5); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor6), aor6); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor7), aor7); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor8), aor8); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor9), aor9); + assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor10), aor10); + assert.equal(exports.roundTripOptionalAPIOptionalResult(null), null); } /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */