From c9185c25f145f76f54d10d795703aa9a7c707f9b Mon Sep 17 00:00:00 2001 From: William Taylor Date: Wed, 6 May 2026 18:38:16 +1000 Subject: [PATCH] BridgeJS: Add support for exporting structs using a box --- .../Sources/BridgeJSCore/ExportSwift.swift | 152 +- .../BridgeJSCore/ExternalModuleIndex.swift | 17 +- .../Sources/BridgeJSCore/ImportTS.swift | 4 +- .../BridgeJSCore/SwiftToSkeleton.swift | 129 +- .../Sources/BridgeJSLink/BridgeJSLink.swift | 310 +- .../Sources/BridgeJSLink/JSGlueGen.swift | 20 +- .../BridgeJSSkeleton/BridgeJSSkeleton.swift | 48 +- .../Inputs/MacroSwift/BoxedStruct.swift | 35 + .../BridgeJSCodegenTests/BoxedStruct.json | 406 ++ .../BridgeJSCodegenTests/BoxedStruct.swift | 299 ++ .../BridgeJSLinkTests/BoxedStruct.d.ts | 62 + .../BridgeJSLinkTests/BoxedStruct.js | 475 ++ .../JavaScriptKit/BridgeJSIntrinsics.swift | 108 + .../Exporting-Swift/Exporting-Swift-Struct.md | 22 +- Sources/JavaScriptKit/Macros.swift | 22 +- .../BoxedStructTests.swift | 219 + .../Generated/BridgeJS.swift | 815 +++ .../Generated/JavaScript/BridgeJS.json | 4659 +++++++++++------ .../JavaScript/BoxedStructTests.mjs | 199 + Tests/prelude.mjs | 8 + 20 files changed, 6125 insertions(+), 1884 deletions(-) create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/BoxedStruct.swift create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/BoxedStruct.json create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/BoxedStruct.swift create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/BoxedStruct.d.ts create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/BoxedStruct.js create mode 100644 Tests/BridgeJSRuntimeTests/BoxedStructTests.swift create mode 100644 Tests/BridgeJSRuntimeTests/JavaScript/BoxedStructTests.mjs diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index b649b244d..134c58ca6 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -77,10 +77,15 @@ public class ExportSwift { } try withSpan("Render Structs") { [self] in - let structCodegen = StructCodegen() + let fieldsStructCodegen = FieldsStructCodegen() for structDef in skeleton.structs { - decls.append(contentsOf: structCodegen.renderStructHelpers(structDef)) - decls.append(contentsOf: try renderSingleExportedStruct(struct: structDef)) + switch structDef.structStyle ?? .default { + case .fields: + decls.append(contentsOf: fieldsStructCodegen.renderHelpers(structDef)) + decls.append(contentsOf: try renderSingleExportedFieldsStruct(struct: structDef)) + case .reference: + decls.append(contentsOf: try renderSingleExportedBoxedStruct(struct: structDef)) + } } for function in skeleton.functions { @@ -127,34 +132,29 @@ public class ExportSwift { argumentsToLift = liftingInfo.parameters.map { (name, _) in param.name + name.capitalizedFirstLetter } } - let typeNameForIntrinsic: String let liftingExpr: ExprSyntax switch param.type { case .closure(let signature, _): - typeNameForIntrinsic = param.type.swiftType liftingExpr = ExprSyntax("_BJS_Closure_\(raw: signature.mangleName).bridgeJSLift(\(raw: param.name))") case .swiftStruct(let structName): - typeNameForIntrinsic = structName liftingExpr = ExprSyntax("\(raw: structName).bridgeJSLiftParameter()") case .array: - typeNameForIntrinsic = param.type.swiftType liftingExpr = StackCodegen().liftExpression(for: param.type) + case .swiftBoxedStruct(let underlying): + // We inline this instead of going through a `bridgeJSLiftParameter` helper, so we can get a lvalue for mutating functions. + liftingExpr = ExprSyntax( + "\(raw: argumentsToLift.joined(separator: ", ")).assumingMemoryBound(to: \(raw: underlying).self).pointee" + ) case .nullable(let wrappedType, let kind): - let optionalSwiftType: String - if case .null = kind { - optionalSwiftType = "Optional" - } else { - optionalSwiftType = "JSUndefinedOr" - } - typeNameForIntrinsic = "\(optionalSwiftType)<\(wrappedType.swiftType)>" + let optionalSwiftType = kind == .null ? "Optional" : "JSUndefinedOr" + let typeName = "\(optionalSwiftType)<\(wrappedType.swiftType)>" liftingExpr = ExprSyntax( - "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" + "\(raw: typeName).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) default: - typeNameForIntrinsic = param.type.swiftType liftingExpr = ExprSyntax( - "\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" + "\(raw: param.type.swiftType).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))" ) } @@ -397,12 +397,13 @@ public class ExportSwift { case classStatic(klass: ExportedClass) case classInstance(klass: ExportedClass) case structStatic(structDef: ExportedStruct) + case boxedStructInstance(structDef: ExportedStruct) var isStatic: Bool { switch self { case .enumStatic, .classStatic, .structStatic: return true - case .classInstance: + case .classInstance, .boxedStructInstance: return false } } @@ -413,7 +414,7 @@ public class ExportSwift { return enumDef.name case .classStatic(let klass), .classInstance(let klass): return klass.abiName - case .structStatic(let structDef): + case .structStatic(let structDef), .boxedStructInstance(let structDef): return structDef.abiName } } @@ -424,7 +425,7 @@ public class ExportSwift { return enumDef.swiftCallName case .classStatic(let klass), .classInstance(let klass): return klass.swiftCallName - case .structStatic(let structDef): + case .structStatic(let structDef), .boxedStructInstance(let structDef): return structDef.swiftCallName } } @@ -437,12 +438,23 @@ public class ExportSwift { // property.callName() would use staticContext (the ABI name) as prefix; // use swiftCallName directly so the emitted expression is valid Swift. return "\(klass.swiftCallName).\(property.name)" - case .classInstance: + case .classInstance, .boxedStructInstance: return property.callName() case .structStatic(let structDef): return property.callName(prefix: structDef.swiftCallName) } } + + var selfBridgeType: BridgeType? { + switch self { + case .classInstance(let klass): + return .swiftHeapObject(klass.swiftCallName) + case .boxedStructInstance(let structDef): + return .swiftBoxedStruct(structDef.swiftCallName) + case .enumStatic, .classStatic, .structStatic: + return nil + } + } } /// Renders getter and setter Swift thunk code for a property in any context @@ -457,11 +469,13 @@ public class ExportSwift { let className = context.className let isStatic = context.isStatic - let getterBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic)) + let getterBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic) + ) - if !isStatic { + if let selfBridgeType = context.selfBridgeType { try getterBuilder.liftParameter( - param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(context.swiftCallName)) + param: Parameter(label: nil, name: "_self", type: selfBridgeType) ) } @@ -480,11 +494,9 @@ public class ExportSwift { effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic) ) - // Lift parameters based on property type - if !isStatic { - // Instance properties need _self parameter + if let selfBridgeType = context.selfBridgeType { try setterBuilder.liftParameter( - param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(context.swiftCallName)) + param: Parameter(label: nil, name: "_self", type: selfBridgeType) ) } @@ -547,7 +559,6 @@ public class ExportSwift { private func renderSingleExportedMethod( method: ExportedFunction, - ownerTypeName: String, instanceSelfType: BridgeType ) throws -> DeclSyntax { let builder = ExportedThunkBuilder(effects: method.effects) @@ -559,7 +570,7 @@ public class ExportSwift { } if method.effects.isStatic { - builder.call(name: "\(ownerTypeName).\(method.name)", returnType: method.returnType) + builder.call(name: "\(instanceSelfType.swiftType).\(method.name)", returnType: method.returnType) } else { builder.callMethod(methodName: method.name, returnType: method.returnType) } @@ -567,7 +578,7 @@ public class ExportSwift { return builder.render(abiName: method.abiName) } - func renderSingleExportedStruct(struct structDef: ExportedStruct) throws -> [DeclSyntax] { + private func renderSingleExportedFieldsStruct(struct structDef: ExportedStruct) throws -> [DeclSyntax] { var decls: [DeclSyntax] = [] if let constructor = structDef.constructor { @@ -593,7 +604,6 @@ public class ExportSwift { decls.append( try renderSingleExportedMethod( method: method, - ownerTypeName: structDef.swiftCallName, instanceSelfType: .swiftStruct(structDef.swiftCallName) ) ) @@ -602,6 +612,66 @@ public class ExportSwift { return decls } + private func renderSingleExportedBoxedStruct(struct structDef: ExportedStruct) throws -> [DeclSyntax] { + var decls: [DeclSyntax] = [] + + if let constructor = structDef.constructor { + decls.append( + try renderSingleExportedConstructor( + constructor: constructor, + callName: structDef.swiftCallName, + returnType: .swiftBoxedStruct(structDef.swiftCallName) + ) + ) + } + + for property in structDef.properties { + let context: PropertyRenderingContext = + property.isStatic + ? .structStatic(structDef: structDef) + : .boxedStructInstance(structDef: structDef) + decls.append(contentsOf: try renderSingleExportedProperty(property: property, context: context)) + } + + for method in structDef.methods { + decls.append( + try renderSingleExportedMethod( + method: method, + instanceSelfType: .swiftBoxedStruct(structDef.swiftCallName) + ) + ) + } + + do { + let copyDecl = SwiftCodePattern.buildExposedFunctionDecl( + abiName: "bjs_\(structDef.abiName)_copy", + signature: SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: [("pointer", .pointer)], + returnType: .pointer + ) + ) { printer in + printer.write("return \(structDef.swiftCallName).bridgeJSCopyBox(pointer)") + } + decls.append(DeclSyntax(copyDecl)) + } + do { + let deinitDecl = SwiftCodePattern.buildExposedFunctionDecl( + abiName: "bjs_\(structDef.abiName)_deinit", + signature: SwiftSignatureBuilder.buildABIFunctionSignature( + abiParameters: [("pointer", .pointer)], + returnType: nil + ) + ) { printer in + printer.write("\(structDef.swiftCallName).bridgeJSReleaseBox(pointer)") + } + decls.append(DeclSyntax(deinitDecl)) + } + + decls.append("extension \(raw: structDef.swiftCallName): _BridgedSwiftBoxedValueStruct {}") + + return decls + } + /// # Example /// /// Given the following Swift code: @@ -665,7 +735,6 @@ public class ExportSwift { decls.append( try renderSingleExportedMethod( method: method, - ownerTypeName: klass.swiftCallName, instanceSelfType: .swiftHeapObject(klass.swiftCallName) ) ) @@ -753,7 +822,7 @@ struct StackCodegen { func liftExpression(for type: BridgeType) -> ExprSyntax { switch type { case .string, .integer, .bool, .float, .double, - .jsObject(nil), .jsValue, .swiftStruct, .swiftHeapObject, .unsafePointer, + .jsObject(nil), .jsValue, .swiftStruct, .swiftHeapObject, .swiftBoxedStruct, .unsafePointer, .swiftProtocol, .caseEnum, .associatedValueEnum, .rawValueEnum, .array, .dictionary: return "\(raw: type.swiftType).bridgeJSStackPop()" case .jsObject(let className?): @@ -771,7 +840,7 @@ struct StackCodegen { let typeName = kind == .null ? "Optional" : "JSUndefinedOr" switch wrappedType { case .string, .integer, .bool, .float, .double, .jsObject(nil), .jsValue, - .swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum, + .swiftStruct, .swiftHeapObject, .swiftBoxedStruct, .caseEnum, .associatedValueEnum, .rawValueEnum, .array, .dictionary: return "\(raw: typeName)<\(raw: wrappedType.swiftType)>.bridgeJSStackPop()" case .jsObject(let className?): @@ -794,7 +863,7 @@ struct StackCodegen { ) -> [CodeBlockItemSyntax] { switch type { case .string, .integer, .bool, .float, .double, .jsValue, - .jsObject(nil), .swiftHeapObject, .unsafePointer, .closure, + .jsObject(nil), .swiftHeapObject, .swiftBoxedStruct, .unsafePointer, .closure, .caseEnum, .rawValueEnum, .associatedValueEnum, .swiftStruct, .nullable: return ["\(raw: accessor).bridgeJSStackPush()"] case .jsObject(_?): @@ -1115,12 +1184,12 @@ struct EnumCodegen { } } -// MARK: - StructCodegen +// MARK: - FieldsStructCodegen -struct StructCodegen { +struct FieldsStructCodegen { private let stackCodegen = StackCodegen() - func renderStructHelpers(_ structDef: ExportedStruct) -> [DeclSyntax] { + func renderHelpers(_ structDef: ExportedStruct) -> [DeclSyntax] { let typeName = structDef.swiftCallName let lowerExternName = "swift_js_struct_lower_\(structDef.abiName)" @@ -1453,6 +1522,7 @@ extension BridgeType { case .jsObject(nil): return "JSObject" case .jsObject(let name?): return name case .swiftHeapObject(let name): return name + case .swiftBoxedStruct(let name): return name case .unsafePointer(let ptr): return ptr.swiftType case .swiftProtocol(let name): return "Any\(name)" case .void: return "Void" @@ -1510,6 +1580,7 @@ extension BridgeType { static let jsObject = LiftingIntrinsicInfo(parameters: [("value", .i32)]) static let jsValue = LiftingIntrinsicInfo(parameters: [("kind", .i32), ("payload1", .i32), ("payload2", .f64)]) static let swiftHeapObject = LiftingIntrinsicInfo(parameters: [("value", .pointer)]) + static let swiftBoxedStruct = LiftingIntrinsicInfo(parameters: [("value", .pointer)]) static let unsafePointer = LiftingIntrinsicInfo(parameters: [("pointer", .pointer)]) static let void = LiftingIntrinsicInfo(parameters: []) static let caseEnum = LiftingIntrinsicInfo(parameters: [("value", .i32)]) @@ -1528,6 +1599,7 @@ extension BridgeType { case .jsObject: return .jsObject case .jsValue: return .jsValue case .swiftHeapObject: return .swiftHeapObject + case .swiftBoxedStruct: return .swiftBoxedStruct case .unsafePointer: return .unsafePointer case .swiftProtocol: return .jsObject case .void: return .void @@ -1566,6 +1638,7 @@ extension BridgeType { static let jsObject = LoweringIntrinsicInfo(returnType: .i32) static let jsValue = LoweringIntrinsicInfo(returnType: nil) static let swiftHeapObject = LoweringIntrinsicInfo(returnType: .pointer) + static let swiftBoxedStruct = LoweringIntrinsicInfo(returnType: .pointer) static let unsafePointer = LoweringIntrinsicInfo(returnType: .pointer) static let void = LoweringIntrinsicInfo(returnType: nil) static let caseEnum = LoweringIntrinsicInfo(returnType: .i32) @@ -1586,6 +1659,7 @@ extension BridgeType { case .jsObject: return .jsObject case .jsValue: return .jsValue case .swiftHeapObject: return .swiftHeapObject + case .swiftBoxedStruct: return .swiftBoxedStruct case .unsafePointer: return .unsafePointer case .swiftProtocol: return .jsObject case .void: return .void diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExternalModuleIndex.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExternalModuleIndex.swift index 91fd4388a..fe1efcbea 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExternalModuleIndex.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExternalModuleIndex.swift @@ -40,24 +40,13 @@ public struct ExternalModuleIndex { } for klass in exported.classes { - register(dotPath: klass.swiftCallName, bridgeType: .swiftHeapObject(klass.swiftCallName)) + register(dotPath: klass.swiftCallName, bridgeType: klass.bridgeType) } for structDef in exported.structs { - register(dotPath: structDef.swiftCallName, bridgeType: .swiftStruct(structDef.swiftCallName)) + register(dotPath: structDef.swiftCallName, bridgeType: structDef.bridgeType) } for enumDef in exported.enums { - let bridgeType: BridgeType - switch enumDef.enumType { - case .simple: - bridgeType = .caseEnum(enumDef.swiftCallName) - case .rawValue: - guard let rawType = enumDef.rawType else { continue } - bridgeType = .rawValueEnum(enumDef.swiftCallName, rawType) - case .associatedValue: - bridgeType = .associatedValueEnum(enumDef.swiftCallName) - case .namespace: - bridgeType = .namespaceEnum(enumDef.swiftCallName) - } + guard let bridgeType = enumDef.bridgeType else { continue } register(dotPath: enumDef.swiftCallName, bridgeType: bridgeType) } for proto in exported.protocols { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index d491c4058..b3693edb7 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -918,7 +918,7 @@ extension BridgeType { return LoweringParameterInfo(loweredParameters: [("funcRef", .i32)]) case .unsafePointer: return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) - case .swiftHeapObject: + case .swiftHeapObject, .swiftBoxedStruct: return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)]) case .swiftProtocol: switch context { @@ -997,7 +997,7 @@ extension BridgeType { return LiftingReturnInfo(valueToLift: .i32) case .unsafePointer: return LiftingReturnInfo(valueToLift: .pointer) - case .swiftHeapObject: + case .swiftHeapObject, .swiftBoxedStruct: return LiftingReturnInfo(valueToLift: .pointer) case .swiftProtocol: switch context { diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift index f39ac16f8..46a4151ca 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift @@ -366,6 +366,11 @@ public final class SwiftToSkeleton { if structDecl.attributes.hasAttribute(name: "JSClass") { return .jsObject(swiftCallName) } + if let jsAttribute = structDecl.attributes.firstJSAttribute, + SwiftToSkeleton.extractStructStyle(from: jsAttribute) == .reference + { + return .swiftBoxedStruct(swiftCallName) + } return .swiftStruct(swiftCallName) } @@ -523,6 +528,22 @@ public final class SwiftToSkeleton { } } + static func extractStructStyle(from jsAttribute: AttributeSyntax) -> JSStructStyle? { + guard let arguments = jsAttribute.arguments?.as(LabeledExprListSyntax.self), + let styleArg = arguments.first(where: { $0.label?.text == "structStyle" }) + else { + return nil + } + let text = styleArg.expression.trimmedDescription + if text.contains("reference") { + return .reference + } + if text.contains("fields") { + return .fields + } + return nil + } + /// Strips surrounding backticks from an identifier (e.g. "`Foo`" -> "Foo"). static func normalizeIdentifier(_ name: String) -> String { guard name.hasPrefix("`"), name.hasSuffix("`"), name.count >= 2 else { @@ -1397,8 +1418,17 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { let structAbiName = exportedStructByName[structKey]?.abiName ?? "unknown" staticContext = .structName(structAbiName) } else { - diagnose(node: node, message: "@JS var must be static in structs (instance fields don't need @JS)") - return .skipChildren + switch exportedStructByName[structKey]?.structStyle ?? .default { + case .reference: + staticContext = nil + case .fields: + diagnose( + node: node, + message: "@JS var must be static in structs (instance fields don't need @JS)", + hint: "Export the struct using @JS(structStyle: .reference) instead" + ) + return .skipChildren + } } } @@ -1661,12 +1691,12 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { for associatedValue in enumCase.associatedValues { switch associatedValue.type { case .string, .integer, .float, .double, .bool, .caseEnum, .rawValueEnum, - .swiftStruct, .swiftHeapObject, .jsObject, .associatedValueEnum, .array: + .swiftStruct, .swiftHeapObject, .swiftBoxedStruct, .jsObject, .associatedValueEnum, .array: break case .nullable(let wrappedType, _): switch wrappedType { case .string, .integer, .float, .double, .bool, .caseEnum, .rawValueEnum, - .swiftStruct, .swiftHeapObject, .jsObject, .associatedValueEnum, .array: + .swiftStruct, .swiftHeapObject, .swiftBoxedStruct, .jsObject, .associatedValueEnum, .array: break default: diagnose( @@ -1772,54 +1802,61 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { for: node, message: "Struct visibility must be at least internal" ) + let structStyle = SwiftToSkeleton.extractStructStyle(from: jsAttribute) var properties: [ExportedProperty] = [] - // Process all variables in struct as readonly (value semantics) and don't require @JS - for member in node.memberBlock.members { - if let varDecl = member.decl.as(VariableDeclSyntax.self) { - let isStatic = varDecl.modifiers.contains { modifier in - modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) - } - - // Handled with error in visitVariable - if varDecl.attributes.hasJSAttribute() { - continue - } - // Skips static non-@JS properties - if isStatic { - continue - } - - for binding in varDecl.bindings { - guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self) else { - continue + switch structStyle ?? .default { + case .reference: + // Reference structs require @JS on variables to export + break + case .fields: + // Process all variables in struct as readonly (value semantics) and don't require @JS + for member in node.memberBlock.members { + if let varDecl = member.decl.as(VariableDeclSyntax.self) { + let isStatic = varDecl.modifiers.contains { modifier in + modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) } - let fieldName = pattern.identifier.text - - guard let typeAnnotation = binding.typeAnnotation else { - diagnose(node: binding, message: "Struct field must have explicit type annotation") + // Handled with error in visitVariable + if varDecl.attributes.hasJSAttribute() { continue } - - guard - let fieldType = withLookupErrors({ - self.parent.lookupType(for: typeAnnotation.type, errors: &$0) - }) - else { + // Skips static non-@JS properties + if isStatic { continue } - let property = ExportedProperty( - name: fieldName, - type: fieldType, - isReadonly: true, - isStatic: false, - namespace: effectiveNamespace, - staticContext: nil - ) - properties.append(property) + for binding in varDecl.bindings { + guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self) else { + continue + } + + let fieldName = pattern.identifier.text + + guard let typeAnnotation = binding.typeAnnotation else { + diagnose(node: binding, message: "Struct field must have explicit type annotation") + continue + } + + guard + let fieldType = withLookupErrors({ + self.parent.lookupType(for: typeAnnotation.type, errors: &$0) + }) + else { + continue + } + + let property = ExportedProperty( + name: fieldName, + type: fieldType, + isReadonly: true, + isStatic: false, + namespace: effectiveNamespace, + staticContext: nil + ) + properties.append(property) + } } } } @@ -1831,7 +1868,8 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { explicitAccessControl: explicitAccessControl, properties: properties, methods: [], - namespace: effectiveNamespace + namespace: effectiveNamespace, + structStyle: structStyle ) exportedStructByName[structUniqueKey] = exportedStruct @@ -1858,6 +1896,11 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { return } + guard exportedStruct.structStyle ?? .default == .fields else { + // This validation is only required for fields structs. + return + } + let instanceProps = exportedStruct.properties.filter { !$0.isStatic } let expectedLabels = instanceProps.map(\.name) let actualLabels = constructor.parameters.compactMap(\.label) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 64a0d2394..ad1be3dc5 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -178,8 +178,17 @@ public struct BridgeJSLink { private func collectLinkData() throws -> LinkData { var data = LinkData() - // Swift heap object class definitions - if skeletons.contains(where: { $0.exported?.classes.isEmpty == false }) { + let hasAnyReferenceStruct = + skeletons + .contains { skeleton in + skeleton.exported?.structs.contains(where: { $0.structStyle ?? .default == .reference }) ?? false + } + let hasAnyClasses = + skeletons + .contains { $0.exported?.classes.isEmpty == false } + let hasAnyHeapObject = hasAnyClasses || hasAnyReferenceStruct + + if hasAnyHeapObject { data.classLines.append( contentsOf: swiftHeapObjectClassJs.split(separator: "\n", omittingEmptySubsequences: false).map { String($0) @@ -231,11 +240,25 @@ public struct BridgeJSLink { var structExportEntries: [(js: [String], dts: [String])] = [] for structDefinition in skeleton.structs { - let (jsStruct, dtsType, dtsExportEntry) = try renderExportedStruct(structDefinition) - data.topLevelDtsTypeLines.append(contentsOf: dtsType) + switch structDefinition.structStyle ?? .default { + case .reference: + let (jsType, dtsType, dtsExportEntry) = try renderExportedBoxedStruct(structDefinition) + data.classLines.append(contentsOf: jsType) + data.dtsClassLines.append(contentsOf: dtsType) + + if structDefinition.namespace == nil { + data.exportsLines.append("\(structDefinition.name),") + data.dtsExportLines.append(contentsOf: dtsExportEntry) + } else { + data.namespacedClassDtsExportEntries[structDefinition.name] = dtsExportEntry + } + case .fields: + let (jsStruct, dtsType, dtsExportEntry) = try renderExportedStruct(structDefinition) + data.topLevelDtsTypeLines.append(contentsOf: dtsType) - if structDefinition.namespace == nil && (!jsStruct.isEmpty || !dtsExportEntry.isEmpty) { - structExportEntries.append((js: jsStruct, dts: dtsExportEntry)) + if structDefinition.namespace == nil && (!jsStruct.isEmpty || !dtsExportEntry.isEmpty) { + structExportEntries.append((js: jsStruct, dts: dtsExportEntry)) + } } } @@ -355,7 +378,11 @@ public struct BridgeJSLink { private func generateAddImports(needsImportsObject: Bool) throws -> CodeFragmentPrinter { let printer = CodeFragmentPrinter() - let allStructs = skeletons.compactMap { $0.exported?.structs }.flatMap { $0 } + let allFieldsStructs = + skeletons + .compactMap { $0.exported?.structs } + .flatMap { $0 } + .filter { $0.structStyle ?? .default == .fields } printer.write("return {") try printer.indent { printer.write(lines: [ @@ -487,8 +514,8 @@ public struct BridgeJSLink { printer.write("return \(JSGlueVariableScope.reservedI64Stack).pop();") } printer.write("}") - if !allStructs.isEmpty { - for structDef in allStructs { + if !allFieldsStructs.isEmpty { + for structDef in allFieldsStructs { printer.write("bjs[\"swift_js_struct_lower_\(structDef.abiName)\"] = function(objectId) {") printer.indent { printer.write( @@ -999,11 +1026,16 @@ public struct BridgeJSLink { printer.write(lines: generateVariableDeclarations()) let bodyPrinter = CodeFragmentPrinter() - let allStructs = exportedSkeletons.flatMap { $0.structs } - for structDef in allStructs { + let allFieldsStructs = exportedSkeletons.flatMap { + $0.structs.filter { $0.structStyle ?? .default == .fields } + } + for structDef in allFieldsStructs { let structPrinter = CodeFragmentPrinter() let structScope = JSGlueVariableScope(intrinsicRegistry: intrinsicRegistry) - let fragment = IntrinsicJSFragment.structHelper(structDefinition: structDef, allStructs: allStructs) + let fragment = IntrinsicJSFragment.structHelper( + structDefinition: structDef, + allStructs: allFieldsStructs + ) _ = try fragment.printCode( [structDef.name], IntrinsicJSFragment.PrintCodeContext( @@ -1048,9 +1080,7 @@ public struct BridgeJSLink { printer.indent { printer.indent { - // Swift class wrappers - let swiftClassWrappers = renderSwiftClassWrappers() - printer.write(lines: swiftClassWrappers) + printer.write(lines: renderSwiftClassWrappers()) // Import object builders for importBuilder in data.importObjectBuilders { @@ -1157,7 +1187,7 @@ public struct BridgeJSLink { let printer = CodeFragmentPrinter() for skeleton in skeletons.compactMap(\.exported) { - for structDef in skeleton.structs { + for structDef in skeleton.structs where structDef.structStyle ?? .default == .fields { printer.write( "const \(structDef.name)Helpers = __bjs_create\(structDef.name)Helpers();" ) @@ -1441,7 +1471,7 @@ public struct BridgeJSLink { } } return type.tsType - case .swiftStruct(let name): + case .swiftStruct(let name), .swiftBoxedStruct(let name): return name.components(separatedBy: ".").last ?? name case .nullable(let wrapped, let kind): let base = resolveTypeScriptType(wrapped, exportedSkeletons: exportedSkeletons) @@ -2026,102 +2056,105 @@ extension BridgeJSLink { } if let constructor: ExportedConstructor = klass.constructor { - let thunkBuilder = ExportedThunkBuilder( - effects: constructor.effects, - intrinsicRegistry: intrinsicRegistry + try renderHeapObjectConstructor( + constructor: constructor, + ownerName: klass.name, + constructorReturnType: .swiftHeapObject(klass.name), + jsPrinter: jsPrinter, + dtsExportEntryPrinter: dtsExportEntryPrinter ) - for param in constructor.parameters { - try thunkBuilder.lowerParameter(param: param) - } + } - let constructorParamList = DefaultValueUtils.formatParameterList(constructor.parameters) + for method in klass.methods { + try renderHeapObjectMethod( + method: method, + jsPrinter: jsPrinter, + dtsTypePrinter: dtsTypePrinter, + dtsExportEntryPrinter: dtsExportEntryPrinter + ) + } - jsPrinter.indent { - jsPrinter.write("constructor(\(constructorParamList)) {") - let returnExpr = thunkBuilder.callConstructor(abiName: constructor.abiName) - let constructCall = "\(klass.name).__construct(\(returnExpr))" - jsPrinter.indent { - thunkBuilder.renderFunctionBody( - into: jsPrinter, - returnExpr: constructCall - ) - } - jsPrinter.write("}") - } + for property in klass.properties { + try renderHeapObjectProperty( + property: property, + className: klass.abiName, + isStatic: property.isStatic, + jsPrinter: jsPrinter, + dtsPrinter: property.isStatic ? dtsExportEntryPrinter : dtsTypePrinter + ) + } - dtsExportEntryPrinter.indent { - let jsDocLines = DefaultValueUtils.formatJSDoc(for: constructor.parameters) - for line in jsDocLines { - dtsExportEntryPrinter.write(line) - } - dtsExportEntryPrinter.write( - "new\(renderTSSignature(parameters: constructor.parameters, returnType: .swiftHeapObject(klass.name), effects: constructor.effects));" - ) - } + jsPrinter.write("}") + dtsTypePrinter.write("}") + dtsExportEntryPrinter.write("}") + + return (jsPrinter.lines, dtsTypePrinter.lines, dtsExportEntryPrinter.lines) + } + + func renderExportedBoxedStruct( + _ structDef: ExportedStruct + ) throws -> (js: [String], dtsType: [String], dtsExportEntry: [String]) { + let jsPrinter = CodeFragmentPrinter() + let dtsTypePrinter = CodeFragmentPrinter() + let dtsExportEntryPrinter = CodeFragmentPrinter() + + dtsTypePrinter.write("export interface \(structDef.name) extends SwiftHeapObject {") + dtsExportEntryPrinter.write("\(structDef.name): {") + jsPrinter.write("class \(structDef.name) extends SwiftHeapObject {") + + // Synthesized copy + + dtsTypePrinter.indent { + dtsTypePrinter.write("copy(): this;") } - for method in klass.methods { - if method.effects.isStatic { - let thunkBuilder = ExportedThunkBuilder( - effects: method.effects, - intrinsicRegistry: intrinsicRegistry + jsPrinter.indent { + jsPrinter.write("copy() {") + jsPrinter.indent { + jsPrinter.write( + "return \(structDef.name).__construct(instance.exports.bjs_\(structDef.abiName)_copy(this.pointer));" ) - for param in method.parameters { - try thunkBuilder.lowerParameter(param: param) - } - let returnExpr = try thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) + } + jsPrinter.write("}") + jsPrinter.nextLine() + } - jsPrinter.indent { - jsPrinter.write( - lines: thunkBuilder.renderFunction( - name: method.name, - parameters: method.parameters, - returnExpr: returnExpr, - declarationPrefixKeyword: "static" - ) - ) - } + // Constructor - dtsExportEntryPrinter.indent { - dtsExportEntryPrinter.write( - "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" - ) - } - } else { - let thunkBuilder = ExportedThunkBuilder( - effects: method.effects, - intrinsicRegistry: intrinsicRegistry + jsPrinter.indent { + jsPrinter.write("static __construct(ptr) {") + jsPrinter.indent { + jsPrinter.write( + "return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_\(structDef.abiName)_deinit, \(structDef.name).prototype, null);" ) - thunkBuilder.lowerSelf() - for param in method.parameters { - try thunkBuilder.lowerParameter(param: param) - } - let returnExpr = try thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) + } + jsPrinter.write("}") + jsPrinter.nextLine() + } - jsPrinter.indent { - jsPrinter.write( - lines: thunkBuilder.renderFunction( - name: method.name, - parameters: method.parameters, - returnExpr: returnExpr, - declarationPrefixKeyword: nil - ) - ) - } + if let constructor = structDef.constructor { + try renderHeapObjectConstructor( + constructor: constructor, + ownerName: structDef.name, + constructorReturnType: .swiftBoxedStruct(structDef.name), + jsPrinter: jsPrinter, + dtsExportEntryPrinter: dtsExportEntryPrinter + ) + } - dtsTypePrinter.indent { - dtsTypePrinter.write( - "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" - ) - } - } + for method in structDef.methods { + try renderHeapObjectMethod( + method: method, + jsPrinter: jsPrinter, + dtsTypePrinter: dtsTypePrinter, + dtsExportEntryPrinter: dtsExportEntryPrinter + ) } - // Generate property getters and setters - for property in klass.properties { - try renderClassProperty( + for property in structDef.properties { + try renderHeapObjectProperty( property: property, - className: klass.abiName, + className: structDef.abiName, isStatic: property.isStatic, jsPrinter: jsPrinter, dtsPrinter: property.isStatic ? dtsExportEntryPrinter : dtsTypePrinter @@ -2135,7 +2168,82 @@ extension BridgeJSLink { return (jsPrinter.lines, dtsTypePrinter.lines, dtsExportEntryPrinter.lines) } - private func renderClassProperty( + // Used by classes and boxed structs. + private func renderHeapObjectConstructor( + constructor: ExportedConstructor, + ownerName: String, + constructorReturnType: BridgeType, + jsPrinter: CodeFragmentPrinter, + dtsExportEntryPrinter: CodeFragmentPrinter + ) throws { + let thunkBuilder = ExportedThunkBuilder( + effects: constructor.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in constructor.parameters { + try thunkBuilder.lowerParameter(param: param) + } + + let constructorParamList = DefaultValueUtils.formatParameterList(constructor.parameters) + + jsPrinter.indent { + jsPrinter.write("constructor(\(constructorParamList)) {") + let returnExpr = thunkBuilder.callConstructor(abiName: constructor.abiName) + let constructCall = "\(ownerName).__construct(\(returnExpr))" + jsPrinter.indent { + thunkBuilder.renderFunctionBody(into: jsPrinter, returnExpr: constructCall) + } + jsPrinter.write("}") + } + + dtsExportEntryPrinter.indent { + for line in DefaultValueUtils.formatJSDoc(for: constructor.parameters) { + dtsExportEntryPrinter.write(line) + } + dtsExportEntryPrinter.write( + "new\(renderTSSignature(parameters: constructor.parameters, returnType: constructorReturnType, effects: constructor.effects));" + ) + } + } + + // Used by classes and boxed structs. + private func renderHeapObjectMethod( + method: ExportedFunction, + jsPrinter: CodeFragmentPrinter, + dtsTypePrinter: CodeFragmentPrinter, + dtsExportEntryPrinter: CodeFragmentPrinter + ) throws { + let thunkBuilder = ExportedThunkBuilder( + effects: method.effects, + intrinsicRegistry: intrinsicRegistry + ) + if !method.effects.isStatic { + thunkBuilder.lowerSelf() + } + for param in method.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) + + jsPrinter.indent { + jsPrinter.write( + lines: thunkBuilder.renderFunction( + name: method.name, + parameters: method.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: method.effects.isStatic ? "static" : nil + ) + ) + } + + let dtsLine = + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + let targetPrinter = method.effects.isStatic ? dtsExportEntryPrinter : dtsTypePrinter + targetPrinter.indent { targetPrinter.write(dtsLine) } + } + + // Used by classes and boxed structs. + private func renderHeapObjectProperty( property: ExportedProperty, className: String, isStatic: Bool, @@ -2197,7 +2305,7 @@ extension BridgeJSLink { // Add instance property to TypeScript interface definition let readonly = property.isReadonly ? "readonly " : "" dtsPrinter.indent { - dtsPrinter.write("\(readonly)\(property.name): \(property.type.tsType);") + dtsPrinter.write("\(readonly)\(property.name): \(resolveTypeScriptType(property.type));") } } @@ -3599,7 +3707,7 @@ extension BridgeType { return name ?? "any" case .jsValue: return "any" - case .swiftHeapObject(let name): + case .swiftHeapObject(let name), .swiftBoxedStruct(let name): return name case .unsafePointer: return "number" diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 1ad397f71..6c4d01ff0 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -972,7 +972,7 @@ struct IntrinsicJSFragment: Sendable { return optionalLiftReturnFromStorage(storage: JSGlueVariableScope.reservedStorageToReturnString) } - if case .swiftHeapObject(let className) = wrappedType { + if let className = wrappedType.heapObjectName { return optionalLiftReturnHeapObject(className: className, kind: kind) } @@ -1290,7 +1290,7 @@ struct IntrinsicJSFragment: Sendable { case .string: return .stringLowerParameter case .jsObject: return .jsObjectLowerParameter case .jsValue: return .jsValueLower - case .swiftHeapObject: return .swiftHeapObjectLowerParameter + case .swiftHeapObject, .swiftBoxedStruct: return .swiftHeapObjectLowerParameter case .swiftProtocol: return .jsObjectLowerParameter case .void: return .void case .nullable(let wrappedType, let kind): @@ -1350,7 +1350,7 @@ struct IntrinsicJSFragment: Sendable { case .string: return .stringLiftReturn case .jsObject: return .jsObjectLiftReturn case .jsValue: return .jsValueLift - case .swiftHeapObject(let name): return .swiftHeapObjectLiftReturn(name) + case .swiftHeapObject(let name), .swiftBoxedStruct(let name): return .swiftHeapObjectLiftReturn(name) case .swiftProtocol: return .jsObjectLiftReturn case .void: return .void case .nullable(let wrappedType, let kind): @@ -1409,7 +1409,7 @@ struct IntrinsicJSFragment: Sendable { case .string: return .stringLiftParameter case .jsObject: return .jsObjectLiftParameter case .jsValue: return .jsValueLiftParameter - case .swiftHeapObject(let name): + case .swiftHeapObject(let name), .swiftBoxedStruct(let name): return .swiftHeapObjectLiftParameter(name) case .swiftProtocol: return .jsObjectLiftParameter case .void: @@ -1493,7 +1493,7 @@ struct IntrinsicJSFragment: Sendable { case .string: return .stringLowerReturn case .jsObject: return .jsObjectLowerReturn case .jsValue: return .jsValueLowerReturn(context: context) - case .swiftHeapObject: return .swiftHeapObjectLowerReturn + case .swiftHeapObject, .swiftBoxedStruct: return .swiftHeapObjectLowerReturn case .swiftProtocol: return .jsObjectLowerReturn case .void: return .void case .nullable(let wrappedType, let kind): @@ -2033,7 +2033,7 @@ struct IntrinsicJSFragment: Sendable { return [resultVar] } ) - case .swiftHeapObject(let className): + case .swiftHeapObject(let className), .swiftBoxedStruct(let className): return IntrinsicJSFragment( parameters: [], printCode: { arguments, context in @@ -2158,7 +2158,7 @@ struct IntrinsicJSFragment: Sendable { return [] } ) - case .swiftHeapObject: + case .swiftHeapObject, .swiftBoxedStruct: return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in @@ -2651,7 +2651,7 @@ private extension BridgeType { return .stackABI case .jsValue: return .inlineFlag - case .swiftHeapObject: + case .swiftHeapObject, .swiftBoxedStruct: return .inlineFlag case .unsafePointer: return .inlineFlag @@ -2687,7 +2687,7 @@ private extension BridgeType { switch self { case .swiftProtocol: return .i32(0) - case .swiftHeapObject: + case .swiftHeapObject, .swiftBoxedStruct: return .pointer case .caseEnum, .associatedValueEnum: return .i32(-1) @@ -2729,7 +2729,7 @@ private extension BridgeType { return [("value", .i32)] case .jsValue: return [("kind", .i32), ("payload1", .i32), ("payload2", .f64)] - case .swiftHeapObject: + case .swiftHeapObject, .swiftBoxedStruct: return [("pointer", .pointer)] case .unsafePointer: return [("pointer", .pointer)] diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index 346b7333b..e52ce2605 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -272,9 +272,19 @@ public enum BridgeType: Codable, Equatable, Hashable, Sendable { case namespaceEnum(String) case swiftProtocol(String) case swiftStruct(String) + case swiftBoxedStruct(String) indirect case closure(ClosureSignature, useJSTypedClosure: Bool) } +extension BridgeType { + public var heapObjectName: String? { + switch self { + case .swiftHeapObject(let name), .swiftBoxedStruct(let name): return name + default: return nil + } + } +} + public enum WasmCoreType: String, Codable, Sendable { case i32, i64, f32, f64, pointer } @@ -664,6 +674,13 @@ public struct StructField: Codable, Equatable, Sendable { } } +public enum JSStructStyle: String, Codable, Equatable, Sendable { + case fields + case reference + + public static var `default`: JSStructStyle { .fields } +} + public struct ExportedStruct: Codable, Equatable, Sendable, NamespacedExportedType { public let name: String public let swiftCallName: String @@ -672,6 +689,14 @@ public struct ExportedStruct: Codable, Equatable, Sendable, NamespacedExportedTy public var constructor: ExportedConstructor? public var methods: [ExportedFunction] public let namespace: [String]? + public var structStyle: JSStructStyle? + + public var bridgeType: BridgeType { + switch structStyle ?? .default { + case .reference: return .swiftBoxedStruct(swiftCallName) + case .fields: return .swiftStruct(swiftCallName) + } + } public init( name: String, @@ -680,7 +705,8 @@ public struct ExportedStruct: Codable, Equatable, Sendable, NamespacedExportedTy properties: [ExportedProperty] = [], constructor: ExportedConstructor? = nil, methods: [ExportedFunction] = [], - namespace: [String]? + namespace: [String]?, + structStyle: JSStructStyle? = nil ) { self.name = name self.swiftCallName = swiftCallName @@ -689,6 +715,7 @@ public struct ExportedStruct: Codable, Equatable, Sendable, NamespacedExportedTy self.constructor = constructor self.methods = methods self.namespace = namespace + self.structStyle = structStyle } } @@ -776,6 +803,17 @@ public struct ExportedEnum: Codable, Equatable, Sendable, NamespacedExportedType "\(name)\(Self.objectSuffix)" } + public var bridgeType: BridgeType? { + switch enumType { + case .simple: return .caseEnum(swiftCallName) + case .rawValue: + guard let rawType else { return nil } + return .rawValueEnum(swiftCallName, rawType) + case .associatedValue: return .associatedValueEnum(swiftCallName) + case .namespace: return .namespaceEnum(swiftCallName) + } + } + public init( name: String, swiftCallName: String, @@ -883,6 +921,8 @@ public struct ExportedClass: Codable, NamespacedExportedType { public var namespace: [String]? public var identityMode: Bool? // nil = use config default, true/false = override + public var bridgeType: BridgeType { .swiftHeapObject(swiftCallName) } + public init( name: String, swiftCallName: String, @@ -1545,7 +1585,7 @@ extension BridgeType { case .string: return nil case .jsObject: return .i32 case .jsValue: return nil - case .swiftHeapObject: + case .swiftHeapObject, .swiftBoxedStruct: // UnsafeMutableRawPointer is returned as an i32 pointer return .pointer case .unsafePointer: @@ -1599,7 +1639,7 @@ extension BridgeType { return "\(typeName.count)\(typeName)C" case .jsValue: return "7JSValueV" - case .swiftHeapObject(let name): + case .swiftHeapObject(let name), .swiftBoxedStruct(let name): return "\(name.count)\(name)C" case .unsafePointer(let ptr): func sanitize(_ s: String) -> String { @@ -1666,7 +1706,7 @@ extension BridgeType { default: return false } - case .bool, .caseEnum, .swiftHeapObject, .associatedValueEnum, .jsObject: + case .bool, .caseEnum, .swiftHeapObject, .swiftBoxedStruct, .associatedValueEnum, .jsObject: return false default: return false diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/BoxedStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/BoxedStruct.swift new file mode 100644 index 000000000..40ba75c6a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/BoxedStruct.swift @@ -0,0 +1,35 @@ +@JS(structStyle: .reference) struct LargePayload { + @JS let largeContents: [Int] +} + +@JS(structStyle: .reference) struct Hi { + @JS let largeContents: [Int] + + @JS init(largeContents: [Int]) + @JS func summarize() -> String + @JS func appendingZero() -> Hi +} + +@JS(structStyle: .reference) struct Container { + @JS let payload: LargePayload +} + +@JS(structStyle: .reference) struct MutableBox { + @JS var counter: Int + @JS let label: String +} + +@JS func roundtripBoxed(_ p: LargePayload) -> LargePayload + +@JS func mayMakeHi(_ flag: Bool) -> Hi? + +@JS struct ValueWithBoxedField { + let payload: Hi + let label: String +} + +// Boxed structs inside Array / Dictionary parameters and returns. +@JS func consumeBoxedArray(_ items: [Hi]) -> [Hi] +@JS func consumeBoxedDictionary(_ items: [String: Hi]) -> [String: Hi] +@JS func optionalBoxedArray(_ flag: Bool) -> [Hi]? +@JS func arrayOfOptionalBoxed(_ flag: Bool) -> [Hi?] diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/BoxedStruct.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/BoxedStruct.json new file mode 100644 index 000000000..e3bd698c8 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/BoxedStruct.json @@ -0,0 +1,406 @@ +{ + "exported" : { + "classes" : [ + + ], + "enums" : [ + + ], + "exposeToGlobal" : false, + "functions" : [ + { + "abiName" : "bjs_roundtripBoxed", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripBoxed", + "parameters" : [ + { + "label" : "_", + "name" : "p", + "type" : { + "swiftBoxedStruct" : { + "_0" : "LargePayload" + } + } + } + ], + "returnType" : { + "swiftBoxedStruct" : { + "_0" : "LargePayload" + } + } + }, + { + "abiName" : "bjs_mayMakeHi", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "mayMakeHi", + "parameters" : [ + { + "label" : "_", + "name" : "flag", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_consumeBoxedArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "consumeBoxedArray", + "parameters" : [ + { + "label" : "_", + "name" : "items", + "type" : { + "array" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + } + } + } + }, + { + "abiName" : "bjs_consumeBoxedDictionary", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "consumeBoxedDictionary", + "parameters" : [ + { + "label" : "_", + "name" : "items", + "type" : { + "dictionary" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + } + } + } + } + ], + "returnType" : { + "dictionary" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + } + } + } + }, + { + "abiName" : "bjs_optionalBoxedArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "optionalBoxedArray", + "parameters" : [ + { + "label" : "_", + "name" : "flag", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + } + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_arrayOfOptionalBoxed", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "arrayOfOptionalBoxed", + "parameters" : [ + { + "label" : "_", + "name" : "flag", + "type" : { + "bool" : { + + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "nullable" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + }, + "_1" : "null" + } + } + } + } + } + ], + "protocols" : [ + + ], + "structs" : [ + { + "methods" : [ + + ], + "name" : "LargePayload", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "largeContents", + "type" : { + "array" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + } + ], + "structStyle" : "reference", + "swiftCallName" : "LargePayload" + }, + { + "constructor" : { + "abiName" : "bjs_Hi_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "largeContents", + "name" : "largeContents", + "type" : { + "array" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Hi_summarize", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "summarize", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_Hi_appendingZero", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "appendingZero", + "parameters" : [ + + ], + "returnType" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + } + } + ], + "name" : "Hi", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "largeContents", + "type" : { + "array" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + } + ], + "structStyle" : "reference", + "swiftCallName" : "Hi" + }, + { + "methods" : [ + + ], + "name" : "Container", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "payload", + "type" : { + "swiftBoxedStruct" : { + "_0" : "LargePayload" + } + } + } + ], + "structStyle" : "reference", + "swiftCallName" : "Container" + }, + { + "methods" : [ + + ], + "name" : "MutableBox", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "counter", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "label", + "type" : { + "string" : { + + } + } + } + ], + "structStyle" : "reference", + "swiftCallName" : "MutableBox" + }, + { + "methods" : [ + + ], + "name" : "ValueWithBoxedField", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "payload", + "type" : { + "swiftBoxedStruct" : { + "_0" : "Hi" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "label", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "ValueWithBoxedField" + } + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/BoxedStruct.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/BoxedStruct.swift new file mode 100644 index 000000000..ff3a20fc3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/BoxedStruct.swift @@ -0,0 +1,299 @@ +@_expose(wasm, "bjs_LargePayload_largeContents_get") +@_cdecl("bjs_LargePayload_largeContents_get") +public func _bjs_LargePayload_largeContents_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: LargePayload.self).pointee.largeContents + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_LargePayload_copy") +@_cdecl("bjs_LargePayload_copy") +public func _bjs_LargePayload_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return LargePayload.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_LargePayload_deinit") +@_cdecl("bjs_LargePayload_deinit") +public func _bjs_LargePayload_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + LargePayload.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension LargePayload: _BridgedSwiftBoxedValueStruct {} + +@_expose(wasm, "bjs_Hi_init") +@_cdecl("bjs_Hi_init") +public func _bjs_Hi_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Hi(largeContents: [Int].bridgeJSStackPop()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Hi_largeContents_get") +@_cdecl("bjs_Hi_largeContents_get") +public func _bjs_Hi_largeContents_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: Hi.self).pointee.largeContents + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Hi_summarize") +@_cdecl("bjs_Hi_summarize") +public func _bjs_Hi_summarize(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: Hi.self).pointee.summarize() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Hi_appendingZero") +@_cdecl("bjs_Hi_appendingZero") +public func _bjs_Hi_appendingZero(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: Hi.self).pointee.appendingZero() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Hi_copy") +@_cdecl("bjs_Hi_copy") +public func _bjs_Hi_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return Hi.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Hi_deinit") +@_cdecl("bjs_Hi_deinit") +public func _bjs_Hi_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Hi.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Hi: _BridgedSwiftBoxedValueStruct {} + +@_expose(wasm, "bjs_Container_payload_get") +@_cdecl("bjs_Container_payload_get") +public func _bjs_Container_payload_get(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: Container.self).pointee.payload + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_copy") +@_cdecl("bjs_Container_copy") +public func _bjs_Container_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return Container.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_deinit") +@_cdecl("bjs_Container_deinit") +public func _bjs_Container_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Container.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Container: _BridgedSwiftBoxedValueStruct {} + +@_expose(wasm, "bjs_MutableBox_counter_get") +@_cdecl("bjs_MutableBox_counter_get") +public func _bjs_MutableBox_counter_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: MutableBox.self).pointee.counter + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableBox_counter_set") +@_cdecl("bjs_MutableBox_counter_set") +public func _bjs_MutableBox_counter_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + _self.assumingMemoryBound(to: MutableBox.self).pointee.counter = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableBox_label_get") +@_cdecl("bjs_MutableBox_label_get") +public func _bjs_MutableBox_label_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: MutableBox.self).pointee.label + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableBox_copy") +@_cdecl("bjs_MutableBox_copy") +public func _bjs_MutableBox_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return MutableBox.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableBox_deinit") +@_cdecl("bjs_MutableBox_deinit") +public func _bjs_MutableBox_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + MutableBox.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension MutableBox: _BridgedSwiftBoxedValueStruct {} + +extension ValueWithBoxedField: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> ValueWithBoxedField { + let label = String.bridgeJSStackPop() + let payload = Hi.bridgeJSStackPop() + return ValueWithBoxedField(payload: payload, label: label) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.payload.bridgeJSStackPush() + self.label.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_ValueWithBoxedField(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_ValueWithBoxedField())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ValueWithBoxedField") +fileprivate func _bjs_struct_lower_ValueWithBoxedField_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_ValueWithBoxedField_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_ValueWithBoxedField(_ objectId: Int32) -> Void { + return _bjs_struct_lower_ValueWithBoxedField_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_ValueWithBoxedField") +fileprivate func _bjs_struct_lift_ValueWithBoxedField_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_ValueWithBoxedField_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_ValueWithBoxedField() -> Int32 { + return _bjs_struct_lift_ValueWithBoxedField_extern() +} + +@_expose(wasm, "bjs_roundtripBoxed") +@_cdecl("bjs_roundtripBoxed") +public func _bjs_roundtripBoxed(_ p: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundtripBoxed(_: p.assumingMemoryBound(to: LargePayload.self).pointee) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_mayMakeHi") +@_cdecl("bjs_mayMakeHi") +public func _bjs_mayMakeHi(_ flag: Int32) -> Void { + #if arch(wasm32) + let ret = mayMakeHi(_: Bool.bridgeJSLiftParameter(flag)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_consumeBoxedArray") +@_cdecl("bjs_consumeBoxedArray") +public func _bjs_consumeBoxedArray() -> Void { + #if arch(wasm32) + let ret = consumeBoxedArray(_: [Hi].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_consumeBoxedDictionary") +@_cdecl("bjs_consumeBoxedDictionary") +public func _bjs_consumeBoxedDictionary() -> Void { + #if arch(wasm32) + let ret = consumeBoxedDictionary(_: [String: Hi].bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_optionalBoxedArray") +@_cdecl("bjs_optionalBoxedArray") +public func _bjs_optionalBoxedArray(_ flag: Int32) -> Void { + #if arch(wasm32) + let ret = optionalBoxedArray(_: Bool.bridgeJSLiftParameter(flag)) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_arrayOfOptionalBoxed") +@_cdecl("bjs_arrayOfOptionalBoxed") +public func _bjs_arrayOfOptionalBoxed(_ flag: Int32) -> Void { + #if arch(wasm32) + let ret = arrayOfOptionalBoxed(_: Bool.bridgeJSLiftParameter(flag)) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/BoxedStruct.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/BoxedStruct.d.ts new file mode 100644 index 000000000..f3a85f053 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/BoxedStruct.d.ts @@ -0,0 +1,62 @@ +// 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 interface ValueWithBoxedField { + payload: Hi; + label: string; +} +/// 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 LargePayload extends SwiftHeapObject { + copy(): this; + readonly largeContents: number[]; +} +export interface Hi extends SwiftHeapObject { + copy(): this; + summarize(): string; + appendingZero(): Hi; + readonly largeContents: number[]; +} +export interface Container extends SwiftHeapObject { + copy(): this; + readonly payload: LargePayload; +} +export interface MutableBox extends SwiftHeapObject { + copy(): this; + counter: number; + readonly label: string; +} +export type Exports = { + LargePayload: { + } + Hi: { + new(largeContents: number[]): Hi; + } + Container: { + } + MutableBox: { + } + roundtripBoxed(p: LargePayload): LargePayload; + mayMakeHi(flag: boolean): Hi | null; + consumeBoxedArray(items: Hi[]): Hi[]; + consumeBoxedDictionary(items: Record): Record; + optionalBoxedArray(flag: boolean): Hi[] | null; + arrayOfOptionalBoxed(flag: boolean): (Hi | 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/BoxedStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/BoxedStruct.js new file mode 100644 index 000000000..c743f0cb3 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/BoxedStruct.js @@ -0,0 +1,475 @@ +// 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; + let decodeString; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let strStack = []; + let i32Stack = []; + let i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createValueWithBoxedFieldHelpers = () => ({ + lower: (value) => { + ptrStack.push(value.payload.pointer); + const bytes = textEncoder.encode(value.label); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + }, + lift: () => { + const string = strStack.pop(); + const ptr = ptrStack.pop(); + const obj = _exports['Hi'].__construct(ptr); + return { payload: obj, label: string }; + } + }); + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + tmpRetString = decodeString(ptr, len); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + swift.memory.release(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + return swift.memory.retain(decodeString(ptr, len)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr, len); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const value = decodeString(ptr, len); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + bjs["swift_js_struct_lower_ValueWithBoxedField"] = function(objectId) { + structHelpers.ValueWithBoxedField.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_ValueWithBoxedField"] = function() { + const value = structHelpers.ValueWithBoxedField.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = decodeString(ptr, len); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.identityMap?.delete(state.pointer); + state.deinit(state.pointer); + }); + + /// Represents a Swift heap object like a class instance or an actor instance. + class SwiftHeapObject { + static __wrap(pointer, deinit, prototype, identityCache) { + const makeFresh = (identityMap) => { + const obj = Object.create(prototype); + const state = { pointer, deinit, hasReleased: false, identityMap }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + if (identityMap) { + identityMap.set(pointer, new WeakRef(obj)); + } + return obj; + }; + + if (!identityCache) { + return makeFresh(null); + } + + const cached = identityCache.get(pointer)?.deref(); + if (cached && !cached.__swiftHeapObjectState.hasReleased) { + deinit(pointer); + return cached; + } + if (identityCache.has(pointer)) { + identityCache.delete(pointer); + } + + return makeFresh(identityCache); + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.identityMap?.delete(state.pointer); + state.deinit(state.pointer); + } + } + class LargePayload extends SwiftHeapObject { + copy() { + return LargePayload.__construct(instance.exports.bjs_LargePayload_copy(this.pointer)); + } + + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_LargePayload_deinit, LargePayload.prototype, null); + } + + get largeContents() { + instance.exports.bjs_LargePayload_largeContents_get(this.pointer); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + return arrayResult; + } + } + class Hi extends SwiftHeapObject { + copy() { + return Hi.__construct(instance.exports.bjs_Hi_copy(this.pointer)); + } + + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Hi_deinit, Hi.prototype, null); + } + + constructor(largeContents) { + for (const elem of largeContents) { + i32Stack.push((elem | 0)); + } + i32Stack.push(largeContents.length); + const ret = instance.exports.bjs_Hi_init(); + return Hi.__construct(ret); + } + summarize() { + instance.exports.bjs_Hi_summarize(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + appendingZero() { + const ret = instance.exports.bjs_Hi_appendingZero(this.pointer); + return Hi.__construct(ret); + } + get largeContents() { + instance.exports.bjs_Hi_largeContents_get(this.pointer); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const int = i32Stack.pop(); + arrayResult.push(int); + } + arrayResult.reverse(); + return arrayResult; + } + } + class Container extends SwiftHeapObject { + copy() { + return Container.__construct(instance.exports.bjs_Container_copy(this.pointer)); + } + + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Container_deinit, Container.prototype, null); + } + + get payload() { + const ret = instance.exports.bjs_Container_payload_get(this.pointer); + return LargePayload.__construct(ret); + } + } + class MutableBox extends SwiftHeapObject { + copy() { + return MutableBox.__construct(instance.exports.bjs_MutableBox_copy(this.pointer)); + } + + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_MutableBox_deinit, MutableBox.prototype, null); + } + + get counter() { + const ret = instance.exports.bjs_MutableBox_counter_get(this.pointer); + return ret; + } + set counter(value) { + instance.exports.bjs_MutableBox_counter_set(this.pointer, value); + } + get label() { + instance.exports.bjs_MutableBox_label_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + const ValueWithBoxedFieldHelpers = __bjs_createValueWithBoxedFieldHelpers(); + structHelpers.ValueWithBoxedField = ValueWithBoxedFieldHelpers; + + const exports = { + LargePayload, + Hi, + Container, + MutableBox, + roundtripBoxed: function bjs_roundtripBoxed(p) { + const ret = instance.exports.bjs_roundtripBoxed(p.pointer); + return LargePayload.__construct(ret); + }, + mayMakeHi: function bjs_mayMakeHi(flag) { + instance.exports.bjs_mayMakeHi(flag); + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + const optResult = pointer === null ? null : Hi.__construct(pointer); + return optResult; + }, + consumeBoxedArray: function bjs_consumeBoxedArray(items) { + for (const elem of items) { + ptrStack.push(elem.pointer); + } + i32Stack.push(items.length); + instance.exports.bjs_consumeBoxedArray(); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = ptrStack.pop(); + const obj = Hi.__construct(ptr); + arrayResult.push(obj); + } + arrayResult.reverse(); + return arrayResult; + }, + consumeBoxedDictionary: function bjs_consumeBoxedDictionary(items) { + const entries = Object.entries(items); + for (const entry of entries) { + const [key, value] = entry; + const bytes = textEncoder.encode(key); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + ptrStack.push(value.pointer); + } + i32Stack.push(entries.length); + instance.exports.bjs_consumeBoxedDictionary(); + const dictLen = i32Stack.pop(); + const dictResult = {}; + for (let i = 0; i < dictLen; i++) { + const ptr = ptrStack.pop(); + const obj = Hi.__construct(ptr); + const string = strStack.pop(); + dictResult[string] = obj; + } + return dictResult; + }, + optionalBoxedArray: function bjs_optionalBoxedArray(flag) { + instance.exports.bjs_optionalBoxedArray(flag); + const isSome = i32Stack.pop(); + let optResult; + if (isSome) { + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = ptrStack.pop(); + const obj = Hi.__construct(ptr); + arrayResult.push(obj); + } + arrayResult.reverse(); + optResult = arrayResult; + } else { + optResult = null; + } + return optResult; + }, + arrayOfOptionalBoxed: function bjs_arrayOfOptionalBoxed(flag) { + instance.exports.bjs_arrayOfOptionalBoxed(flag); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const isSome = i32Stack.pop(); + let optValue; + if (isSome === 0) { + optValue = null; + } else { + const ptr = ptrStack.pop(); + const obj = Hi.__construct(ptr); + optValue = obj; + } + arrayResult.push(optValue); + } + arrayResult.reverse(); + return arrayResult; + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index ebad67a4d..91faa4fea 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -607,6 +607,62 @@ extension JSValue: _BridgedSwiftStackType { /// The conformance is automatically synthesized by the BridgeJS code generator. public protocol _BridgedSwiftHeapObject: AnyObject, _BridgedSwiftStackType {} +/// Allocate a box and assign a value for a `@JS(structStyle: .reference)` struct. +@_spi(BridgeJS) @_transparent +public func _bridgeJSAllocateBox(_ value: consuming T) -> UnsafeMutableRawPointer { + let p = UnsafeMutablePointer.allocate(capacity: 1) + p.initialize(to: value) + return UnsafeMutableRawPointer(p) +} + +@_spi(BridgeJS) @_transparent +public func _bridgeJSDeallocateBox(_ pointer: UnsafeMutableRawPointer, as: T.Type) { + let p = pointer.assumingMemoryBound(to: T.self) + p.deinitialize(count: 1) + p.deallocate() +} + +public protocol _BridgedSwiftBoxedValueStruct: _BridgedSwiftStackType where StackLiftResult == Self {} + +extension _BridgedSwiftBoxedValueStruct { + // MARK: ImportTS + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> UnsafeMutableRawPointer { + return _bridgeJSAllocateBox(self) + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Self { + return pointer.assumingMemoryBound(to: Self.self).pointee + } + + // MARK: ExportSwift + + // `bridgeJSLiftParameter` is not provided here, the codegen emits the + // explicit `p.assumingMemoryBound(to: Self.self).pointee` chain instead, so + // we have an l-value for mutating methods. + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> UnsafeMutableRawPointer { + return _bridgeJSAllocateBox(self) + } + + // MARK: Stack ABI + @_spi(BridgeJS) public static func bridgeJSStackPop() -> Self { + _swift_js_pop_pointer().assumingMemoryBound(to: Self.self).pointee + } + @_spi(BridgeJS) public consuming func bridgeJSStackPush() { + _swift_js_push_pointer(_bridgeJSAllocateBox(self)) + } + + // MARK: Per-struct `bjs__copy` / `bjs__deinit` thunks + @_spi(BridgeJS) @_transparent public static func bridgeJSCopyBox( + _ pointer: UnsafeMutableRawPointer + ) -> UnsafeMutableRawPointer { + return _bridgeJSAllocateBox(pointer.assumingMemoryBound(to: Self.self).pointee) + } + + @_spi(BridgeJS) @_transparent public static func bridgeJSReleaseBox(_ pointer: UnsafeMutableRawPointer) { + _bridgeJSDeallocateBox(pointer, as: Self.self) + } +} + /// Define the lowering/lifting for `_BridgedSwiftHeapObject` extension _BridgedSwiftHeapObject { @@ -1772,6 +1828,58 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftHeapObject { } } +extension _BridgedAsOptional where Wrapped: _BridgedSwiftBoxedValueStruct { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> ( + isSome: Int32, pointer: UnsafeMutableRawPointer + ) { + switch asOptional { + case .none: + return (isSome: 0, pointer: UnsafeMutableRawPointer(bitPattern: 1)!) + case .some(let value): + return (isSome: 1, pointer: _bridgeJSAllocateBox(value)) + } + } + + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ pointer: UnsafeMutableRawPointer) -> Self { + if pointer == UnsafeMutableRawPointer(bitPattern: 0) { + return Self(optional: nil) + } else { + return Self(optional: Wrapped.bridgeJSLiftReturn(pointer)) + } + } + + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter( + _ isSome: Int32, + _ pointer: UnsafeMutableRawPointer + ) -> Self { + Self( + optional: Optional._bridgeJSLiftParameter( + isSome, + pointer, + liftWrapped: { $0.assumingMemoryBound(to: Wrapped.self).pointee } + ) + ) + } + + @_spi(BridgeJS) public static func bridgeJSLiftReturnFromSideChannel() -> Self { + let pointer = _swift_js_get_optional_heap_object_pointer() + if pointer == UnsafeMutableRawPointer(bitPattern: 0) { + return Self(optional: nil) + } else { + return Self(optional: Wrapped.bridgeJSLiftReturn(pointer)) + } + } + + @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { + switch asOptional { + case .none: + _swift_js_return_optional_heap_object(0, nil) + case .some(let value): + _swift_js_return_optional_heap_object(1, _bridgeJSAllocateBox(value)) + } + } +} + extension _BridgedAsOptional where Wrapped: _BridgedSwiftCaseEnum { @_spi(BridgeJS) public consuming func bridgeJSLowerParameter() -> (isSome: Int32, value: Int32) { asOptional._bridgeJSLowerParameter(noneValue: 0, lowerWrapped: { $0.bridgeJSLowerParameter() }) diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md index c4a9524d9..82189842b 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Struct.md @@ -153,6 +153,26 @@ Structs use **copy semantics** when crossing the Swift/JavaScript boundary: This differs from classes, which use reference semantics and share state across the boundary. +## Structs Exported as References + +By default, every field of the struct will be copied on every boundary crossing. For a struct that holds a large payload (e.g. a large array, `String`), this copy can be very inefficient. Marking a struct with `@JS(structStyle: .reference)` opts into boxing: the struct lives on the Swift heap and JavaScript holds an opaque handle to it, so no field-by-field copy is performed. + +### Syntax + +```swift +@JS(structStyle: .reference) struct Dataset { + @JS let values: [Int] + + @JS init(values: [Int]) { + self.values = values + } + + @JS func summarize() -> String { + "\(values.count) values, with a sum of \(values.reduce(0, +))" + } +} +``` + ## Supported Features | Swift Feature | Status | @@ -166,7 +186,7 @@ This differs from classes, which use reference semantics and share state across | Static methods | ✅ | | Static properties | ✅ | | Extension methods/properties | ✅ | -| Property observers (`willSet`, `didSet`) | ❌ | +| Property observers (`willSet`, `didSet`) | ✅ (reference mode only) | | Generics | ❌ | | Conformances | ❌ | diff --git a/Sources/JavaScriptKit/Macros.swift b/Sources/JavaScriptKit/Macros.swift index 3189cdeab..cd165ec9a 100644 --- a/Sources/JavaScriptKit/Macros.swift +++ b/Sources/JavaScriptKit/Macros.swift @@ -6,6 +6,17 @@ public enum JSEnumStyle: String { case tsEnum } +/// Controls how Swift structs annotated with `@JS` cross the JavaScript/Swift +/// boundary. +/// - `fields`: Field-by-field copy on each crossing. The JS side sees a plain +/// object. Every stored property is auto-exported. +/// - `reference`: Heap-allocate the struct and pass a pointer across the +/// boundary. Stored properties need `@JS` to be visible. +public enum JSStructStyle: String { + case fields + case reference +} + /// Controls where BridgeJS reads imported JS values from. /// /// - `global`: Read from `globalThis`. @@ -110,11 +121,18 @@ public enum JSImportFrom: String { /// or `.tsEnum` to emit a TypeScript `enum`. /// `.tsEnum` is supported for case enums and raw-value enums with String or numeric raw types. /// Bool raw-value enums are not supported with `.tsEnum` and will produce an error. +/// - Parameter structStyle: Controls how the struct crosses the boundary: `.fields` (default when +/// unspecified) copies each stored property, while `.reference` heap-allocates +/// the struct and exposes it as a JS reference. /// /// - Important: This feature is still experimental. No API stability is guaranteed, and the API may change in future releases. @attached(peer) -public macro JS(namespace: String? = nil, enumStyle: JSEnumStyle = .const, identityMode: Bool = false) = - Builtin.ExternalMacro +public macro JS( + namespace: String? = nil, + enumStyle: JSEnumStyle = .const, + identityMode: Bool = false, + structStyle: JSStructStyle? = nil +) = Builtin.ExternalMacro /// A macro that generates a Swift getter that reads a value from JavaScript. /// diff --git a/Tests/BridgeJSRuntimeTests/BoxedStructTests.swift b/Tests/BridgeJSRuntimeTests/BoxedStructTests.swift new file mode 100644 index 000000000..ba9d77536 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/BoxedStructTests.swift @@ -0,0 +1,219 @@ +import XCTest +import JavaScriptKit + +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "runBoxedStructWorks") +@_extern(c) +func runBoxedStructWorks() -> Void + +@JS(structStyle: .reference) struct BoxedSummary { + @JS let largeContents: [Int] + @JS let label: String + + @JS init(largeContents: [Int], label: String) { + self.largeContents = largeContents + self.label = label + } + + @JS func summarize() -> String { + "\(label): count=\(largeContents.count) sum=\(largeContents.reduce(0, +))" + } + + @JS func appendingZero() -> BoxedSummary { + BoxedSummary(largeContents: largeContents + [0], label: label) + } +} + +@JS(structStyle: .reference) struct LeakCheckBoxed { + let id: Int + + @JS init(id: Int) { self.id = id } + + @JS func incremented() -> LeakCheckBoxed { + LeakCheckBoxed(id: id + 1) + } +} + +@JS func makeBoxedSummary(_ values: [Int], _ label: String) -> BoxedSummary { + BoxedSummary(largeContents: values, label: label) +} + +@JS struct ValueWithBoxedField { + let payload: BoxedSummary + let label: String + + @JS init(payload: BoxedSummary, label: String) { + self.payload = payload + self.label = label + } +} + +@JS func makeValueWithBoxedField(_ values: [Int], _ payloadLabel: String, _ outerLabel: String) -> ValueWithBoxedField { + ValueWithBoxedField( + payload: BoxedSummary(largeContents: values, label: payloadLabel), + label: outerLabel + ) +} + +@JS func roundtripValueWithBoxedField(_ value: ValueWithBoxedField) -> ValueWithBoxedField { value } + +@JS struct ValueWithOptionalBoxedField { + let payload: BoxedSummary? + let tag: String + + @JS init(payload: BoxedSummary?, tag: String) { + self.payload = payload + self.tag = tag + } +} + +@JS func makeValueWithOptionalBoxedField(_ flag: Bool, _ tag: String) -> ValueWithOptionalBoxedField { + ValueWithOptionalBoxedField( + payload: flag ? BoxedSummary(largeContents: [9, 9], label: "inner") : nil, + tag: tag + ) +} + +@JS func roundtripValueWithOptionalBoxedField( + _ value: ValueWithOptionalBoxedField +) -> ValueWithOptionalBoxedField { value } + +@JS func consumeBoxedArray(_ items: [BoxedSummary]) -> [BoxedSummary] { + items.map { BoxedSummary(largeContents: $0.largeContents + [0], label: $0.label + "!") } +} + +@JS func makeBoxedArray(_ count: Int) -> [BoxedSummary] { + (0.. [String: BoxedSummary] { + var result: [String: BoxedSummary] = [:] + for (key, value) in items { + result[key] = BoxedSummary(largeContents: value.largeContents, label: key + ":" + value.label) + } + return result +} + +@JS func optionalBoxedArray(_ flag: Bool) -> [BoxedSummary]? { + flag ? [BoxedSummary(largeContents: [1], label: "a"), BoxedSummary(largeContents: [2], label: "b")] : nil +} + +@JS func arrayOfOptionalBoxed(_ flag: Bool) -> [BoxedSummary?] { + flag + ? [BoxedSummary(largeContents: [1], label: "x"), nil, BoxedSummary(largeContents: [2], label: "y")] + : [] +} + +@JS func roundtripBoxedSummary(_ value: BoxedSummary) -> BoxedSummary { value } + +@JS func boxedSummaryLabel(_ value: BoxedSummary) -> String { value.label } + +@JS func optionalBoxedSummary(_ flag: Bool) -> BoxedSummary? { + flag ? BoxedSummary(largeContents: [1, 2, 3], label: "present") : nil +} + +@JS func roundtripOptionalBoxedSummary(_ value: BoxedSummary?) -> BoxedSummary? { + value +} + +@JS func makeLeakCheckBoxed(_ id: Int) -> LeakCheckBoxed { LeakCheckBoxed(id: id) } + +@JS(structStyle: .reference) struct MutableCounter { + let count: Int + + @JS init(count: Int) { self.count = count } + + @JS mutating func bump() { + self = MutableCounter(count: count + 1) + } + + @JS func currentCount() -> Int { count } +} + +@JS func makeMutableCounter(_ initial: Int) -> MutableCounter { + MutableCounter(count: initial) +} + +@JS(structStyle: .reference) struct DirectMutable { + @JS var count: Int + @JS let label: String + + @JS init(count: Int, label: String) { + self.count = count + self.label = label + } + + @JS func describe() -> String { + "\(label):\(count)" + } +} + +@JS func makeDirectMutable(_ count: Int, _ label: String) -> DirectMutable { + DirectMutable(count: count, label: label) +} + +@JS class BoxedStructConsumer { + @JS init() {} + + @JS func formatSummary(_ value: BoxedSummary) -> String { + "\(value.label):\(value.largeContents.reduce(0, +))" + } + + @JS func mergeLabels(_ a: BoxedSummary, _ b: BoxedSummary) -> String { + "\(a.label)+\(b.label)" + } +} + +@JS(structStyle: .reference) struct BoxedConsumer { + let tag: String + + @JS init(tag: String) { self.tag = tag } + + @JS func describe(_ other: BoxedSummary) -> String { + "\(tag)→\(other.label)" + } +} + +@JS class TrackedThing { + nonisolated(unsafe) static var deinitCount = 0 + let id: Int + + @JS init(id: Int) { + self.id = id + } + + @JS func getId() -> Int { id } + + deinit { + TrackedThing.deinitCount += 1 + } +} + +@JS func getTrackedDeinitCount() -> Int { TrackedThing.deinitCount } + +@JS func resetTrackedDeinitCount() { TrackedThing.deinitCount = 0 } + +@JS(structStyle: .reference) struct BoxWithTrackedClass { + @JS let tracked: TrackedThing + let label: String + + @JS init(tracked: TrackedThing, label: String) { + self.tracked = tracked + self.label = label + } + + @JS func describeTracked() -> String { + "\(label):\(tracked.getId())" + } +} + +@JS func makeBoxWithFreshTracked(_ id: Int, _ label: String) -> BoxWithTrackedClass { + BoxWithTrackedClass(tracked: TrackedThing(id: id), label: label) +} + +@JS func roundtripBoxWithTrackedClass(_ box: BoxWithTrackedClass) -> BoxWithTrackedClass { box } + +final class BoxedStructTests: XCTestCase { + func testBoxedStructEndToEnd() { + runBoxedStructWorks() + } +} diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 4d920873d..a038e3206 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -5193,6 +5193,474 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { } } +@_expose(wasm, "bjs_BoxedSummary_init") +@_cdecl("bjs_BoxedSummary_init") +public func _bjs_BoxedSummary_init(_ labelBytes: Int32, _ labelLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = BoxedSummary(largeContents: [Int].bridgeJSStackPop(), label: String.bridgeJSLiftParameter(labelBytes, labelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedSummary_largeContents_get") +@_cdecl("bjs_BoxedSummary_largeContents_get") +public func _bjs_BoxedSummary_largeContents_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: BoxedSummary.self).pointee.largeContents + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedSummary_label_get") +@_cdecl("bjs_BoxedSummary_label_get") +public func _bjs_BoxedSummary_label_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: BoxedSummary.self).pointee.label + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedSummary_summarize") +@_cdecl("bjs_BoxedSummary_summarize") +public func _bjs_BoxedSummary_summarize(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: BoxedSummary.self).pointee.summarize() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedSummary_appendingZero") +@_cdecl("bjs_BoxedSummary_appendingZero") +public func _bjs_BoxedSummary_appendingZero(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: BoxedSummary.self).pointee.appendingZero() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedSummary_copy") +@_cdecl("bjs_BoxedSummary_copy") +public func _bjs_BoxedSummary_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return BoxedSummary.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedSummary_deinit") +@_cdecl("bjs_BoxedSummary_deinit") +public func _bjs_BoxedSummary_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + BoxedSummary.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension BoxedSummary: _BridgedSwiftBoxedValueStruct {} + +@_expose(wasm, "bjs_LeakCheckBoxed_init") +@_cdecl("bjs_LeakCheckBoxed_init") +public func _bjs_LeakCheckBoxed_init(_ id: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = LeakCheckBoxed(id: Int.bridgeJSLiftParameter(id)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_LeakCheckBoxed_incremented") +@_cdecl("bjs_LeakCheckBoxed_incremented") +public func _bjs_LeakCheckBoxed_incremented(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: LeakCheckBoxed.self).pointee.incremented() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_LeakCheckBoxed_copy") +@_cdecl("bjs_LeakCheckBoxed_copy") +public func _bjs_LeakCheckBoxed_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return LeakCheckBoxed.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_LeakCheckBoxed_deinit") +@_cdecl("bjs_LeakCheckBoxed_deinit") +public func _bjs_LeakCheckBoxed_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + LeakCheckBoxed.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension LeakCheckBoxed: _BridgedSwiftBoxedValueStruct {} + +extension ValueWithBoxedField: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> ValueWithBoxedField { + let label = String.bridgeJSStackPop() + let payload = BoxedSummary.bridgeJSStackPop() + return ValueWithBoxedField(payload: payload, label: label) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.payload.bridgeJSStackPush() + self.label.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_ValueWithBoxedField(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_ValueWithBoxedField())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ValueWithBoxedField") +fileprivate func _bjs_struct_lower_ValueWithBoxedField_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_ValueWithBoxedField_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_ValueWithBoxedField(_ objectId: Int32) -> Void { + return _bjs_struct_lower_ValueWithBoxedField_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_ValueWithBoxedField") +fileprivate func _bjs_struct_lift_ValueWithBoxedField_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_ValueWithBoxedField_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_ValueWithBoxedField() -> Int32 { + return _bjs_struct_lift_ValueWithBoxedField_extern() +} + +@_expose(wasm, "bjs_ValueWithBoxedField_init") +@_cdecl("bjs_ValueWithBoxedField_init") +public func _bjs_ValueWithBoxedField_init(_ payload: UnsafeMutableRawPointer, _ labelBytes: Int32, _ labelLength: Int32) -> Void { + #if arch(wasm32) + let ret = ValueWithBoxedField(payload: payload.assumingMemoryBound(to: BoxedSummary.self).pointee, label: String.bridgeJSLiftParameter(labelBytes, labelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension ValueWithOptionalBoxedField: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> ValueWithOptionalBoxedField { + let tag = String.bridgeJSStackPop() + let payload = Optional.bridgeJSStackPop() + return ValueWithOptionalBoxedField(payload: payload, tag: tag) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.payload.bridgeJSStackPush() + self.tag.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_ValueWithOptionalBoxedField(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_ValueWithOptionalBoxedField())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_ValueWithOptionalBoxedField") +fileprivate func _bjs_struct_lower_ValueWithOptionalBoxedField_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_ValueWithOptionalBoxedField_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_ValueWithOptionalBoxedField(_ objectId: Int32) -> Void { + return _bjs_struct_lower_ValueWithOptionalBoxedField_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_ValueWithOptionalBoxedField") +fileprivate func _bjs_struct_lift_ValueWithOptionalBoxedField_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_ValueWithOptionalBoxedField_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_ValueWithOptionalBoxedField() -> Int32 { + return _bjs_struct_lift_ValueWithOptionalBoxedField_extern() +} + +@_expose(wasm, "bjs_ValueWithOptionalBoxedField_init") +@_cdecl("bjs_ValueWithOptionalBoxedField_init") +public func _bjs_ValueWithOptionalBoxedField_init(_ payloadIsSome: Int32, _ payloadValue: UnsafeMutableRawPointer, _ tagBytes: Int32, _ tagLength: Int32) -> Void { + #if arch(wasm32) + let ret = ValueWithOptionalBoxedField(payload: Optional.bridgeJSLiftParameter(payloadIsSome, payloadValue), tag: String.bridgeJSLiftParameter(tagBytes, tagLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableCounter_init") +@_cdecl("bjs_MutableCounter_init") +public func _bjs_MutableCounter_init(_ count: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = MutableCounter(count: Int.bridgeJSLiftParameter(count)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableCounter_bump") +@_cdecl("bjs_MutableCounter_bump") +public func _bjs_MutableCounter_bump(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + _self.assumingMemoryBound(to: MutableCounter.self).pointee.bump() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableCounter_currentCount") +@_cdecl("bjs_MutableCounter_currentCount") +public func _bjs_MutableCounter_currentCount(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: MutableCounter.self).pointee.currentCount() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableCounter_copy") +@_cdecl("bjs_MutableCounter_copy") +public func _bjs_MutableCounter_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return MutableCounter.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MutableCounter_deinit") +@_cdecl("bjs_MutableCounter_deinit") +public func _bjs_MutableCounter_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + MutableCounter.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension MutableCounter: _BridgedSwiftBoxedValueStruct {} + +@_expose(wasm, "bjs_DirectMutable_init") +@_cdecl("bjs_DirectMutable_init") +public func _bjs_DirectMutable_init(_ count: Int32, _ labelBytes: Int32, _ labelLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = DirectMutable(count: Int.bridgeJSLiftParameter(count), label: String.bridgeJSLiftParameter(labelBytes, labelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DirectMutable_count_get") +@_cdecl("bjs_DirectMutable_count_get") +public func _bjs_DirectMutable_count_get(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: DirectMutable.self).pointee.count + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DirectMutable_count_set") +@_cdecl("bjs_DirectMutable_count_set") +public func _bjs_DirectMutable_count_set(_ _self: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + _self.assumingMemoryBound(to: DirectMutable.self).pointee.count = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DirectMutable_label_get") +@_cdecl("bjs_DirectMutable_label_get") +public func _bjs_DirectMutable_label_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: DirectMutable.self).pointee.label + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DirectMutable_describe") +@_cdecl("bjs_DirectMutable_describe") +public func _bjs_DirectMutable_describe(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: DirectMutable.self).pointee.describe() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DirectMutable_copy") +@_cdecl("bjs_DirectMutable_copy") +public func _bjs_DirectMutable_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return DirectMutable.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_DirectMutable_deinit") +@_cdecl("bjs_DirectMutable_deinit") +public func _bjs_DirectMutable_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + DirectMutable.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension DirectMutable: _BridgedSwiftBoxedValueStruct {} + +@_expose(wasm, "bjs_BoxedConsumer_init") +@_cdecl("bjs_BoxedConsumer_init") +public func _bjs_BoxedConsumer_init(_ tagBytes: Int32, _ tagLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = BoxedConsumer(tag: String.bridgeJSLiftParameter(tagBytes, tagLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedConsumer_describe") +@_cdecl("bjs_BoxedConsumer_describe") +public func _bjs_BoxedConsumer_describe(_ _self: UnsafeMutableRawPointer, _ other: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: BoxedConsumer.self).pointee.describe(_: other.assumingMemoryBound(to: BoxedSummary.self).pointee) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedConsumer_copy") +@_cdecl("bjs_BoxedConsumer_copy") +public func _bjs_BoxedConsumer_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return BoxedConsumer.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedConsumer_deinit") +@_cdecl("bjs_BoxedConsumer_deinit") +public func _bjs_BoxedConsumer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + BoxedConsumer.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension BoxedConsumer: _BridgedSwiftBoxedValueStruct {} + +@_expose(wasm, "bjs_BoxWithTrackedClass_init") +@_cdecl("bjs_BoxWithTrackedClass_init") +public func _bjs_BoxWithTrackedClass_init(_ tracked: UnsafeMutableRawPointer, _ labelBytes: Int32, _ labelLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = BoxWithTrackedClass(tracked: TrackedThing.bridgeJSLiftParameter(tracked), label: String.bridgeJSLiftParameter(labelBytes, labelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxWithTrackedClass_tracked_get") +@_cdecl("bjs_BoxWithTrackedClass_tracked_get") +public func _bjs_BoxWithTrackedClass_tracked_get(_ _self: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: BoxWithTrackedClass.self).pointee.tracked + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxWithTrackedClass_describeTracked") +@_cdecl("bjs_BoxWithTrackedClass_describeTracked") +public func _bjs_BoxWithTrackedClass_describeTracked(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = _self.assumingMemoryBound(to: BoxWithTrackedClass.self).pointee.describeTracked() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxWithTrackedClass_copy") +@_cdecl("bjs_BoxWithTrackedClass_copy") +public func _bjs_BoxWithTrackedClass_copy(_ pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + return BoxWithTrackedClass.bridgeJSCopyBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxWithTrackedClass_deinit") +@_cdecl("bjs_BoxWithTrackedClass_deinit") +public func _bjs_BoxWithTrackedClass_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + BoxWithTrackedClass.bridgeJSReleaseBox(pointer) + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension BoxWithTrackedClass: _BridgedSwiftBoxedValueStruct {} + extension Point: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Point { let y = Int.bridgeJSStackPop() @@ -6441,6 +6909,236 @@ public func _bjs_ArrayMembers_firstString() -> Void { #endif } +@_expose(wasm, "bjs_makeBoxedSummary") +@_cdecl("bjs_makeBoxedSummary") +public func _bjs_makeBoxedSummary(_ labelBytes: Int32, _ labelLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = makeBoxedSummary(_: [Int].bridgeJSStackPop(), _: String.bridgeJSLiftParameter(labelBytes, labelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeValueWithBoxedField") +@_cdecl("bjs_makeValueWithBoxedField") +public func _bjs_makeValueWithBoxedField(_ payloadLabelBytes: Int32, _ payloadLabelLength: Int32, _ outerLabelBytes: Int32, _ outerLabelLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeValueWithBoxedField(_: [Int].bridgeJSStackPop(), _: String.bridgeJSLiftParameter(payloadLabelBytes, payloadLabelLength), _: String.bridgeJSLiftParameter(outerLabelBytes, outerLabelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripValueWithBoxedField") +@_cdecl("bjs_roundtripValueWithBoxedField") +public func _bjs_roundtripValueWithBoxedField() -> Void { + #if arch(wasm32) + let ret = roundtripValueWithBoxedField(_: ValueWithBoxedField.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeValueWithOptionalBoxedField") +@_cdecl("bjs_makeValueWithOptionalBoxedField") +public func _bjs_makeValueWithOptionalBoxedField(_ flag: Int32, _ tagBytes: Int32, _ tagLength: Int32) -> Void { + #if arch(wasm32) + let ret = makeValueWithOptionalBoxedField(_: Bool.bridgeJSLiftParameter(flag), _: String.bridgeJSLiftParameter(tagBytes, tagLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripValueWithOptionalBoxedField") +@_cdecl("bjs_roundtripValueWithOptionalBoxedField") +public func _bjs_roundtripValueWithOptionalBoxedField() -> Void { + #if arch(wasm32) + let ret = roundtripValueWithOptionalBoxedField(_: ValueWithOptionalBoxedField.bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_consumeBoxedArray") +@_cdecl("bjs_consumeBoxedArray") +public func _bjs_consumeBoxedArray() -> Void { + #if arch(wasm32) + let ret = consumeBoxedArray(_: [BoxedSummary].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeBoxedArray") +@_cdecl("bjs_makeBoxedArray") +public func _bjs_makeBoxedArray(_ count: Int32) -> Void { + #if arch(wasm32) + let ret = makeBoxedArray(_: Int.bridgeJSLiftParameter(count)) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_consumeBoxedDictionary") +@_cdecl("bjs_consumeBoxedDictionary") +public func _bjs_consumeBoxedDictionary() -> Void { + #if arch(wasm32) + let ret = consumeBoxedDictionary(_: [String: BoxedSummary].bridgeJSLiftParameter()) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_optionalBoxedArray") +@_cdecl("bjs_optionalBoxedArray") +public func _bjs_optionalBoxedArray(_ flag: Int32) -> Void { + #if arch(wasm32) + let ret = optionalBoxedArray(_: Bool.bridgeJSLiftParameter(flag)) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_arrayOfOptionalBoxed") +@_cdecl("bjs_arrayOfOptionalBoxed") +public func _bjs_arrayOfOptionalBoxed(_ flag: Int32) -> Void { + #if arch(wasm32) + let ret = arrayOfOptionalBoxed(_: Bool.bridgeJSLiftParameter(flag)) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripBoxedSummary") +@_cdecl("bjs_roundtripBoxedSummary") +public func _bjs_roundtripBoxedSummary(_ value: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundtripBoxedSummary(_: value.assumingMemoryBound(to: BoxedSummary.self).pointee) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_boxedSummaryLabel") +@_cdecl("bjs_boxedSummaryLabel") +public func _bjs_boxedSummaryLabel(_ value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = boxedSummaryLabel(_: value.assumingMemoryBound(to: BoxedSummary.self).pointee) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_optionalBoxedSummary") +@_cdecl("bjs_optionalBoxedSummary") +public func _bjs_optionalBoxedSummary(_ flag: Int32) -> Void { + #if arch(wasm32) + let ret = optionalBoxedSummary(_: Bool.bridgeJSLiftParameter(flag)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripOptionalBoxedSummary") +@_cdecl("bjs_roundtripOptionalBoxedSummary") +public func _bjs_roundtripOptionalBoxedSummary(_ valueIsSome: Int32, _ valueValue: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = roundtripOptionalBoxedSummary(_: Optional.bridgeJSLiftParameter(valueIsSome, valueValue)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeLeakCheckBoxed") +@_cdecl("bjs_makeLeakCheckBoxed") +public func _bjs_makeLeakCheckBoxed(_ id: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = makeLeakCheckBoxed(_: Int.bridgeJSLiftParameter(id)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeMutableCounter") +@_cdecl("bjs_makeMutableCounter") +public func _bjs_makeMutableCounter(_ initial: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = makeMutableCounter(_: Int.bridgeJSLiftParameter(initial)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeDirectMutable") +@_cdecl("bjs_makeDirectMutable") +public func _bjs_makeDirectMutable(_ count: Int32, _ labelBytes: Int32, _ labelLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = makeDirectMutable(_: Int.bridgeJSLiftParameter(count), _: String.bridgeJSLiftParameter(labelBytes, labelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_getTrackedDeinitCount") +@_cdecl("bjs_getTrackedDeinitCount") +public func _bjs_getTrackedDeinitCount() -> Int32 { + #if arch(wasm32) + let ret = getTrackedDeinitCount() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_resetTrackedDeinitCount") +@_cdecl("bjs_resetTrackedDeinitCount") +public func _bjs_resetTrackedDeinitCount() -> Void { + #if arch(wasm32) + resetTrackedDeinitCount() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_makeBoxWithFreshTracked") +@_cdecl("bjs_makeBoxWithFreshTracked") +public func _bjs_makeBoxWithFreshTracked(_ id: Int32, _ labelBytes: Int32, _ labelLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = makeBoxWithFreshTracked(_: Int.bridgeJSLiftParameter(id), _: String.bridgeJSLiftParameter(labelBytes, labelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundtripBoxWithTrackedClass") +@_cdecl("bjs_roundtripBoxWithTrackedClass") +public func _bjs_roundtripBoxWithTrackedClass(_ box: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundtripBoxWithTrackedClass(_: box.assumingMemoryBound(to: BoxWithTrackedClass.self).pointee) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_roundTripVoid") @_cdecl("bjs_roundTripVoid") public func _bjs_roundTripVoid() -> Void { @@ -7872,6 +8570,123 @@ public func _bjs_arrayMembersFirst() -> Void { #endif } +@_expose(wasm, "bjs_BoxedStructConsumer_init") +@_cdecl("bjs_BoxedStructConsumer_init") +public func _bjs_BoxedStructConsumer_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = BoxedStructConsumer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedStructConsumer_formatSummary") +@_cdecl("bjs_BoxedStructConsumer_formatSummary") +public func _bjs_BoxedStructConsumer_formatSummary(_ _self: UnsafeMutableRawPointer, _ value: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = BoxedStructConsumer.bridgeJSLiftParameter(_self).formatSummary(_: value.assumingMemoryBound(to: BoxedSummary.self).pointee) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedStructConsumer_mergeLabels") +@_cdecl("bjs_BoxedStructConsumer_mergeLabels") +public func _bjs_BoxedStructConsumer_mergeLabels(_ _self: UnsafeMutableRawPointer, _ a: UnsafeMutableRawPointer, _ b: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = BoxedStructConsumer.bridgeJSLiftParameter(_self).mergeLabels(_: a.assumingMemoryBound(to: BoxedSummary.self).pointee, _: b.assumingMemoryBound(to: BoxedSummary.self).pointee) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_BoxedStructConsumer_deinit") +@_cdecl("bjs_BoxedStructConsumer_deinit") +public func _bjs_BoxedStructConsumer_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension BoxedStructConsumer: ConvertibleToJSValue, _BridgedSwiftHeapObject, _BridgedSwiftProtocolExportable { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_BoxedStructConsumer_wrap(Unmanaged.passRetained(self).toOpaque())))) + } + consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { + _bjs_BoxedStructConsumer_wrap(Unmanaged.passRetained(self).toOpaque()) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_BoxedStructConsumer_wrap") +fileprivate func _bjs_BoxedStructConsumer_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_BoxedStructConsumer_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_BoxedStructConsumer_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_BoxedStructConsumer_wrap_extern(pointer) +} + +@_expose(wasm, "bjs_TrackedThing_init") +@_cdecl("bjs_TrackedThing_init") +public func _bjs_TrackedThing_init(_ id: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = TrackedThing(id: Int.bridgeJSLiftParameter(id)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TrackedThing_getId") +@_cdecl("bjs_TrackedThing_getId") +public func _bjs_TrackedThing_getId(_ _self: UnsafeMutableRawPointer) -> Int32 { + #if arch(wasm32) + let ret = TrackedThing.bridgeJSLiftParameter(_self).getId() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_TrackedThing_deinit") +@_cdecl("bjs_TrackedThing_deinit") +public func _bjs_TrackedThing_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension TrackedThing: ConvertibleToJSValue, _BridgedSwiftHeapObject, _BridgedSwiftProtocolExportable { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_TrackedThing_wrap(Unmanaged.passRetained(self).toOpaque())))) + } + consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { + _bjs_TrackedThing_wrap(Unmanaged.passRetained(self).toOpaque()) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_TrackedThing_wrap") +fileprivate func _bjs_TrackedThing_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_TrackedThing_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_TrackedThing_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_TrackedThing_wrap_extern(pointer) +} + @_expose(wasm, "bjs_ClosureSupportExports_static_makeIntToInt") @_cdecl("bjs_ClosureSupportExports_static_makeIntToInt") public func _bjs_ClosureSupportExports_static_makeIntToInt(_ base: Int32) -> Int32 { diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index d9108f2e7..7718539f4 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -1,6 +1,136 @@ { "exported" : { "classes" : [ + { + "constructor" : { + "abiName" : "bjs_BoxedStructConsumer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_BoxedStructConsumer_formatSummary", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "formatSummary", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_BoxedStructConsumer_mergeLabels", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "mergeLabels", + "parameters" : [ + { + "label" : "_", + "name" : "a", + "type" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + } + }, + { + "label" : "_", + "name" : "b", + "type" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "BoxedStructConsumer", + "properties" : [ + + ], + "swiftCallName" : "BoxedStructConsumer" + }, + { + "constructor" : { + "abiName" : "bjs_TrackedThing_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "id", + "name" : "id", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_TrackedThing_getId", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getId", + "parameters" : [ + + ], + "returnType" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "TrackedThing", + "properties" : [ + + ], + "swiftCallName" : "TrackedThing" + }, { "methods" : [ { @@ -11059,109 +11189,142 @@ "exposeToGlobal" : false, "functions" : [ { - "abiName" : "bjs_roundTripVoid", + "abiName" : "bjs_makeBoxedSummary", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripVoid", + "name" : "makeBoxedSummary", "parameters" : [ + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + }, + { + "label" : "_", + "name" : "label", + "type" : { + "string" : { + } + } + } ], "returnType" : { - "void" : { - + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } } }, { - "abiName" : "bjs_roundTripFloat", + "abiName" : "bjs_makeValueWithBoxedField", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripFloat", + "name" : "makeValueWithBoxedField", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "values", "type" : { - "float" : { + "array" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + }, + { + "label" : "_", + "name" : "payloadLabel", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "outerLabel", + "type" : { + "string" : { } } } ], "returnType" : { - "float" : { - + "swiftStruct" : { + "_0" : "ValueWithBoxedField" } } }, { - "abiName" : "bjs_roundTripDouble", + "abiName" : "bjs_roundtripValueWithBoxedField", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripDouble", + "name" : "roundtripValueWithBoxedField", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "value", "type" : { - "double" : { - + "swiftStruct" : { + "_0" : "ValueWithBoxedField" } } } ], "returnType" : { - "double" : { - + "swiftStruct" : { + "_0" : "ValueWithBoxedField" } } }, { - "abiName" : "bjs_roundTripBool", + "abiName" : "bjs_makeValueWithOptionalBoxedField", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripBool", + "name" : "makeValueWithOptionalBoxedField", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "flag", "type" : { "bool" : { } } - } - ], - "returnType" : { - "bool" : { - - } - } - }, - { - "abiName" : "bjs_roundTripString", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "roundTripString", - "parameters" : [ + }, { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "tag", "type" : { "string" : { @@ -11170,273 +11333,267 @@ } ], "returnType" : { - "string" : { - + "swiftStruct" : { + "_0" : "ValueWithOptionalBoxedField" } } }, { - "abiName" : "bjs_roundTripSwiftHeapObject", + "abiName" : "bjs_roundtripValueWithOptionalBoxedField", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripSwiftHeapObject", + "name" : "roundtripValueWithOptionalBoxedField", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "value", "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "swiftStruct" : { + "_0" : "ValueWithOptionalBoxedField" } } } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "swiftStruct" : { + "_0" : "ValueWithOptionalBoxedField" } } }, { - "abiName" : "bjs_roundTripUnsafeRawPointer", + "abiName" : "bjs_consumeBoxedArray", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripUnsafeRawPointer", + "name" : "consumeBoxedArray", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "items", "type" : { - "unsafePointer" : { + "array" : { "_0" : { - "kind" : "unsafeRawPointer" + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } } } } } ], "returnType" : { - "unsafePointer" : { + "array" : { "_0" : { - "kind" : "unsafeRawPointer" + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } } } } }, { - "abiName" : "bjs_roundTripUnsafeMutableRawPointer", + "abiName" : "bjs_makeBoxedArray", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripUnsafeMutableRawPointer", + "name" : "makeBoxedArray", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "count", "type" : { - "unsafePointer" : { + "integer" : { "_0" : { - "kind" : "unsafeMutableRawPointer" + "isSigned" : true, + "width" : "word" } } } } ], "returnType" : { - "unsafePointer" : { + "array" : { "_0" : { - "kind" : "unsafeMutableRawPointer" + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } } } } }, { - "abiName" : "bjs_roundTripOpaquePointer", + "abiName" : "bjs_consumeBoxedDictionary", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripOpaquePointer", + "name" : "consumeBoxedDictionary", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "items", "type" : { - "unsafePointer" : { + "dictionary" : { "_0" : { - "kind" : "opaquePointer" + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } } } } } ], "returnType" : { - "unsafePointer" : { + "dictionary" : { "_0" : { - "kind" : "opaquePointer" + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } } } } }, { - "abiName" : "bjs_roundTripUnsafePointer", + "abiName" : "bjs_optionalBoxedArray", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripUnsafePointer", + "name" : "optionalBoxedArray", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "flag", "type" : { - "unsafePointer" : { - "_0" : { - "kind" : "unsafePointer", - "pointee" : "UInt8" - } + "bool" : { + } } } ], "returnType" : { - "unsafePointer" : { + "nullable" : { "_0" : { - "kind" : "unsafePointer", - "pointee" : "UInt8" - } + "array" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + } + } + }, + "_1" : "null" } } }, { - "abiName" : "bjs_roundTripUnsafeMutablePointer", + "abiName" : "bjs_arrayOfOptionalBoxed", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripUnsafeMutablePointer", + "name" : "arrayOfOptionalBoxed", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "flag", "type" : { - "unsafePointer" : { - "_0" : { - "kind" : "unsafeMutablePointer", - "pointee" : "UInt8" - } + "bool" : { + } } } ], "returnType" : { - "unsafePointer" : { + "array" : { "_0" : { - "kind" : "unsafeMutablePointer", - "pointee" : "UInt8" + "nullable" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + }, + "_1" : "null" + } } } } }, { - "abiName" : "bjs_roundTripJSObject", + "abiName" : "bjs_roundtripBoxedSummary", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripJSObject", + "name" : "roundtripBoxedSummary", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "value", "type" : { - "jsObject" : { - + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } } } ], "returnType" : { - "jsObject" : { - + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } } }, { - "abiName" : "bjs_roundTripDictionaryExport", + "abiName" : "bjs_boxedSummaryLabel", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripDictionaryExport", + "name" : "boxedSummaryLabel", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "value", "type" : { - "dictionary" : { - "_0" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - } + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } } } ], "returnType" : { - "dictionary" : { - "_0" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - } + "string" : { + } } }, { - "abiName" : "bjs_roundTripOptionalDictionaryExport", + "abiName" : "bjs_optionalBoxedSummary", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripOptionalDictionaryExport", + "name" : "optionalBoxedSummary", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "flag", "type" : { - "nullable" : { - "_0" : { - "dictionary" : { - "_0" : { - "string" : { + "bool" : { - } - } - } - }, - "_1" : "null" } } } @@ -11444,12 +11601,8 @@ "returnType" : { "nullable" : { "_0" : { - "dictionary" : { - "_0" : { - "string" : { - - } - } + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } }, "_1" : "null" @@ -11457,47 +11610,22 @@ } }, { - "abiName" : "bjs_roundTripJSValue", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "roundTripJSValue", - "parameters" : [ - { - "label" : "v", - "name" : "v", - "type" : { - "jsValue" : { - - } - } - } - ], - "returnType" : { - "jsValue" : { - - } - } - }, - { - "abiName" : "bjs_roundTripOptionalJSValue", + "abiName" : "bjs_roundtripOptionalBoxedSummary", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripOptionalJSValue", + "name" : "roundtripOptionalBoxedSummary", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "value", "type" : { "nullable" : { "_0" : { - "jsValue" : { - + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } }, "_1" : "null" @@ -11508,8 +11636,8 @@ "returnType" : { "nullable" : { "_0" : { - "jsValue" : { - + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } }, "_1" : "null" @@ -11517,106 +11645,106 @@ } }, { - "abiName" : "bjs_roundTripOptionalJSValueArray", + "abiName" : "bjs_makeLeakCheckBoxed", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripOptionalJSValueArray", + "name" : "makeLeakCheckBoxed", "parameters" : [ { - "label" : "v", - "name" : "v", + "label" : "_", + "name" : "id", "type" : { - "nullable" : { + "integer" : { "_0" : { - "array" : { - "_0" : { - "jsValue" : { - - } - } - } - }, - "_1" : "null" + "isSigned" : true, + "width" : "word" + } } } } ], "returnType" : { - "nullable" : { - "_0" : { - "array" : { - "_0" : { - "jsValue" : { - - } - } - } - }, - "_1" : "null" + "swiftBoxedStruct" : { + "_0" : "LeakCheckBoxed" } } }, { - "abiName" : "bjs_makeImportedFoo", + "abiName" : "bjs_makeMutableCounter", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "makeImportedFoo", + "name" : "makeMutableCounter", "parameters" : [ { - "label" : "value", - "name" : "value", + "label" : "_", + "name" : "initial", "type" : { - "string" : { - + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } } } } ], "returnType" : { - "jsObject" : { - "_0" : "Foo" + "swiftBoxedStruct" : { + "_0" : "MutableCounter" } } }, { - "abiName" : "bjs_throwsSwiftError", + "abiName" : "bjs_makeDirectMutable", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsSwiftError", + "name" : "makeDirectMutable", "parameters" : [ { - "label" : "shouldThrow", - "name" : "shouldThrow", + "label" : "_", + "name" : "count", "type" : { - "bool" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "_", + "name" : "label", + "type" : { + "string" : { } } } ], "returnType" : { - "void" : { - + "swiftBoxedStruct" : { + "_0" : "DirectMutable" } } }, { - "abiName" : "bjs_throwsWithIntResult", + "abiName" : "bjs_getTrackedDeinitCount", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithIntResult", + "name" : "getTrackedDeinitCount", "parameters" : [ ], @@ -11630,1434 +11758,1516 @@ } }, { - "abiName" : "bjs_throwsWithStringResult", + "abiName" : "bjs_resetTrackedDeinitCount", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithStringResult", + "name" : "resetTrackedDeinitCount", "parameters" : [ ], "returnType" : { - "string" : { + "void" : { } } }, { - "abiName" : "bjs_throwsWithBoolResult", + "abiName" : "bjs_makeBoxWithFreshTracked", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithBoolResult", + "name" : "makeBoxWithFreshTracked", "parameters" : [ + { + "label" : "_", + "name" : "id", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "_", + "name" : "label", + "type" : { + "string" : { + } + } + } ], "returnType" : { - "bool" : { - + "swiftBoxedStruct" : { + "_0" : "BoxWithTrackedClass" } } }, { - "abiName" : "bjs_throwsWithFloatResult", + "abiName" : "bjs_roundtripBoxWithTrackedClass", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithFloatResult", + "name" : "roundtripBoxWithTrackedClass", "parameters" : [ - + { + "label" : "_", + "name" : "box", + "type" : { + "swiftBoxedStruct" : { + "_0" : "BoxWithTrackedClass" + } + } + } ], "returnType" : { - "float" : { - + "swiftBoxedStruct" : { + "_0" : "BoxWithTrackedClass" } } }, { - "abiName" : "bjs_throwsWithDoubleResult", + "abiName" : "bjs_roundTripVoid", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithDoubleResult", + "name" : "roundTripVoid", "parameters" : [ ], "returnType" : { - "double" : { + "void" : { } } }, { - "abiName" : "bjs_throwsWithSwiftHeapObjectResult", + "abiName" : "bjs_roundTripFloat", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithSwiftHeapObjectResult", + "name" : "roundTripFloat", "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "float" : { + } + } + } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "float" : { + } } }, { - "abiName" : "bjs_throwsWithJSObjectResult", + "abiName" : "bjs_roundTripDouble", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : true + "isThrows" : false }, - "name" : "throwsWithJSObjectResult", + "name" : "roundTripDouble", "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "double" : { + } + } + } ], "returnType" : { - "jsObject" : { + "double" : { } } }, { - "abiName" : "bjs_asyncRoundTripVoid", + "abiName" : "bjs_roundTripBool", "effects" : { - "isAsync" : true, + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "asyncRoundTripVoid", + "name" : "roundTripBool", "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "bool" : { + } + } + } ], "returnType" : { - "void" : { + "bool" : { } } }, { - "abiName" : "bjs_asyncRoundTripInt", + "abiName" : "bjs_roundTripString", "effects" : { - "isAsync" : true, + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "asyncRoundTripInt", + "name" : "roundTripString", "parameters" : [ { "label" : "v", "name" : "v", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "string" : { + } } } ], "returnType" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "string" : { + } } }, { - "abiName" : "bjs_asyncRoundTripFloat", + "abiName" : "bjs_roundTripSwiftHeapObject", "effects" : { - "isAsync" : true, + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "asyncRoundTripFloat", + "name" : "roundTripSwiftHeapObject", "parameters" : [ { "label" : "v", "name" : "v", "type" : { - "float" : { - + "swiftHeapObject" : { + "_0" : "Greeter" } } } ], "returnType" : { - "float" : { - + "swiftHeapObject" : { + "_0" : "Greeter" } } }, { - "abiName" : "bjs_asyncRoundTripDouble", + "abiName" : "bjs_roundTripUnsafeRawPointer", "effects" : { - "isAsync" : true, + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "asyncRoundTripDouble", + "name" : "roundTripUnsafeRawPointer", "parameters" : [ { "label" : "v", "name" : "v", "type" : { - "double" : { - + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } } } } ], "returnType" : { - "double" : { - + "unsafePointer" : { + "_0" : { + "kind" : "unsafeRawPointer" + } } } }, { - "abiName" : "bjs_asyncRoundTripBool", + "abiName" : "bjs_roundTripUnsafeMutableRawPointer", "effects" : { - "isAsync" : true, + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "asyncRoundTripBool", + "name" : "roundTripUnsafeMutableRawPointer", "parameters" : [ { "label" : "v", "name" : "v", "type" : { - "bool" : { - + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } } } } ], "returnType" : { - "bool" : { - + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutableRawPointer" + } } } }, { - "abiName" : "bjs_asyncRoundTripString", + "abiName" : "bjs_roundTripOpaquePointer", "effects" : { - "isAsync" : true, + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "asyncRoundTripString", + "name" : "roundTripOpaquePointer", "parameters" : [ { "label" : "v", "name" : "v", "type" : { - "string" : { - + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } } } } ], "returnType" : { - "string" : { - + "unsafePointer" : { + "_0" : { + "kind" : "opaquePointer" + } } } }, { - "abiName" : "bjs_asyncRoundTripSwiftHeapObject", + "abiName" : "bjs_roundTripUnsafePointer", "effects" : { - "isAsync" : true, + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "asyncRoundTripSwiftHeapObject", + "name" : "roundTripUnsafePointer", "parameters" : [ { "label" : "v", "name" : "v", "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } } } } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "unsafePointer" : { + "_0" : { + "kind" : "unsafePointer", + "pointee" : "UInt8" + } } } }, { - "abiName" : "bjs_asyncRoundTripJSObject", + "abiName" : "bjs_roundTripUnsafeMutablePointer", "effects" : { - "isAsync" : true, + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "asyncRoundTripJSObject", + "name" : "roundTripUnsafeMutablePointer", "parameters" : [ { "label" : "v", "name" : "v", "type" : { - "jsObject" : { - + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } } } } ], "returnType" : { - "jsObject" : { - + "unsafePointer" : { + "_0" : { + "kind" : "unsafeMutablePointer", + "pointee" : "UInt8" + } } } }, { - "abiName" : "bjs_takeGreeter", + "abiName" : "bjs_roundTripJSObject", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "takeGreeter", + "name" : "roundTripJSObject", "parameters" : [ { - "label" : "g", - "name" : "g", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - } - }, - { - "label" : "name", - "name" : "name", + "label" : "v", + "name" : "v", "type" : { - "string" : { + "jsObject" : { } } } ], "returnType" : { - "void" : { + "jsObject" : { } } }, { - "abiName" : "bjs_createCalculator", + "abiName" : "bjs_roundTripDictionaryExport", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "createCalculator", + "name" : "roundTripDictionaryExport", "parameters" : [ - + { + "label" : "v", + "name" : "v", + "type" : { + "dictionary" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Calculator" + "dictionary" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } } } }, { - "abiName" : "bjs_useCalculator", + "abiName" : "bjs_roundTripOptionalDictionaryExport", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "useCalculator", + "name" : "roundTripOptionalDictionaryExport", "parameters" : [ { - "label" : "calc", - "name" : "calc", - "type" : { - "swiftHeapObject" : { - "_0" : "Calculator" - } - } - }, - { - "label" : "x", - "name" : "x", - "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - } - }, - { - "label" : "y", - "name" : "y", + "label" : "v", + "name" : "v", "type" : { - "integer" : { + "nullable" : { "_0" : { - "isSigned" : true, - "width" : "word" - } + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" } } } ], "returnType" : { - "integer" : { + "nullable" : { "_0" : { - "isSigned" : true, - "width" : "word" - } + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "null" } } }, { - "abiName" : "bjs_testGreeterToJSValue", + "abiName" : "bjs_roundTripJSValue", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "testGreeterToJSValue", + "name" : "roundTripJSValue", "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "jsValue" : { + } + } + } ], "returnType" : { - "jsObject" : { + "jsValue" : { } } }, { - "abiName" : "bjs_testCalculatorToJSValue", + "abiName" : "bjs_roundTripOptionalJSValue", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "testCalculatorToJSValue", + "name" : "roundTripOptionalJSValue", "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "jsValue" : { + } + }, + "_1" : "null" + } + } + } ], "returnType" : { - "jsObject" : { + "nullable" : { + "_0" : { + "jsValue" : { + } + }, + "_1" : "null" } } }, { - "abiName" : "bjs_testSwiftClassAsJSValue", + "abiName" : "bjs_roundTripOptionalJSValueArray", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "testSwiftClassAsJSValue", + "name" : "roundTripOptionalJSValueArray", "parameters" : [ { - "label" : "greeter", - "name" : "greeter", + "label" : "v", + "name" : "v", "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "null" } } } ], "returnType" : { - "jsObject" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + } + } + } + }, + "_1" : "null" } } }, { - "abiName" : "bjs_setDirection", + "abiName" : "bjs_makeImportedFoo", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "setDirection", + "name" : "makeImportedFoo", "parameters" : [ { - "label" : "_", - "name" : "direction", + "label" : "value", + "name" : "value", "type" : { - "caseEnum" : { - "_0" : "Direction" + "string" : { + } } } ], "returnType" : { - "caseEnum" : { - "_0" : "Direction" + "jsObject" : { + "_0" : "Foo" } } }, { - "abiName" : "bjs_getDirection", + "abiName" : "bjs_throwsSwiftError", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "getDirection", + "name" : "throwsSwiftError", "parameters" : [ + { + "label" : "shouldThrow", + "name" : "shouldThrow", + "type" : { + "bool" : { + } + } + } ], "returnType" : { - "caseEnum" : { - "_0" : "Direction" + "void" : { + } } }, { - "abiName" : "bjs_processDirection", + "abiName" : "bjs_throwsWithIntResult", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "processDirection", + "name" : "throwsWithIntResult", "parameters" : [ - { - "label" : "_", - "name" : "input", - "type" : { - "caseEnum" : { - "_0" : "Direction" - } - } - } + ], "returnType" : { - "caseEnum" : { - "_0" : "Status" + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } } } }, { - "abiName" : "bjs_setTheme", + "abiName" : "bjs_throwsWithStringResult", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "setTheme", + "name" : "throwsWithStringResult", "parameters" : [ - { - "label" : "_", - "name" : "theme", - "type" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" - } - } - } + ], "returnType" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "string" : { + } } }, { - "abiName" : "bjs_getTheme", + "abiName" : "bjs_throwsWithBoolResult", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "getTheme", + "name" : "throwsWithBoolResult", "parameters" : [ ], "returnType" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "bool" : { + } } }, { - "abiName" : "bjs_setHttpStatus", + "abiName" : "bjs_throwsWithFloatResult", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "setHttpStatus", + "name" : "throwsWithFloatResult", "parameters" : [ - { - "label" : "_", - "name" : "status", - "type" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" - } - } - } + ], "returnType" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" + "float" : { + } } }, { - "abiName" : "bjs_getHttpStatus", + "abiName" : "bjs_throwsWithDoubleResult", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "getHttpStatus", + "name" : "throwsWithDoubleResult", "parameters" : [ ], "returnType" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" + "double" : { + } } }, { - "abiName" : "bjs_setFileSize", + "abiName" : "bjs_throwsWithSwiftHeapObjectResult", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "setFileSize", - "parameters" : [ - { - "label" : "_", - "name" : "size", - "type" : { - "rawValueEnum" : { - "_0" : "FileSize", - "_1" : "Int64" - } - } - } - ], - "returnType" : { - "rawValueEnum" : { - "_0" : "FileSize", - "_1" : "Int64" - } - } - }, - { - "abiName" : "bjs_getFileSize", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "getFileSize", + "name" : "throwsWithSwiftHeapObjectResult", "parameters" : [ ], "returnType" : { - "rawValueEnum" : { - "_0" : "FileSize", - "_1" : "Int64" + "swiftHeapObject" : { + "_0" : "Greeter" } } }, { - "abiName" : "bjs_setSessionId", + "abiName" : "bjs_throwsWithJSObjectResult", "effects" : { "isAsync" : false, "isStatic" : false, - "isThrows" : false + "isThrows" : true }, - "name" : "setSessionId", + "name" : "throwsWithJSObjectResult", "parameters" : [ - { - "label" : "_", - "name" : "session", - "type" : { - "rawValueEnum" : { - "_0" : "SessionId", - "_1" : "UInt64" - } - } - } + ], "returnType" : { - "rawValueEnum" : { - "_0" : "SessionId", - "_1" : "UInt64" + "jsObject" : { + } } }, { - "abiName" : "bjs_getSessionId", + "abiName" : "bjs_asyncRoundTripVoid", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "getSessionId", + "name" : "asyncRoundTripVoid", "parameters" : [ ], "returnType" : { - "rawValueEnum" : { - "_0" : "SessionId", - "_1" : "UInt64" + "void" : { + } } }, { - "abiName" : "bjs_processTheme", + "abiName" : "bjs_asyncRoundTripInt", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "processTheme", + "name" : "asyncRoundTripInt", "parameters" : [ { - "label" : "_", - "name" : "theme", + "label" : "v", + "name" : "v", "type" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } } } }, { - "abiName" : "bjs_setTSDirection", + "abiName" : "bjs_asyncRoundTripFloat", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "setTSDirection", + "name" : "asyncRoundTripFloat", "parameters" : [ { - "label" : "_", - "name" : "direction", + "label" : "v", + "name" : "v", "type" : { - "caseEnum" : { - "_0" : "TSDirection" + "float" : { + } } } ], "returnType" : { - "caseEnum" : { - "_0" : "TSDirection" + "float" : { + } } }, { - "abiName" : "bjs_getTSDirection", + "abiName" : "bjs_asyncRoundTripDouble", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "getTSDirection", + "name" : "asyncRoundTripDouble", "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "double" : { + } + } + } ], "returnType" : { - "caseEnum" : { - "_0" : "TSDirection" + "double" : { + } } }, { - "abiName" : "bjs_setTSTheme", + "abiName" : "bjs_asyncRoundTripBool", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "setTSTheme", + "name" : "asyncRoundTripBool", "parameters" : [ { - "label" : "_", - "name" : "theme", + "label" : "v", + "name" : "v", "type" : { - "rawValueEnum" : { - "_0" : "TSTheme", - "_1" : "String" + "bool" : { + } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "TSTheme", - "_1" : "String" + "bool" : { + } } }, { - "abiName" : "bjs_getTSTheme", + "abiName" : "bjs_asyncRoundTripString", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "getTSTheme", + "name" : "asyncRoundTripString", "parameters" : [ + { + "label" : "v", + "name" : "v", + "type" : { + "string" : { + } + } + } ], "returnType" : { - "rawValueEnum" : { - "_0" : "TSTheme", - "_1" : "String" + "string" : { + } } }, { - "abiName" : "bjs_createConverter", + "abiName" : "bjs_asyncRoundTripSwiftHeapObject", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "createConverter", + "name" : "asyncRoundTripSwiftHeapObject", "parameters" : [ - + { + "label" : "v", + "name" : "v", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } ], "returnType" : { "swiftHeapObject" : { - "_0" : "Utils.Converter" + "_0" : "Greeter" } } }, { - "abiName" : "bjs_useConverter", + "abiName" : "bjs_asyncRoundTripJSObject", "effects" : { - "isAsync" : false, + "isAsync" : true, "isStatic" : false, "isThrows" : false }, - "name" : "useConverter", + "name" : "asyncRoundTripJSObject", "parameters" : [ { - "label" : "converter", - "name" : "converter", - "type" : { - "swiftHeapObject" : { - "_0" : "Utils.Converter" - } - } - }, - { - "label" : "value", - "name" : "value", + "label" : "v", + "name" : "v", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "jsObject" : { + } } } ], "returnType" : { - "string" : { + "jsObject" : { } } }, { - "abiName" : "bjs_roundTripConverterArray", + "abiName" : "bjs_takeGreeter", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripConverterArray", + "name" : "takeGreeter", "parameters" : [ { - "label" : "_", - "name" : "converters", + "label" : "g", + "name" : "g", "type" : { - "array" : { - "_0" : { - "swiftHeapObject" : { - "_0" : "Utils.Converter" - } - } + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + } } } ], "returnType" : { - "array" : { - "_0" : { - "swiftHeapObject" : { - "_0" : "Utils.Converter" - } - } + "void" : { + } } }, { - "abiName" : "bjs_createHTTPServer", + "abiName" : "bjs_createCalculator", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "createHTTPServer", + "name" : "createCalculator", "parameters" : [ ], "returnType" : { "swiftHeapObject" : { - "_0" : "Networking.API.HTTPServer" + "_0" : "Calculator" } } }, { - "abiName" : "bjs_createUUID", + "abiName" : "bjs_useCalculator", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "createUUID", + "name" : "useCalculator", "parameters" : [ { - "label" : "value", - "name" : "value", + "label" : "calc", + "name" : "calc", "type" : { - "string" : { - + "swiftHeapObject" : { + "_0" : "Calculator" + } + } + }, + { + "label" : "x", + "name" : "x", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } } } } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "UUID" + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } } } }, { - "abiName" : "bjs_roundTripUUID", + "abiName" : "bjs_testGreeterToJSValue", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripUUID", + "name" : "testGreeterToJSValue", "parameters" : [ - { - "label" : "_", - "name" : "uuid", - "type" : { - "swiftHeapObject" : { - "_0" : "UUID" - } - } - } + ], "returnType" : { - "swiftHeapObject" : { - "_0" : "UUID" + "jsObject" : { + } } }, { - "abiName" : "bjs_roundtripNetworkingAPIMethod", + "abiName" : "bjs_testCalculatorToJSValue", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundtripNetworkingAPIMethod", + "name" : "testCalculatorToJSValue", "parameters" : [ - { - "label" : "_", - "name" : "method", - "type" : { - "caseEnum" : { - "_0" : "Networking.API.Method" - } - } - } + ], "returnType" : { - "caseEnum" : { - "_0" : "Networking.API.Method" + "jsObject" : { + } } }, { - "abiName" : "bjs_roundtripConfigurationLogLevel", + "abiName" : "bjs_testSwiftClassAsJSValue", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundtripConfigurationLogLevel", + "name" : "testSwiftClassAsJSValue", "parameters" : [ { - "label" : "_", - "name" : "level", + "label" : "greeter", + "name" : "greeter", "type" : { - "rawValueEnum" : { - "_0" : "Configuration.LogLevel", - "_1" : "String" + "swiftHeapObject" : { + "_0" : "Greeter" } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Configuration.LogLevel", - "_1" : "String" + "jsObject" : { + } } }, { - "abiName" : "bjs_roundtripConfigurationPort", + "abiName" : "bjs_setDirection", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundtripConfigurationPort", + "name" : "setDirection", "parameters" : [ { "label" : "_", - "name" : "port", + "name" : "direction", "type" : { - "rawValueEnum" : { - "_0" : "Configuration.Port", - "_1" : "Int" + "caseEnum" : { + "_0" : "Direction" } } } ], "returnType" : { - "rawValueEnum" : { - "_0" : "Configuration.Port", - "_1" : "Int" + "caseEnum" : { + "_0" : "Direction" } } }, { - "abiName" : "bjs_processConfigurationLogLevel", + "abiName" : "bjs_getDirection", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "processConfigurationLogLevel", + "name" : "getDirection", "parameters" : [ - { - "label" : "_", - "name" : "level", - "type" : { - "rawValueEnum" : { - "_0" : "Configuration.LogLevel", - "_1" : "String" - } - } - } + ], "returnType" : { - "rawValueEnum" : { - "_0" : "Configuration.Port", - "_1" : "Int" + "caseEnum" : { + "_0" : "Direction" } } }, { - "abiName" : "bjs_roundtripInternalSupportedMethod", + "abiName" : "bjs_processDirection", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundtripInternalSupportedMethod", + "name" : "processDirection", "parameters" : [ { "label" : "_", - "name" : "method", + "name" : "input", "type" : { "caseEnum" : { - "_0" : "Internal.SupportedMethod" + "_0" : "Direction" } } } ], "returnType" : { "caseEnum" : { - "_0" : "Internal.SupportedMethod" + "_0" : "Status" } } }, { - "abiName" : "bjs_roundtripAPIResult", + "abiName" : "bjs_setTheme", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundtripAPIResult", + "name" : "setTheme", "parameters" : [ { - "label" : "result", - "name" : "result", + "label" : "_", + "name" : "theme", "type" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" } } }, { - "abiName" : "bjs_makeAPIResultSuccess", + "abiName" : "bjs_getTheme", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAPIResultSuccess", + "name" : "getTheme", "parameters" : [ - { - "label" : "_", - "name" : "value", - "type" : { - "string" : { - } - } - } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" } } }, { - "abiName" : "bjs_makeAPIResultFailure", + "abiName" : "bjs_setHttpStatus", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAPIResultFailure", + "name" : "setHttpStatus", "parameters" : [ { "label" : "_", - "name" : "value", + "name" : "status", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" } } }, { - "abiName" : "bjs_makeAPIResultInfo", + "abiName" : "bjs_getHttpStatus", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAPIResultInfo", + "name" : "getHttpStatus", "parameters" : [ ], "returnType" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" } } }, { - "abiName" : "bjs_makeAPIResultFlag", + "abiName" : "bjs_setFileSize", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAPIResultFlag", + "name" : "setFileSize", "parameters" : [ { "label" : "_", - "name" : "value", + "name" : "size", "type" : { - "bool" : { - + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" } } }, { - "abiName" : "bjs_makeAPIResultRate", + "abiName" : "bjs_getFileSize", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAPIResultRate", + "name" : "getFileSize", "parameters" : [ - { - "label" : "_", - "name" : "value", - "type" : { - "float" : { - } - } - } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "FileSize", + "_1" : "Int64" } } }, { - "abiName" : "bjs_makeAPIResultPrecise", + "abiName" : "bjs_setSessionId", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAPIResultPrecise", + "name" : "setSessionId", "parameters" : [ { "label" : "_", - "name" : "value", + "name" : "session", "type" : { - "double" : { - + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "APIResult" + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" } } }, { - "abiName" : "bjs_roundtripComplexResult", + "abiName" : "bjs_getSessionId", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundtripComplexResult", + "name" : "getSessionId", "parameters" : [ - { - "label" : "_", - "name" : "result", - "type" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" - } - } - } + ], "returnType" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" + "rawValueEnum" : { + "_0" : "SessionId", + "_1" : "UInt64" } } }, { - "abiName" : "bjs_makeComplexResultSuccess", + "abiName" : "bjs_processTheme", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeComplexResultSuccess", + "name" : "processTheme", "parameters" : [ { "label" : "_", - "name" : "value", + "name" : "theme", "type" : { - "string" : { - + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" } } }, { - "abiName" : "bjs_makeComplexResultError", + "abiName" : "bjs_setTSDirection", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeComplexResultError", + "name" : "setTSDirection", "parameters" : [ { "label" : "_", - "name" : "message", - "type" : { - "string" : { - - } - } - }, - { - "label" : "_", - "name" : "code", + "name" : "direction", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "caseEnum" : { + "_0" : "TSDirection" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" + "caseEnum" : { + "_0" : "TSDirection" } } }, { - "abiName" : "bjs_makeComplexResultLocation", + "abiName" : "bjs_getTSDirection", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeComplexResultLocation", + "name" : "getTSDirection", "parameters" : [ - { - "label" : "_", - "name" : "lat", - "type" : { - "double" : { - } - } - }, + ], + "returnType" : { + "caseEnum" : { + "_0" : "TSDirection" + } + } + }, + { + "abiName" : "bjs_setTSTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setTSTheme", + "parameters" : [ { "label" : "_", - "name" : "lng", + "name" : "theme", "type" : { - "double" : { - + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" } } - }, - { - "label" : "_", - "name" : "name", - "type" : { - "string" : { + } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" + } + } + }, + { + "abiName" : "bjs_getTSTheme", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getTSTheme", + "parameters" : [ - } - } + ], + "returnType" : { + "rawValueEnum" : { + "_0" : "TSTheme", + "_1" : "String" } + } + }, + { + "abiName" : "bjs_createConverter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createConverter", + "parameters" : [ + ], "returnType" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" + "swiftHeapObject" : { + "_0" : "Utils.Converter" } } }, { - "abiName" : "bjs_makeComplexResultStatus", + "abiName" : "bjs_useConverter", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeComplexResultStatus", + "name" : "useConverter", "parameters" : [ { - "label" : "_", - "name" : "active", + "label" : "converter", + "name" : "converter", "type" : { - "bool" : { - + "swiftHeapObject" : { + "_0" : "Utils.Converter" } } }, { - "label" : "_", - "name" : "code", + "label" : "value", + "name" : "value", "type" : { "integer" : { "_0" : { @@ -13066,306 +13276,282 @@ } } } - }, + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_roundTripConverterArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripConverterArray", + "parameters" : [ { "label" : "_", - "name" : "message", + "name" : "converters", "type" : { - "string" : { - + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Utils.Converter" + } + } } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Utils.Converter" + } + } } } }, { - "abiName" : "bjs_makeComplexResultCoordinates", + "abiName" : "bjs_createHTTPServer", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeComplexResultCoordinates", + "name" : "createHTTPServer", "parameters" : [ - { - "label" : "_", - "name" : "x", - "type" : { - "double" : { - } - } - }, + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Networking.API.HTTPServer" + } + } + }, + { + "abiName" : "bjs_createUUID", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createUUID", + "parameters" : [ { - "label" : "_", - "name" : "y", + "label" : "value", + "name" : "value", "type" : { - "double" : { + "string" : { } } - }, + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "UUID" + } + } + }, + { + "abiName" : "bjs_roundTripUUID", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUUID", + "parameters" : [ { "label" : "_", - "name" : "z", + "name" : "uuid", "type" : { - "double" : { - + "swiftHeapObject" : { + "_0" : "UUID" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" + "swiftHeapObject" : { + "_0" : "UUID" } } }, { - "abiName" : "bjs_makeComplexResultComprehensive", + "abiName" : "bjs_roundtripNetworkingAPIMethod", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeComplexResultComprehensive", + "name" : "roundtripNetworkingAPIMethod", "parameters" : [ { "label" : "_", - "name" : "flag1", + "name" : "method", "type" : { - "bool" : { - - } - } - }, - { - "label" : "_", - "name" : "flag2", - "type" : { - "bool" : { - - } - } - }, - { - "label" : "_", - "name" : "count1", - "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - } - }, - { - "label" : "_", - "name" : "count2", - "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - } - }, - { - "label" : "_", - "name" : "value1", - "type" : { - "double" : { - - } - } - }, - { - "label" : "_", - "name" : "value2", - "type" : { - "double" : { - - } - } - }, - { - "label" : "_", - "name" : "text1", - "type" : { - "string" : { - - } - } - }, - { - "label" : "_", - "name" : "text2", - "type" : { - "string" : { - - } - } - }, - { - "label" : "_", - "name" : "text3", - "type" : { - "string" : { - + "caseEnum" : { + "_0" : "Networking.API.Method" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" + "caseEnum" : { + "_0" : "Networking.API.Method" } } }, { - "abiName" : "bjs_makeComplexResultInfo", + "abiName" : "bjs_roundtripConfigurationLogLevel", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeComplexResultInfo", + "name" : "roundtripConfigurationLogLevel", "parameters" : [ - + { + "label" : "_", + "name" : "level", + "type" : { + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" + } + } + } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "ComplexResult" + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" } } }, { - "abiName" : "bjs_makeUtilitiesResultSuccess", + "abiName" : "bjs_roundtripConfigurationPort", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeUtilitiesResultSuccess", + "name" : "roundtripConfigurationPort", "parameters" : [ { "label" : "_", - "name" : "message", + "name" : "port", "type" : { - "string" : { - + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "Utilities.Result" + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" } } }, { - "abiName" : "bjs_makeUtilitiesResultFailure", + "abiName" : "bjs_processConfigurationLogLevel", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeUtilitiesResultFailure", + "name" : "processConfigurationLogLevel", "parameters" : [ { "label" : "_", - "name" : "error", - "type" : { - "string" : { - - } - } - }, - { - "label" : "_", - "name" : "code", + "name" : "level", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "rawValueEnum" : { + "_0" : "Configuration.LogLevel", + "_1" : "String" } } } ], "returnType" : { - "associatedValueEnum" : { - "_0" : "Utilities.Result" + "rawValueEnum" : { + "_0" : "Configuration.Port", + "_1" : "Int" } } }, { - "abiName" : "bjs_makeUtilitiesResultStatus", + "abiName" : "bjs_roundtripInternalSupportedMethod", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeUtilitiesResultStatus", + "name" : "roundtripInternalSupportedMethod", "parameters" : [ { "label" : "_", - "name" : "active", - "type" : { - "bool" : { - - } - } - }, - { - "label" : "_", - "name" : "code", + "name" : "method", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "caseEnum" : { + "_0" : "Internal.SupportedMethod" } } - }, + } + ], + "returnType" : { + "caseEnum" : { + "_0" : "Internal.SupportedMethod" + } + } + }, + { + "abiName" : "bjs_roundtripAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundtripAPIResult", + "parameters" : [ { - "label" : "_", - "name" : "message", + "label" : "result", + "name" : "result", "type" : { - "string" : { - + "associatedValueEnum" : { + "_0" : "APIResult" } } } ], "returnType" : { "associatedValueEnum" : { - "_0" : "Utilities.Result" + "_0" : "APIResult" } } }, { - "abiName" : "bjs_makeAPINetworkingResultSuccess", + "abiName" : "bjs_makeAPIResultSuccess", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAPINetworkingResultSuccess", + "name" : "makeAPIResultSuccess", "parameters" : [ { "label" : "_", - "name" : "message", + "name" : "value", "type" : { "string" : { @@ -13375,31 +13561,22 @@ ], "returnType" : { "associatedValueEnum" : { - "_0" : "API.NetworkingResult" + "_0" : "APIResult" } } }, { - "abiName" : "bjs_makeAPINetworkingResultFailure", + "abiName" : "bjs_makeAPIResultFailure", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAPINetworkingResultFailure", + "name" : "makeAPIResultFailure", "parameters" : [ { "label" : "_", - "name" : "error", - "type" : { - "string" : { - - } - } - }, - { - "label" : "_", - "name" : "code", + "name" : "value", "type" : { "integer" : { "_0" : { @@ -13412,307 +13589,265 @@ ], "returnType" : { "associatedValueEnum" : { - "_0" : "API.NetworkingResult" + "_0" : "APIResult" } } }, { - "abiName" : "bjs_roundtripUtilitiesResult", + "abiName" : "bjs_makeAPIResultInfo", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundtripUtilitiesResult", + "name" : "makeAPIResultInfo", "parameters" : [ - { - "label" : "_", - "name" : "result", - "type" : { - "associatedValueEnum" : { - "_0" : "Utilities.Result" - } - } - } + ], "returnType" : { "associatedValueEnum" : { - "_0" : "Utilities.Result" + "_0" : "APIResult" } } }, { - "abiName" : "bjs_roundtripAPINetworkingResult", + "abiName" : "bjs_makeAPIResultFlag", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundtripAPINetworkingResult", + "name" : "makeAPIResultFlag", "parameters" : [ { "label" : "_", - "name" : "result", + "name" : "value", "type" : { - "associatedValueEnum" : { - "_0" : "API.NetworkingResult" + "bool" : { + } } } ], "returnType" : { "associatedValueEnum" : { - "_0" : "API.NetworkingResult" + "_0" : "APIResult" } } }, { - "abiName" : "bjs_roundTripAllTypesResult", + "abiName" : "bjs_makeAPIResultRate", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripAllTypesResult", + "name" : "makeAPIResultRate", "parameters" : [ { "label" : "_", - "name" : "result", + "name" : "value", "type" : { - "associatedValueEnum" : { - "_0" : "AllTypesResult" + "float" : { + } } } ], "returnType" : { "associatedValueEnum" : { - "_0" : "AllTypesResult" + "_0" : "APIResult" } } }, { - "abiName" : "bjs_roundTripTypedPayloadResult", + "abiName" : "bjs_makeAPIResultPrecise", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripTypedPayloadResult", + "name" : "makeAPIResultPrecise", "parameters" : [ { "label" : "_", - "name" : "result", + "name" : "value", "type" : { - "associatedValueEnum" : { - "_0" : "TypedPayloadResult" + "double" : { + } } } ], "returnType" : { "associatedValueEnum" : { - "_0" : "TypedPayloadResult" + "_0" : "APIResult" } } }, { - "abiName" : "bjs_createPropertyHolder", + "abiName" : "bjs_roundtripComplexResult", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "createPropertyHolder", + "name" : "roundtripComplexResult", "parameters" : [ { - "label" : "intValue", - "name" : "intValue", - "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - } - }, - { - "label" : "floatValue", - "name" : "floatValue", - "type" : { - "float" : { - - } - } - }, - { - "label" : "doubleValue", - "name" : "doubleValue", - "type" : { - "double" : { - - } - } - }, - { - "label" : "boolValue", - "name" : "boolValue", - "type" : { - "bool" : { - - } - } - }, - { - "label" : "stringValue", - "name" : "stringValue", - "type" : { - "string" : { - - } - } - }, - { - "label" : "jsObject", - "name" : "jsObject", + "label" : "_", + "name" : "result", "type" : { - "jsObject" : { - + "associatedValueEnum" : { + "_0" : "ComplexResult" } } } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "PropertyHolder" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_testPropertyHolder", + "abiName" : "bjs_makeComplexResultSuccess", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "testPropertyHolder", + "name" : "makeComplexResultSuccess", "parameters" : [ { - "label" : "holder", - "name" : "holder", + "label" : "_", + "name" : "value", "type" : { - "swiftHeapObject" : { - "_0" : "PropertyHolder" + "string" : { + } } } ], "returnType" : { - "string" : { - + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_resetObserverCounts", + "abiName" : "bjs_makeComplexResultError", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "resetObserverCounts", + "name" : "makeComplexResultError", "parameters" : [ + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { - ], - "returnType" : { - "void" : { - + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } } - } - }, - { - "abiName" : "bjs_getObserverStats", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "getObserverStats", - "parameters" : [ - ], "returnType" : { - "string" : { - + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_formatName", + "abiName" : "bjs_makeComplexResultLocation", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "formatName", + "name" : "makeComplexResultLocation", "parameters" : [ { "label" : "_", - "name" : "name", + "name" : "lat", "type" : { - "string" : { + "double" : { } } }, { - "label" : "transform", - "name" : "transform", + "label" : "_", + "name" : "lng", "type" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSS_SS", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "string" : { + "double" : { - } - } - ], - "returnType" : { - "string" : { + } + } + }, + { + "label" : "_", + "name" : "name", + "type" : { + "string" : { - } - }, - "sendingParameters" : false - }, - "useJSTypedClosure" : false } } } ], "returnType" : { - "string" : { - + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_makeFormatter", + "abiName" : "bjs_makeComplexResultStatus", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeFormatter", + "name" : "makeComplexResultStatus", "parameters" : [ { - "label" : "prefix", - "name" : "prefix", + "label" : "_", + "name" : "active", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "_", + "name" : "message", "type" : { "string" : { @@ -13721,698 +13856,1553 @@ } ], "returnType" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSS_SS", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "string" : { - - } - } - ], - "returnType" : { - "string" : { - - } - }, - "sendingParameters" : false - }, - "useJSTypedClosure" : false + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_makeAdder", + "abiName" : "bjs_makeComplexResultCoordinates", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "makeAdder", + "name" : "makeComplexResultCoordinates", "parameters" : [ { - "label" : "base", - "name" : "base", + "label" : "_", + "name" : "x", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "double" : { + } } - } - ], - "returnType" : { - "closure" : { - "_0" : { - "isAsync" : false, - "isThrows" : false, - "mangleName" : "20BridgeJSRuntimeTestsSi_Si", - "moduleName" : "BridgeJSRuntimeTests", - "parameters" : [ - { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - } - ], - "returnType" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } - }, - "sendingParameters" : false - }, - "useJSTypedClosure" : false - } - } - }, - { - "abiName" : "bjs_roundTripPointerFields", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "roundTripPointerFields", - "parameters" : [ + }, { "label" : "_", - "name" : "value", + "name" : "y", "type" : { - "swiftStruct" : { - "_0" : "PointerFields" + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "z", + "type" : { + "double" : { + } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "PointerFields" + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_testStructDefault", + "abiName" : "bjs_makeComplexResultComprehensive", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "testStructDefault", + "name" : "makeComplexResultComprehensive", "parameters" : [ { - "defaultValue" : { - "structLiteral" : { - "_0" : "DataPoint", - "_1" : [ - { - "name" : "x", - "value" : { - "float" : { - "_0" : 1 - } - } - }, - { - "name" : "y", - "value" : { - "float" : { - "_0" : 2 - } - } - }, - { - "name" : "label", - "value" : { - "string" : { - "_0" : "default" - } - } - }, - { - "name" : "optCount", - "value" : { - "null" : { + "label" : "_", + "name" : "flag1", + "type" : { + "bool" : { - } - } - }, - { - "name" : "optFlag", - "value" : { - "null" : { + } + } + }, + { + "label" : "_", + "name" : "flag2", + "type" : { + "bool" : { - } - } - } - ] } - }, - "label" : "point", - "name" : "point", + } + }, + { + "label" : "_", + "name" : "count1", "type" : { - "swiftStruct" : { - "_0" : "DataPoint" + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "_", + "name" : "count2", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "_", + "name" : "value1", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "value2", + "type" : { + "double" : { + + } + } + }, + { + "label" : "_", + "name" : "text1", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "text2", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "text3", + "type" : { + "string" : { + } } } ], "returnType" : { - "string" : { - + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_cartToJSObject", + "abiName" : "bjs_makeComplexResultInfo", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "cartToJSObject", + "name" : "makeComplexResultInfo", "parameters" : [ - { - "label" : "_", - "name" : "cart", - "type" : { - "swiftStruct" : { - "_0" : "CopyableCart" - } - } - } + ], "returnType" : { - "jsObject" : { - + "associatedValueEnum" : { + "_0" : "ComplexResult" } } }, { - "abiName" : "bjs_nestedCartToJSObject", + "abiName" : "bjs_makeUtilitiesResultSuccess", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "nestedCartToJSObject", + "name" : "makeUtilitiesResultSuccess", "parameters" : [ { "label" : "_", - "name" : "cart", + "name" : "message", "type" : { - "swiftStruct" : { - "_0" : "CopyableNestedCart" + "string" : { + } } } ], "returnType" : { - "jsObject" : { - + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } }, { - "abiName" : "bjs_roundTripDataPoint", + "abiName" : "bjs_makeUtilitiesResultFailure", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripDataPoint", + "name" : "makeUtilitiesResultFailure", "parameters" : [ { "label" : "_", - "name" : "data", + "name" : "error", "type" : { - "swiftStruct" : { - "_0" : "DataPoint" + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "DataPoint" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } }, { - "abiName" : "bjs_roundTripPublicPoint", + "abiName" : "bjs_makeUtilitiesResultStatus", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripPublicPoint", + "name" : "makeUtilitiesResultStatus", "parameters" : [ { "label" : "_", - "name" : "point", + "name" : "active", "type" : { - "swiftStruct" : { - "_0" : "PublicPoint" + "bool" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "_", + "name" : "message", + "type" : { + "string" : { + } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "PublicPoint" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } }, { - "abiName" : "bjs_roundTripContact", + "abiName" : "bjs_makeAPINetworkingResultSuccess", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripContact", + "name" : "makeAPINetworkingResultSuccess", "parameters" : [ { "label" : "_", - "name" : "contact", + "name" : "message", "type" : { - "swiftStruct" : { - "_0" : "Contact" + "string" : { + } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "Contact" + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" } } }, { - "abiName" : "bjs_roundTripConfig", + "abiName" : "bjs_makeAPINetworkingResultFailure", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripConfig", + "name" : "makeAPINetworkingResultFailure", "parameters" : [ { "label" : "_", - "name" : "config", + "name" : "error", "type" : { - "swiftStruct" : { - "_0" : "Config" + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "code", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "Config" + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" } } }, { - "abiName" : "bjs_roundTripSessionData", + "abiName" : "bjs_roundtripUtilitiesResult", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripSessionData", + "name" : "roundtripUtilitiesResult", "parameters" : [ { "label" : "_", - "name" : "session", + "name" : "result", "type" : { - "swiftStruct" : { - "_0" : "SessionData" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "SessionData" + "associatedValueEnum" : { + "_0" : "Utilities.Result" } } }, { - "abiName" : "bjs_roundTripValidationReport", + "abiName" : "bjs_roundtripAPINetworkingResult", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripValidationReport", + "name" : "roundtripAPINetworkingResult", "parameters" : [ { "label" : "_", - "name" : "report", + "name" : "result", "type" : { - "swiftStruct" : { - "_0" : "ValidationReport" + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "ValidationReport" + "associatedValueEnum" : { + "_0" : "API.NetworkingResult" } } }, { - "abiName" : "bjs_roundTripAdvancedConfig", + "abiName" : "bjs_roundTripAllTypesResult", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripAdvancedConfig", + "name" : "roundTripAllTypesResult", "parameters" : [ { "label" : "_", - "name" : "config", + "name" : "result", "type" : { - "swiftStruct" : { - "_0" : "AdvancedConfig" + "associatedValueEnum" : { + "_0" : "AllTypesResult" } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "AdvancedConfig" + "associatedValueEnum" : { + "_0" : "AllTypesResult" } } }, { - "abiName" : "bjs_roundTripMeasurementConfig", + "abiName" : "bjs_roundTripTypedPayloadResult", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripMeasurementConfig", + "name" : "roundTripTypedPayloadResult", "parameters" : [ { "label" : "_", - "name" : "config", + "name" : "result", "type" : { - "swiftStruct" : { - "_0" : "MeasurementConfig" + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "MeasurementConfig" + "associatedValueEnum" : { + "_0" : "TypedPayloadResult" } } }, { - "abiName" : "bjs_updateValidationReport", + "abiName" : "bjs_createPropertyHolder", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "updateValidationReport", + "name" : "createPropertyHolder", "parameters" : [ { - "label" : "_", - "name" : "newResult", + "label" : "intValue", + "name" : "intValue", "type" : { - "nullable" : { + "integer" : { "_0" : { - "associatedValueEnum" : { - "_0" : "APIResult" - } - }, - "_1" : "null" + "isSigned" : true, + "width" : "word" + } } } }, { - "label" : "_", - "name" : "report", + "label" : "floatValue", + "name" : "floatValue", "type" : { - "swiftStruct" : { - "_0" : "ValidationReport" + "float" : { + + } + } + }, + { + "label" : "doubleValue", + "name" : "doubleValue", + "type" : { + "double" : { + + } + } + }, + { + "label" : "boolValue", + "name" : "boolValue", + "type" : { + "bool" : { + + } + } + }, + { + "label" : "stringValue", + "name" : "stringValue", + "type" : { + "string" : { + + } + } + }, + { + "label" : "jsObject", + "name" : "jsObject", + "type" : { + "jsObject" : { + } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "ValidationReport" + "swiftHeapObject" : { + "_0" : "PropertyHolder" } } }, { - "abiName" : "bjs_testContainerWithStruct", + "abiName" : "bjs_testPropertyHolder", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "testContainerWithStruct", + "name" : "testPropertyHolder", "parameters" : [ { - "label" : "_", - "name" : "point", + "label" : "holder", + "name" : "holder", "type" : { - "swiftStruct" : { - "_0" : "DataPoint" + "swiftHeapObject" : { + "_0" : "PropertyHolder" } } } ], "returnType" : { - "swiftHeapObject" : { - "_0" : "Container" + "string" : { + } } }, { - "abiName" : "bjs_roundTripJSObjectContainer", + "abiName" : "bjs_resetObserverCounts", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripJSObjectContainer", + "name" : "resetObserverCounts", "parameters" : [ - { - "label" : "_", - "name" : "container", - "type" : { - "swiftStruct" : { - "_0" : "JSObjectContainer" - } - } - } + ], "returnType" : { - "swiftStruct" : { - "_0" : "JSObjectContainer" + "void" : { + } } }, { - "abiName" : "bjs_roundTripFooContainer", + "abiName" : "bjs_getObserverStats", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripFooContainer", + "name" : "getObserverStats", "parameters" : [ - { - "label" : "_", - "name" : "container", - "type" : { - "swiftStruct" : { - "_0" : "FooContainer" - } - } - } + ], "returnType" : { - "swiftStruct" : { - "_0" : "FooContainer" + "string" : { + } } }, { - "abiName" : "bjs_roundTripArrayMembers", + "abiName" : "bjs_formatName", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "roundTripArrayMembers", + "name" : "formatName", "parameters" : [ { "label" : "_", - "name" : "value", + "name" : "name", "type" : { - "swiftStruct" : { - "_0" : "ArrayMembers" - } + "string" : { + + } + } + }, + { + "label" : "transform", + "name" : "transform", + "type" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false + } } } ], "returnType" : { - "swiftStruct" : { - "_0" : "ArrayMembers" + "string" : { + } } }, { - "abiName" : "bjs_arrayMembersSum", + "abiName" : "bjs_makeFormatter", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "arrayMembersSum", + "name" : "makeFormatter", "parameters" : [ { - "label" : "_", - "name" : "value", + "label" : "prefix", + "name" : "prefix", "type" : { - "swiftStruct" : { - "_0" : "ArrayMembers" + "string" : { + } } - }, + } + ], + "returnType" : { + "closure" : { + "_0" : { + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSS_SS", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "string" : { + + } + } + ], + "returnType" : { + "string" : { + + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false + } + } + }, + { + "abiName" : "bjs_makeAdder", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "makeAdder", + "parameters" : [ { - "label" : "_", - "name" : "values", + "label" : "base", + "name" : "base", "type" : { - "array" : { + "integer" : { "_0" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } - } + "isSigned" : true, + "width" : "word" } } } } ], "returnType" : { - "integer" : { + "closure" : { "_0" : { - "isSigned" : true, - "width" : "word" - } + "isAsync" : false, + "isThrows" : false, + "mangleName" : "20BridgeJSRuntimeTestsSi_Si", + "moduleName" : "BridgeJSRuntimeTests", + "parameters" : [ + { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + ], + "returnType" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + }, + "sendingParameters" : false + }, + "useJSTypedClosure" : false } } }, { - "abiName" : "bjs_arrayMembersFirst", + "abiName" : "bjs_roundTripPointerFields", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "arrayMembersFirst", + "name" : "roundTripPointerFields", "parameters" : [ { "label" : "_", "name" : "value", "type" : { "swiftStruct" : { - "_0" : "ArrayMembers" + "_0" : "PointerFields" } } - }, + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PointerFields" + } + } + }, + { + "abiName" : "bjs_testStructDefault", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testStructDefault", + "parameters" : [ { - "label" : "_", - "name" : "values", - "type" : { - "array" : { - "_0" : { - "string" : { + "defaultValue" : { + "structLiteral" : { + "_0" : "DataPoint", + "_1" : [ + { + "name" : "x", + "value" : { + "float" : { + "_0" : 1 + } + } + }, + { + "name" : "y", + "value" : { + "float" : { + "_0" : 2 + } + } + }, + { + "name" : "label", + "value" : { + "string" : { + "_0" : "default" + } + } + }, + { + "name" : "optCount", + "value" : { + "null" : { + + } + } + }, + { + "name" : "optFlag", + "value" : { + "null" : { + } + } } - } + ] + } + }, + "label" : "point", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "DataPoint" } } } ], "returnType" : { - "nullable" : { - "_0" : { - "string" : { + "string" : { - } - }, - "_1" : "null" } } - } - ], - "protocols" : [ + }, { - "methods" : [ - - ], - "name" : "ArrayElementProtocol", - "properties" : [ + "abiName" : "bjs_cartToJSObject", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "cartToJSObject", + "parameters" : [ { - "isReadonly" : false, - "name" : "value", + "label" : "_", + "name" : "cart", "type" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "swiftStruct" : { + "_0" : "CopyableCart" } } } - ] + ], + "returnType" : { + "jsObject" : { + + } + } }, { - "methods" : [ - { - "abiName" : "bjs_DataProcessor_increment", - "effects" : { - "isAsync" : false, + "abiName" : "bjs_nestedCartToJSObject", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "nestedCartToJSObject", + "parameters" : [ + { + "label" : "_", + "name" : "cart", + "type" : { + "swiftStruct" : { + "_0" : "CopyableNestedCart" + } + } + } + ], + "returnType" : { + "jsObject" : { + + } + } + }, + { + "abiName" : "bjs_roundTripDataPoint", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripDataPoint", + "parameters" : [ + { + "label" : "_", + "name" : "data", + "type" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + }, + { + "abiName" : "bjs_roundTripPublicPoint", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripPublicPoint", + "parameters" : [ + { + "label" : "_", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "PublicPoint" + } + } + }, + { + "abiName" : "bjs_roundTripContact", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripContact", + "parameters" : [ + { + "label" : "_", + "name" : "contact", + "type" : { + "swiftStruct" : { + "_0" : "Contact" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Contact" + } + } + }, + { + "abiName" : "bjs_roundTripConfig", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripConfig", + "parameters" : [ + { + "label" : "_", + "name" : "config", + "type" : { + "swiftStruct" : { + "_0" : "Config" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Config" + } + } + }, + { + "abiName" : "bjs_roundTripSessionData", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripSessionData", + "parameters" : [ + { + "label" : "_", + "name" : "session", + "type" : { + "swiftStruct" : { + "_0" : "SessionData" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "SessionData" + } + } + }, + { + "abiName" : "bjs_roundTripValidationReport", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripValidationReport", + "parameters" : [ + { + "label" : "_", + "name" : "report", + "type" : { + "swiftStruct" : { + "_0" : "ValidationReport" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "ValidationReport" + } + } + }, + { + "abiName" : "bjs_roundTripAdvancedConfig", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripAdvancedConfig", + "parameters" : [ + { + "label" : "_", + "name" : "config", + "type" : { + "swiftStruct" : { + "_0" : "AdvancedConfig" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "AdvancedConfig" + } + } + }, + { + "abiName" : "bjs_roundTripMeasurementConfig", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripMeasurementConfig", + "parameters" : [ + { + "label" : "_", + "name" : "config", + "type" : { + "swiftStruct" : { + "_0" : "MeasurementConfig" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "MeasurementConfig" + } + } + }, + { + "abiName" : "bjs_updateValidationReport", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "updateValidationReport", + "parameters" : [ + { + "label" : "_", + "name" : "newResult", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "label" : "_", + "name" : "report", + "type" : { + "swiftStruct" : { + "_0" : "ValidationReport" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "ValidationReport" + } + } + }, + { + "abiName" : "bjs_testContainerWithStruct", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "testContainerWithStruct", + "parameters" : [ + { + "label" : "_", + "name" : "point", + "type" : { + "swiftStruct" : { + "_0" : "DataPoint" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Container" + } + } + }, + { + "abiName" : "bjs_roundTripJSObjectContainer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripJSObjectContainer", + "parameters" : [ + { + "label" : "_", + "name" : "container", + "type" : { + "swiftStruct" : { + "_0" : "JSObjectContainer" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "JSObjectContainer" + } + } + }, + { + "abiName" : "bjs_roundTripFooContainer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripFooContainer", + "parameters" : [ + { + "label" : "_", + "name" : "container", + "type" : { + "swiftStruct" : { + "_0" : "FooContainer" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "FooContainer" + } + } + }, + { + "abiName" : "bjs_roundTripArrayMembers", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripArrayMembers", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "ArrayMembers" + } + } + } + ], + "returnType" : { + "swiftStruct" : { + "_0" : "ArrayMembers" + } + } + }, + { + "abiName" : "bjs_arrayMembersSum", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "arrayMembersSum", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "ArrayMembers" + } + } + }, + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + } + ], + "returnType" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "abiName" : "bjs_arrayMembersFirst", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "arrayMembersFirst", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "swiftStruct" : { + "_0" : "ArrayMembers" + } + } + }, + { + "label" : "_", + "name" : "values", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "protocols" : [ + { + "methods" : [ + + ], + "name" : "ArrayElementProtocol", + "properties" : [ + { + "isReadonly" : false, + "name" : "value", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ] + }, + { + "methods" : [ + { + "abiName" : "bjs_DataProcessor_increment", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "increment", + "parameters" : [ + { + "label" : "by", + "name" : "amount", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_getValue", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getValue", + "parameters" : [ + + ], + "returnType" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "abiName" : "bjs_DataProcessor_setLabelElements", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "setLabelElements", + "parameters" : [ + { + "label" : "_", + "name" : "labelPrefix", + "type" : { + "string" : { + + } + } + }, + { + "label" : "_", + "name" : "labelSuffix", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "void" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_getLabel", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getLabel", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_isEven", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "isEven", + "parameters" : [ + + ], + "returnType" : { + "bool" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_processGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "processGreeter", + "parameters" : [ + { + "label" : "_", + "name" : "greeter", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_createGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createGreeter", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "abiName" : "bjs_DataProcessor_processOptionalGreeter", + "effects" : { + "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "increment", + "name" : "processOptionalGreeter", "parameters" : [ { - "label" : "by", - "name" : "amount", + "label" : "_", + "name" : "greeter", "type" : { - "integer" : { + "nullable" : { "_0" : { - "isSigned" : true, - "width" : "word" - } + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_DataProcessor_createOptionalGreeter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createOptionalGreeter", + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + }, + { + "abiName" : "bjs_DataProcessor_handleAPIResult", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "handleAPIResult", + "parameters" : [ + { + "label" : "_", + "name" : "result", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" } } } @@ -14424,17 +15414,34 @@ } }, { - "abiName" : "bjs_DataProcessor_getValue", + "abiName" : "bjs_DataProcessor_getAPIResult", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "getValue", + "name" : "getAPIResult", "parameters" : [ ], "returnType" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + } + ], + "name" : "DataProcessor", + "properties" : [ + { + "isReadonly" : false, + "name" : "count", + "type" : { "integer" : { "_0" : { "isSigned" : true, @@ -14442,226 +15449,535 @@ } } } - }, + }, + { + "isReadonly" : true, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "name" : "optionalTag", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalCount", + "type" : { + "nullable" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "direction", + "type" : { + "nullable" : { + "_0" : { + "caseEnum" : { + "_0" : "Direction" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalTheme", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "Theme", + "_1" : "String" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "httpStatus", + "type" : { + "nullable" : { + "_0" : { + "rawValueEnum" : { + "_0" : "HttpStatus", + "_1" : "Int" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "apiResult", + "type" : { + "nullable" : { + "_0" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : false, + "name" : "helper", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + }, + { + "isReadonly" : false, + "name" : "optionalHelper", + "type" : { + "nullable" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + }, + "_1" : "null" + } + } + } + ] + } + ], + "structs" : [ + { + "constructor" : { + "abiName" : "bjs_BoxedSummary_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "largeContents", + "name" : "largeContents", + "type" : { + "array" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + }, + { + "label" : "label", + "name" : "label", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ { - "abiName" : "bjs_DataProcessor_setLabelElements", + "abiName" : "bjs_BoxedSummary_summarize", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "setLabelElements", + "name" : "summarize", "parameters" : [ - { - "label" : "_", - "name" : "labelPrefix", - "type" : { - "string" : { - - } - } - }, - { - "label" : "_", - "name" : "labelSuffix", - "type" : { - "string" : { - } - } - } ], "returnType" : { - "void" : { + "string" : { } } }, { - "abiName" : "bjs_DataProcessor_getLabel", + "abiName" : "bjs_BoxedSummary_appendingZero", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "getLabel", + "name" : "appendingZero", "parameters" : [ ], "returnType" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + } + } + ], + "name" : "BoxedSummary", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "largeContents", + "type" : { + "array" : { + "_0" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "label", + "type" : { "string" : { } } + } + ], + "structStyle" : "reference", + "swiftCallName" : "BoxedSummary" + }, + { + "constructor" : { + "abiName" : "bjs_LeakCheckBoxed_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false }, + "parameters" : [ + { + "label" : "id", + "name" : "id", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ] + }, + "methods" : [ { - "abiName" : "bjs_DataProcessor_isEven", + "abiName" : "bjs_LeakCheckBoxed_incremented", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "isEven", + "name" : "incremented", "parameters" : [ ], "returnType" : { - "bool" : { - + "swiftBoxedStruct" : { + "_0" : "LeakCheckBoxed" } } + } + ], + "name" : "LeakCheckBoxed", + "properties" : [ + + ], + "structStyle" : "reference", + "swiftCallName" : "LeakCheckBoxed" + }, + { + "constructor" : { + "abiName" : "bjs_ValueWithBoxedField_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false }, - { - "abiName" : "bjs_DataProcessor_processGreeter", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false + "parameters" : [ + { + "label" : "payload", + "name" : "payload", + "type" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + } }, - "name" : "processGreeter", - "parameters" : [ - { - "label" : "_", - "name" : "greeter", - "type" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } + { + "label" : "label", + "name" : "label", + "type" : { + "string" : { + } } - ], - "returnType" : { - "string" : { + } + ] + }, + "methods" : [ + ], + "name" : "ValueWithBoxedField", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "payload", + "type" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } } }, { - "abiName" : "bjs_DataProcessor_createGreeter", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false - }, - "name" : "createGreeter", - "parameters" : [ + "isReadonly" : true, + "isStatic" : false, + "name" : "label", + "type" : { + "string" : { - ], - "returnType" : { - "swiftHeapObject" : { - "_0" : "Greeter" } } + } + ], + "swiftCallName" : "ValueWithBoxedField" + }, + { + "constructor" : { + "abiName" : "bjs_ValueWithOptionalBoxedField_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false }, - { - "abiName" : "bjs_DataProcessor_processOptionalGreeter", - "effects" : { - "isAsync" : false, - "isStatic" : false, - "isThrows" : false + "parameters" : [ + { + "label" : "payload", + "name" : "payload", + "type" : { + "nullable" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + }, + "_1" : "null" + } + } }, - "name" : "processOptionalGreeter", - "parameters" : [ - { - "label" : "_", - "name" : "greeter", - "type" : { - "nullable" : { - "_0" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - }, - "_1" : "null" - } + { + "label" : "tag", + "name" : "tag", + "type" : { + "string" : { + } } - ], - "returnType" : { + } + ] + }, + "methods" : [ + + ], + "name" : "ValueWithOptionalBoxedField", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "payload", + "type" : { + "nullable" : { + "_0" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" + } + }, + "_1" : "null" + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "tag", + "type" : { "string" : { } } + } + ], + "swiftCallName" : "ValueWithOptionalBoxedField" + }, + { + "constructor" : { + "abiName" : "bjs_MutableCounter_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false }, + "parameters" : [ + { + "label" : "count", + "name" : "count", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ] + }, + "methods" : [ { - "abiName" : "bjs_DataProcessor_createOptionalGreeter", + "abiName" : "bjs_MutableCounter_bump", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "createOptionalGreeter", + "name" : "bump", "parameters" : [ - - ], - "returnType" : { - "nullable" : { - "_0" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - }, - "_1" : "null" + + ], + "returnType" : { + "void" : { + } } }, { - "abiName" : "bjs_DataProcessor_handleAPIResult", + "abiName" : "bjs_MutableCounter_currentCount", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "handleAPIResult", + "name" : "currentCount", "parameters" : [ - { - "label" : "_", - "name" : "result", - "type" : { - "nullable" : { - "_0" : { - "associatedValueEnum" : { - "_0" : "APIResult" - } - }, - "_1" : "null" + + ], + "returnType" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "name" : "MutableCounter", + "properties" : [ + + ], + "structStyle" : "reference", + "swiftCallName" : "MutableCounter" + }, + { + "constructor" : { + "abiName" : "bjs_DirectMutable_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "count", + "name" : "count", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" } } } - ], - "returnType" : { - "void" : { + }, + { + "label" : "label", + "name" : "label", + "type" : { + "string" : { + } } } - }, + ] + }, + "methods" : [ { - "abiName" : "bjs_DataProcessor_getAPIResult", + "abiName" : "bjs_DirectMutable_describe", "effects" : { "isAsync" : false, "isStatic" : false, "isThrows" : false }, - "name" : "getAPIResult", + "name" : "describe", "parameters" : [ ], "returnType" : { - "nullable" : { - "_0" : { - "associatedValueEnum" : { - "_0" : "APIResult" - } - }, - "_1" : "null" + "string" : { + } } } ], - "name" : "DataProcessor", + "name" : "DirectMutable", "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "count", "type" : { "integer" : { @@ -14674,129 +15990,136 @@ }, { "isReadonly" : true, - "name" : "name", + "isStatic" : false, + "name" : "label", "type" : { "string" : { } } + } + ], + "structStyle" : "reference", + "swiftCallName" : "DirectMutable" + }, + { + "constructor" : { + "abiName" : "bjs_BoxedConsumer_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false }, - { - "isReadonly" : false, - "name" : "optionalTag", - "type" : { - "nullable" : { - "_0" : { - "string" : { + "parameters" : [ + { + "label" : "tag", + "name" : "tag", + "type" : { + "string" : { - } - }, - "_1" : "null" + } } } - }, + ] + }, + "methods" : [ { - "isReadonly" : false, - "name" : "optionalCount", - "type" : { - "nullable" : { - "_0" : { - "integer" : { - "_0" : { - "isSigned" : true, - "width" : "word" - } + "abiName" : "bjs_BoxedConsumer_describe", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "describe", + "parameters" : [ + { + "label" : "_", + "name" : "other", + "type" : { + "swiftBoxedStruct" : { + "_0" : "BoxedSummary" } - }, - "_1" : "null" + } } - } - }, - { - "isReadonly" : false, - "name" : "direction", - "type" : { - "nullable" : { - "_0" : { - "caseEnum" : { - "_0" : "Direction" - } - }, - "_1" : "null" + ], + "returnType" : { + "string" : { + } } + } + ], + "name" : "BoxedConsumer", + "properties" : [ + + ], + "structStyle" : "reference", + "swiftCallName" : "BoxedConsumer" + }, + { + "constructor" : { + "abiName" : "bjs_BoxWithTrackedClass_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false }, - { - "isReadonly" : false, - "name" : "optionalTheme", - "type" : { - "nullable" : { - "_0" : { - "rawValueEnum" : { - "_0" : "Theme", - "_1" : "String" - } - }, - "_1" : "null" + "parameters" : [ + { + "label" : "tracked", + "name" : "tracked", + "type" : { + "swiftHeapObject" : { + "_0" : "TrackedThing" + } } - } - }, - { - "isReadonly" : false, - "name" : "httpStatus", - "type" : { - "nullable" : { - "_0" : { - "rawValueEnum" : { - "_0" : "HttpStatus", - "_1" : "Int" - } - }, - "_1" : "null" + }, + { + "label" : "label", + "name" : "label", + "type" : { + "string" : { + + } } } - }, + ] + }, + "methods" : [ { - "isReadonly" : false, - "name" : "apiResult", - "type" : { - "nullable" : { - "_0" : { - "associatedValueEnum" : { - "_0" : "APIResult" - } - }, - "_1" : "null" + "abiName" : "bjs_BoxWithTrackedClass_describeTracked", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "describeTracked", + "parameters" : [ + + ], + "returnType" : { + "string" : { + } } - }, + } + ], + "name" : "BoxWithTrackedClass", + "properties" : [ { - "isReadonly" : false, - "name" : "helper", + "isReadonly" : true, + "isStatic" : false, + "name" : "tracked", "type" : { "swiftHeapObject" : { - "_0" : "Greeter" - } - } - }, - { - "isReadonly" : false, - "name" : "optionalHelper", - "type" : { - "nullable" : { - "_0" : { - "swiftHeapObject" : { - "_0" : "Greeter" - } - }, - "_1" : "null" + "_0" : "TrackedThing" } } } - ] - } - ], - "structs" : [ + ], + "structStyle" : "reference", + "swiftCallName" : "BoxWithTrackedClass" + }, { "methods" : [ diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/BoxedStructTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/BoxedStructTests.mjs new file mode 100644 index 000000000..924a2b0f4 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/BoxedStructTests.mjs @@ -0,0 +1,199 @@ +// @ts-check +import assert from "node:assert"; + +/** + * @param {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports + */ +export function runBoxedStructWorks(exports) { + const a = exports.makeBoxedSummary([1, 2, 3], "alpha"); + assert.deepEqual(a.largeContents, [1, 2, 3]); + assert.equal(a.label, "alpha"); + assert.equal(a.summarize(), "alpha: count=3 sum=6"); + + const b = exports.roundtripBoxedSummary(a); + assert.deepEqual(b.largeContents, [1, 2, 3]); + assert.equal(b.label, "alpha"); + + const c = exports.makeBoxedSummary([10, 20], "bravo"); + assert.equal(exports.boxedSummaryLabel(c), "bravo"); + c.release(); + + const original = exports.makeBoxedSummary([1, 2, 3, 4], "copy-test"); + const copy = original.copy(); + assert.notStrictEqual(copy, original); + assert.deepEqual(copy.largeContents, original.largeContents); + assert.equal(copy.label, original.label); + + original.release(); + assert.equal(copy.summarize(), "copy-test: count=4 sum=10"); + copy.release(); + + const seed = exports.makeBoxedSummary([7, 8, 9], "chain"); + const next = seed.appendingZero(); + assert.notStrictEqual(next, seed); + assert.deepEqual(next.largeContents, [7, 8, 9, 0]); + assert.deepEqual(seed.largeContents, [7, 8, 9]); + seed.release(); + next.release(); + + assert.equal(exports.optionalBoxedSummary(false), null); + const optional = exports.optionalBoxedSummary(true); + assert.notEqual(optional, null); + if (optional) { + assert.deepEqual(optional.largeContents, [1, 2, 3]); + const echoed = exports.roundtripOptionalBoxedSummary(optional); + if (!echoed) { throw new Error("expected echoed value"); } + assert.deepEqual(echoed.largeContents, [1, 2, 3]); + echoed.release(); + optional.release(); + } + assert.equal(exports.roundtripOptionalBoxedSummary(null), null); + + const leak1 = exports.makeLeakCheckBoxed(0); + const leak2 = leak1.incremented(); + assert.notStrictEqual(leak2, leak1); + leak1.release(); + leak2.release(); + + const consumer = new exports.BoxedStructConsumer(); + const tag = exports.makeBoxedSummary([5, 5, 5], "tagA"); + assert.equal(consumer.formatSummary(tag), "tagA:15"); + + const tag2 = exports.makeBoxedSummary([1], "tagB"); + assert.equal(consumer.mergeLabels(tag, tag2), "tagA+tagB"); + consumer.release(); + + const inner = new exports.BoxedConsumer("outer"); + assert.equal(inner.describe(tag2), "outer→tagB"); + inner.release(); + tag.release(); + tag2.release(); + + const counter = exports.makeMutableCounter(5); + assert.equal(counter.currentCount(), 5); + counter.bump(); + assert.equal(counter.currentCount(), 6); + counter.bump(); + counter.bump(); + assert.equal(counter.currentCount(), 8); + counter.release(); + + const direct = exports.makeDirectMutable(10, "tag"); + assert.equal(direct.count, 10); + assert.equal(direct.describe(), "tag:10"); + direct.count = 42; + assert.equal(direct.count, 42); + assert.equal(direct.describe(), "tag:42"); + assert.equal(direct.label, "tag"); + direct.release(); + + const valueOuter = exports.makeValueWithBoxedField([1, 2, 3], "inner", "outer"); + assert.equal(valueOuter.label, "outer"); + assert.equal(valueOuter.payload.label, "inner"); + assert.deepEqual(valueOuter.payload.largeContents, [1, 2, 3]); + assert.equal(valueOuter.payload.summarize(), "inner: count=3 sum=6"); + + const valueRound = exports.roundtripValueWithBoxedField(valueOuter); + assert.equal(valueRound.label, "outer"); + assert.deepEqual(valueRound.payload.largeContents, [1, 2, 3]); + // Round-trip allocates a fresh box for the field — distinct JS handle. + assert.notStrictEqual(valueRound.payload, valueOuter.payload); + valueOuter.payload.release(); + valueRound.payload.release(); + + const optionalPresent = exports.makeValueWithOptionalBoxedField(true, "present"); + if (!optionalPresent.payload) { throw new Error("expected payload"); } + assert.equal(optionalPresent.tag, "present"); + assert.deepEqual(optionalPresent.payload.largeContents, [9, 9]); + const optionalEcho = exports.roundtripValueWithOptionalBoxedField(optionalPresent); + if (!optionalEcho.payload) { throw new Error("expected echoed payload"); } + assert.deepEqual(optionalEcho.payload.largeContents, [9, 9]); + optionalPresent.payload.release(); + optionalEcho.payload.release(); + + const optionalAbsent = exports.makeValueWithOptionalBoxedField(false, "absent"); + assert.equal(optionalAbsent.payload, null); + assert.equal(optionalAbsent.tag, "absent"); + const absentEcho = exports.roundtripValueWithOptionalBoxedField(optionalAbsent); + assert.equal(absentEcho.payload, null); + assert.equal(absentEcho.tag, "absent"); + + const inputItems = exports.makeBoxedArray(3); + assert.equal(inputItems.length, 3); + assert.equal(inputItems[0].label, "item0"); + assert.equal(inputItems[1].label, "item1"); + assert.deepEqual(inputItems[2].largeContents, [2]); + + const transformedItems = exports.consumeBoxedArray(inputItems); + assert.equal(transformedItems.length, 3); + assert.equal(transformedItems[0].label, "item0!"); + assert.deepEqual(transformedItems[0].largeContents, [0, 0]); + assert.equal(transformedItems[2].label, "item2!"); + assert.notStrictEqual(transformedItems[0], inputItems[0]); + inputItems.forEach((item) => item.release()); + transformedItems.forEach((item) => item.release()); + + const dictInput = { + alpha: exports.makeBoxedSummary([1, 2], "one"), + beta: exports.makeBoxedSummary([3, 4], "two"), + }; + const dictResult = exports.consumeBoxedDictionary(dictInput); + assert.equal(Object.keys(dictResult).sort().join(","), "alpha,beta"); + assert.equal(dictResult.alpha.label, "alpha:one"); + assert.equal(dictResult.beta.label, "beta:two"); + assert.deepEqual(dictResult.alpha.largeContents, [1, 2]); + Object.values(dictInput).forEach((b) => b.release()); + Object.values(dictResult).forEach((b) => b.release()); + + assert.equal(exports.optionalBoxedArray(false), null); + const optionalArr = exports.optionalBoxedArray(true); + if (!optionalArr) { throw new Error("expected non-null array"); } + assert.equal(optionalArr.length, 2); + assert.equal(optionalArr[0].label, "a"); + assert.equal(optionalArr[1].label, "b"); + optionalArr.forEach((b) => b.release()); + + const mixed = exports.arrayOfOptionalBoxed(true); + assert.equal(mixed.length, 3); + if (!mixed[0] || !mixed[2]) { throw new Error("expected entries 0 and 2 to be present"); } + assert.equal(mixed[0].label, "x"); + assert.equal(mixed[1], null); + assert.equal(mixed[2].label, "y"); + mixed[0].release(); + mixed[2].release(); + assert.deepEqual(exports.arrayOfOptionalBoxed(false), []); + + // Lifetime: a class held only by a boxed struct's field is deinit'd when the + // last box referencing it is released. + exports.resetTrackedDeinitCount(); + assert.equal(exports.getTrackedDeinitCount(), 0); + + const lifetimeBox = exports.makeBoxWithFreshTracked(42, "owned"); + assert.equal(lifetimeBox.describeTracked(), "owned:42"); + assert.equal(exports.getTrackedDeinitCount(), 0); + + const echoed = exports.roundtripBoxWithTrackedClass(lifetimeBox); + assert.notStrictEqual(echoed, lifetimeBox); + assert.equal(echoed.describeTracked(), "owned:42"); + assert.equal(exports.getTrackedDeinitCount(), 0); + + lifetimeBox.release(); + assert.equal(exports.getTrackedDeinitCount(), 0); + assert.equal(echoed.describeTracked(), "owned:42"); + + echoed.release(); + assert.equal(exports.getTrackedDeinitCount(), 1); + + // Lifetime: class outlives its box when JS holds a separate handle. + exports.resetTrackedDeinitCount(); + const survivingBox = exports.makeBoxWithFreshTracked(7, "survivor"); + const tracked = survivingBox.tracked; + assert.equal(tracked.getId(), 7); + + survivingBox.release(); + assert.equal(exports.getTrackedDeinitCount(), 0); + assert.equal(tracked.getId(), 7); + + tracked.release(); + assert.equal(exports.getTrackedDeinitCount(), 1); +} diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 10c73ec2f..291f537cd 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -5,6 +5,7 @@ import { } from '../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; import { ImportedFoo } from './BridgeJSRuntimeTests/JavaScript/Types.mjs'; import { runJsOptionalSupportTests } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs'; +import { runBoxedStructWorks } from './BridgeJSRuntimeTests/JavaScript/BoxedStructTests.mjs'; import { getImports as getClosureSupportImports } from './BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs'; import { getImports as getSwiftClassSupportImports } from './BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs'; import { getImports as getOptionalSupportImports } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs'; @@ -180,6 +181,13 @@ export async function setupOptions(options, context) { } return BridgeJSRuntimeTests_runJsStructWorks(exports); } + bridgeJSRuntimeTests["runBoxedStructWorks"] = () => { + const exports = getExports(); + if (!exports) { + throw new Error("No exports!?"); + } + runBoxedStructWorks(exports); + } const bridgeJSGlobalTests = importObject["BridgeJSGlobalTests"] || {}; bridgeJSGlobalTests["runJsWorksGlobal"] = () => { return BridgeJSGlobalTests_runJsWorksGlobal();