diff --git a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json index cfd7c19e..cbd7d10e 100644 --- a/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json +++ b/Benchmarks/Sources/Generated/JavaScript/BridgeJS.ExportSwift.json @@ -5,6 +5,7 @@ "abiName" : "bjs_EnumRoundtrip_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -16,6 +17,7 @@ "abiName" : "bjs_EnumRoundtrip_take", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "take", @@ -40,6 +42,7 @@ "abiName" : "bjs_EnumRoundtrip_makeSuccess", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeSuccess", @@ -56,6 +59,7 @@ "abiName" : "bjs_EnumRoundtrip_makeFailure", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeFailure", @@ -72,6 +76,7 @@ "abiName" : "bjs_EnumRoundtrip_makeFlag", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeFlag", @@ -88,6 +93,7 @@ "abiName" : "bjs_EnumRoundtrip_makeRate", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeRate", @@ -104,6 +110,7 @@ "abiName" : "bjs_EnumRoundtrip_makePrecise", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makePrecise", @@ -120,6 +127,7 @@ "abiName" : "bjs_EnumRoundtrip_makeInfo", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeInfo", @@ -136,6 +144,7 @@ "abiName" : "bjs_EnumRoundtrip_roundtrip", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtrip", @@ -168,6 +177,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -179,6 +189,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_take", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "take", @@ -203,6 +214,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_makeSuccess", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeSuccess", @@ -219,6 +231,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_makeError", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeError", @@ -235,6 +248,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_makeLocation", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeLocation", @@ -251,6 +265,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_makeStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeStatus", @@ -267,6 +282,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_makeCoordinates", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeCoordinates", @@ -283,6 +299,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_makeComprehensive", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeComprehensive", @@ -299,6 +316,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_makeInfo", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeInfo", @@ -315,6 +333,7 @@ "abiName" : "bjs_ComplexResultRoundtrip_roundtrip", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtrip", @@ -347,6 +366,7 @@ "abiName" : "bjs_StringRoundtrip_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -358,6 +378,7 @@ "abiName" : "bjs_StringRoundtrip_take", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "take", @@ -382,6 +403,7 @@ "abiName" : "bjs_StringRoundtrip_make", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "make", @@ -474,6 +496,12 @@ ], "emitStyle" : "const", "name" : "APIResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "APIResult" }, { @@ -664,6 +692,12 @@ ], "emitStyle" : "const", "name" : "ComplexResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "ComplexResult" } ], @@ -672,6 +706,7 @@ "abiName" : "bjs_run", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "run", diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ExportSwift.json b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ExportSwift.json index 625556f2..5ef85519 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ExportSwift.json +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/JavaScript/BridgeJS.ExportSwift.json @@ -5,6 +5,7 @@ "abiName" : "bjs_PlayBridgeJS_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -16,6 +17,7 @@ "abiName" : "bjs_PlayBridgeJS_update", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "update", @@ -58,6 +60,7 @@ "abiName" : "bjs_PlayBridgeJSOutput_outputJs", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "outputJs", @@ -74,6 +77,7 @@ "abiName" : "bjs_PlayBridgeJSOutput_outputDts", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "outputDts", @@ -90,6 +94,7 @@ "abiName" : "bjs_PlayBridgeJSOutput_importSwiftGlue", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "importSwiftGlue", @@ -106,6 +111,7 @@ "abiName" : "bjs_PlayBridgeJSOutput_exportSwiftGlue", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "exportSwiftGlue", diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 0b94442a..6679c4a8 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -88,18 +88,19 @@ public class ExportSwift { } } - /// Temporary storage for enum data during visitor traversal since EnumCaseDeclSyntax lacks parent context - struct CurrentEnum { - var name: String? - var cases: [EnumCase] = [] - var rawType: String? + /// Creates a unique key for an enum by combining name and namespace + private func enumKey(name: String, namespace: [String]?) -> String { + if let namespace = namespace, !namespace.isEmpty { + return "\(namespace.joined(separator: ".")).\(name)" + } else { + return name + } } - var currentEnum = CurrentEnum() enum State { case topLevel case classBody(name: String, key: String) - case enumBody(name: String) + case enumBody(name: String, key: String) } struct StateStack { @@ -152,36 +153,74 @@ public class ExportSwift { } override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { + guard node.attributes.hasJSAttribute() else { + return .skipChildren + } + + let isStatic = node.modifiers.contains { modifier in + modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) + } + switch state { case .topLevel: - if let exportedFunction = visitFunction( - node: node - ) { + if isStatic { + diagnose(node: node, message: "Top-level functions cannot be static") + return .skipChildren + } + if let exportedFunction = visitFunction(node: node, isStatic: false) { exportedFunctions.append(exportedFunction) } return .skipChildren - case .classBody(_, let classKey): + case .classBody(let className, let classKey): if let exportedFunction = visitFunction( - node: node + node: node, + isStatic: isStatic, + className: className, + classKey: classKey ) { exportedClassByName[classKey]?.methods.append(exportedFunction) } return .skipChildren - case .enumBody: - diagnose(node: node, message: "Functions are not supported inside enums") + case .enumBody(let enumName, let enumKey): + if !isStatic { + diagnose(node: node, message: "Only static functions are supported in enums") + return .skipChildren + } + if let exportedFunction = visitFunction(node: node, isStatic: isStatic, enumName: enumName) { + if var currentEnum = exportedEnumByName[enumKey] { + currentEnum.staticMethods.append(exportedFunction) + exportedEnumByName[enumKey] = currentEnum + } + } return .skipChildren } } - private func visitFunction(node: FunctionDeclSyntax) -> ExportedFunction? { + private func visitFunction( + node: FunctionDeclSyntax, + isStatic: Bool, + className: String? = nil, + classKey: String? = nil, + enumName: String? = nil + ) -> ExportedFunction? { guard let jsAttribute = node.attributes.firstJSAttribute else { return nil } let name = node.name.text - let namespace = extractNamespace(from: jsAttribute) - if namespace != nil, case .classBody = state { + let attributeNamespace = extractNamespace(from: jsAttribute) + let computedNamespace = computeNamespace(for: node) + + let finalNamespace: [String]? + + if let computed = computedNamespace, !computed.isEmpty { + finalNamespace = computed + } else { + finalNamespace = attributeNamespace + } + + if attributeNamespace != nil, case .classBody = state { diagnose( node: jsAttribute, message: "Namespace is only needed in top-level declaration", @@ -189,6 +228,14 @@ public class ExportSwift { ) } + if attributeNamespace != nil, case .enumBody = state { + diagnose( + node: jsAttribute, + message: "Namespace is not supported for enum static functions", + hint: "Remove the namespace from @JS attribute - enum functions inherit namespace from enum" + ) + } + var parameters: [Parameter] = [] for param in node.signature.parameterClause.parameters { let resolvedType = self.parent.lookupType(for: param.type) @@ -226,20 +273,42 @@ public class ExportSwift { } let abiName: String + let staticContext: StaticContext? + switch state { case .topLevel: - abiName = "bjs_\(name)" + staticContext = nil case .classBody(let className, _): - abiName = "bjs_\(className)_\(name)" - case .enumBody: - abiName = "" - diagnose( - node: node, - message: "Functions are not supported inside enums" - ) + if isStatic { + staticContext = .className(className) + } else { + staticContext = nil + } + case .enumBody(let enumName, let enumKey): + if !isStatic { + diagnose(node: node, message: "Only static functions are supported in enums") + return nil + } + + let isNamespaceEnum = exportedEnumByName[enumKey]?.cases.isEmpty ?? true + staticContext = isNamespaceEnum ? .namespaceEnum : .enumName(enumName) } - guard let effects = collectEffects(signature: node.signature) else { + let classNameForABI: String? + if case .classBody(let className, _) = state { + classNameForABI = className + } else { + classNameForABI = nil + } + abiName = ABINameGenerator.generateABIName( + baseName: name, + namespace: finalNamespace, + staticContext: isStatic ? staticContext : nil, + operation: nil, + className: classNameForABI + ) + + guard let effects = collectEffects(signature: node.signature, isStatic: isStatic) else { return nil } @@ -249,11 +318,12 @@ public class ExportSwift { parameters: parameters, returnType: returnType, effects: effects, - namespace: namespace + namespace: finalNamespace, + staticContext: staticContext ) } - private func collectEffects(signature: FunctionSignatureSyntax) -> Effects? { + private func collectEffects(signature: FunctionSignatureSyntax, isStatic: Bool = false) -> Effects? { let isAsync = signature.effectSpecifiers?.asyncSpecifier != nil var isThrows = false if let throwsClause: ThrowsClauseSyntax = signature.effectSpecifiers?.throwsClause { @@ -274,7 +344,7 @@ public class ExportSwift { } isThrows = true } - return Effects(isAsync: isAsync, isThrows: isThrows) + return Effects(isAsync: isAsync, isThrows: isThrows, isStatic: isStatic) } private func extractNamespace( @@ -313,9 +383,9 @@ public class ExportSwift { } override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind { - guard node.attributes.hasJSAttribute() else { return .skipChildren } + guard let jsAttribute = node.attributes.firstJSAttribute else { return .skipChildren } guard case .classBody(let className, _) = state else { - if case .enumBody(_) = state { + if case .enumBody(_, _) = state { diagnose(node: node, message: "Initializers are not supported inside enums") } else { diagnose(node: node, message: "@JS init must be inside a @JS class") @@ -323,9 +393,7 @@ public class ExportSwift { return .skipChildren } - if let jsAttribute = node.attributes.firstJSAttribute, - extractNamespace(from: jsAttribute) != nil - { + if extractNamespace(from: jsAttribute) != nil { diagnose( node: jsAttribute, message: "Namespace is not supported for initializer declarations", @@ -360,22 +428,54 @@ public class ExportSwift { } override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { - guard node.attributes.hasJSAttribute() else { return .skipChildren } - guard case .classBody(_, let classKey) = state else { - diagnose(node: node, message: "@JS var must be inside a @JS class") - return .skipChildren + guard let jsAttribute = node.attributes.firstJSAttribute else { return .skipChildren } + + let isStatic = node.modifiers.contains { modifier in + modifier.name.tokenKind == .keyword(.static) || modifier.name.tokenKind == .keyword(.class) } - if let jsAttribute = node.attributes.firstJSAttribute, - extractNamespace(from: jsAttribute) != nil - { + let attributeNamespace = extractNamespace(from: jsAttribute) + if attributeNamespace != nil { diagnose( - node: jsAttribute, - message: "Namespace is not supported for property declarations", - hint: "Remove the namespace from @JS attribute" + node: node.attributes.firstJSAttribute!, + message: "Namespace parameter within @JS attribute is not supported for property declarations", + hint: + "Remove the namespace from @JS attribute. If you need dedicated namespace, consider using a nested enum or class instead." ) } + let computedNamespace = computeNamespace(for: node) + let finalNamespace: [String]? + + if let computed = computedNamespace, !computed.isEmpty { + finalNamespace = computed + } else { + finalNamespace = nil + } + + // Determine static context and validate placement + let staticContext: StaticContext? + let classKey: String + + switch state { + case .classBody(let className, let key): + classKey = key + staticContext = isStatic ? .className(className) : nil + case .enumBody(let enumName, let enumKey): + if !isStatic { + diagnose(node: node, message: "Only static properties are supported in enums") + return .skipChildren + } + classKey = enumKey + + let isNamespaceEnum = exportedEnumByName[enumKey]?.cases.isEmpty ?? true + staticContext = isStatic ? (isNamespaceEnum ? .namespaceEnum : .enumName(enumName)) : nil + + case .topLevel: + diagnose(node: node, message: "@JS var must be inside a @JS class or enum") + return .skipChildren + } + // Process each binding (variable declaration) for binding in node.bindings { guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self) else { @@ -419,10 +519,20 @@ public class ExportSwift { let exportedProperty = ExportedProperty( name: propertyName, type: propertyType, - isReadonly: isReadonly + isReadonly: isReadonly, + isStatic: isStatic, + namespace: finalNamespace, + staticContext: staticContext ) - exportedClassByName[classKey]?.properties.append(exportedProperty) + if case .enumBody(_, let enumKey) = state { + if var currentEnum = exportedEnumByName[enumKey] { + currentEnum.staticProperties.append(exportedProperty) + exportedEnumByName[enumKey] = currentEnum + } + } else { + exportedClassByName[classKey]?.properties.append(exportedProperty) + } } return .skipChildren @@ -506,49 +616,79 @@ public class ExportSwift { return .skipChildren } - currentEnum.name = name - currentEnum.cases = [] - currentEnum.rawType = rawType + let effectiveNamespace = computedNamespace ?? attributeNamespace + let emitStyle = extractEnumStyle(from: jsAttribute) ?? .const + let swiftCallName = ExportSwift.computeSwiftCallName(for: node, itemName: name) + let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( + for: node, + message: "Enum visibility must be at least internal" + ) + + // Create enum directly in dictionary + let exportedEnum = ExportedEnum( + name: name, + swiftCallName: swiftCallName, + explicitAccessControl: explicitAccessControl, + cases: [], // Will be populated in visit(EnumCaseDeclSyntax) + rawType: rawType, + namespace: effectiveNamespace, + emitStyle: emitStyle, + staticMethods: [], + staticProperties: [] + ) + + let enumUniqueKey = enumKey(name: name, namespace: effectiveNamespace) + exportedEnumByName[enumUniqueKey] = exportedEnum + exportedEnumNames.append(enumUniqueKey) - stateStack.push(state: .enumBody(name: name)) + stateStack.push(state: .enumBody(name: name, key: enumUniqueKey)) return .visitChildren } override func visitPost(_ node: EnumDeclSyntax) { - guard let jsAttribute = node.attributes.firstJSAttribute, - let enumName = currentEnum.name - else { + guard let jsAttribute = node.attributes.firstJSAttribute else { // Only pop if we have a valid enum that was processed - if case .enumBody(_) = stateStack.current { + if case .enumBody(_, _) = stateStack.current { stateStack.pop() } return } - let attributeNamespace = extractNamespace(from: jsAttribute) - let computedNamespace = computeNamespace(for: node) + guard case .enumBody(_, let enumKey) = stateStack.current else { + return + } - let effectiveNamespace: [String]? - if computedNamespace == nil && attributeNamespace != nil { - effectiveNamespace = attributeNamespace - } else { - effectiveNamespace = computedNamespace + guard let exportedEnum = exportedEnumByName[enumKey] else { + stateStack.pop() + return } - let emitStyle = extractEnumStyle(from: jsAttribute) ?? .const - if case .tsEnum = emitStyle, - let raw = currentEnum.rawType, - let rawEnum = SwiftEnumRawType.from(raw), rawEnum == .bool - { - diagnose( - node: jsAttribute, - message: "TypeScript enum style is not supported for Bool raw-value enums", - hint: "Use enumStyle: .const or change the raw type to String or a numeric type" - ) + let emitStyle = exportedEnum.emitStyle + + if case .tsEnum = emitStyle { + // Check for Bool raw type limitation + if let raw = exportedEnum.rawType, + let rawEnum = SwiftEnumRawType.from(raw), rawEnum == .bool + { + diagnose( + node: jsAttribute, + message: "TypeScript enum style is not supported for Bool raw-value enums", + hint: "Use enumStyle: .const or change the raw type to String or a numeric type" + ) + } + + // Check for static functions limitation + if !exportedEnum.staticMethods.isEmpty { + diagnose( + node: jsAttribute, + message: "TypeScript enum style does not support static functions", + hint: "Use enumStyle: .const to generate a const object that supports static functions" + ) + } } - if currentEnum.cases.contains(where: { !$0.associatedValues.isEmpty }) { + if exportedEnum.cases.contains(where: { !$0.associatedValues.isEmpty }) { if case .tsEnum = emitStyle { diagnose( node: jsAttribute, @@ -556,7 +696,7 @@ public class ExportSwift { hint: "Use enumStyle: .const in order to map associated-value enums" ) } - for enumCase in currentEnum.cases { + for enumCase in exportedEnum.cases { for associatedValue in enumCase.associatedValues { switch associatedValue.type { case .string, .int, .float, .double, .bool: @@ -585,34 +725,20 @@ public class ExportSwift { } } - let swiftCallName = ExportSwift.computeSwiftCallName(for: node, itemName: enumName) - let explicitAccessControl = computeExplicitAtLeastInternalAccessControl( - for: node, - message: "Enum visibility must be at least internal" - ) - let exportedEnum = ExportedEnum( - name: enumName, - swiftCallName: swiftCallName, - explicitAccessControl: explicitAccessControl, - cases: currentEnum.cases, - rawType: currentEnum.rawType, - namespace: effectiveNamespace, - emitStyle: emitStyle - ) - exportedEnumByName[enumName] = exportedEnum - exportedEnumNames.append(enumName) - - currentEnum = CurrentEnum() stateStack.pop() } override func visit(_ node: EnumCaseDeclSyntax) -> SyntaxVisitorContinueKind { + guard case .enumBody(_, let enumKey) = stateStack.current else { + return .visitChildren + } + for element in node.elements { let caseName = element.name.text let rawValue: String? var associatedValues: [AssociatedValue] = [] - if currentEnum.rawType != nil { + if exportedEnumByName[enumKey]?.rawType != nil { if let stringLiteral = element.rawValue?.value.as(StringLiteralExprSyntax.self) { rawValue = stringLiteral.segments.first?.as(StringSegmentSyntax.self)?.content.text } else if let boolLiteral = element.rawValue?.value.as(BooleanLiteralExprSyntax.self) { @@ -647,8 +773,7 @@ public class ExportSwift { rawValue: rawValue, associatedValues: associatedValues ) - - currentEnum.cases.append(enumCase) + exportedEnumByName[enumKey]?.cases.append(enumCase) } return .visitChildren @@ -862,6 +987,19 @@ public class ExportSwift { case .namespace: () } + + for staticMethod in enumDef.staticMethods { + decls.append(try renderSingleExportedFunction(function: staticMethod)) + } + + for staticProperty in enumDef.staticProperties { + decls.append( + contentsOf: try renderSingleExportedProperty( + property: staticProperty, + context: .enumStatic(enumDef: enumDef) + ) + ) + } } for function in exportedFunctions { @@ -965,6 +1103,14 @@ public class ExportSwift { append(item) } + func callStaticProperty(name: String, returnType: BridgeType) { + if returnType == .void { + append("\(raw: name)") + } else { + append("let ret = \(raw: name)") + } + } + func callMethod(klassName: String, methodName: String, returnType: BridgeType) { let (_, selfExpr) = removeFirstLiftedParameter() let item = renderCallStatement( @@ -989,6 +1135,11 @@ public class ExportSwift { append("\(raw: selfExpr).\(raw: propertyName) = \(raw: newValueExpr)") } + func callStaticPropertySetter(klassName: String, propertyName: String) { + let (_, newValueExpr) = removeFirstLiftedParameter() + append("\(raw: klassName).\(raw: propertyName) = \(raw: newValueExpr)") + } + func lowerReturnValue(returnType: BridgeType) throws { if effects.isAsync { // Async functions always return a Promise, which is a JSObject @@ -1264,12 +1415,110 @@ public class ExportSwift { } } + /// Context for property rendering that determines call behavior and ABI generation + private enum PropertyRenderingContext { + case enumStatic(enumDef: ExportedEnum) + case classStatic(klass: ExportedClass) + case classInstance(klass: ExportedClass) + } + + /// Renders getter and setter Swift thunk code for a property in any context + /// This unified function eliminates duplication between enum static, class static, and class instance property rendering + private func renderSingleExportedProperty( + property: ExportedProperty, + context: PropertyRenderingContext + ) throws -> [DeclSyntax] { + var decls: [DeclSyntax] = [] + + let (callName, className, isStatic): (String, String, Bool) + switch context { + case .enumStatic(let enumDef): + callName = property.callName(prefix: enumDef.swiftCallName) + className = enumDef.name + isStatic = true + case .classStatic(let klass): + callName = property.callName() + className = klass.name + isStatic = true + + case .classInstance(let klass): + callName = property.callName() + className = klass.name + isStatic = false + } + + let getterBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic)) + + if !isStatic { + try getterBuilder.liftParameter( + param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(className)) + ) + } + + if isStatic { + getterBuilder.callStaticProperty(name: callName, returnType: property.type) + } else { + getterBuilder.callPropertyGetter(klassName: className, propertyName: callName, returnType: property.type) + } + + try getterBuilder.lowerReturnValue(returnType: property.type) + decls.append(getterBuilder.render(abiName: property.getterAbiName(className: className))) + + // Generate property setter if not readonly + if !property.isReadonly { + let setterBuilder = ExportedThunkBuilder( + effects: Effects(isAsync: false, isThrows: false, isStatic: isStatic) + ) + + // Lift parameters based on property type + if !isStatic { + // Instance properties need _self parameter + try setterBuilder.liftParameter( + param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(className)) + ) + } + + try setterBuilder.liftParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + + if isStatic { + let klassName = callName.components(separatedBy: ".").dropLast().joined(separator: ".") + setterBuilder.callStaticPropertySetter(klassName: klassName, propertyName: property.name) + } else { + setterBuilder.callPropertySetter(klassName: className, propertyName: callName) + } + + try setterBuilder.lowerReturnValue(returnType: .void) + decls.append(setterBuilder.render(abiName: property.setterAbiName(className: className))) + } + + return decls + } + func renderSingleExportedFunction(function: ExportedFunction) throws -> DeclSyntax { let builder = ExportedThunkBuilder(effects: function.effects) for param in function.parameters { try builder.liftParameter(param: param) } - builder.call(name: function.name, returnType: function.returnType) + + if function.effects.isStatic, let staticContext = function.staticContext { + let callName: String + switch staticContext { + case .className(let baseName), .enumName(let baseName): + callName = "\(baseName).\(function.name)" + case .namespaceEnum: + if let namespace = function.namespace, !namespace.isEmpty { + callName = "\(namespace.joined(separator: ".")).\(function.name)" + } else { + callName = function.name + } + } + builder.call(name: callName, returnType: function.returnType) + } else { + builder.call(name: function.name, returnType: function.returnType) + } + try builder.lowerReturnValue(returnType: function.returnType) return builder.render(abiName: function.abiName) } @@ -1335,51 +1584,45 @@ public class ExportSwift { } for method in klass.methods { let builder = ExportedThunkBuilder(effects: method.effects) - try builder.liftParameter( - param: Parameter(label: nil, name: "_self", type: BridgeType.swiftHeapObject(klass.swiftCallName)) - ) - for param in method.parameters { - try builder.liftParameter(param: param) + + if method.effects.isStatic { + for param in method.parameters { + try builder.liftParameter(param: param) + } + builder.call(name: "\(klass.swiftCallName).\(method.name)", returnType: method.returnType) + } else { + try builder.liftParameter( + param: Parameter(label: nil, name: "_self", type: BridgeType.swiftHeapObject(klass.swiftCallName)) + ) + for param in method.parameters { + try builder.liftParameter(param: param) + } + builder.callMethod( + klassName: klass.swiftCallName, + methodName: method.name, + returnType: method.returnType + ) } - builder.callMethod( - klassName: klass.swiftCallName, - methodName: method.name, - returnType: method.returnType - ) try builder.lowerReturnValue(returnType: method.returnType) decls.append(builder.render(abiName: method.abiName)) } // Generate property getters and setters for property in klass.properties { - // Generate getter - let getterBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) - try getterBuilder.liftParameter( - param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(klass.name)) - ) - getterBuilder.callPropertyGetter( - klassName: klass.name, - propertyName: property.name, - returnType: property.type - ) - try getterBuilder.lowerReturnValue(returnType: property.type) - decls.append(getterBuilder.render(abiName: property.getterAbiName(className: klass.name))) - - // Generate setter if property is not readonly - if !property.isReadonly { - let setterBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) - try setterBuilder.liftParameter( - param: Parameter(label: nil, name: "_self", type: .swiftHeapObject(klass.name)) - ) - try setterBuilder.liftParameter( - param: Parameter(label: "value", name: "value", type: property.type) + if property.isStatic { + decls.append( + contentsOf: try renderSingleExportedProperty( + property: property, + context: .classStatic(klass: klass) + ) ) - setterBuilder.callPropertySetter( - klassName: klass.name, - propertyName: property.name + } else { + decls.append( + contentsOf: try renderSingleExportedProperty( + property: property, + context: .classInstance(klass: klass) + ) ) - try setterBuilder.lowerReturnValue(returnType: .void) - decls.append(setterBuilder.render(abiName: property.setterAbiName(className: klass.name))) } } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 9715014c..42bfef50 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -76,6 +76,7 @@ struct BridgeJSLink { var topLevelEnumLines: [String] = [] var topLevelDtsEnumLines: [String] = [] var importObjectBuilders: [ImportObjectBuilder] = [] + var enumStaticAssignments: [String] = [] } private func collectLinkData() throws -> LinkData { @@ -147,7 +148,11 @@ struct BridgeJSLink { for function in skeleton.functions { var (js, dts) = try renderExportedFunction(function: function) - if function.namespace != nil { + if function.effects.isStatic, + case .namespaceEnum = function.staticContext + { + data.namespacedFunctions.append(function) + } else if function.namespace != nil { data.namespacedFunctions.append(function) } @@ -156,6 +161,129 @@ struct BridgeJSLink { data.exportsLines.append(contentsOf: js) data.dtsExportLines.append(contentsOf: dts) } + + for enumDefinition in skeleton.enums where enumDefinition.enumType == .namespace { + for function in enumDefinition.staticMethods { + // Create namespace function with full namespace path (parent namespace + enum name) + var functionWithNamespace = function + let fullNamespace = (enumDefinition.namespace ?? []) + [enumDefinition.name] + functionWithNamespace.namespace = fullNamespace + data.namespacedFunctions.append(functionWithNamespace) + + var (js, dts) = try renderExportedFunction(function: functionWithNamespace) + js[0] = "\(functionWithNamespace.name): " + js[0] + js[js.count - 1] += "," + data.exportsLines.append(contentsOf: js) + data.dtsExportLines.append(contentsOf: dts) + } + + for property in enumDefinition.staticProperties { + let fullNamespace = (enumDefinition.namespace ?? []) + [enumDefinition.name] + let namespacePath = fullNamespace.joined(separator: ".") + let (propJs, _) = try renderNamespaceStaticProperty( + property: property, + namespacePath: namespacePath + ) + data.enumStaticAssignments.append(contentsOf: propJs) + } + } + + for enumDefinition in skeleton.enums + where enumDefinition.enumType != .namespace && enumDefinition.emitStyle != .tsEnum { + let enumExportPrinter = CodeFragmentPrinter() + let enumValuesName = "\(enumDefinition.name)Values" + + for function in enumDefinition.staticMethods { + let thunkBuilder = ExportedThunkBuilder(effects: function.effects) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + + let methodPrinter = CodeFragmentPrinter() + methodPrinter.write( + "\(function.name): function(\(function.parameters.map { $0.name }.joined(separator: ", "))) {" + ) + methodPrinter.indent { + methodPrinter.write(contentsOf: thunkBuilder.body) + methodPrinter.write(contentsOf: thunkBuilder.cleanupCode) + methodPrinter.write(lines: thunkBuilder.checkExceptionLines()) + if let returnExpr = returnExpr { + methodPrinter.write("return \(returnExpr);") + } + } + methodPrinter.write("},") + + enumExportPrinter.write(lines: methodPrinter.lines) + } + + let enumExportLines = enumExportPrinter.lines + + let enumPropertyPrinter = CodeFragmentPrinter() + + for property in enumDefinition.staticProperties { + let getterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) + let getterReturnExpr = try getterThunkBuilder.call( + abiName: property.getterAbiName(), + returnType: property.type + ) + + enumPropertyPrinter.write("get \(property.name)() {") + enumPropertyPrinter.indent { + enumPropertyPrinter.write(contentsOf: getterThunkBuilder.body) + enumPropertyPrinter.write(contentsOf: getterThunkBuilder.cleanupCode) + enumPropertyPrinter.write(lines: getterThunkBuilder.checkExceptionLines()) + if let returnExpr = getterReturnExpr { + enumPropertyPrinter.write("return \(returnExpr);") + } + } + enumPropertyPrinter.write("},") + + if !property.isReadonly { + let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) + try setterThunkBuilder.lowerParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + _ = try setterThunkBuilder.call( + abiName: property.setterAbiName(), + returnType: .void + ) + + enumPropertyPrinter.write("set \(property.name)(value) {") + enumPropertyPrinter.indent { + enumPropertyPrinter.write(contentsOf: setterThunkBuilder.body) + enumPropertyPrinter.write(contentsOf: setterThunkBuilder.cleanupCode) + enumPropertyPrinter.write(lines: setterThunkBuilder.checkExceptionLines()) + } + enumPropertyPrinter.write("},") + } + } + + let enumPropertyLines = enumPropertyPrinter.lines + + let exportsPrinter = CodeFragmentPrinter() + let dtsExportsPrinter = CodeFragmentPrinter() + + if !enumExportLines.isEmpty || !enumPropertyLines.isEmpty { + exportsPrinter.write("\(enumDefinition.name): {") + exportsPrinter.indent { + exportsPrinter.write("...\(enumValuesName),") + var allLines = enumExportLines + enumPropertyLines + if let lastLineIndex = allLines.indices.last, allLines[lastLineIndex].hasSuffix(",") { + allLines[lastLineIndex] = String(allLines[lastLineIndex].dropLast()) + } + exportsPrinter.write(lines: allLines) + } + exportsPrinter.write("},") + } else { + exportsPrinter.write("\(enumDefinition.name): \(enumValuesName),") + } + + dtsExportsPrinter.write("\(enumDefinition.name): \(enumDefinition.name)Object") + + data.exportsLines.append(contentsOf: exportsPrinter.lines) + data.dtsExportLines.append(contentsOf: dtsExportsPrinter.lines) + } } // Process imported skeletons @@ -446,6 +574,34 @@ struct BridgeJSLink { printer.nextLine() printer.write(lines: data.topLevelDtsEnumLines) + // Generate Object types for const-style enums + for skeleton in exportedSkeletons { + for enumDefinition in skeleton.enums + where enumDefinition.enumType != .namespace && enumDefinition.emitStyle != .tsEnum { + let enumValuesName = "\(enumDefinition.name)Values" + let enumObjectName = "\(enumDefinition.name)Object" + + if !enumDefinition.staticMethods.isEmpty || !enumDefinition.staticProperties.isEmpty { + printer.write("export type \(enumObjectName) = typeof \(enumValuesName) & {") + printer.indent { + for function in enumDefinition.staticMethods { + printer.write( + "\(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" + ) + } + for property in enumDefinition.staticProperties { + let readonly = property.isReadonly ? "readonly " : "" + printer.write("\(readonly)\(property.name): \(property.type.tsType);") + } + } + printer.write("};") + } else { + printer.write("export type \(enumObjectName) = typeof \(enumValuesName);") + } + printer.nextLine() + } + } + // Type definitions section (namespace declarations, class definitions, imported types) let namespaceBuilder = NamespaceBuilder() let namespaceDeclarationsLines = namespaceBuilder.namespaceDeclarations( @@ -509,12 +665,20 @@ struct BridgeJSLink { printer.write(lines: data.topLevelEnumLines) // Namespace assignments section - let namespaceBuilder = NamespaceBuilder() - let topLevelNamespaceCode = namespaceBuilder.renderTopLevelEnumNamespaceAssignments( - namespacedEnums: data.namespacedEnums + let topLevelNamespaceCode = generateNamespaceInitializationCode( + namespacePaths: Set(data.namespacedEnums.compactMap { $0.namespace }) ) printer.write(lines: topLevelNamespaceCode) + // Add enum assignments to global namespace + for enumDef in data.namespacedEnums { + if enumDef.enumType != .namespace { + let namespacePath = enumDef.namespace?.joined(separator: ".") ?? "" + let enumValuesName = enumDef.emitStyle == .tsEnum ? enumDef.name : "\(enumDef.name)Values" + printer.write("globalThis.\(namespacePath).\(enumValuesName) = \(enumValuesName);") + } + } + // Main function declaration printer.write("export async function createInstantiator(options, \(JSGlueVariableScope.reservedSwift)) {") @@ -573,28 +737,25 @@ struct BridgeJSLink { // Exports / return section let hasNamespacedItems = !data.namespacedFunctions.isEmpty || !data.namespacedClasses.isEmpty + let hasNamespacedEnums = !data.namespacedEnums.isEmpty + let hasAnyNamespacedItems = hasNamespacedItems || hasNamespacedEnums printer.write(lines: data.classLines) - if hasNamespacedItems { - printer.write("const exports = {") - printer.indent { - printer.write(lines: data.exportsLines) - } - printer.write("};") - let namespaceSetupCode = namespaceBuilder.renderGlobalNamespace( - namespacedFunctions: data.namespacedFunctions, - namespacedClasses: data.namespacedClasses - ) - printer.write(lines: namespaceSetupCode) - printer.write("return exports;") - } else { - printer.write("return {") - printer.indent { - printer.write(lines: data.exportsLines) - } - printer.write("};") + // Initialize all namespaces before property assignments + if hasAnyNamespacedItems { + let allNamespacePaths = collectAllNamespacePaths(data: data) + let namespaceInitializationCode = generateNamespaceInitializationCode( + namespacePaths: allNamespacePaths + ) + printer.write(lines: namespaceInitializationCode) } + + let propertyAssignments = generateNamespacePropertyAssignments( + data: data, + hasAnyNamespacedItems: hasAnyNamespacedItems + ) + printer.write(lines: propertyAssignments) } printer.write("},") } @@ -618,8 +779,9 @@ struct BridgeJSLink { for skeleton in exportedSkeletons { for enumDef in skeleton.enums where enumDef.enumType == .associatedValue { let base = enumDef.name + let baseValues = "\(base)Values" printer.write( - "const \(base)Helpers = __bjs_create\(base)Helpers()(\(JSGlueVariableScope.reservedTmpParamInts), \(JSGlueVariableScope.reservedTmpParamF32s), \(JSGlueVariableScope.reservedTmpParamF64s), \(JSGlueVariableScope.reservedTextEncoder), \(JSGlueVariableScope.reservedSwift));" + "const \(base)Helpers = __bjs_create\(baseValues)Helpers()(\(JSGlueVariableScope.reservedTmpParamInts), \(JSGlueVariableScope.reservedTmpParamF32s), \(JSGlueVariableScope.reservedTmpParamF64s), \(JSGlueVariableScope.reservedTextEncoder), \(JSGlueVariableScope.reservedSwift));" ) printer.write("enumHelpers.\(base) = \(base)Helpers;") printer.nextLine() @@ -662,6 +824,94 @@ struct BridgeJSLink { return wrapperLines } + /// Collects all unique namespace paths from functions, classes, enums, and static properties + private func collectAllNamespacePaths(data: LinkData) -> Set<[String]> { + let functionNamespacePaths: Set<[String]> = Set( + data.namespacedFunctions.compactMap { $0.namespace } + ) + let classNamespacePaths: Set<[String]> = Set( + data.namespacedClasses.compactMap { $0.namespace } + ) + let allRegularNamespacePaths = functionNamespacePaths.union(classNamespacePaths) + + let enumNamespacePaths: Set<[String]> = Set( + data.namespacedEnums.compactMap { $0.namespace } + ) + var staticPropertyNamespacePaths: Set<[String]> = Set() + for skeleton in exportedSkeletons { + for enumDefinition in skeleton.enums { + for property in enumDefinition.staticProperties { + if let namespace = property.namespace, !namespace.isEmpty { + staticPropertyNamespacePaths.insert(namespace) + } + } + } + } + + return allRegularNamespacePaths.union(enumNamespacePaths).union(staticPropertyNamespacePaths) + } + + /// Generates JavaScript code lines for initializing namespace objects on globalThis + private func generateNamespaceInitializationCode(namespacePaths: Set<[String]>) -> [String] { + let printer = CodeFragmentPrinter() + var allUniqueNamespaces: [String] = [] + var seen = Set() + + namespacePaths.forEach { namespacePath in + namespacePath.enumerated().forEach { (index, _) in + let path = namespacePath[0...index].joined(separator: ".") + if seen.insert(path).inserted { + allUniqueNamespaces.append(path) + } + } + } + + allUniqueNamespaces.sorted().forEach { namespace in + printer.write("if (typeof globalThis.\(namespace) === 'undefined') {") + printer.indent { + printer.write("globalThis.\(namespace) = {};") + } + printer.write("}") + } + + return printer.lines + } + + /// Generates JavaScript code for assigning namespaced items to globalThis + private func generateNamespacePropertyAssignments(data: LinkData, hasAnyNamespacedItems: Bool) -> [String] { + let printer = CodeFragmentPrinter() + + printer.write(lines: data.enumStaticAssignments) + + if hasAnyNamespacedItems { + printer.write("const exports = {") + printer.indent() + printer.write(lines: data.exportsLines.map { "\($0)" }) + printer.unindent() + printer.write("};") + + data.namespacedClasses.forEach { klass in + let namespacePath: String = klass.namespace?.joined(separator: ".") ?? "" + printer.write("globalThis.\(namespacePath).\(klass.name) = exports.\(klass.name);") + } + + data.namespacedFunctions.forEach { function in + let namespacePath: String = function.namespace?.joined(separator: ".") ?? "" + printer.write("globalThis.\(namespacePath).\(function.name) = exports.\(function.name);") + } + + printer.write("return exports;") + } else { + printer.write("return {") + printer.indent() + printer.write(lines: data.exportsLines.map { "\($0)" }) + printer.unindent() + printer.write("};") + } + + return printer.lines + } + private func generateImportedTypeDefinitions() -> [String] { let printer = CodeFragmentPrinter() @@ -818,12 +1068,12 @@ struct BridgeJSLink { let scope = JSGlueVariableScope() let cleanup = CodeFragmentPrinter() let printer = CodeFragmentPrinter() + let enumValuesName = enumDefinition.emitStyle == .tsEnum ? enumDefinition.name : "\(enumDefinition.name)Values" switch enumDefinition.enumType { case .simple: let fragment = IntrinsicJSFragment.simpleEnumHelper(enumDefinition: enumDefinition) - _ = fragment.printCode([enumDefinition.name], scope, printer, cleanup) - + _ = fragment.printCode([enumValuesName], scope, printer, cleanup) jsLines.append(contentsOf: printer.lines) case .rawValue: guard enumDefinition.rawType != nil else { @@ -831,13 +1081,11 @@ struct BridgeJSLink { } let fragment = IntrinsicJSFragment.rawValueEnumHelper(enumDefinition: enumDefinition) - _ = fragment.printCode([enumDefinition.name], scope, printer, cleanup) - + _ = fragment.printCode([enumValuesName], scope, printer, cleanup) jsLines.append(contentsOf: printer.lines) case .associatedValue: let fragment = IntrinsicJSFragment.associatedValueEnumHelper(enumDefinition: enumDefinition) - _ = fragment.printCode([enumDefinition.name], scope, printer, cleanup) - + _ = fragment.printCode([enumValuesName], scope, printer, cleanup) jsLines.append(contentsOf: printer.lines) case .namespace: break @@ -852,6 +1100,7 @@ struct BridgeJSLink { private func generateDeclarations(enumDefinition: ExportedEnum) -> [String] { let printer = CodeFragmentPrinter() + let enumValuesName = enumDefinition.emitStyle == .tsEnum ? enumDefinition.name : "\(enumDefinition.name)Values" switch enumDefinition.emitStyle { case .tsEnum: @@ -877,7 +1126,7 @@ struct BridgeJSLink { } case .const: - printer.write("export const \(enumDefinition.name): {") + printer.write("export const \(enumValuesName): {") switch enumDefinition.enumType { case .simple, .rawValue: printer.indent { @@ -891,10 +1140,11 @@ struct BridgeJSLink { ) printer.write("readonly \(caseName): \(value);") } + } printer.write("};") printer.write( - "export type \(enumDefinition.name) = typeof \(enumDefinition.name)[keyof typeof \(enumDefinition.name)];" + "export type \(enumDefinition.name)Tag = typeof \(enumValuesName)[keyof typeof \(enumValuesName)];" ) printer.nextLine() case .associatedValue: @@ -907,6 +1157,7 @@ struct BridgeJSLink { } } printer.write("};") + } printer.write("};") printer.nextLine() @@ -915,11 +1166,11 @@ struct BridgeJSLink { for enumCase in enumDefinition.cases { if enumCase.associatedValues.isEmpty { unionParts.append( - "{ tag: typeof \(enumDefinition.name).Tag.\(enumCase.name.capitalizedFirstLetter) }" + "{ tag: typeof \(enumValuesName).Tag.\(enumCase.name.capitalizedFirstLetter) }" ) } else { var fields: [String] = [ - "tag: typeof \(enumDefinition.name).Tag.\(enumCase.name.capitalizedFirstLetter)" + "tag: typeof \(enumValuesName).Tag.\(enumCase.name.capitalizedFirstLetter)" ] for (associatedValueIndex, associatedValue) in enumCase.associatedValues.enumerated() { let prop = associatedValue.label ?? "param\(associatedValueIndex)" @@ -929,7 +1180,9 @@ struct BridgeJSLink { } } - printer.write("export type \(enumDefinition.name) =") + let unionTypeName = + enumDefinition.emitStyle == .tsEnum ? enumDefinition.name : "\(enumDefinition.name)Tag" + printer.write("export type \(unionTypeName) =") printer.write(" " + unionParts.joined(separator: " | ")) printer.nextLine() case .namespace: @@ -955,6 +1208,10 @@ struct BridgeJSLink { extension BridgeJSLink { func renderExportedFunction(function: ExportedFunction) throws -> (js: [String], dts: [String]) { + if function.effects.isStatic, let staticContext = function.staticContext { + return try renderStaticFunction(function: function, staticContext: staticContext) + } + let thunkBuilder = ExportedThunkBuilder(effects: function.effects) for param in function.parameters { try thunkBuilder.lowerParameter(param: param) @@ -974,6 +1231,267 @@ extension BridgeJSLink { return (funcLines, dtsLines) } + private func renderStaticFunction( + function: ExportedFunction, + staticContext: StaticContext + ) throws -> (js: [String], dts: [String]) { + switch staticContext { + case .className(let className): + return try renderClassStaticFunction(function: function, className: className) + case .enumName(let enumName): + return try renderEnumStaticFunction(function: function, enumName: enumName) + case .namespaceEnum: + if let namespace = function.namespace, !namespace.isEmpty { + return try renderNamespaceFunction(function: function, namespace: namespace.joined(separator: ".")) + } else { + return try renderExportedFunction(function: function) + } + } + } + + private func renderClassStaticFunction( + function: ExportedFunction, + className: String + ) throws -> (js: [String], dts: [String]) { + let thunkBuilder = ExportedThunkBuilder(effects: function.effects) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + + let funcLines = thunkBuilder.renderFunction( + name: function.name, + parameters: function.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: "static" + ) + + let dtsLines = [ + "static \(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" + ] + + return (funcLines, dtsLines) + } + + private func renderEnumStaticFunction( + function: ExportedFunction, + enumName: String + ) throws -> (js: [String], dts: [String]) { + let thunkBuilder = ExportedThunkBuilder(effects: function.effects) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + + let printer = CodeFragmentPrinter() + printer.write("\(function.name)(\(function.parameters.map { $0.name }.joined(separator: ", "))) {") + printer.indent { + printer.write(contentsOf: thunkBuilder.body) + printer.write(contentsOf: thunkBuilder.cleanupCode) + printer.write(lines: thunkBuilder.checkExceptionLines()) + if let returnExpr = returnExpr { + printer.write("return \(returnExpr);") + } + } + printer.write("},") + + let dtsLines = [ + "\(function.name)\(renderTSSignature(parameters: function.parameters, returnType: function.returnType, effects: function.effects));" + ] + + return (printer.lines, dtsLines) + } + + private func renderNamespaceFunction( + function: ExportedFunction, + namespace: String + ) throws -> (js: [String], dts: [String]) { + let thunkBuilder = ExportedThunkBuilder(effects: function.effects) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + + let funcLines = thunkBuilder.renderFunction( + name: function.abiName, + parameters: function.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: "function" + ) + + let dtsLines: [String] = [] + + return (funcLines, dtsLines) + } + + private func renderEnumStaticFunctionAssignment( + function: ExportedFunction, + enumName: String + ) throws -> [String] { + let thunkBuilder = ExportedThunkBuilder(effects: function.effects) + for param in function.parameters { + try thunkBuilder.lowerParameter(param: param) + } + let returnExpr = try thunkBuilder.call(abiName: function.abiName, returnType: function.returnType) + + let printer = CodeFragmentPrinter() + printer.write( + "\(enumName).\(function.name) = function(\(function.parameters.map { $0.name }.joined(separator: ", "))) {" + ) + printer.indent { + printer.write(contentsOf: thunkBuilder.body) + printer.write(contentsOf: thunkBuilder.cleanupCode) + printer.write(lines: thunkBuilder.checkExceptionLines()) + if let returnExpr = returnExpr { + printer.write("return \(returnExpr);") + } + } + printer.write("};") + + return printer.lines + } + + /// Renders an enum static property as getter/setter assignments on the enum object + private func renderEnumStaticProperty( + property: ExportedProperty, + enumName: String + ) throws -> (js: [String], dts: [String]) { + var jsLines: [String] = [] + + // Generate getter assignment + let getterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) + let getterReturnExpr = try getterThunkBuilder.call( + abiName: property.getterAbiName(), + returnType: property.type + ) + + let getterLines = getterThunkBuilder.renderFunction( + name: property.name, + parameters: [], + returnExpr: getterReturnExpr, + declarationPrefixKeyword: nil + ) + + // Build Object.defineProperty call + var definePropertyLines: [String] = [] + definePropertyLines.append("Object.defineProperty(\(enumName), '\(property.name)', { get: function() {") + + // Add getter body (skip function declaration and closing brace) + if getterLines.count > 2 { + let bodyLines = Array(getterLines[1.. 2 { + let bodyLines = Array(setterLines[1.. (js: [String], dts: [String]) { + var jsLines: [String] = [] + + // Generate getter assignment + let getterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) + let getterReturnExpr = try getterThunkBuilder.call( + abiName: property.getterAbiName(), + returnType: property.type + ) + + let getterLines = getterThunkBuilder.renderFunction( + name: property.name, + parameters: [], + returnExpr: getterReturnExpr, + declarationPrefixKeyword: nil + ) + + // Build Object.defineProperty call for namespace + var definePropertyLines: [String] = [] + definePropertyLines.append( + "Object.defineProperty(globalThis.\(namespacePath), '\(property.name)', { get: function() {" + ) + + // Add getter body (skip function declaration and closing brace) + if getterLines.count > 2 { + let bodyLines = Array(getterLines[1.. 2 { + let bodyLines = Array(setterLines[1.. (js: [String], dtsType: [String], dtsExportEntry: [String]) { @@ -1023,80 +1541,154 @@ extension BridgeJSLink { } for method in klass.methods { - let thunkBuilder = ExportedThunkBuilder(effects: method.effects) - thunkBuilder.lowerSelf() - for param in method.parameters { - try thunkBuilder.lowerParameter(param: param) - } - let returnExpr = try thunkBuilder.call(abiName: method.abiName, returnType: method.returnType) + if method.effects.isStatic { + let thunkBuilder = ExportedThunkBuilder(effects: method.effects) + 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: nil + jsPrinter.indent { + jsPrinter.write( + lines: thunkBuilder.renderFunction( + name: method.name, + parameters: method.parameters, + returnExpr: returnExpr, + declarationPrefixKeyword: "static" + ) ) - ) - } + } - dtsTypePrinter.indent { - dtsTypePrinter.write( - "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" - ) + dtsExportEntryPrinter.indent { + dtsExportEntryPrinter.write( + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) + } + } else { + let thunkBuilder = ExportedThunkBuilder(effects: method.effects) + 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: nil + ) + ) + } + + dtsTypePrinter.indent { + dtsTypePrinter.write( + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) + } } } // Generate property getters and setters for property in klass.properties { - // Generate getter - let getterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) - getterThunkBuilder.lowerSelf() - let getterReturnExpr = try getterThunkBuilder.call( - abiName: property.getterAbiName(className: klass.name), - returnType: property.type - ) + if property.isStatic { + // Generate static property getter + let getterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) + let getterReturnExpr = try getterThunkBuilder.call( + abiName: property.getterAbiName(), + returnType: property.type + ) - jsPrinter.indent { - jsPrinter.write( - lines: getterThunkBuilder.renderFunction( - name: property.name, - parameters: [], - returnExpr: getterReturnExpr, - declarationPrefixKeyword: "get" + jsPrinter.indent { + jsPrinter.write( + lines: getterThunkBuilder.renderFunction( + name: property.name, + parameters: [], + returnExpr: getterReturnExpr, + declarationPrefixKeyword: "static get" + ) ) - ) - } + } - // Generate setter if not readonly - if !property.isReadonly { - let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) - setterThunkBuilder.lowerSelf() - try setterThunkBuilder.lowerParameter( - param: Parameter(label: "value", name: "value", type: property.type) - ) - _ = try setterThunkBuilder.call( - abiName: property.setterAbiName(className: klass.name), - returnType: .void + // Generate static property setter if not readonly + if !property.isReadonly { + let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) + try setterThunkBuilder.lowerParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + _ = try setterThunkBuilder.call( + abiName: property.setterAbiName(), + returnType: .void + ) + + jsPrinter.indent { + jsPrinter.write( + lines: setterThunkBuilder.renderFunction( + name: property.name, + parameters: [.init(label: nil, name: "value", type: property.type)], + returnExpr: nil, + declarationPrefixKeyword: "static set" + ) + ) + } + } + + // Add static property to TypeScript exports definition (not instance interface) + let readonly = property.isReadonly ? "readonly " : "" + dtsExportEntryPrinter.indent { + dtsExportEntryPrinter.write("\(readonly)\(property.name): \(property.type.tsType);") + } + } else { + // Generate instance property getter + let getterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) + getterThunkBuilder.lowerSelf() + let getterReturnExpr = try getterThunkBuilder.call( + abiName: property.getterAbiName(className: klass.name), + returnType: property.type ) jsPrinter.indent { jsPrinter.write( - lines: setterThunkBuilder.renderFunction( + lines: getterThunkBuilder.renderFunction( name: property.name, - parameters: [.init(label: nil, name: "value", type: property.type)], - returnExpr: nil, - declarationPrefixKeyword: "set" + parameters: [], + returnExpr: getterReturnExpr, + declarationPrefixKeyword: "get" ) ) } - } - // Add TypeScript property definition - let readonly = property.isReadonly ? "readonly " : "" - dtsTypePrinter.indent { - dtsTypePrinter.write("\(readonly)\(property.name): \(property.type.tsType);") + // Generate instance property setter if not readonly + if !property.isReadonly { + let setterThunkBuilder = ExportedThunkBuilder(effects: Effects(isAsync: false, isThrows: false)) + setterThunkBuilder.lowerSelf() + try setterThunkBuilder.lowerParameter( + param: Parameter(label: "value", name: "value", type: property.type) + ) + _ = try setterThunkBuilder.call( + abiName: property.setterAbiName(className: klass.name), + returnType: .void + ) + + jsPrinter.indent { + jsPrinter.write( + lines: setterThunkBuilder.renderFunction( + name: property.name, + parameters: [.init(label: nil, name: "value", type: property.type)], + returnExpr: nil, + declarationPrefixKeyword: "set" + ) + ) + } + } + + // Add instance property to TypeScript interface definition + let readonly = property.isReadonly ? "readonly " : "" + dtsTypePrinter.indent { + dtsTypePrinter.write("\(readonly)\(property.name): \(property.type.tsType);") + } } } @@ -1269,114 +1861,11 @@ extension BridgeJSLink { } struct NamespaceBuilder { - - /// Generates JavaScript code for setting up global namespace structure - /// - /// This function creates the necessary JavaScript code to properly expose namespaced - /// functions, classes, and enums on the global object (globalThis). It ensures that - /// nested namespace paths are created correctly and that all exported items are - /// accessible through their full namespace paths. - /// - /// For example, if you have @JS("Utils.Math") func add() it will generate code that - /// makes globalThis.Utils.Math.add accessible. - /// - /// - Parameters: - /// - namespacedFunctions: Functions annotated with @JS("namespace.path") - /// - namespacedClasses: Classes annotated with @JS("namespace.path") - /// - Returns: Array of JavaScript code lines that set up the global namespace structure - func renderGlobalNamespace( - namespacedFunctions: [ExportedFunction], - namespacedClasses: [ExportedClass] - ) -> [String] { - let printer = CodeFragmentPrinter() - var uniqueNamespaces: [String] = [] - var seen = Set() - - let functionNamespacePaths: Set<[String]> = Set( - namespacedFunctions - .compactMap { $0.namespace } - ) - let classNamespacePaths: Set<[String]> = Set( - namespacedClasses - .compactMap { $0.namespace } - ) - - let allNamespacePaths = - functionNamespacePaths - .union(classNamespacePaths) - - allNamespacePaths.forEach { namespacePath in - namespacePath.makeIterator().enumerated().forEach { (index, _) in - let path = namespacePath[0...index].joined(separator: ".") - if seen.insert(path).inserted { - uniqueNamespaces.append(path) - } - } - } - - uniqueNamespaces.sorted().forEach { namespace in - printer.write("if (typeof globalThis.\(namespace) === 'undefined') {") - printer.indent { - printer.write("globalThis.\(namespace) = {};") - } - printer.write("}") - } - - namespacedClasses.forEach { klass in - let namespacePath: String = klass.namespace?.joined(separator: ".") ?? "" - printer.write("globalThis.\(namespacePath).\(klass.name) = exports.\(klass.name);") - } - - namespacedFunctions.forEach { function in - let namespacePath: String = function.namespace?.joined(separator: ".") ?? "" - printer.write("globalThis.\(namespacePath).\(function.name) = exports.\(function.name);") - } - - return printer.lines - } - - func renderTopLevelEnumNamespaceAssignments(namespacedEnums: [ExportedEnum]) -> [String] { - guard !namespacedEnums.isEmpty else { return [] } - - let printer = CodeFragmentPrinter() - var uniqueNamespaces: [String] = [] - var seen = Set() - - for enumDef in namespacedEnums { - guard let namespacePath = enumDef.namespace else { continue } - namespacePath.enumerated().forEach { (index, _) in - let path = namespacePath[0...index].joined(separator: ".") - if !seen.contains(path) { - seen.insert(path) - uniqueNamespaces.append(path) - } - } - } - - for namespace in uniqueNamespaces { - printer.write("if (typeof globalThis.\(namespace) === 'undefined') {") - printer.indent { - printer.write("globalThis.\(namespace) = {};") - } - printer.write("}") - } - - if !uniqueNamespaces.isEmpty { - printer.nextLine() - } - - for enumDef in namespacedEnums { - let namespacePath = enumDef.namespace?.joined(separator: ".") ?? "" - printer.write("globalThis.\(namespacePath).\(enumDef.name) = \(enumDef.name);") - } - printer.nextLine() - return printer.lines - } - private struct NamespaceContent { var functions: [ExportedFunction] = [] var classes: [ExportedClass] = [] var enums: [ExportedEnum] = [] + var staticProperties: [ExportedProperty] = [] } private final class NamespaceNode { @@ -1422,7 +1911,18 @@ extension BridgeJSLink { for skeleton in exportedSkeletons { for function in skeleton.functions { - if let namespace = function.namespace { + if function.effects.isStatic, + case .namespaceEnum = function.staticContext + { + // Use the function's namespace property instead of enumName + if let namespace = function.namespace { + var currentNode = rootNode + for part in namespace { + currentNode = currentNode.addChild(part) + } + currentNode.content.functions.append(function) + } + } else if let namespace = function.namespace { var currentNode = rootNode for part in namespace { currentNode = currentNode.addChild(part) @@ -1447,6 +1947,30 @@ extension BridgeJSLink { } currentNode.content.enums.append(enumDefinition) } + + if enumDefinition.enumType == .namespace { + for function in enumDefinition.staticMethods { + var currentNode = rootNode + // Build full namespace path: parent namespace + enum name + let fullNamespace = (enumDefinition.namespace ?? []) + [enumDefinition.name] + for part in fullNamespace { + currentNode = currentNode.addChild(part) + } + currentNode.content.functions.append(function) + } + + // Add static properties to namespace content for TypeScript declarations + for property in enumDefinition.staticProperties { + var currentNode = rootNode + let fullNamespace = (enumDefinition.namespace ?? []) + [enumDefinition.name] + for part in fullNamespace { + currentNode = currentNode.addChild(part) + } + if !currentNode.content.staticProperties.contains(where: { $0.name == property.name }) { + currentNode.content.staticProperties.append(property) + } + } + } } } @@ -1488,6 +2012,8 @@ extension BridgeJSLink { let sortedEnums = childNode.content.enums.sorted { $0.name < $1.name } for enumDefinition in sortedEnums { let style: EnumEmitStyle = enumDefinition.emitStyle + let enumValuesName = + enumDefinition.emitStyle == .tsEnum ? enumDefinition.name : "\(enumDefinition.name)Values" switch enumDefinition.enumType { case .simple: switch style { @@ -1501,7 +2027,7 @@ extension BridgeJSLink { } printer.write("}") case .const: - printer.write("const \(enumDefinition.name): {") + printer.write("const \(enumValuesName): {") printer.indent { for (index, enumCase) in enumDefinition.cases.enumerated() { let caseName = enumCase.name.capitalizedFirstLetter @@ -1510,7 +2036,7 @@ extension BridgeJSLink { } printer.write("};") printer.write( - "type \(enumDefinition.name) = typeof \(enumDefinition.name)[keyof typeof \(enumDefinition.name)];" + "type \(enumDefinition.name)Tag = typeof \(enumValuesName)[keyof typeof \(enumValuesName)];" ) } case .rawValue: @@ -1528,7 +2054,7 @@ extension BridgeJSLink { } printer.write("}") case .const: - printer.write("const \(enumDefinition.name): {") + printer.write("const \(enumValuesName): {") printer.indent { for enumCase in enumDefinition.cases { let caseName = enumCase.name.capitalizedFirstLetter @@ -1539,11 +2065,11 @@ extension BridgeJSLink { } printer.write("};") printer.write( - "type \(enumDefinition.name) = typeof \(enumDefinition.name)[keyof typeof \(enumDefinition.name)];" + "type \(enumDefinition.name)Tag = typeof \(enumValuesName)[keyof typeof \(enumValuesName)];" ) } case .associatedValue: - printer.write("const \(enumDefinition.name): {") + printer.write("const \(enumValuesName): {") printer.indent { printer.write("readonly Tag: {") printer.indent { @@ -1560,11 +2086,11 @@ extension BridgeJSLink { for enumCase in enumDefinition.cases { if enumCase.associatedValues.isEmpty { unionParts.append( - "{ tag: typeof \(enumDefinition.name).Tag.\(enumCase.name.capitalizedFirstLetter) }" + "{ tag: typeof \(enumValuesName).Tag.\(enumCase.name.capitalizedFirstLetter) }" ) } else { var fields: [String] = [ - "tag: typeof \(enumDefinition.name).Tag.\(enumCase.name.capitalizedFirstLetter)" + "tag: typeof \(enumValuesName).Tag.\(enumCase.name.capitalizedFirstLetter)" ] for (associatedValueIndex, associatedValue) in enumCase.associatedValues .enumerated() @@ -1575,7 +2101,9 @@ extension BridgeJSLink { unionParts.append("{ \(fields.joined(separator: "; ")) }") } } - printer.write("type \(enumDefinition.name) =") + let unionTypeName = + enumDefinition.emitStyle == .tsEnum ? enumDefinition.name : "\(enumDefinition.name)Tag" + printer.write("type \(unionTypeName) =") printer.write(" " + unionParts.joined(separator: " | ")) case .namespace: continue @@ -1588,6 +2116,11 @@ extension BridgeJSLink { "\(function.name)\(renderTSSignatureCallback(function.parameters, function.returnType, function.effects));" printer.write(signature) } + let sortedProperties = childNode.content.staticProperties.sorted { $0.name < $1.name } + for property in sortedProperties { + let readonly = property.isReadonly ? "var " : "let " + printer.write("\(readonly)\(property.name): \(property.type.tsType);") + } generateNamespaceDeclarations(node: childNode, depth: depth + 1) @@ -1768,11 +2301,11 @@ extension BridgeType { case .optional(let wrappedType): return "\(wrappedType.tsType) | null" case .caseEnum(let name): - return name + return "\(name)Tag" case .rawValueEnum(let name, _): - return name + return "\(name)Tag" case .associatedValueEnum(let name): - return name + return "\(name)Tag" case .namespaceEnum(let name): return name } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index ad07774d..8b0f3f47 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -536,7 +536,7 @@ struct IntrinsicJSFragment: Sendable { printer.write("\(caseName): \(index),") } } - printer.write("}") + printer.write("},") } printer.write("};") printer.nextLine() diff --git a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift index 32df40d1..e581fa40 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift @@ -1,5 +1,70 @@ // This file is shared between BridgeTool and BridgeJSLink +// MARK: - ABI Name Generation + +/// Utility for generating consistent ABI names across all exported and imported types +public struct ABINameGenerator { + static let prefixComponent = "bjs" + + /// Generates ABI name using standardized namespace + context pattern + public static func generateABIName( + baseName: String, + namespace: [String]?, + staticContext: StaticContext?, + operation: String? = nil, + className: String? = nil + ) -> String { + + let namespacePart: String? + if let namespace = namespace, !namespace.isEmpty { + namespacePart = namespace.joined(separator: "_") + } else { + namespacePart = nil + } + + let contextPart: String? + if let staticContext = staticContext { + switch staticContext { + case .className(let name), .enumName(let name): + contextPart = name + case .namespaceEnum: + contextPart = namespacePart + } + } else if let className = className { + contextPart = className + } else { + contextPart = namespacePart + } + + var components = [ABINameGenerator.prefixComponent] + if let context = contextPart { + components.append(context) + } + + if staticContext != nil { + components.append("static") + } + + components.append(baseName) + + if let operation = operation { + components.append(operation) + } + + return components.joined(separator: "_") + } + + static func generateImportedABIName( + baseName: String, + context: ImportedTypeSkeleton? = nil, + operation: String? = nil + ) -> String { + return [ABINameGenerator.prefixComponent, context?.name, baseName, operation].compactMap { $0 }.joined( + separator: "_" + ) + } +} + // MARK: - Types public enum BridgeType: Codable, Equatable, Sendable { @@ -62,7 +127,7 @@ public enum SwiftEnumRawType: String, CaseIterable, Codable, Sendable { } } -public struct Parameter: Codable { +public struct Parameter: Codable, Equatable, Sendable { public let label: String? public let name: String public let type: BridgeType @@ -74,16 +139,26 @@ public struct Parameter: Codable { } } -public struct Effects: Codable { +public struct Effects: Codable, Equatable, Sendable { public var isAsync: Bool public var isThrows: Bool + public var isStatic: Bool - public init(isAsync: Bool, isThrows: Bool) { + public init(isAsync: Bool, isThrows: Bool, isStatic: Bool = false) { self.isAsync = isAsync self.isThrows = isThrows + self.isStatic = isStatic } } +// MARK: - Static Function Context + +public enum StaticContext: Codable, Equatable, Sendable { + case className(String) + case enumName(String) + case namespaceEnum +} + // MARK: - Enum Skeleton public struct AssociatedValue: Codable, Equatable, Sendable { @@ -120,10 +195,12 @@ public struct ExportedEnum: Codable, Equatable, Sendable { public let name: String public let swiftCallName: String public let explicitAccessControl: String? - public let cases: [EnumCase] + public var cases: [EnumCase] public let rawType: String? public let namespace: [String]? public let emitStyle: EnumEmitStyle + public var staticMethods: [ExportedFunction] + public var staticProperties: [ExportedProperty] = [] public var enumType: EnumType { if cases.isEmpty { return .namespace @@ -141,7 +218,9 @@ public struct ExportedEnum: Codable, Equatable, Sendable { cases: [EnumCase], rawType: String?, namespace: [String]?, - emitStyle: EnumEmitStyle + emitStyle: EnumEmitStyle, + staticMethods: [ExportedFunction] = [], + staticProperties: [ExportedProperty] = [] ) { self.name = name self.swiftCallName = swiftCallName @@ -150,6 +229,8 @@ public struct ExportedEnum: Codable, Equatable, Sendable { self.rawType = rawType self.namespace = namespace self.emitStyle = emitStyle + self.staticMethods = staticMethods + self.staticProperties = staticProperties } } @@ -162,13 +243,14 @@ public enum EnumType: String, Codable, Sendable { // MARK: - Exported Skeleton -public struct ExportedFunction: Codable { +public struct ExportedFunction: Codable, Equatable, Sendable { public var name: String public var abiName: String public var parameters: [Parameter] public var returnType: BridgeType public var effects: Effects public var namespace: [String]? + public var staticContext: StaticContext? public init( name: String, @@ -176,7 +258,8 @@ public struct ExportedFunction: Codable { parameters: [Parameter], returnType: BridgeType, effects: Effects, - namespace: [String]? = nil + namespace: [String]? = nil, + staticContext: StaticContext? = nil ) { self.name = name self.abiName = abiName @@ -184,6 +267,7 @@ public struct ExportedFunction: Codable { self.returnType = returnType self.effects = effects self.namespace = namespace + self.staticContext = staticContext } } @@ -229,23 +313,66 @@ public struct ExportedConstructor: Codable { } } -public struct ExportedProperty: Codable { +public struct ExportedProperty: Codable, Equatable, Sendable { public var name: String public var type: BridgeType public var isReadonly: Bool + public var isStatic: Bool + public var namespace: [String]? + public var staticContext: StaticContext? - public init(name: String, type: BridgeType, isReadonly: Bool = false) { + public init( + name: String, + type: BridgeType, + isReadonly: Bool = false, + isStatic: Bool = false, + namespace: [String]? = nil, + staticContext: StaticContext? = nil + ) { self.name = name self.type = type self.isReadonly = isReadonly + self.isStatic = isStatic + self.namespace = namespace + self.staticContext = staticContext + } + + public func callName(prefix: String? = nil) -> String { + if let staticContext = staticContext { + switch staticContext { + case .className(let baseName), .enumName(let baseName): + return "\(baseName).\(name)" + case .namespaceEnum: + if let namespace = namespace, !namespace.isEmpty { + let namespacePath = namespace.joined(separator: ".") + return "\(namespacePath).\(name)" + } + } + } + if let prefix = prefix { + return "\(prefix).\(name)" + } + return name } - public func getterAbiName(className: String) -> String { - return "bjs_\(className)_\(name)_get" + public func getterAbiName(className: String = "") -> String { + return ABINameGenerator.generateABIName( + baseName: name, + namespace: namespace, + staticContext: isStatic ? staticContext : nil, + operation: "get", + className: isStatic ? nil : className + ) } - public func setterAbiName(className: String) -> String { - return "bjs_\(className)_\(name)_set" + public func setterAbiName(className: String = "") -> String { + return ABINameGenerator.generateABIName( + baseName: name, + namespace: namespace, + staticContext: isStatic ? staticContext : nil, + operation: "set", + className: isStatic ? nil : className + ) } } @@ -272,7 +399,10 @@ public struct ImportedFunctionSkeleton: Codable { public let documentation: String? public func abiName(context: ImportedTypeSkeleton?) -> String { - return context.map { "bjs_\($0.name)_\(name)" } ?? "bjs_\(name)" + return ABINameGenerator.generateImportedABIName( + baseName: name, + context: context + ) } } @@ -280,7 +410,10 @@ public struct ImportedConstructorSkeleton: Codable { public let parameters: [Parameter] public func abiName(context: ImportedTypeSkeleton) -> String { - return "bjs_\(context.name)_init" + return ABINameGenerator.generateImportedABIName( + baseName: "init", + context: context + ) } } @@ -291,11 +424,19 @@ public struct ImportedPropertySkeleton: Codable { public let documentation: String? public func getterAbiName(context: ImportedTypeSkeleton) -> String { - return "bjs_\(context.name)_\(name)_get" + return ABINameGenerator.generateImportedABIName( + baseName: name, + context: context, + operation: "get" + ) } public func setterAbiName(context: ImportedTypeSkeleton) -> String { - return "bjs_\(context.name)_\(name)_set" + return ABINameGenerator.generateImportedABIName( + baseName: name, + context: context, + operation: "set" + ) } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StaticFunctions.swift new file mode 100644 index 00000000..1d42cf41 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StaticFunctions.swift @@ -0,0 +1,40 @@ +@JS class MathUtils { + @JS init() {} + + @JS class func subtract(a: Int, b: Int) -> Int { + return a - b + } + + @JS static func add(a: Int, b: Int) -> Int { + return a + b + } + + @JS func multiply(x: Int, y: Int) -> Int { + return x * y + } +} + +@JS enum Calculator { + case scientific + case basic + + @JS static func square(value: Int) -> Int { + return value * value + } +} + +@JS +enum APIResult { + case success(String) + case failure(Int) + + @JS static func roundtrip(value: APIResult) -> APIResult {} +} + +@JS enum Utils { + @JS enum String { + @JS static func uppercase(_ text: String) -> String { + return text.uppercased() + } + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StaticProperties.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StaticProperties.swift new file mode 100644 index 00000000..1a89b55c --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StaticProperties.swift @@ -0,0 +1,42 @@ +@JS class PropertyClass { + @JS init() {} + + @JS static let staticConstant: String = "constant" + @JS static var staticVariable: Int = 42 + @JS static var jsObjectProperty: JSObject = JSObject() + @JS class var classVariable: String = "overridable" + + @JS static var computedProperty: String { + get { return "\(staticVariable) computed" } + set { staticVariable = newValue + 5 } + } + + @JS static var readOnlyComputed: Int { + return 100 + } + + @JS static var optionalProperty: String? = nil +} + +@JS enum PropertyEnum { + case value1 + case value2 + + @JS static var enumProperty: String = "enum value" + @JS static let enumConstant: Int = 42 + @JS static var computedEnum: String { + get { return enumProperty + " computed" } + set { enumProperty = newValue + " computed" } + } +} + +@JS enum PropertyNamespace { + @JS static var namespaceProperty: String = "namespace" + @JS static let namespaceConstant: String = "constant" + + @JS enum Nested { + @JS nonisolated(unsafe) static var nestedProperty: Int = 999 + @JS static let nestedConstant: String = "nested" + @JS nonisolated(unsafe) static var nestedDouble: Double = 1.414 + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts index 4195e9a2..aac40514 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.d.ts @@ -4,7 +4,7 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export const APIResult: { +export const APIResultValues: { readonly Tag: { readonly Success: 0; readonly Failure: 1; @@ -15,10 +15,10 @@ export const APIResult: { }; }; -export type APIResult = - { tag: typeof APIResult.Tag.Success; param0: string } | { tag: typeof APIResult.Tag.Failure; param0: number } | { tag: typeof APIResult.Tag.Flag; param0: boolean } | { tag: typeof APIResult.Tag.Rate; param0: number } | { tag: typeof APIResult.Tag.Precise; param0: number } | { tag: typeof APIResult.Tag.Info } +export type APIResultTag = + { tag: typeof APIResultValues.Tag.Success; param0: string } | { tag: typeof APIResultValues.Tag.Failure; param0: number } | { tag: typeof APIResultValues.Tag.Flag; param0: boolean } | { tag: typeof APIResultValues.Tag.Rate; param0: number } | { tag: typeof APIResultValues.Tag.Precise; param0: number } | { tag: typeof APIResultValues.Tag.Info } -export const ComplexResult: { +export const ComplexResultValues: { readonly Tag: { readonly Success: 0; readonly Error: 1; @@ -29,10 +29,10 @@ export const ComplexResult: { }; }; -export type ComplexResult = - { tag: typeof ComplexResult.Tag.Success; param0: string } | { tag: typeof ComplexResult.Tag.Error; param0: string; param1: number } | { tag: typeof ComplexResult.Tag.Status; param0: boolean; param1: number; param2: string } | { tag: typeof ComplexResult.Tag.Coordinates; param0: number; param1: number; param2: number } | { tag: typeof ComplexResult.Tag.Comprehensive; param0: boolean; param1: boolean; param2: number; param3: number; param4: number; param5: number; param6: string; param7: string; param8: string } | { tag: typeof ComplexResult.Tag.Info } +export type ComplexResultTag = + { tag: typeof ComplexResultValues.Tag.Success; param0: string } | { tag: typeof ComplexResultValues.Tag.Error; param0: string; param1: number } | { tag: typeof ComplexResultValues.Tag.Status; param0: boolean; param1: number; param2: string } | { tag: typeof ComplexResultValues.Tag.Coordinates; param0: number; param1: number; param2: number } | { tag: typeof ComplexResultValues.Tag.Comprehensive; param0: boolean; param1: boolean; param2: number; param3: number; param4: number; param5: number; param6: string; param7: string; param8: string } | { tag: typeof ComplexResultValues.Tag.Info } -export const APIOptionalResult: { +export const APIOptionalResultValues: { readonly Tag: { readonly Success: 0; readonly Failure: 1; @@ -40,47 +40,62 @@ export const APIOptionalResult: { }; }; -export type APIOptionalResult = - { tag: typeof APIOptionalResult.Tag.Success; param0: string | null } | { tag: typeof APIOptionalResult.Tag.Failure; param0: number | null; param1: boolean | null } | { tag: typeof APIOptionalResult.Tag.Status; param0: boolean | null; param1: number | null; param2: string | null } +export type APIOptionalResultTag = + { tag: typeof APIOptionalResultValues.Tag.Success; param0: string | null } | { tag: typeof APIOptionalResultValues.Tag.Failure; param0: number | null; param1: boolean | null } | { tag: typeof APIOptionalResultValues.Tag.Status; param0: boolean | null; param1: number | null; param2: string | null } + +export type APIResultObject = typeof APIResultValues; + +export type ComplexResultObject = typeof ComplexResultValues; + +export type ResultObject = typeof ResultValues; + +export type NetworkingResultObject = typeof NetworkingResultValues; + +export type APIOptionalResultObject = typeof APIOptionalResultValues; export {}; declare global { namespace API { - const NetworkingResult: { + const NetworkingResultValues: { readonly Tag: { readonly Success: 0; readonly Failure: 1; }; }; - type NetworkingResult = - { tag: typeof NetworkingResult.Tag.Success; param0: string } | { tag: typeof NetworkingResult.Tag.Failure; param0: string; param1: number } + type NetworkingResultTag = + { tag: typeof NetworkingResultValues.Tag.Success; param0: string } | { tag: typeof NetworkingResultValues.Tag.Failure; param0: string; param1: number } } namespace Utilities { - const Result: { + const ResultValues: { readonly Tag: { readonly Success: 0; readonly Failure: 1; readonly Status: 2; }; }; - type Result = - { tag: typeof Result.Tag.Success; param0: string } | { tag: typeof Result.Tag.Failure; param0: string; param1: number } | { tag: typeof Result.Tag.Status; param0: boolean; param1: number; param2: string } + type ResultTag = + { tag: typeof ResultValues.Tag.Success; param0: string } | { tag: typeof ResultValues.Tag.Failure; param0: string; param1: number } | { tag: typeof ResultValues.Tag.Status; param0: boolean; param1: number; param2: string } } } export type Exports = { - handle(result: APIResult): void; - getResult(): APIResult; - roundtripAPIResult(result: APIResult): APIResult; - roundTripOptionalAPIResult(result: APIResult | null): APIResult | null; - handleComplex(result: ComplexResult): void; - getComplexResult(): ComplexResult; - roundtripComplexResult(result: ComplexResult): ComplexResult; - roundTripOptionalComplexResult(result: ComplexResult | null): ComplexResult | null; - roundTripOptionalUtilitiesResult(result: Utilities.Result | null): Utilities.Result | null; - roundTripOptionalNetworkingResult(result: NetworkingResult | null): NetworkingResult | null; - roundTripOptionalAPIOptionalResult(result: APIOptionalResult | null): APIOptionalResult | null; + handle(result: APIResultTag): void; + getResult(): APIResultTag; + roundtripAPIResult(result: APIResultTag): APIResultTag; + roundTripOptionalAPIResult(result: APIResultTag | null): APIResultTag | null; + handleComplex(result: ComplexResultTag): void; + getComplexResult(): ComplexResultTag; + roundtripComplexResult(result: ComplexResultTag): ComplexResultTag; + roundTripOptionalComplexResult(result: ComplexResultTag | null): ComplexResultTag | null; + roundTripOptionalUtilitiesResult(result: Utilities.ResultTag | null): Utilities.ResultTag | null; + roundTripOptionalNetworkingResult(result: NetworkingResultTag | null): NetworkingResultTag | null; + roundTripOptionalAPIOptionalResult(result: APIOptionalResultTag | null): APIOptionalResultTag | null; + APIResult: APIResultObject + ComplexResult: ComplexResultObject + Result: ResultObject + NetworkingResult: NetworkingResultObject + APIOptionalResult: APIOptionalResultObject } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js index f7ca2dd8..ea0aef15 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.Export.js @@ -4,7 +4,7 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export const APIResult = { +export const APIResultValues = { Tag: { Success: 0, Failure: 1, @@ -12,15 +12,15 @@ export const APIResult = { Rate: 3, Precise: 4, Info: 5, - } + }, }; -const __bjs_createAPIResultHelpers = () => { +const __bjs_createAPIResultValuesHelpers = () => { return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ lower: (value) => { const enumTag = value.tag; switch (enumTag) { - case APIResult.Tag.Success: { + case APIResultValues.Tag.Success: { const bytes = textEncoder.encode(value.param0); const id = swift.memory.retain(bytes); tmpParamInts.push(bytes.length); @@ -28,65 +28,65 @@ const __bjs_createAPIResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: APIResult.Tag.Success, cleanup }; + return { caseId: APIResultValues.Tag.Success, cleanup }; } - case APIResult.Tag.Failure: { + case APIResultValues.Tag.Failure: { tmpParamInts.push((value.param0 | 0)); const cleanup = undefined; - return { caseId: APIResult.Tag.Failure, cleanup }; + return { caseId: APIResultValues.Tag.Failure, cleanup }; } - case APIResult.Tag.Flag: { + case APIResultValues.Tag.Flag: { tmpParamInts.push(value.param0 ? 1 : 0); const cleanup = undefined; - return { caseId: APIResult.Tag.Flag, cleanup }; + return { caseId: APIResultValues.Tag.Flag, cleanup }; } - case APIResult.Tag.Rate: { + case APIResultValues.Tag.Rate: { tmpParamF32s.push(Math.fround(value.param0)); const cleanup = undefined; - return { caseId: APIResult.Tag.Rate, cleanup }; + return { caseId: APIResultValues.Tag.Rate, cleanup }; } - case APIResult.Tag.Precise: { + case APIResultValues.Tag.Precise: { tmpParamF64s.push(value.param0); const cleanup = undefined; - return { caseId: APIResult.Tag.Precise, cleanup }; + return { caseId: APIResultValues.Tag.Precise, cleanup }; } - case APIResult.Tag.Info: { + case APIResultValues.Tag.Info: { const cleanup = undefined; - return { caseId: APIResult.Tag.Info, cleanup }; + return { caseId: APIResultValues.Tag.Info, cleanup }; } - default: throw new Error("Unknown APIResult tag: " + String(enumTag)); + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); } }, raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { - case APIResult.Tag.Success: { + case APIResultValues.Tag.Success: { const string = tmpRetStrings.pop(); - return { tag: APIResult.Tag.Success, param0: string }; + return { tag: APIResultValues.Tag.Success, param0: string }; } - case APIResult.Tag.Failure: { + case APIResultValues.Tag.Failure: { const int = tmpRetInts.pop(); - return { tag: APIResult.Tag.Failure, param0: int }; + return { tag: APIResultValues.Tag.Failure, param0: int }; } - case APIResult.Tag.Flag: { + case APIResultValues.Tag.Flag: { const bool = tmpRetInts.pop(); - return { tag: APIResult.Tag.Flag, param0: bool }; + return { tag: APIResultValues.Tag.Flag, param0: bool }; } - case APIResult.Tag.Rate: { + case APIResultValues.Tag.Rate: { const f32 = tmpRetF32s.pop(); - return { tag: APIResult.Tag.Rate, param0: f32 }; + return { tag: APIResultValues.Tag.Rate, param0: f32 }; } - case APIResult.Tag.Precise: { + case APIResultValues.Tag.Precise: { const f64 = tmpRetF64s.pop(); - return { tag: APIResult.Tag.Precise, param0: f64 }; + return { tag: APIResultValues.Tag.Precise, param0: f64 }; } - case APIResult.Tag.Info: return { tag: APIResult.Tag.Info }; - default: throw new Error("Unknown APIResult tag returned from Swift: " + String(tag)); + case APIResultValues.Tag.Info: return { tag: APIResultValues.Tag.Info }; + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); } } }); }; -export const ComplexResult = { +export const ComplexResultValues = { Tag: { Success: 0, Error: 1, @@ -94,15 +94,15 @@ export const ComplexResult = { Coordinates: 3, Comprehensive: 4, Info: 5, - } + }, }; -const __bjs_createComplexResultHelpers = () => { +const __bjs_createComplexResultValuesHelpers = () => { return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ lower: (value) => { const enumTag = value.tag; switch (enumTag) { - case ComplexResult.Tag.Success: { + case ComplexResultValues.Tag.Success: { const bytes = textEncoder.encode(value.param0); const id = swift.memory.retain(bytes); tmpParamInts.push(bytes.length); @@ -110,9 +110,9 @@ const __bjs_createComplexResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: ComplexResult.Tag.Success, cleanup }; + return { caseId: ComplexResultValues.Tag.Success, cleanup }; } - case ComplexResult.Tag.Error: { + case ComplexResultValues.Tag.Error: { tmpParamInts.push((value.param1 | 0)); const bytes = textEncoder.encode(value.param0); const id = swift.memory.retain(bytes); @@ -121,9 +121,9 @@ const __bjs_createComplexResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: ComplexResult.Tag.Error, cleanup }; + return { caseId: ComplexResultValues.Tag.Error, cleanup }; } - case ComplexResult.Tag.Status: { + case ComplexResultValues.Tag.Status: { const bytes = textEncoder.encode(value.param2); const id = swift.memory.retain(bytes); tmpParamInts.push(bytes.length); @@ -133,16 +133,16 @@ const __bjs_createComplexResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: ComplexResult.Tag.Status, cleanup }; + return { caseId: ComplexResultValues.Tag.Status, cleanup }; } - case ComplexResult.Tag.Coordinates: { + case ComplexResultValues.Tag.Coordinates: { tmpParamF64s.push(value.param2); tmpParamF64s.push(value.param1); tmpParamF64s.push(value.param0); const cleanup = undefined; - return { caseId: ComplexResult.Tag.Coordinates, cleanup }; + return { caseId: ComplexResultValues.Tag.Coordinates, cleanup }; } - case ComplexResult.Tag.Comprehensive: { + case ComplexResultValues.Tag.Comprehensive: { const bytes = textEncoder.encode(value.param8); const id = swift.memory.retain(bytes); tmpParamInts.push(bytes.length); @@ -166,40 +166,40 @@ const __bjs_createComplexResultHelpers = () => { swift.memory.release(id1); swift.memory.release(id2); }; - return { caseId: ComplexResult.Tag.Comprehensive, cleanup }; + return { caseId: ComplexResultValues.Tag.Comprehensive, cleanup }; } - case ComplexResult.Tag.Info: { + case ComplexResultValues.Tag.Info: { const cleanup = undefined; - return { caseId: ComplexResult.Tag.Info, cleanup }; + return { caseId: ComplexResultValues.Tag.Info, cleanup }; } - default: throw new Error("Unknown ComplexResult tag: " + String(enumTag)); + default: throw new Error("Unknown ComplexResultValues tag: " + String(enumTag)); } }, raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { - case ComplexResult.Tag.Success: { + case ComplexResultValues.Tag.Success: { const string = tmpRetStrings.pop(); - return { tag: ComplexResult.Tag.Success, param0: string }; + return { tag: ComplexResultValues.Tag.Success, param0: string }; } - case ComplexResult.Tag.Error: { + case ComplexResultValues.Tag.Error: { const int = tmpRetInts.pop(); const string = tmpRetStrings.pop(); - return { tag: ComplexResult.Tag.Error, param0: string, param1: int }; + return { tag: ComplexResultValues.Tag.Error, param0: string, param1: int }; } - case ComplexResult.Tag.Status: { + case ComplexResultValues.Tag.Status: { const string = tmpRetStrings.pop(); const int = tmpRetInts.pop(); const bool = tmpRetInts.pop(); - return { tag: ComplexResult.Tag.Status, param0: bool, param1: int, param2: string }; + return { tag: ComplexResultValues.Tag.Status, param0: bool, param1: int, param2: string }; } - case ComplexResult.Tag.Coordinates: { + case ComplexResultValues.Tag.Coordinates: { const f64 = tmpRetF64s.pop(); const f641 = tmpRetF64s.pop(); const f642 = tmpRetF64s.pop(); - return { tag: ComplexResult.Tag.Coordinates, param0: f642, param1: f641, param2: f64 }; + return { tag: ComplexResultValues.Tag.Coordinates, param0: f642, param1: f641, param2: f64 }; } - case ComplexResult.Tag.Comprehensive: { + case ComplexResultValues.Tag.Comprehensive: { const string = tmpRetStrings.pop(); const string1 = tmpRetStrings.pop(); const string2 = tmpRetStrings.pop(); @@ -209,28 +209,28 @@ const __bjs_createComplexResultHelpers = () => { const int1 = tmpRetInts.pop(); const bool = tmpRetInts.pop(); const bool1 = tmpRetInts.pop(); - return { tag: ComplexResult.Tag.Comprehensive, param0: bool1, param1: bool, param2: int1, param3: int, param4: f641, param5: f64, param6: string2, param7: string1, param8: string }; + return { tag: ComplexResultValues.Tag.Comprehensive, param0: bool1, param1: bool, param2: int1, param3: int, param4: f641, param5: f64, param6: string2, param7: string1, param8: string }; } - case ComplexResult.Tag.Info: return { tag: ComplexResult.Tag.Info }; - default: throw new Error("Unknown ComplexResult tag returned from Swift: " + String(tag)); + case ComplexResultValues.Tag.Info: return { tag: ComplexResultValues.Tag.Info }; + default: throw new Error("Unknown ComplexResultValues tag returned from Swift: " + String(tag)); } } }); }; -export const Result = { +export const ResultValues = { Tag: { Success: 0, Failure: 1, Status: 2, - } + }, }; -const __bjs_createResultHelpers = () => { +const __bjs_createResultValuesHelpers = () => { return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ lower: (value) => { const enumTag = value.tag; switch (enumTag) { - case Result.Tag.Success: { + case ResultValues.Tag.Success: { const bytes = textEncoder.encode(value.param0); const id = swift.memory.retain(bytes); tmpParamInts.push(bytes.length); @@ -238,9 +238,9 @@ const __bjs_createResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: Result.Tag.Success, cleanup }; + return { caseId: ResultValues.Tag.Success, cleanup }; } - case Result.Tag.Failure: { + case ResultValues.Tag.Failure: { tmpParamInts.push((value.param1 | 0)); const bytes = textEncoder.encode(value.param0); const id = swift.memory.retain(bytes); @@ -249,9 +249,9 @@ const __bjs_createResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: Result.Tag.Failure, cleanup }; + return { caseId: ResultValues.Tag.Failure, cleanup }; } - case Result.Tag.Status: { + case ResultValues.Tag.Status: { const bytes = textEncoder.encode(value.param2); const id = swift.memory.retain(bytes); tmpParamInts.push(bytes.length); @@ -261,47 +261,47 @@ const __bjs_createResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: Result.Tag.Status, cleanup }; + return { caseId: ResultValues.Tag.Status, cleanup }; } - default: throw new Error("Unknown Result tag: " + String(enumTag)); + default: throw new Error("Unknown ResultValues tag: " + String(enumTag)); } }, raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { - case Result.Tag.Success: { + case ResultValues.Tag.Success: { const string = tmpRetStrings.pop(); - return { tag: Result.Tag.Success, param0: string }; + return { tag: ResultValues.Tag.Success, param0: string }; } - case Result.Tag.Failure: { + case ResultValues.Tag.Failure: { const int = tmpRetInts.pop(); const string = tmpRetStrings.pop(); - return { tag: Result.Tag.Failure, param0: string, param1: int }; + return { tag: ResultValues.Tag.Failure, param0: string, param1: int }; } - case Result.Tag.Status: { + case ResultValues.Tag.Status: { const string = tmpRetStrings.pop(); const int = tmpRetInts.pop(); const bool = tmpRetInts.pop(); - return { tag: Result.Tag.Status, param0: bool, param1: int, param2: string }; + return { tag: ResultValues.Tag.Status, param0: bool, param1: int, param2: string }; } - default: throw new Error("Unknown Result tag returned from Swift: " + String(tag)); + default: throw new Error("Unknown ResultValues tag returned from Swift: " + String(tag)); } } }); }; -export const NetworkingResult = { +export const NetworkingResultValues = { Tag: { Success: 0, Failure: 1, - } + }, }; -const __bjs_createNetworkingResultHelpers = () => { +const __bjs_createNetworkingResultValuesHelpers = () => { return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ lower: (value) => { const enumTag = value.tag; switch (enumTag) { - case NetworkingResult.Tag.Success: { + case NetworkingResultValues.Tag.Success: { const bytes = textEncoder.encode(value.param0); const id = swift.memory.retain(bytes); tmpParamInts.push(bytes.length); @@ -309,9 +309,9 @@ const __bjs_createNetworkingResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: NetworkingResult.Tag.Success, cleanup }; + return { caseId: NetworkingResultValues.Tag.Success, cleanup }; } - case NetworkingResult.Tag.Failure: { + case NetworkingResultValues.Tag.Failure: { tmpParamInts.push((value.param1 | 0)); const bytes = textEncoder.encode(value.param0); const id = swift.memory.retain(bytes); @@ -320,42 +320,42 @@ const __bjs_createNetworkingResultHelpers = () => { const cleanup = () => { swift.memory.release(id); }; - return { caseId: NetworkingResult.Tag.Failure, cleanup }; + return { caseId: NetworkingResultValues.Tag.Failure, cleanup }; } - default: throw new Error("Unknown NetworkingResult tag: " + String(enumTag)); + default: throw new Error("Unknown NetworkingResultValues tag: " + String(enumTag)); } }, raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { - case NetworkingResult.Tag.Success: { + case NetworkingResultValues.Tag.Success: { const string = tmpRetStrings.pop(); - return { tag: NetworkingResult.Tag.Success, param0: string }; + return { tag: NetworkingResultValues.Tag.Success, param0: string }; } - case NetworkingResult.Tag.Failure: { + case NetworkingResultValues.Tag.Failure: { const int = tmpRetInts.pop(); const string = tmpRetStrings.pop(); - return { tag: NetworkingResult.Tag.Failure, param0: string, param1: int }; + return { tag: NetworkingResultValues.Tag.Failure, param0: string, param1: int }; } - default: throw new Error("Unknown NetworkingResult tag returned from Swift: " + String(tag)); + default: throw new Error("Unknown NetworkingResultValues tag returned from Swift: " + String(tag)); } } }); }; -export const APIOptionalResult = { +export const APIOptionalResultValues = { Tag: { Success: 0, Failure: 1, Status: 2, - } + }, }; -const __bjs_createAPIOptionalResultHelpers = () => { +const __bjs_createAPIOptionalResultValuesHelpers = () => { return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ lower: (value) => { const enumTag = value.tag; switch (enumTag) { - case APIOptionalResult.Tag.Success: { + case APIOptionalResultValues.Tag.Success: { const isSome = value.param0 != null; let id; if (isSome) { @@ -373,9 +373,9 @@ const __bjs_createAPIOptionalResultHelpers = () => { swift.memory.release(id); } }; - return { caseId: APIOptionalResult.Tag.Success, cleanup }; + return { caseId: APIOptionalResultValues.Tag.Success, cleanup }; } - case APIOptionalResult.Tag.Failure: { + case APIOptionalResultValues.Tag.Failure: { const isSome = value.param1 != null; tmpParamInts.push(isSome ? (value.param1 ? 1 : 0) : 0); tmpParamInts.push(isSome ? 1 : 0); @@ -383,9 +383,9 @@ const __bjs_createAPIOptionalResultHelpers = () => { tmpParamInts.push(isSome1 ? (value.param0 | 0) : 0); tmpParamInts.push(isSome1 ? 1 : 0); const cleanup = undefined; - return { caseId: APIOptionalResult.Tag.Failure, cleanup }; + return { caseId: APIOptionalResultValues.Tag.Failure, cleanup }; } - case APIOptionalResult.Tag.Status: { + case APIOptionalResultValues.Tag.Status: { const isSome = value.param2 != null; let id; if (isSome) { @@ -409,15 +409,15 @@ const __bjs_createAPIOptionalResultHelpers = () => { swift.memory.release(id); } }; - return { caseId: APIOptionalResult.Tag.Status, cleanup }; + return { caseId: APIOptionalResultValues.Tag.Status, cleanup }; } - default: throw new Error("Unknown APIOptionalResult tag: " + String(enumTag)); + default: throw new Error("Unknown APIOptionalResultValues tag: " + String(enumTag)); } }, raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { const tag = tmpRetTag | 0; switch (tag) { - case APIOptionalResult.Tag.Success: { + case APIOptionalResultValues.Tag.Success: { const isSome = tmpRetInts.pop(); let optional; if (isSome) { @@ -426,9 +426,9 @@ const __bjs_createAPIOptionalResultHelpers = () => { } else { optional = null; } - return { tag: APIOptionalResult.Tag.Success, param0: optional }; + return { tag: APIOptionalResultValues.Tag.Success, param0: optional }; } - case APIOptionalResult.Tag.Failure: { + case APIOptionalResultValues.Tag.Failure: { const isSome = tmpRetInts.pop(); let optional; if (isSome) { @@ -445,9 +445,9 @@ const __bjs_createAPIOptionalResultHelpers = () => { } else { optional1 = null; } - return { tag: APIOptionalResult.Tag.Failure, param0: optional1, param1: optional }; + return { tag: APIOptionalResultValues.Tag.Failure, param0: optional1, param1: optional }; } - case APIOptionalResult.Tag.Status: { + case APIOptionalResultValues.Tag.Status: { const isSome = tmpRetInts.pop(); let optional; if (isSome) { @@ -472,23 +472,21 @@ const __bjs_createAPIOptionalResultHelpers = () => { } else { optional2 = null; } - return { tag: APIOptionalResult.Tag.Status, param0: optional2, param1: optional1, param2: optional }; + return { tag: APIOptionalResultValues.Tag.Status, param0: optional2, param1: optional1, param2: optional }; } - default: throw new Error("Unknown APIOptionalResult tag returned from Swift: " + String(tag)); + default: throw new Error("Unknown APIOptionalResultValues tag returned from Swift: " + String(tag)); } } }); }; -if (typeof globalThis.Utilities === 'undefined') { - globalThis.Utilities = {}; -} if (typeof globalThis.API === 'undefined') { globalThis.API = {}; } - -globalThis.Utilities.Result = Result; -globalThis.API.NetworkingResult = NetworkingResult; - +if (typeof globalThis.Utilities === 'undefined') { + globalThis.Utilities = {}; +} +globalThis.Utilities.ResultValues = ResultValues; +globalThis.API.NetworkingResultValues = NetworkingResultValues; export async function createInstantiator(options, swift) { let instance; let memory; @@ -629,19 +627,19 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - const APIResultHelpers = __bjs_createAPIResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); enumHelpers.APIResult = APIResultHelpers; - const ComplexResultHelpers = __bjs_createComplexResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + const ComplexResultHelpers = __bjs_createComplexResultValuesHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); enumHelpers.ComplexResult = ComplexResultHelpers; - const ResultHelpers = __bjs_createResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + const ResultHelpers = __bjs_createResultValuesHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); enumHelpers.Result = ResultHelpers; - const NetworkingResultHelpers = __bjs_createNetworkingResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + const NetworkingResultHelpers = __bjs_createNetworkingResultValuesHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); enumHelpers.NetworkingResult = NetworkingResultHelpers; - const APIOptionalResultHelpers = __bjs_createAPIOptionalResultHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + const APIOptionalResultHelpers = __bjs_createAPIOptionalResultValuesHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); enumHelpers.APIOptionalResult = APIOptionalResultHelpers; setException = (error) => { @@ -651,7 +649,13 @@ export async function createInstantiator(options, swift) { /** @param {WebAssembly.Instance} instance */ createExports: (instance) => { const js = swift.memory.heap; - return { + if (typeof globalThis.API === 'undefined') { + globalThis.API = {}; + } + if (typeof globalThis.Utilities === 'undefined') { + globalThis.Utilities = {}; + } + const exports = { handle: function bjs_handle(result) { const { caseId: resultCaseId, cleanup: resultCleanup } = enumHelpers.APIResult.lower(result); instance.exports.bjs_handle(resultCaseId); @@ -781,7 +785,13 @@ export async function createInstantiator(options, swift) { if (resultCleanup) { resultCleanup(); } return optResult; }, + APIResult: APIResultValues, + ComplexResult: ComplexResultValues, + Result: ResultValues, + NetworkingResult: NetworkingResultValues, + APIOptionalResult: APIOptionalResultValues, }; + return exports; }, } } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.d.ts index 9a04f59a..47fb52d9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.d.ts @@ -4,20 +4,20 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export const Direction: { +export const DirectionValues: { readonly North: 0; readonly South: 1; readonly East: 2; readonly West: 3; }; -export type Direction = typeof Direction[keyof typeof Direction]; +export type DirectionTag = typeof DirectionValues[keyof typeof DirectionValues]; -export const Status: { +export const StatusValues: { readonly Loading: 0; readonly Success: 1; readonly Error: 2; }; -export type Status = typeof Status[keyof typeof Status]; +export type StatusTag = typeof StatusValues[keyof typeof StatusValues]; export enum TSDirection { North = 0, @@ -26,19 +26,28 @@ export enum TSDirection { West = 3, } -export const PublicStatus: { +export const PublicStatusValues: { readonly Success: 0; }; -export type PublicStatus = typeof PublicStatus[keyof typeof PublicStatus]; +export type PublicStatusTag = typeof PublicStatusValues[keyof typeof PublicStatusValues]; + +export type DirectionObject = typeof DirectionValues; + +export type StatusObject = typeof StatusValues; + +export type PublicStatusObject = typeof PublicStatusValues; export type Exports = { - setDirection(direction: Direction): void; - getDirection(): Direction; - processDirection(input: Direction): Status; - roundTripOptionalDirection(input: Direction | null): Direction | null; - setTSDirection(direction: TSDirection): void; - getTSDirection(): TSDirection; - roundTripOptionalTSDirection(input: TSDirection | null): TSDirection | null; + setDirection(direction: DirectionTag): void; + getDirection(): DirectionTag; + processDirection(input: DirectionTag): StatusTag; + roundTripOptionalDirection(input: DirectionTag | null): DirectionTag | null; + setTSDirection(direction: TSDirectionTag): void; + getTSDirection(): TSDirectionTag; + roundTripOptionalTSDirection(input: TSDirectionTag | null): TSDirectionTag | null; + Direction: DirectionObject + Status: StatusObject + PublicStatus: PublicStatusObject } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js index 5eb0b420..9cbed9a2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.Export.js @@ -4,14 +4,14 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export const Direction = { +export const DirectionValues = { North: 0, South: 1, East: 2, West: 3, }; -export const Status = { +export const StatusValues = { Loading: 0, Success: 1, Error: 2, @@ -24,7 +24,7 @@ export const TSDirection = { West: 3, }; -export const PublicStatus = { +export const PublicStatusValues = { Success: 0, }; @@ -207,6 +207,9 @@ export async function createInstantiator(options, swift) { tmpRetOptionalInt = undefined; return optResult; }, + Direction: DirectionValues, + Status: StatusValues, + PublicStatus: PublicStatusValues, }; }, } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.d.ts index 3d37ca6c..7c05f171 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.d.ts @@ -4,49 +4,57 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. +export type MethodObject = typeof MethodValues; + +export type LogLevelObject = typeof LogLevelValues; + +export type PortObject = typeof PortValues; + +export type SupportedMethodObject = typeof SupportedMethodValues; + export {}; declare global { namespace Configuration { - const LogLevel: { + const LogLevelValues: { readonly Debug: "debug"; readonly Info: "info"; readonly Warning: "warning"; readonly Error: "error"; }; - type LogLevel = typeof LogLevel[keyof typeof LogLevel]; - const Port: { + type LogLevelTag = typeof LogLevelValues[keyof typeof LogLevelValues]; + const PortValues: { readonly Http: 80; readonly Https: 443; readonly Development: 3000; }; - type Port = typeof Port[keyof typeof Port]; + type PortTag = typeof PortValues[keyof typeof PortValues]; } namespace Networking { namespace API { class HTTPServer { constructor(); - call(method: Networking.API.Method): void; + call(method: Networking.API.MethodTag): void; } - const Method: { + const MethodValues: { readonly Get: 0; readonly Post: 1; readonly Put: 2; readonly Delete: 3; }; - type Method = typeof Method[keyof typeof Method]; + type MethodTag = typeof MethodValues[keyof typeof MethodValues]; } namespace APIV2 { namespace Internal { class TestServer { constructor(); - call(method: Internal.SupportedMethod): void; + call(method: Internal.SupportedMethodTag): void; } - const SupportedMethod: { + const SupportedMethodValues: { readonly Get: 0; readonly Post: 1; }; - type SupportedMethod = typeof SupportedMethod[keyof typeof SupportedMethod]; + type SupportedMethodTag = typeof SupportedMethodValues[keyof typeof SupportedMethodValues]; } } } @@ -69,10 +77,10 @@ export interface Converter extends SwiftHeapObject { toString(value: number): string; } export interface HTTPServer extends SwiftHeapObject { - call(method: Networking.API.Method): void; + call(method: Networking.API.MethodTag): void; } export interface TestServer extends SwiftHeapObject { - call(method: Internal.SupportedMethod): void; + call(method: Internal.SupportedMethodTag): void; } export type Exports = { Converter: { @@ -84,6 +92,10 @@ export type Exports = { TestServer: { new(): TestServer; } + Method: MethodObject + LogLevel: LogLevelObject + Port: PortObject + SupportedMethod: SupportedMethodObject } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js index 0aff338b..b934456f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Export.js @@ -4,52 +4,50 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export const Method = { +export const MethodValues = { Get: 0, Post: 1, Put: 2, Delete: 3, }; -export const LogLevel = { +export const LogLevelValues = { Debug: "debug", Info: "info", Warning: "warning", Error: "error", }; -export const Port = { +export const PortValues = { Http: 80, Https: 443, Development: 3000, }; -export const SupportedMethod = { +export const SupportedMethodValues = { Get: 0, Post: 1, }; +if (typeof globalThis.Configuration === 'undefined') { + globalThis.Configuration = {}; +} if (typeof globalThis.Networking === 'undefined') { globalThis.Networking = {}; } if (typeof globalThis.Networking.API === 'undefined') { globalThis.Networking.API = {}; } -if (typeof globalThis.Configuration === 'undefined') { - globalThis.Configuration = {}; -} if (typeof globalThis.Networking.APIV2 === 'undefined') { globalThis.Networking.APIV2 = {}; } if (typeof globalThis.Networking.APIV2.Internal === 'undefined') { globalThis.Networking.APIV2.Internal = {}; } - -globalThis.Networking.API.Method = Method; -globalThis.Configuration.LogLevel = LogLevel; -globalThis.Configuration.Port = Port; -globalThis.Networking.APIV2.Internal.SupportedMethod = SupportedMethod; - +globalThis.Networking.API.MethodValues = MethodValues; +globalThis.Configuration.LogLevelValues = LogLevelValues; +globalThis.Configuration.PortValues = PortValues; +globalThis.Networking.APIV2.Internal.SupportedMethodValues = SupportedMethodValues; export async function createInstantiator(options, swift) { let instance; let memory; @@ -273,11 +271,9 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_TestServer_call(this.pointer, method); } } - const exports = { - Converter, - HTTPServer, - TestServer, - }; + if (typeof globalThis.Configuration === 'undefined') { + globalThis.Configuration = {}; + } if (typeof globalThis.Networking === 'undefined') { globalThis.Networking = {}; } @@ -293,6 +289,15 @@ export async function createInstantiator(options, swift) { if (typeof globalThis.Utils === 'undefined') { globalThis.Utils = {}; } + const exports = { + Converter, + HTTPServer, + TestServer, + Method: MethodValues, + LogLevel: LogLevelValues, + Port: PortValues, + SupportedMethod: SupportedMethodValues, + }; globalThis.Utils.Converter = exports.Converter; globalThis.Networking.API.HTTPServer = exports.HTTPServer; globalThis.Networking.APIV2.Internal.TestServer = exports.TestServer; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts index 96297187..b92c54ce 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.d.ts @@ -4,12 +4,12 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export const Theme: { +export const ThemeValues: { readonly Light: "light"; readonly Dark: "dark"; readonly Auto: "auto"; }; -export type Theme = typeof Theme[keyof typeof Theme]; +export type ThemeTag = typeof ThemeValues[keyof typeof ThemeValues]; export enum TSTheme { Light = "light", @@ -17,18 +17,18 @@ export enum TSTheme { Auto = "auto", } -export const FeatureFlag: { +export const FeatureFlagValues: { readonly Enabled: true; readonly Disabled: false; }; -export type FeatureFlag = typeof FeatureFlag[keyof typeof FeatureFlag]; +export type FeatureFlagTag = typeof FeatureFlagValues[keyof typeof FeatureFlagValues]; -export const HttpStatus: { +export const HttpStatusValues: { readonly Ok: 200; readonly NotFound: 404; readonly ServerError: 500; }; -export type HttpStatus = typeof HttpStatus[keyof typeof HttpStatus]; +export type HttpStatusTag = typeof HttpStatusValues[keyof typeof HttpStatusValues]; export enum TSHttpStatus { Ok = 200, @@ -36,99 +36,129 @@ export enum TSHttpStatus { ServerError = 500, } -export const Priority: { +export const PriorityValues: { readonly Lowest: 1; readonly Low: 2; readonly Medium: 3; readonly High: 4; readonly Highest: 5; }; -export type Priority = typeof Priority[keyof typeof Priority]; +export type PriorityTag = typeof PriorityValues[keyof typeof PriorityValues]; -export const FileSize: { +export const FileSizeValues: { readonly Tiny: 1024; readonly Small: 10240; readonly Medium: 102400; readonly Large: 1048576; }; -export type FileSize = typeof FileSize[keyof typeof FileSize]; +export type FileSizeTag = typeof FileSizeValues[keyof typeof FileSizeValues]; -export const UserId: { +export const UserIdValues: { readonly Guest: 0; readonly User: 1000; readonly Admin: 9999; }; -export type UserId = typeof UserId[keyof typeof UserId]; +export type UserIdTag = typeof UserIdValues[keyof typeof UserIdValues]; -export const TokenId: { +export const TokenIdValues: { readonly Invalid: 0; readonly Session: 12345; readonly Refresh: 67890; }; -export type TokenId = typeof TokenId[keyof typeof TokenId]; +export type TokenIdTag = typeof TokenIdValues[keyof typeof TokenIdValues]; -export const SessionId: { +export const SessionIdValues: { readonly None: 0; readonly Active: 9876543210; readonly Expired: 1234567890; }; -export type SessionId = typeof SessionId[keyof typeof SessionId]; +export type SessionIdTag = typeof SessionIdValues[keyof typeof SessionIdValues]; -export const Precision: { +export const PrecisionValues: { readonly Rough: 0.1; readonly Normal: 0.01; readonly Fine: 0.001; }; -export type Precision = typeof Precision[keyof typeof Precision]; +export type PrecisionTag = typeof PrecisionValues[keyof typeof PrecisionValues]; -export const Ratio: { +export const RatioValues: { readonly Quarter: 0.25; readonly Half: 0.5; readonly Golden: 1.618; readonly Pi: 3.14159; }; -export type Ratio = typeof Ratio[keyof typeof Ratio]; +export type RatioTag = typeof RatioValues[keyof typeof RatioValues]; + +export type ThemeObject = typeof ThemeValues; + +export type FeatureFlagObject = typeof FeatureFlagValues; + +export type HttpStatusObject = typeof HttpStatusValues; + +export type PriorityObject = typeof PriorityValues; + +export type FileSizeObject = typeof FileSizeValues; + +export type UserIdObject = typeof UserIdValues; + +export type TokenIdObject = typeof TokenIdValues; + +export type SessionIdObject = typeof SessionIdValues; + +export type PrecisionObject = typeof PrecisionValues; + +export type RatioObject = typeof RatioValues; export type Exports = { - setTheme(theme: Theme): void; - getTheme(): Theme; - roundTripOptionalTheme(input: Theme | null): Theme | null; - setTSTheme(theme: TSTheme): void; - getTSTheme(): TSTheme; - roundTripOptionalTSTheme(input: TSTheme | null): TSTheme | null; - setFeatureFlag(flag: FeatureFlag): void; - getFeatureFlag(): FeatureFlag; - roundTripOptionalFeatureFlag(input: FeatureFlag | null): FeatureFlag | null; - setHttpStatus(status: HttpStatus): void; - getHttpStatus(): HttpStatus; - roundTripOptionalHttpStatus(input: HttpStatus | null): HttpStatus | null; - setTSHttpStatus(status: TSHttpStatus): void; - getTSHttpStatus(): TSHttpStatus; - roundTripOptionalHttpStatus(input: TSHttpStatus | null): TSHttpStatus | null; - setPriority(priority: Priority): void; - getPriority(): Priority; - roundTripOptionalPriority(input: Priority | null): Priority | null; - setFileSize(size: FileSize): void; - getFileSize(): FileSize; - roundTripOptionalFileSize(input: FileSize | null): FileSize | null; - setUserId(id: UserId): void; - getUserId(): UserId; - roundTripOptionalUserId(input: UserId | null): UserId | null; - setTokenId(token: TokenId): void; - getTokenId(): TokenId; - roundTripOptionalTokenId(input: TokenId | null): TokenId | null; - setSessionId(session: SessionId): void; - getSessionId(): SessionId; - roundTripOptionalSessionId(input: SessionId | null): SessionId | null; - setPrecision(precision: Precision): void; - getPrecision(): Precision; - roundTripOptionalPrecision(input: Precision | null): Precision | null; - setRatio(ratio: Ratio): void; - getRatio(): Ratio; - roundTripOptionalRatio(input: Ratio | null): Ratio | null; - processTheme(theme: Theme): HttpStatus; - convertPriority(status: HttpStatus): Priority; - validateSession(session: SessionId): Theme; + setTheme(theme: ThemeTag): void; + getTheme(): ThemeTag; + roundTripOptionalTheme(input: ThemeTag | null): ThemeTag | null; + setTSTheme(theme: TSThemeTag): void; + getTSTheme(): TSThemeTag; + roundTripOptionalTSTheme(input: TSThemeTag | null): TSThemeTag | null; + setFeatureFlag(flag: FeatureFlagTag): void; + getFeatureFlag(): FeatureFlagTag; + roundTripOptionalFeatureFlag(input: FeatureFlagTag | null): FeatureFlagTag | null; + setHttpStatus(status: HttpStatusTag): void; + getHttpStatus(): HttpStatusTag; + roundTripOptionalHttpStatus(input: HttpStatusTag | null): HttpStatusTag | null; + setTSHttpStatus(status: TSHttpStatusTag): void; + getTSHttpStatus(): TSHttpStatusTag; + roundTripOptionalHttpStatus(input: TSHttpStatusTag | null): TSHttpStatusTag | null; + setPriority(priority: PriorityTag): void; + getPriority(): PriorityTag; + roundTripOptionalPriority(input: PriorityTag | null): PriorityTag | null; + setFileSize(size: FileSizeTag): void; + getFileSize(): FileSizeTag; + roundTripOptionalFileSize(input: FileSizeTag | null): FileSizeTag | null; + setUserId(id: UserIdTag): void; + getUserId(): UserIdTag; + roundTripOptionalUserId(input: UserIdTag | null): UserIdTag | null; + setTokenId(token: TokenIdTag): void; + getTokenId(): TokenIdTag; + roundTripOptionalTokenId(input: TokenIdTag | null): TokenIdTag | null; + setSessionId(session: SessionIdTag): void; + getSessionId(): SessionIdTag; + roundTripOptionalSessionId(input: SessionIdTag | null): SessionIdTag | null; + setPrecision(precision: PrecisionTag): void; + getPrecision(): PrecisionTag; + roundTripOptionalPrecision(input: PrecisionTag | null): PrecisionTag | null; + setRatio(ratio: RatioTag): void; + getRatio(): RatioTag; + roundTripOptionalRatio(input: RatioTag | null): RatioTag | null; + processTheme(theme: ThemeTag): HttpStatusTag; + convertPriority(status: HttpStatusTag): PriorityTag; + validateSession(session: SessionIdTag): ThemeTag; + Theme: ThemeObject + FeatureFlag: FeatureFlagObject + HttpStatus: HttpStatusObject + Priority: PriorityObject + FileSize: FileSizeObject + UserId: UserIdObject + TokenId: TokenIdObject + SessionId: SessionIdObject + Precision: PrecisionObject + Ratio: RatioObject } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js index fe1b4258..3c7239b7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.Export.js @@ -4,7 +4,7 @@ // To update this file, just rebuild your project or run // `swift package bridge-js`. -export const Theme = { +export const ThemeValues = { Light: "light", Dark: "dark", Auto: "auto", @@ -16,12 +16,12 @@ export const TSTheme = { Auto: "auto", }; -export const FeatureFlag = { +export const FeatureFlagValues = { Enabled: true, Disabled: false, }; -export const HttpStatus = { +export const HttpStatusValues = { Ok: 200, NotFound: 404, ServerError: 500, @@ -33,7 +33,7 @@ export const TSHttpStatus = { ServerError: 500, }; -export const Priority = { +export const PriorityValues = { Lowest: 1, Low: 2, Medium: 3, @@ -41,38 +41,38 @@ export const Priority = { Highest: 5, }; -export const FileSize = { +export const FileSizeValues = { Tiny: 1024, Small: 10240, Medium: 102400, Large: 1048576, }; -export const UserId = { +export const UserIdValues = { Guest: 0, User: 1000, Admin: 9999, }; -export const TokenId = { +export const TokenIdValues = { Invalid: 0, Session: 12345, Refresh: 67890, }; -export const SessionId = { +export const SessionIdValues = { None: 0, Active: 9876543210, Expired: 1234567890, }; -export const Precision = { +export const PrecisionValues = { Rough: 0.1, Normal: 0.01, Fine: 0.001, }; -export const Ratio = { +export const RatioValues = { Quarter: 0.25, Half: 0.5, Golden: 1.618, @@ -437,6 +437,16 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }, + Theme: ThemeValues, + FeatureFlag: FeatureFlagValues, + HttpStatus: HttpStatusValues, + Priority: PriorityValues, + FileSize: FileSizeValues, + UserId: UserIdValues, + TokenId: TokenIdValues, + SessionId: SessionIdValues, + Precision: PrecisionValues, + Ratio: RatioValues, }; }, } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js index 4631fb24..5044b4b1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Export.js @@ -232,23 +232,6 @@ export async function createInstantiator(options, swift) { return ret; } } - const exports = { - Greeter, - Converter, - UUID, - plainFunction: function bjs_plainFunction() { - instance.exports.bjs_plainFunction(); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - }, - namespacedFunction: function bjs_namespacedFunction() { - instance.exports.bjs_namespacedFunction(); - const ret = tmpRetString; - tmpRetString = undefined; - return ret; - }, - }; if (typeof globalThis.MyModule === 'undefined') { globalThis.MyModule = {}; } @@ -267,6 +250,23 @@ export async function createInstantiator(options, swift) { if (typeof globalThis.__Swift.Foundation === 'undefined') { globalThis.__Swift.Foundation = {}; } + const exports = { + Greeter, + Converter, + UUID, + plainFunction: function bjs_plainFunction() { + instance.exports.bjs_plainFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + namespacedFunction: function bjs_MyModule_Utils_namespacedFunction() { + instance.exports.bjs_MyModule_Utils_namespacedFunction(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + }; globalThis.__Swift.Foundation.Greeter = exports.Greeter; globalThis.Utils.Converters.Converter = exports.Converter; globalThis.__Swift.Foundation.UUID = exports.UUID; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.d.ts new file mode 100644 index 00000000..9622891a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.d.ts @@ -0,0 +1,68 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +export const CalculatorValues: { + readonly Scientific: 0; + readonly Basic: 1; +}; +export type CalculatorTag = typeof CalculatorValues[keyof typeof CalculatorValues]; + +export const APIResultValues: { + readonly Tag: { + readonly Success: 0; + readonly Failure: 1; + }; +}; + +export type APIResultTag = + { tag: typeof APIResultValues.Tag.Success; param0: string } | { tag: typeof APIResultValues.Tag.Failure; param0: number } + +export type CalculatorObject = typeof CalculatorValues & { + square(value: number): number; +}; + +export type APIResultObject = typeof APIResultValues & { + roundtrip(value: APIResultTag): APIResultTag; +}; + +export {}; + +declare global { + namespace Utils { + namespace String { + uppercase(text: string): 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 MathUtils extends SwiftHeapObject { + multiply(x: number, y: number): number; +} +export type Exports = { + MathUtils: { + new(): MathUtils; + subtract(a: number, b: number): number; + add(a: number, b: number): number; + } + Calculator: CalculatorObject + APIResult: APIResultObject +} +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/StaticFunctions.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.js new file mode 100644 index 00000000..44ad0a93 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Export.js @@ -0,0 +1,296 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +export const CalculatorValues = { + Scientific: 0, + Basic: 1, +}; + +export const APIResultValues = { + Tag: { + Success: 0, + Failure: 1, + }, +}; + +const __bjs_createAPIResultValuesHelpers = () => { + return (tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift) => ({ + lower: (value) => { + const enumTag = value.tag; + switch (enumTag) { + case APIResultValues.Tag.Success: { + const bytes = textEncoder.encode(value.param0); + const id = swift.memory.retain(bytes); + tmpParamInts.push(bytes.length); + tmpParamInts.push(id); + const cleanup = () => { + swift.memory.release(id); + }; + return { caseId: APIResultValues.Tag.Success, cleanup }; + } + case APIResultValues.Tag.Failure: { + tmpParamInts.push((value.param0 | 0)); + const cleanup = undefined; + return { caseId: APIResultValues.Tag.Failure, cleanup }; + } + default: throw new Error("Unknown APIResultValues tag: " + String(enumTag)); + } + }, + raise: (tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s) => { + const tag = tmpRetTag | 0; + switch (tag) { + case APIResultValues.Tag.Success: { + const string = tmpRetStrings.pop(); + return { tag: APIResultValues.Tag.Success, param0: string }; + } + case APIResultValues.Tag.Failure: { + const int = tmpRetInts.pop(); + return { tag: APIResultValues.Tag.Failure, param0: int }; + } + default: throw new Error("Unknown APIResultValues tag returned from Swift: " + String(tag)); + } + } + }); +}; +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + const enumHelpers = {}; + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + const bjs = {}; + importObject["bjs"] = bjs; + const imports = options.getImports(importsContext); + bjs["swift_js_return_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + return swift.memory.retain(textDecoder.decode(bytes)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr, len); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_MathUtils_wrap"] = function(pointer) { + const obj = MathUtils.__construct(pointer); + return swift.memory.retain(obj); + }; + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + const APIResultHelpers = __bjs_createAPIResultValuesHelpers()(tmpParamInts, tmpParamF32s, tmpParamF64s, textEncoder, swift); + enumHelpers.APIResult = APIResultHelpers; + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + /// Represents a Swift heap object like a class instance or an actor instance. + class SwiftHeapObject { + static __wrap(pointer, deinit, prototype) { + const obj = Object.create(prototype); + obj.pointer = pointer; + obj.hasReleased = false; + obj.deinit = deinit; + obj.registry = new FinalizationRegistry((pointer) => { + deinit(pointer); + }); + obj.registry.register(this, obj.pointer); + return obj; + } + + release() { + this.registry.unregister(this); + this.deinit(this.pointer); + } + } + class MathUtils extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_MathUtils_deinit, MathUtils.prototype); + } + + constructor() { + const ret = instance.exports.bjs_MathUtils_init(); + return MathUtils.__construct(ret); + } + static subtract(a, b) { + const ret = instance.exports.bjs_MathUtils_static_subtract(a, b); + return ret; + } + static add(a, b) { + const ret = instance.exports.bjs_MathUtils_static_add(a, b); + return ret; + } + multiply(x, y) { + const ret = instance.exports.bjs_MathUtils_multiply(this.pointer, x, y); + return ret; + } + } + if (typeof globalThis.Utils === 'undefined') { + globalThis.Utils = {}; + } + if (typeof globalThis.Utils.String === 'undefined') { + globalThis.Utils.String = {}; + } + const exports = { + MathUtils, + uppercase: function bjs_Utils_String_static_uppercase(text) { + const textBytes = textEncoder.encode(text); + const textId = swift.memory.retain(textBytes); + instance.exports.bjs_Utils_String_static_uppercase(textId, textBytes.length); + const ret = tmpRetString; + tmpRetString = undefined; + swift.memory.release(textId); + return ret; + }, + Calculator: { + ...CalculatorValues, + square: function(value) { + const ret = instance.exports.bjs_Calculator_static_square(value); + return ret; + } + }, + APIResult: { + ...APIResultValues, + roundtrip: function(value) { + const { caseId: valueCaseId, cleanup: valueCleanup } = enumHelpers.APIResult.lower(value); + instance.exports.bjs_APIResult_static_roundtrip(valueCaseId); + const ret = enumHelpers.APIResult.raise(tmpRetTag, tmpRetStrings, tmpRetInts, tmpRetF32s, tmpRetF64s); + if (valueCleanup) { valueCleanup(); } + return ret; + } + }, + }; + globalThis.Utils.String.uppercase = exports.uppercase; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.d.ts new file mode 100644 index 00000000..40e28718 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.d.ts @@ -0,0 +1,63 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +export const PropertyEnumValues: { + readonly Value1: 0; + readonly Value2: 1; +}; +export type PropertyEnumTag = typeof PropertyEnumValues[keyof typeof PropertyEnumValues]; + +export type PropertyEnumObject = typeof PropertyEnumValues & { + enumProperty: string; + readonly enumConstant: number; + computedEnum: string; +}; + +export {}; + +declare global { + namespace PropertyNamespace { + var namespaceConstant: string; + let namespaceProperty: string; + namespace Nested { + var nestedConstant: string; + let nestedDouble: number; + let nestedProperty: number; + } + } +} + +/// 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 PropertyClass extends SwiftHeapObject { +} +export type Exports = { + PropertyClass: { + new(): PropertyClass; + readonly staticConstant: string; + staticVariable: number; + jsObjectProperty: any; + classVariable: string; + computedProperty: string; + readonly readOnlyComputed: number; + optionalProperty: string | null; + } + PropertyEnum: PropertyEnumObject +} +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/StaticProperties.Export.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.js new file mode 100644 index 00000000..eb1c5ad1 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Export.js @@ -0,0 +1,334 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +export const PropertyEnumValues = { + Value1: 0, + Value2: 1, +}; + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let tmpRetTag; + let tmpRetStrings = []; + let tmpRetInts = []; + let tmpRetF32s = []; + let tmpRetF64s = []; + let tmpParamInts = []; + let tmpParamF32s = []; + let tmpParamF64s = []; + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + const bjs = {}; + importObject["bjs"] = bjs; + const imports = options.getImports(importsContext); + bjs["swift_js_return_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + return swift.memory.retain(textDecoder.decode(bytes)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr, len); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_tag"] = function(tag) { + tmpRetTag = tag; + } + bjs["swift_js_push_int"] = function(v) { + tmpRetInts.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + tmpRetF32s.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + tmpRetF64s.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const bytes = new Uint8Array(memory.buffer, ptr, len); + const value = textDecoder.decode(bytes); + tmpRetStrings.push(value); + } + bjs["swift_js_pop_param_int32"] = function() { + return tmpParamInts.pop(); + } + bjs["swift_js_pop_param_f32"] = function() { + return tmpParamF32s.pop(); + } + bjs["swift_js_pop_param_f64"] = function() { + return tmpParamF64s.pop(); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + const bytes = new Uint8Array(memory.buffer, ptr, len); + tmpRetString = textDecoder.decode(bytes); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_PropertyClass_wrap"] = function(pointer) { + const obj = PropertyClass.__construct(pointer); + return swift.memory.retain(obj); + }; + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + /// Represents a Swift heap object like a class instance or an actor instance. + class SwiftHeapObject { + static __wrap(pointer, deinit, prototype) { + const obj = Object.create(prototype); + obj.pointer = pointer; + obj.hasReleased = false; + obj.deinit = deinit; + obj.registry = new FinalizationRegistry((pointer) => { + deinit(pointer); + }); + obj.registry.register(this, obj.pointer); + return obj; + } + + release() { + this.registry.unregister(this); + this.deinit(this.pointer); + } + } + class PropertyClass extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_PropertyClass_deinit, PropertyClass.prototype); + } + + constructor() { + const ret = instance.exports.bjs_PropertyClass_init(); + return PropertyClass.__construct(ret); + } + static get staticConstant() { + instance.exports.bjs_PropertyClass_static_staticConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static get staticVariable() { + const ret = instance.exports.bjs_PropertyClass_static_staticVariable_get(); + return ret; + } + static set staticVariable(value) { + instance.exports.bjs_PropertyClass_static_staticVariable_set(value); + } + static get jsObjectProperty() { + const ret = instance.exports.bjs_PropertyClass_static_jsObjectProperty_get(); + const ret1 = swift.memory.getObject(ret); + swift.memory.release(ret); + return ret1; + } + static set jsObjectProperty(value) { + instance.exports.bjs_PropertyClass_static_jsObjectProperty_set(swift.memory.retain(value)); + } + static get classVariable() { + instance.exports.bjs_PropertyClass_static_classVariable_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static set classVariable(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyClass_static_classVariable_set(valueId, valueBytes.length); + swift.memory.release(valueId); + } + static get computedProperty() { + instance.exports.bjs_PropertyClass_static_computedProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static set computedProperty(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyClass_static_computedProperty_set(valueId, valueBytes.length); + swift.memory.release(valueId); + } + static get readOnlyComputed() { + const ret = instance.exports.bjs_PropertyClass_static_readOnlyComputed_get(); + return ret; + } + static get optionalProperty() { + instance.exports.bjs_PropertyClass_static_optionalProperty_get(); + const optResult = tmpRetString; + tmpRetString = undefined; + return optResult; + } + static set optionalProperty(value) { + const isSome = value != null; + let valueId, valueBytes; + if (isSome) { + valueBytes = textEncoder.encode(value); + valueId = swift.memory.retain(valueBytes); + } + instance.exports.bjs_PropertyClass_static_optionalProperty_set(+isSome, isSome ? valueId : 0, isSome ? valueBytes.length : 0); + if (valueId != undefined) { + swift.memory.release(valueId); + } + } + } + Object.defineProperty(globalThis.PropertyNamespace, 'namespaceProperty', { get: function() { + instance.exports.bjs_PropertyNamespace_static_namespaceProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, set: function(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyNamespace_static_namespaceProperty_set(valueId, valueBytes.length); + swift.memory.release(valueId); + } }); + Object.defineProperty(globalThis.PropertyNamespace, 'namespaceConstant', { get: function() { + instance.exports.bjs_PropertyNamespace_static_namespaceConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } }); + Object.defineProperty(globalThis.PropertyNamespace.Nested, 'nestedProperty', { get: function() { + const ret = instance.exports.bjs_PropertyNamespace_Nested_static_nestedProperty_get(); + return ret; + }, set: function(value) { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedProperty_set(value); + } }); + Object.defineProperty(globalThis.PropertyNamespace.Nested, 'nestedConstant', { get: function() { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedConstant_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } }); + Object.defineProperty(globalThis.PropertyNamespace.Nested, 'nestedDouble', { get: function() { + const ret = instance.exports.bjs_PropertyNamespace_Nested_static_nestedDouble_get(); + return ret; + }, set: function(value) { + instance.exports.bjs_PropertyNamespace_Nested_static_nestedDouble_set(value); + } }); + return { + PropertyClass, + PropertyEnum: { + ...PropertyEnumValues, + get enumProperty() { + instance.exports.bjs_PropertyEnum_static_enumProperty_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set enumProperty(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyEnum_static_enumProperty_set(valueId, valueBytes.length); + swift.memory.release(valueId); + }, + get enumConstant() { + const ret = instance.exports.bjs_PropertyEnum_static_enumConstant_get(); + return ret; + }, + get computedEnum() { + instance.exports.bjs_PropertyEnum_static_computedEnum_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + }, + set computedEnum(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_PropertyEnum_static_computedEnum_set(valueId, valueBytes.length); + swift.memory.release(valueId); + } + }, + }; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.json index c0d5347d..b9f86357 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Async.json @@ -10,6 +10,7 @@ "abiName" : "bjs_asyncReturnVoid", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncReturnVoid", @@ -26,6 +27,7 @@ "abiName" : "bjs_asyncRoundTripInt", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripInt", @@ -50,6 +52,7 @@ "abiName" : "bjs_asyncRoundTripString", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripString", @@ -74,6 +77,7 @@ "abiName" : "bjs_asyncRoundTripBool", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripBool", @@ -98,6 +102,7 @@ "abiName" : "bjs_asyncRoundTripFloat", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripFloat", @@ -122,6 +127,7 @@ "abiName" : "bjs_asyncRoundTripDouble", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripDouble", @@ -146,6 +152,7 @@ "abiName" : "bjs_asyncRoundTripJSObject", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripJSObject", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json index 1f2b15fe..6a9cf04c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumAssociatedValue.json @@ -74,6 +74,12 @@ ], "emitStyle" : "const", "name" : "APIResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "APIResult" }, { @@ -238,8 +244,28 @@ ], "emitStyle" : "const", "name" : "ComplexResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "ComplexResult" }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utilities", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utilities" + }, { "cases" : [ { @@ -304,6 +330,12 @@ "name" : "Result", "namespace" : [ "Utilities" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + ], "swiftCallName" : "Utilities.Result" }, @@ -345,6 +377,12 @@ "name" : "NetworkingResult", "namespace" : [ "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + ], "swiftCallName" : "NetworkingResult" }, @@ -434,6 +472,12 @@ ], "emitStyle" : "const", "name" : "APIOptionalResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "APIOptionalResult" } ], @@ -442,6 +486,7 @@ "abiName" : "bjs_handle", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "handle", @@ -466,6 +511,7 @@ "abiName" : "bjs_getResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getResult", @@ -482,6 +528,7 @@ "abiName" : "bjs_roundtripAPIResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripAPIResult", @@ -506,6 +553,7 @@ "abiName" : "bjs_roundTripOptionalAPIResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalAPIResult", @@ -538,6 +586,7 @@ "abiName" : "bjs_handleComplex", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "handleComplex", @@ -562,6 +611,7 @@ "abiName" : "bjs_getComplexResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getComplexResult", @@ -578,6 +628,7 @@ "abiName" : "bjs_roundtripComplexResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripComplexResult", @@ -602,6 +653,7 @@ "abiName" : "bjs_roundTripOptionalComplexResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalComplexResult", @@ -634,6 +686,7 @@ "abiName" : "bjs_roundTripOptionalUtilitiesResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalUtilitiesResult", @@ -666,6 +719,7 @@ "abiName" : "bjs_roundTripOptionalNetworkingResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalNetworkingResult", @@ -698,6 +752,7 @@ "abiName" : "bjs_roundTripOptionalAPIOptionalResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalAPIOptionalResult", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.json index 38b26020..1184b4b0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumCase.json @@ -32,6 +32,12 @@ ], "emitStyle" : "const", "name" : "Direction", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Direction" }, { @@ -57,6 +63,12 @@ ], "emitStyle" : "const", "name" : "Status", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Status" }, { @@ -88,6 +100,12 @@ ], "emitStyle" : "tsEnum", "name" : "TSDirection", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "TSDirection" }, { @@ -102,6 +120,12 @@ "emitStyle" : "const", "explicitAccessControl" : "public", "name" : "PublicStatus", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "PublicStatus" } ], @@ -110,6 +134,7 @@ "abiName" : "bjs_setDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setDirection", @@ -134,6 +159,7 @@ "abiName" : "bjs_getDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getDirection", @@ -150,6 +176,7 @@ "abiName" : "bjs_processDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "processDirection", @@ -174,6 +201,7 @@ "abiName" : "bjs_roundTripOptionalDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalDirection", @@ -206,6 +234,7 @@ "abiName" : "bjs_setTSDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setTSDirection", @@ -230,6 +259,7 @@ "abiName" : "bjs_getTSDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getTSDirection", @@ -246,6 +276,7 @@ "abiName" : "bjs_roundTripOptionalTSDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalTSDirection", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.json index 2ec852f1..673cfccc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumNamespace.json @@ -5,6 +5,7 @@ "abiName" : "bjs_Converter_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -16,9 +17,13 @@ "abiName" : "bjs_Converter_toString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "toString", + "namespace" : [ + "Utils" + ], "parameters" : [ { "label" : "value", @@ -51,6 +56,7 @@ "abiName" : "bjs_HTTPServer_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -62,9 +68,14 @@ "abiName" : "bjs_HTTPServer_call", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "call", + "namespace" : [ + "Networking", + "API" + ], "parameters" : [ { "label" : "_", @@ -98,6 +109,7 @@ "abiName" : "bjs_TestServer_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -109,9 +121,15 @@ "abiName" : "bjs_TestServer_call", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "call", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], "parameters" : [ { "label" : "_", @@ -149,8 +167,45 @@ ], "emitStyle" : "const", "name" : "Utils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Utils" }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Networking", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "API", + "namespace" : [ + "Networking" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking.API" + }, { "cases" : [ { @@ -183,9 +238,29 @@ "namespace" : [ "Networking", "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + ], "swiftCallName" : "Networking.API.Method" }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Configuration", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration" + }, { "cases" : [ { @@ -223,6 +298,12 @@ "Configuration" ], "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Configuration.LogLevel" }, { @@ -255,8 +336,32 @@ "Configuration" ], "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Configuration.Port" }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Internal", + "namespace" : [ + "Networking", + "APIV2" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal" + }, { "cases" : [ { @@ -278,6 +383,12 @@ "Networking", "APIV2", "Internal" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + ], "swiftCallName" : "Internal.SupportedMethod" } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json index c6f17c0a..207fd11a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/EnumRawType.json @@ -30,6 +30,12 @@ "emitStyle" : "const", "name" : "Theme", "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Theme" }, { @@ -59,6 +65,12 @@ "emitStyle" : "tsEnum", "name" : "TSTheme", "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "TSTheme" }, { @@ -81,6 +93,12 @@ "emitStyle" : "const", "name" : "FeatureFlag", "rawType" : "Bool", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "FeatureFlag" }, { @@ -110,6 +128,12 @@ "emitStyle" : "const", "name" : "HttpStatus", "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "HttpStatus" }, { @@ -139,6 +163,12 @@ "emitStyle" : "tsEnum", "name" : "TSHttpStatus", "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "TSHttpStatus" }, { @@ -182,6 +212,12 @@ "emitStyle" : "const", "name" : "Priority", "rawType" : "Int32", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Priority" }, { @@ -218,6 +254,12 @@ "emitStyle" : "const", "name" : "FileSize", "rawType" : "Int64", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "FileSize" }, { @@ -247,6 +289,12 @@ "emitStyle" : "const", "name" : "UserId", "rawType" : "UInt", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "UserId" }, { @@ -276,6 +324,12 @@ "emitStyle" : "const", "name" : "TokenId", "rawType" : "UInt32", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "TokenId" }, { @@ -305,6 +359,12 @@ "emitStyle" : "const", "name" : "SessionId", "rawType" : "UInt64", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "SessionId" }, { @@ -334,6 +394,12 @@ "emitStyle" : "const", "name" : "Precision", "rawType" : "Float", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Precision" }, { @@ -370,6 +436,12 @@ "emitStyle" : "const", "name" : "Ratio", "rawType" : "Double", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Ratio" } ], @@ -378,6 +450,7 @@ "abiName" : "bjs_setTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setTheme", @@ -403,6 +476,7 @@ "abiName" : "bjs_getTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getTheme", @@ -420,6 +494,7 @@ "abiName" : "bjs_roundTripOptionalTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalTheme", @@ -454,6 +529,7 @@ "abiName" : "bjs_setTSTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setTSTheme", @@ -479,6 +555,7 @@ "abiName" : "bjs_getTSTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getTSTheme", @@ -496,6 +573,7 @@ "abiName" : "bjs_roundTripOptionalTSTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalTSTheme", @@ -530,6 +608,7 @@ "abiName" : "bjs_setFeatureFlag", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setFeatureFlag", @@ -555,6 +634,7 @@ "abiName" : "bjs_getFeatureFlag", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getFeatureFlag", @@ -572,6 +652,7 @@ "abiName" : "bjs_roundTripOptionalFeatureFlag", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalFeatureFlag", @@ -606,6 +687,7 @@ "abiName" : "bjs_setHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setHttpStatus", @@ -631,6 +713,7 @@ "abiName" : "bjs_getHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getHttpStatus", @@ -648,6 +731,7 @@ "abiName" : "bjs_roundTripOptionalHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalHttpStatus", @@ -682,6 +766,7 @@ "abiName" : "bjs_setTSHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setTSHttpStatus", @@ -707,6 +792,7 @@ "abiName" : "bjs_getTSHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getTSHttpStatus", @@ -724,6 +810,7 @@ "abiName" : "bjs_roundTripOptionalHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalHttpStatus", @@ -758,6 +845,7 @@ "abiName" : "bjs_setPriority", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setPriority", @@ -783,6 +871,7 @@ "abiName" : "bjs_getPriority", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getPriority", @@ -800,6 +889,7 @@ "abiName" : "bjs_roundTripOptionalPriority", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalPriority", @@ -834,6 +924,7 @@ "abiName" : "bjs_setFileSize", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setFileSize", @@ -859,6 +950,7 @@ "abiName" : "bjs_getFileSize", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getFileSize", @@ -876,6 +968,7 @@ "abiName" : "bjs_roundTripOptionalFileSize", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalFileSize", @@ -910,6 +1003,7 @@ "abiName" : "bjs_setUserId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setUserId", @@ -935,6 +1029,7 @@ "abiName" : "bjs_getUserId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getUserId", @@ -952,6 +1047,7 @@ "abiName" : "bjs_roundTripOptionalUserId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalUserId", @@ -986,6 +1082,7 @@ "abiName" : "bjs_setTokenId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setTokenId", @@ -1011,6 +1108,7 @@ "abiName" : "bjs_getTokenId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getTokenId", @@ -1028,6 +1126,7 @@ "abiName" : "bjs_roundTripOptionalTokenId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalTokenId", @@ -1062,6 +1161,7 @@ "abiName" : "bjs_setSessionId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setSessionId", @@ -1087,6 +1187,7 @@ "abiName" : "bjs_getSessionId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getSessionId", @@ -1104,6 +1205,7 @@ "abiName" : "bjs_roundTripOptionalSessionId", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalSessionId", @@ -1138,6 +1240,7 @@ "abiName" : "bjs_setPrecision", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setPrecision", @@ -1163,6 +1266,7 @@ "abiName" : "bjs_getPrecision", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getPrecision", @@ -1180,6 +1284,7 @@ "abiName" : "bjs_roundTripOptionalPrecision", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalPrecision", @@ -1214,6 +1319,7 @@ "abiName" : "bjs_setRatio", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setRatio", @@ -1239,6 +1345,7 @@ "abiName" : "bjs_getRatio", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getRatio", @@ -1256,6 +1363,7 @@ "abiName" : "bjs_roundTripOptionalRatio", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalRatio", @@ -1290,6 +1398,7 @@ "abiName" : "bjs_processTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "processTheme", @@ -1316,6 +1425,7 @@ "abiName" : "bjs_convertPriority", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "convertPriority", @@ -1342,6 +1452,7 @@ "abiName" : "bjs_validateSession", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "validateSession", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.json index bb81e29a..87684f13 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.json @@ -5,6 +5,7 @@ "abiName" : "bjs_Greeter_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -24,6 +25,7 @@ "abiName" : "bjs_Greeter_greet", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "greet", @@ -52,6 +54,7 @@ "abiName" : "bjs_Converter_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -63,6 +66,7 @@ "abiName" : "bjs_Converter_toString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "toString", @@ -100,6 +104,7 @@ "abiName" : "bjs_UUID_uuidString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "uuidString", @@ -132,6 +137,7 @@ "abiName" : "bjs_plainFunction", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "plainFunction", @@ -145,9 +151,10 @@ } }, { - "abiName" : "bjs_namespacedFunction", + "abiName" : "bjs_MyModule_Utils_namespacedFunction", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "namespacedFunction", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift index f0e7f657..f868fa11 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Namespaces.swift @@ -17,9 +17,9 @@ public func _bjs_plainFunction() -> Void { #endif } -@_expose(wasm, "bjs_namespacedFunction") -@_cdecl("bjs_namespacedFunction") -public func _bjs_namespacedFunction() -> Void { +@_expose(wasm, "bjs_MyModule_Utils_namespacedFunction") +@_cdecl("bjs_MyModule_Utils_namespacedFunction") +public func _bjs_MyModule_Utils_namespacedFunction() -> Void { #if arch(wasm32) let ret = namespacedFunction() return ret.bridgeJSLowerReturn() diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.json index 28ac1150..aef4e890 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Optionals.json @@ -5,6 +5,7 @@ "abiName" : "bjs_Greeter_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -28,6 +29,7 @@ "abiName" : "bjs_Greeter_greet", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "greet", @@ -44,6 +46,7 @@ "abiName" : "bjs_Greeter_changeName", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "changeName", @@ -73,6 +76,7 @@ "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "name", "type" : { "optional" : { @@ -92,6 +96,7 @@ "abiName" : "bjs_OptionalPropertyHolder_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -105,6 +110,7 @@ "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "optionalName", "type" : { "optional" : { @@ -118,6 +124,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "optionalAge", "type" : { "optional" : { @@ -131,6 +138,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "optionalGreeter", "type" : { "optional" : { @@ -154,6 +162,7 @@ "abiName" : "bjs_roundTripOptionalClass", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalClass", @@ -186,6 +195,7 @@ "abiName" : "bjs_testOptionalPropertyRoundtrip", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "testOptionalPropertyRoundtrip", @@ -218,6 +228,7 @@ "abiName" : "bjs_roundTripString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripString", @@ -250,6 +261,7 @@ "abiName" : "bjs_roundTripInt", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripInt", @@ -282,6 +294,7 @@ "abiName" : "bjs_roundTripBool", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripBool", @@ -314,6 +327,7 @@ "abiName" : "bjs_roundTripFloat", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripFloat", @@ -346,6 +360,7 @@ "abiName" : "bjs_roundTripDouble", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripDouble", @@ -378,6 +393,7 @@ "abiName" : "bjs_roundTripSyntax", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripSyntax", @@ -410,6 +426,7 @@ "abiName" : "bjs_roundTripMixSyntax", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripMixSyntax", @@ -442,6 +459,7 @@ "abiName" : "bjs_roundTripSwiftSyntax", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripSwiftSyntax", @@ -474,6 +492,7 @@ "abiName" : "bjs_roundTripMixedSwiftSyntax", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripMixedSwiftSyntax", @@ -506,6 +525,7 @@ "abiName" : "bjs_roundTripWithSpaces", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripWithSpaces", @@ -538,6 +558,7 @@ "abiName" : "bjs_roundTripAlias", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripAlias", @@ -570,6 +591,7 @@ "abiName" : "bjs_roundTripOptionalAlias", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalAlias", @@ -602,6 +624,7 @@ "abiName" : "bjs_testMixedOptionals", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "testMixedOptionals", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json index c58f3c8e..10638ebf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveParameters.json @@ -10,6 +10,7 @@ "abiName" : "bjs_check", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "check", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json index ee29313b..b1f89765 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PrimitiveReturn.json @@ -10,6 +10,7 @@ "abiName" : "bjs_checkInt", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "checkInt", @@ -26,6 +27,7 @@ "abiName" : "bjs_checkFloat", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "checkFloat", @@ -42,6 +44,7 @@ "abiName" : "bjs_checkDouble", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "checkDouble", @@ -58,6 +61,7 @@ "abiName" : "bjs_checkBool", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "checkBool", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PropertyTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PropertyTypes.json index e0c5e812..8de3a12d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PropertyTypes.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/PropertyTypes.json @@ -5,6 +5,7 @@ "abiName" : "bjs_PropertyHolder_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -69,6 +70,7 @@ "abiName" : "bjs_PropertyHolder_getAllValues", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getAllValues", @@ -86,6 +88,7 @@ "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "intValue", "type" : { "int" : { @@ -95,6 +98,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "floatValue", "type" : { "float" : { @@ -104,6 +108,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "doubleValue", "type" : { "double" : { @@ -113,6 +118,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "boolValue", "type" : { "bool" : { @@ -122,6 +128,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "stringValue", "type" : { "string" : { @@ -131,6 +138,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyInt", "type" : { "int" : { @@ -140,6 +148,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyFloat", "type" : { "float" : { @@ -149,6 +158,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyDouble", "type" : { "double" : { @@ -158,6 +168,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyBool", "type" : { "bool" : { @@ -167,6 +178,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyString", "type" : { "string" : { @@ -176,6 +188,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "jsObject", "type" : { "jsObject" : { @@ -185,6 +198,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "sibling", "type" : { "swiftHeapObject" : { @@ -194,6 +208,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "lazyValue", "type" : { "string" : { @@ -203,6 +218,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "computedReadonly", "type" : { "int" : { @@ -212,6 +228,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "computedReadWrite", "type" : { "string" : { @@ -221,6 +238,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "observedProperty", "type" : { "int" : { @@ -240,6 +258,7 @@ "abiName" : "bjs_createPropertyHolder", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "createPropertyHolder", @@ -309,6 +328,7 @@ "abiName" : "bjs_testPropertyHolder", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "testPropertyHolder", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.json new file mode 100644 index 00000000..8a73c1b8 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.json @@ -0,0 +1,326 @@ +{ + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_MathUtils_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_MathUtils_static_subtract", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "subtract", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + }, + { + "abiName" : "bjs_MathUtils_static_add", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "add", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + }, + { + "abiName" : "bjs_MathUtils_multiply", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "multiply", + "parameters" : [ + { + "label" : "x", + "name" : "x", + "type" : { + "int" : { + + } + } + }, + { + "label" : "y", + "name" : "y", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + } + } + ], + "name" : "MathUtils", + "properties" : [ + + ], + "swiftCallName" : "MathUtils" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "scientific" + }, + { + "associatedValues" : [ + + ], + "name" : "basic" + } + ], + "emitStyle" : "const", + "name" : "Calculator", + "staticMethods" : [ + { + "abiName" : "bjs_Calculator_static_square", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "square", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "enumName" : { + "_0" : "Calculator" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Calculator" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "APIResult", + "staticMethods" : [ + { + "abiName" : "bjs_APIResult_static_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + } + } + ], + "returnType" : { + "associatedValueEnum" : { + "_0" : "APIResult" + } + }, + "staticContext" : { + "enumName" : { + "_0" : "APIResult" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIResult" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "String", + "namespace" : [ + "Utils" + ], + "staticMethods" : [ + { + "abiName" : "bjs_Utils_String_static_uppercase", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "uppercase", + "namespace" : [ + "Utils", + "String" + ], + "parameters" : [ + { + "label" : "_", + "name" : "text", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utils.String" + } + ], + "functions" : [ + + ], + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.swift new file mode 100644 index 00000000..4e301151 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticFunctions.swift @@ -0,0 +1,166 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +@_spi(BridgeJS) import JavaScriptKit + +extension Calculator: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> Calculator { + return Calculator(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> Calculator { + return Calculator(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .scientific + case 1: + self = .basic + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .scientific: + return 0 + case .basic: + return 1 + } + } +} + +@_expose(wasm, "bjs_Calculator_static_square") +@_cdecl("bjs_Calculator_static_square") +public func _bjs_Calculator_static_square(value: Int32) -> Int32 { + #if arch(wasm32) + let ret = Calculator.square(value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension APIResult: _BridgedSwiftAssociatedValueEnum { + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> APIResult { + switch caseId { + case 0: + return .success(String.bridgeJSLiftParameter(_swift_js_pop_param_int32(), _swift_js_pop_param_int32())) + case 1: + return .failure(Int.bridgeJSLiftParameter(_swift_js_pop_param_int32())) + default: + fatalError("Unknown APIResult case ID: \(caseId)") + } + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() { + switch self { + case .success(let param0): + _swift_js_push_tag(Int32(0)) + var __bjs_param0 = param0 + __bjs_param0.withUTF8 { ptr in + _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + } + case .failure(let param0): + _swift_js_push_tag(Int32(1)) + _swift_js_push_int(Int32(param0)) + } + } +} + +@_expose(wasm, "bjs_APIResult_static_roundtrip") +@_cdecl("bjs_APIResult_static_roundtrip") +public func _bjs_APIResult_static_roundtrip(value: Int32) -> Void { + #if arch(wasm32) + let ret = APIResult.roundtrip(value: APIResult.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Utils_String_static_uppercase") +@_cdecl("bjs_Utils_String_static_uppercase") +public func _bjs_Utils_String_static_uppercase(textBytes: Int32, textLength: Int32) -> Void { + #if arch(wasm32) + let ret = Utils.String.uppercase(_: String.bridgeJSLiftParameter(textBytes, textLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_init") +@_cdecl("bjs_MathUtils_init") +public func _bjs_MathUtils_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = MathUtils() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_static_subtract") +@_cdecl("bjs_MathUtils_static_subtract") +public func _bjs_MathUtils_static_subtract(a: Int32, b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.subtract(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_static_add") +@_cdecl("bjs_MathUtils_static_add") +public func _bjs_MathUtils_static_add(a: Int32, b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.add(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_multiply") +@_cdecl("bjs_MathUtils_multiply") +public func _bjs_MathUtils_multiply(_self: UnsafeMutableRawPointer, x: Int32, y: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.bridgeJSLiftParameter(_self).multiply(x: Int.bridgeJSLiftParameter(x), y: Int.bridgeJSLiftParameter(y)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_deinit") +@_cdecl("bjs_MathUtils_deinit") +public func _bjs_MathUtils_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension MathUtils: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "TestModule", name: "bjs_MathUtils_wrap") + func _bjs_MathUtils_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_MathUtils_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_MathUtils_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticProperties.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticProperties.json new file mode 100644 index 00000000..4808e518 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticProperties.json @@ -0,0 +1,330 @@ +{ + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_PropertyClass_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "PropertyClass", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : true, + "name" : "staticConstant", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticVariable", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "jsObjectProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "jsObject" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "classVariable", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "readOnlyComputed", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "optionalProperty", + "staticContext" : { + "className" : { + "_0" : "PropertyClass" + } + }, + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "swiftCallName" : "PropertyClass" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "value1" + }, + { + "associatedValues" : [ + + ], + "name" : "value2" + } + ], + "emitStyle" : "const", + "name" : "PropertyEnum", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "enumProperty", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "enumConstant", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedEnum", + "staticContext" : { + "enumName" : { + "_0" : "PropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "PropertyEnum" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "PropertyNamespace", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "namespaceProperty", + "namespace" : [ + "PropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "namespaceConstant", + "namespace" : [ + "PropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { + + } + }, + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "PropertyNamespace" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Nested", + "namespace" : [ + "PropertyNamespace" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedProperty", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "nestedConstant", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedDouble", + "namespace" : [ + "PropertyNamespace", + "Nested" + ], + "staticContext" : { + "namespaceEnum" : { + + } + }, + "type" : { + "double" : { + + } + } + } + ], + "swiftCallName" : "PropertyNamespace.Nested" + } + ], + "functions" : [ + + ], + "moduleName" : "TestModule" +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticProperties.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticProperties.swift new file mode 100644 index 00000000..6edd0c8f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StaticProperties.swift @@ -0,0 +1,338 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +@_spi(BridgeJS) import JavaScriptKit + +extension PropertyEnum: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> PropertyEnum { + return PropertyEnum(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> PropertyEnum { + return PropertyEnum(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .value1 + case 1: + self = .value2 + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .value1: + return 0 + case .value2: + return 1 + } + } +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumProperty_get") +@_cdecl("bjs_PropertyEnum_static_enumProperty_get") +public func _bjs_PropertyEnum_static_enumProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyEnum.enumProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumProperty_set") +@_cdecl("bjs_PropertyEnum_static_enumProperty_set") +public func _bjs_PropertyEnum_static_enumProperty_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyEnum.enumProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_enumConstant_get") +@_cdecl("bjs_PropertyEnum_static_enumConstant_get") +public func _bjs_PropertyEnum_static_enumConstant_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyEnum.enumConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_computedEnum_get") +@_cdecl("bjs_PropertyEnum_static_computedEnum_get") +public func _bjs_PropertyEnum_static_computedEnum_get() -> Void { + #if arch(wasm32) + let ret = PropertyEnum.computedEnum + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyEnum_static_computedEnum_set") +@_cdecl("bjs_PropertyEnum_static_computedEnum_set") +public func _bjs_PropertyEnum_static_computedEnum_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyEnum.computedEnum = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceProperty_get") +@_cdecl("bjs_PropertyNamespace_static_namespaceProperty_get") +public func _bjs_PropertyNamespace_static_namespaceProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.namespaceProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceProperty_set") +@_cdecl("bjs_PropertyNamespace_static_namespaceProperty_set") +public func _bjs_PropertyNamespace_static_namespaceProperty_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyNamespace.namespaceProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_static_namespaceConstant_get") +@_cdecl("bjs_PropertyNamespace_static_namespaceConstant_get") +public func _bjs_PropertyNamespace_static_namespaceConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.namespaceConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedProperty_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedProperty_get") +public func _bjs_PropertyNamespace_Nested_static_nestedProperty_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedProperty_set") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedProperty_set") +public func _bjs_PropertyNamespace_Nested_static_nestedProperty_set(value: Int32) -> Void { + #if arch(wasm32) + PropertyNamespace.Nested.nestedProperty = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedConstant_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedConstant_get") +public func _bjs_PropertyNamespace_Nested_static_nestedConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedDouble_get") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedDouble_get") +public func _bjs_PropertyNamespace_Nested_static_nestedDouble_get() -> Float64 { + #if arch(wasm32) + let ret = PropertyNamespace.Nested.nestedDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyNamespace_Nested_static_nestedDouble_set") +@_cdecl("bjs_PropertyNamespace_Nested_static_nestedDouble_set") +public func _bjs_PropertyNamespace_Nested_static_nestedDouble_set(value: Float64) -> Void { + #if arch(wasm32) + PropertyNamespace.Nested.nestedDouble = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_init") +@_cdecl("bjs_PropertyClass_init") +public func _bjs_PropertyClass_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = PropertyClass() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticConstant_get") +@_cdecl("bjs_PropertyClass_static_staticConstant_get") +public func _bjs_PropertyClass_static_staticConstant_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.staticConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticVariable_get") +@_cdecl("bjs_PropertyClass_static_staticVariable_get") +public func _bjs_PropertyClass_static_staticVariable_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.staticVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_staticVariable_set") +@_cdecl("bjs_PropertyClass_static_staticVariable_set") +public func _bjs_PropertyClass_static_staticVariable_set(value: Int32) -> Void { + #if arch(wasm32) + PropertyClass.staticVariable = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_jsObjectProperty_get") +@_cdecl("bjs_PropertyClass_static_jsObjectProperty_get") +public func _bjs_PropertyClass_static_jsObjectProperty_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.jsObjectProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_jsObjectProperty_set") +@_cdecl("bjs_PropertyClass_static_jsObjectProperty_set") +public func _bjs_PropertyClass_static_jsObjectProperty_set(value: Int32) -> Void { + #if arch(wasm32) + PropertyClass.jsObjectProperty = JSObject.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_classVariable_get") +@_cdecl("bjs_PropertyClass_static_classVariable_get") +public func _bjs_PropertyClass_static_classVariable_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.classVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_classVariable_set") +@_cdecl("bjs_PropertyClass_static_classVariable_set") +public func _bjs_PropertyClass_static_classVariable_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.classVariable = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_computedProperty_get") +@_cdecl("bjs_PropertyClass_static_computedProperty_get") +public func _bjs_PropertyClass_static_computedProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.computedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_computedProperty_set") +@_cdecl("bjs_PropertyClass_static_computedProperty_set") +public func _bjs_PropertyClass_static_computedProperty_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.computedProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_readOnlyComputed_get") +@_cdecl("bjs_PropertyClass_static_readOnlyComputed_get") +public func _bjs_PropertyClass_static_readOnlyComputed_get() -> Int32 { + #if arch(wasm32) + let ret = PropertyClass.readOnlyComputed + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_optionalProperty_get") +@_cdecl("bjs_PropertyClass_static_optionalProperty_get") +public func _bjs_PropertyClass_static_optionalProperty_get() -> Void { + #if arch(wasm32) + let ret = PropertyClass.optionalProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_static_optionalProperty_set") +@_cdecl("bjs_PropertyClass_static_optionalProperty_set") +public func _bjs_PropertyClass_static_optionalProperty_set(valueIsSome: Int32, valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + PropertyClass.optionalProperty = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_PropertyClass_deinit") +@_cdecl("bjs_PropertyClass_deinit") +public func _bjs_PropertyClass_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension PropertyClass: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "TestModule", name: "bjs_PropertyClass_wrap") + func _bjs_PropertyClass_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_PropertyClass_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_PropertyClass_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json index 24d7641c..55972aa1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringParameter.json @@ -10,6 +10,7 @@ "abiName" : "bjs_checkString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "checkString", @@ -34,6 +35,7 @@ "abiName" : "bjs_roundtripString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripString", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.json index 75439e36..5d727c85 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/StringReturn.json @@ -10,6 +10,7 @@ "abiName" : "bjs_checkString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "checkString", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.json index ce506f51..59b7f9ef 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/SwiftClass.json @@ -5,6 +5,7 @@ "abiName" : "bjs_Greeter_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -24,6 +25,7 @@ "abiName" : "bjs_Greeter_greet", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "greet", @@ -40,6 +42,7 @@ "abiName" : "bjs_Greeter_changeName", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "changeName", @@ -65,6 +68,7 @@ "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "name", "type" : { "string" : { @@ -106,6 +110,7 @@ "abiName" : "bjs_takeGreeter", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "takeGreeter", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.json index cc3184fb..51d548e6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Throws.json @@ -10,6 +10,7 @@ "abiName" : "bjs_throwsSomething", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsSomething", diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.json index 413fe084..f3f7abaa 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/VoidParameterVoidReturn.json @@ -10,6 +10,7 @@ "abiName" : "bjs_check", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "check", diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md index c19b8c52..41315708 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift-to-JavaScript.md @@ -67,4 +67,6 @@ This command will: - - - +- +- - diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md index d91d0616..3a4df4ae 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Class.md @@ -88,7 +88,8 @@ export type Exports = { | Stored properties: `var`, `let` (with `willSet`, `didSet`) | ✅ | | Computed properties: `var x: X { get set }` | ✅ | | Computed properties with effects: `var x: X { get async throws }` | 🚧 | +| Static / class properties: `static var`, `class let` | ✅ (See )| | Methods: `func` | ✅ (See ) | -| Static/class methods: `static func`, `class func` | 🚧 | +| Static/class methods: `static func`, `class func` | ✅ (See ) | | Subscripts: `subscript()` | ❌ | | Generics | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md index 9c0f9971..93c1fdd2 100644 --- a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Enum.md @@ -13,6 +13,12 @@ BridgeJS supports two output styles for enums, controlled by the `enumStyle` par Examples output of both styles can be found below. +BridgeJS generates separate objects with descriptive naming for `.const` enums: + +- **`EnumNameValues`**: Contains the enum case constants for all enums +- **`EnumNameTag`**: Represents the union type for enums +- **`EnumNameObject`**: Object type for all const-style enums, contains static members for enums with methods/properties or references the values type for simple enums + #### Case Enums **Swift Definition:** @@ -43,50 +49,50 @@ Examples output of both styles can be found below. ```typescript // Const object style (default) -const Direction: { +export const DirectionValues: { readonly North: 0; readonly South: 1; readonly East: 2; readonly West: 3; }; -type Direction = typeof Direction[keyof typeof Direction]; +export type DirectionTag = typeof DirectionValues[keyof typeof DirectionValues]; // Native TypeScript enum style -enum TSDirection { +export enum TSDirection { North = 0, South = 1, East = 2, West = 3, } -const Status: { +export const StatusValues: { readonly Loading: 0; readonly Success: 1; readonly Error: 2; }; -type Status = typeof Status[keyof typeof Status]; +export type StatusTag = typeof StatusValues[keyof typeof StatusValues]; ``` **Usage in TypeScript:** ```typescript -const direction: Direction = exports.Direction.North; -const tsDirection: TSDirection = exports.TSDirection.North; -const status: Status = exports.Status.Loading; +const direction: DirectionTag = DirectionValues.North; +const tsDirection: TSDirection = TSDirection.North; +const status: StatusTag = StatusValues.Loading; -exports.setDirection(exports.Direction.South); -exports.setTSDirection(exports.TSDirection.East); -const currentDirection: Direction = exports.getDirection(); +exports.setDirection(DirectionValues.South); +exports.setTSDirection(TSDirection.East); +const currentDirection: DirectionTag = exports.getDirection(); const currentTSDirection: TSDirection = exports.getTSDirection(); -const result: Status = exports.processDirection(exports.Direction.East); +const result: StatusTag = exports.processDirection(DirectionValues.East); -function handleDirection(direction: Direction) { +function handleDirection(direction: DirectionTag) { switch (direction) { - case exports.Direction.North: + case DirectionValues.North: console.log("Going north"); break; - case exports.Direction.South: + case DirectionValues.South: console.log("Going south"); break; // TypeScript will warn about missing cases @@ -175,15 +181,15 @@ public func _bjs_getDirection() -> Int32 { ```typescript // Const object style (default) -const Theme: { +export const ThemeValues: { readonly Light: "light"; readonly Dark: "dark"; readonly Auto: "auto"; }; -type Theme = typeof Theme[keyof typeof Theme]; +export type ThemeTag = typeof ThemeValues[keyof typeof ThemeValues]; // Native TypeScript enum style -enum TSTheme { +export enum TSTheme { Light = "light", Dark = "dark", Auto = "auto", @@ -193,14 +199,14 @@ enum TSTheme { **Usage in TypeScript:** ```typescript -// Both styles work similarly in usage -const theme: Theme = exports.Theme.Dark; -const tsTheme: TSTheme = exports.TSTheme.Dark; +// Raw value enums work similarly to case enums +const theme: ThemeTag = ThemeValues.Dark; +const tsTheme: TSTheme = TSTheme.Dark; -exports.setTheme(exports.Theme.Light); -const currentTheme: Theme = exports.getTheme(); +exports.setTheme(ThemeValues.Light); +const currentTheme: ThemeTag = exports.getTheme(); -const status: HttpStatus = exports.processTheme(exports.Theme.Auto); +const status: HttpStatusTag = exports.processTheme(ThemeValues.Auto); ``` ##### Integer Raw Values @@ -235,41 +241,41 @@ const status: HttpStatus = exports.processTheme(exports.Theme.Auto); ```typescript // Const object style (default) -const HttpStatus: { +export const HttpStatusValues: { readonly Ok: 200; readonly NotFound: 404; readonly ServerError: 500; }; -type HttpStatus = typeof HttpStatus[keyof typeof HttpStatus]; +export type HttpStatusTag = typeof HttpStatusValues[keyof typeof HttpStatusValues]; // Native TypeScript enum style -enum TSHttpStatus { +export enum TSHttpStatus { Ok = 200, NotFound = 404, ServerError = 500, } -const Priority: { +export const PriorityValues: { readonly Lowest: 1; readonly Low: 2; readonly Medium: 3; readonly High: 4; readonly Highest: 5; }; -type Priority = typeof Priority[keyof typeof Priority]; +export type PriorityTag = typeof PriorityValues[keyof typeof PriorityValues]; ``` **Usage in TypeScript:** ```typescript -const status: HttpStatus = exports.HttpStatus.Ok; -const tsStatus: TSHttpStatus = exports.TSHttpStatus.Ok; -const priority: Priority = exports.Priority.High; +const status: HttpStatusTag = HttpStatusValues.Ok; +const tsStatus: TSHttpStatus = TSHttpStatus.Ok; +const priority: PriorityTag = PriorityValues.High; -exports.setHttpStatus(exports.HttpStatus.NotFound); -exports.setPriority(exports.Priority.Medium); +exports.setHttpStatus(HttpStatusValues.NotFound); +exports.setPriority(PriorityValues.Medium); -const convertedPriority: Priority = exports.convertPriority(exports.HttpStatus.Ok); +const convertedPriority: PriorityTag = exports.convertPriority(HttpStatusValues.Ok); ``` ### Namespace Enums @@ -333,25 +339,25 @@ declare global { namespace API { class HTTPServer { constructor(); - call(method: Networking.API.Method): void; + call(method: Networking.API.MethodTag): void; } - const Method: { + const MethodValues: { readonly Get: 0; readonly Post: 1; }; - type Method = typeof Method[keyof typeof Method]; + type MethodTag = typeof MethodValues[keyof typeof MethodValues]; } namespace APIV2 { namespace Internal { class TestServer { constructor(); - call(method: Internal.SupportedMethod): void; + call(method: Internal.SupportedMethodTag): void; } - const SupportedMethod: { + const SupportedMethodValues: { readonly Get: 0; readonly Post: 1; }; - type SupportedMethod = typeof SupportedMethod[keyof typeof SupportedMethod]; + type SupportedMethodTag = typeof SupportedMethodValues[keyof typeof SupportedMethodValues]; } } } @@ -361,16 +367,16 @@ declare global { **Usage in TypeScript:** ```typescript -// Access nested classes through namespaces -const converter = new globalThis.Utils.Converter(); +// Access nested classes through namespaces (no globalThis prefix needed) +const converter = new Utils.Converter(); const result: string = converter.toString(42) -const server = new globalThis.Networking.API.HTTPServer(); -const method: Networking.API.Method = globalThis.Networking.API.Method.Get; +const server = new Networking.API.HTTPServer(); +const method: Networking.API.MethodTag = Networking.API.MethodValues.Get; server.call(method) -const testServer = new globalThis.Networking.APIV2.Internal.TestServer(); -const supportedMethod: Internal.SupportedMethod = globalThis.Networking.APIV2.Internal.SupportedMethod.Post; +const testServer = new Networking.APIV2.Internal.TestServer(); +const supportedMethod: Internal.SupportedMethodTag = Networking.APIV2.Internal.SupportedMethodValues.Post; testServer.call(supportedMethod); ``` @@ -437,7 +443,7 @@ enum ComplexResult { **Generated TypeScript Declaration:** ```typescript -export const APIResult: { +export const APIResultValues: { readonly Tag: { readonly Success: 0; readonly Failure: 1; @@ -448,15 +454,15 @@ export const APIResult: { }; }; -export type APIResult = - { tag: typeof APIResult.Tag.Success; param0: string } | - { tag: typeof APIResult.Tag.Failure; param0: number } | - { tag: typeof APIResult.Tag.Flag; param0: boolean } | - { tag: typeof APIResult.Tag.Rate; param0: number } | - { tag: typeof APIResult.Tag.Precise; param0: number } | - { tag: typeof APIResult.Tag.Info } +export type APIResultTag = + { tag: typeof APIResultValues.Tag.Success; param0: string } | + { tag: typeof APIResultValues.Tag.Failure; param0: number } | + { tag: typeof APIResultValues.Tag.Flag; param0: boolean } | + { tag: typeof APIResultValues.Tag.Rate; param0: number } | + { tag: typeof APIResultValues.Tag.Precise; param0: number } | + { tag: typeof APIResultValues.Tag.Info } -export const ComplexResult: { +export const ComplexResultValues: { readonly Tag: { readonly Success: 0; readonly Error: 1; @@ -467,31 +473,31 @@ export const ComplexResult: { }; }; -export type ComplexResult = - { tag: typeof ComplexResult.Tag.Success; param0: string } | - { tag: typeof ComplexResult.Tag.Error; param0: string; param1: number } | - { tag: typeof ComplexResult.Tag.Status; param0: boolean; param1: number; param2: string } | - { tag: typeof ComplexResult.Tag.Coordinates; param0: number; param1: number; param2: number } | - { tag: typeof ComplexResult.Tag.Comprehensive; param0: boolean; param1: boolean; param2: number; param3: number; param4: number; param5: number; param6: string; param7: string; param8: string } | - { tag: typeof ComplexResult.Tag.Info } +export type ComplexResultTag = + { tag: typeof ComplexResultValues.Tag.Success; param0: string } | + { tag: typeof ComplexResultValues.Tag.Error; param0: string; param1: number } | + { tag: typeof ComplexResultValues.Tag.Status; param0: boolean; param1: number; param2: string } | + { tag: typeof ComplexResultValues.Tag.Coordinates; param0: number; param1: number; param2: number } | + { tag: typeof ComplexResultValues.Tag.Comprehensive; param0: boolean; param1: boolean; param2: number; param3: number; param4: number; param5: number; param6: string; param7: string; param8: string } | + { tag: typeof ComplexResultValues.Tag.Info } ``` **Usage in TypeScript:** ```typescript -const successResult: APIResult = { - tag: exports.APIResult.Tag.Success, - param0: "Operation completed successfully" +const successResult: APIResultTag = { + tag: APIResultValues.Tag.Success, + param0: "Operation completed successfully" }; -const errorResult: ComplexResult = { - tag: exports.ComplexResult.Tag.Error, +const errorResult: ComplexResultTag = { + tag: ComplexResultValues.Tag.Error, param0: "Network timeout", param1: 503 }; -const statusResult: ComplexResult = { - tag: exports.ComplexResult.Tag.Status, +const statusResult: ComplexResultTag = { + tag: ComplexResultValues.Tag.Status, param0: true, param1: 200, param2: "OK" @@ -500,21 +506,21 @@ const statusResult: ComplexResult = { exports.handle(successResult); exports.handle(errorResult); -const result: APIResult = exports.getResult(); +const result: APIResultTag = exports.getResult(); // Pattern matching with discriminated unions -function processResult(result: APIResult) { +function processResult(result: APIResultTag) { switch (result.tag) { - case exports.APIResult.Tag.Success: + case APIResultValues.Tag.Success: console.log("Success:", result.param0); // TypeScript knows param0 is string break; - case exports.APIResult.Tag.Failure: + case APIResultValues.Tag.Failure: console.log("Failure code:", result.param0); // TypeScript knows param0 is number break; - case exports.APIResult.Tag.Flag: + case APIResultValues.Tag.Flag: console.log("Flag value:", result.param0); // TypeScript knows param0 is boolean break; - case exports.APIResult.Tag.Info: + case APIResultValues.Tag.Info: console.log("Info case has no associated data"); break; // TypeScript will warn about missing cases diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md new file mode 100644 index 00000000..8602d937 --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Functions.md @@ -0,0 +1,166 @@ +# Exporting Swift Static Functions to JS + +Learn how to export Swift static and class functions as JavaScript static methods using BridgeJS. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS supports exporting Swift `static func` and `class func` to JavaScript static methods. Both generate identical JavaScript output but differ in Swift inheritance behavior. + +> Important: Static function support is **Swift → JavaScript only**. JavaScript → Swift static function imports are not currently supported. + +## Class Static Functions + +Classes can export both `static` and `class` functions: + +```swift +@JS class MathUtils { + @JS init() {} + + @JS static func add(a: Int, b: Int) -> Int { + return a + b + } + + @JS class func subtract(a: Int, b: Int) -> Int { + return a - b + } + + @JS func multiply(x: Int, y: Int) -> Int { + return x * y + } +} +``` + +Generated TypeScript definitions: + +```typescript +export type Exports = { + MathUtils: { + new(): MathUtils; + subtract(a: number, b: number): number; + add(a: number, b: number): number; + } +} + +export interface MathUtils extends SwiftHeapObject { + multiply(x: number, y: number): number; +} +``` + +Usage: + +```typescript +// Static methods +const sum = MathUtils.add(5, 3); +const difference = MathUtils.subtract(10, 4); + +// Instance methods +const utils = new MathUtils(); +const product = utils.multiply(4, 7); +``` + +## Values/Tag/Object Pattern + +For enums with static functions, BridgeJS generates a structured pattern: + +- **Values**: Constants for enum cases (`CalculatorValues: { readonly Scientific: 0; readonly Basic: 1; }`) +- **Tag**: Type alias for enum values (`CalculatorTag = typeof CalculatorValues[keyof typeof CalculatorValues]`) +- **Object**: Intersection type combining Values + methods (`CalculatorObject = typeof CalculatorValues & { methods }`) +- **Exports**: Uses Object type for unified access (`Calculator: CalculatorObject`) + +This allows accessing both enum constants and static functions through a single interface: `exports.Calculator.Scientific` and `exports.Calculator.square(5)`. + +## Enum Static Functions + +Enums can contain static functions that are exported as properties: + +```swift +@JS enum Calculator { + case scientific + case basic + + @JS static func square(value: Int) -> Int { + return value * value + } + + @JS static func cube(value: Int) -> Int { + return value * value * value + } +} +``` + +Generated TypeScript definitions: + +```typescript +export const CalculatorValues: { + readonly Scientific: 0; + readonly Basic: 1; +}; +export type CalculatorTag = typeof CalculatorValues[keyof typeof CalculatorValues]; + +export type CalculatorObject = typeof CalculatorValues & { + square(value: number): number; + cube(value: number): number; +}; + +export type Exports = { + Calculator: CalculatorObject +} +``` + +This enables unified access to both enum constants and static functions: + +```typescript +// Access enum constants +const mode: CalculatorTag = exports.Calculator.Scientific; // 0 +const otherMode: CalculatorTag = CalculatorValues.Basic; // 1 + +// Call static functions +const result: number = exports.Calculator.square(5); // 25 +``` + +## Namespace Enum Static Functions + +Namespace enums organize related utility functions and are assigned to `globalThis`: + +```swift +@JS enum Utils { + @JS enum String { + @JS static func uppercase(_ text: String) -> String { + return text.uppercased() + } + } +} +``` + +Generated TypeScript definitions: + +```typescript +declare global { + namespace Utils { + namespace String { + uppercase(text: string): string; + } + } +} +``` + +Usage: + +```typescript +// Direct access via global namespace (no exports needed) +const upper: string = Utils.String.uppercase("hello"); +const result: string = Utils.String.uppercase("world"); +``` + +## Supported Features + +| Swift Static Function Feature | Status | +|:------------------------------|:-------| +| Class `static func` | ✅ | +| Class `class func` | ✅ | +| Enum `static func` | ✅ | +| Namespace enum `static func` | ✅ | +| Generic static functions | ❌ | +| Protocol static requirements | ❌ | diff --git a/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md new file mode 100644 index 00000000..097f644b --- /dev/null +++ b/Sources/JavaScriptKit/Documentation.docc/Articles/BridgeJS/Exporting-Swift/Exporting-Swift-Static-Properties.md @@ -0,0 +1,188 @@ +# Exporting Swift Static Properties to JS + +Learn how to export Swift static and class properties as JavaScript static properties using BridgeJS. + +## Overview + +> Tip: You can quickly preview what interfaces will be exposed on the Swift/TypeScript sides using the [BridgeJS Playground](https://swiftwasm.org/JavaScriptKit/PlayBridgeJS/). + +BridgeJS supports exporting Swift `static var`, `static let`, and `class var` properties to JavaScript static properties. Both stored and computed properties are supported. + +## Class Static Properties + +Classes can export both stored and computed static properties: + +```swift +@JS class Configuration { + @JS init() {} + + @JS static let version = "1.0.0" + @JS static var debugMode = false + @JS class var defaultTimeout = 30 + + @JS static var timestamp: Double { + get { return Date().timeIntervalSince1970 } + set { /* custom setter logic */ } + } + + @JS static var buildNumber: Int { + return 12345 + } +} +``` + +Generated TypeScript definitions: + +```typescript +export type Exports = { + Configuration: { + new(): Configuration; + readonly version: string; + debugMode: boolean; + defaultTimeout: number; + timestamp: number; + readonly buildNumber: number; + } +} + +export interface Configuration extends SwiftHeapObject { + // instance methods here +} +``` + +Usage: + +```typescript +console.log(Configuration.version); // "1.0.0" +console.log(Configuration.debugMode); // false +console.log(Configuration.timestamp); // current timestamp + +Configuration.debugMode = true; +Configuration.timestamp = Date.now() / 1000; +``` + + +## Values/Tag/Object Pattern + +For enums with static properties, BridgeJS generates a structured pattern: + +- **Values**: Constants for enum cases (`PropertyEnumValues: { readonly Value1: 0; readonly Value2: 1; }`) +- **Tag**: Type alias for enum values (`PropertyEnumTag = typeof PropertyEnumValues[keyof typeof PropertyEnumValues]`) +- **Object**: Intersection type combining Values + properties (`PropertyEnumObject = typeof PropertyEnumValues & { properties }`) +- **Exports**: Uses Object type for unified access (`PropertyEnum: PropertyEnumObject`) + +This allows accessing both enum constants and static properties through a single interface: `exports.PropertyEnum.Value1` and `exports.PropertyEnum.enumProperty`. + +## Enum Static Properties + +Enums can contain static properties that are exported alongside enum cases: + +```swift +@JS enum PropertyEnum { + case value1 + case value2 + + @JS static var enumProperty = "mutable" + @JS static let enumConstant = 42 + @JS static var computedEnum: String { + return "computed value" + } +} +``` + +Generated TypeScript definitions: + +```typescript +export const PropertyEnumValues: { + readonly Value1: 0; + readonly Value2: 1; +}; +export type PropertyEnumTag = typeof PropertyEnumValues[keyof typeof PropertyEnumValues]; + +export type PropertyEnumObject = typeof PropertyEnumValues & { + enumProperty: string; + readonly enumConstant: number; + computedEnum: string; +}; + +export type Exports = { + PropertyEnum: PropertyEnumObject +} +``` + +Usage: + +```typescript +const status: PropertyEnumTag = exports.PropertyEnum.Value1; // 0 +const otherStatus: PropertyEnumTag = PropertyEnumValues.Value2; // 1 + +// Access static properties +console.log(exports.PropertyEnum.enumProperty); // "mutable" +console.log(exports.PropertyEnum.enumConstant); // 42 +console.log(exports.PropertyEnum.computedEnum); // "computed value" + +// Modify mutable properties +exports.PropertyEnum.enumProperty = "updated"; + +``` + +## Namespace Enum Static Properties + +Namespace enums organize related static properties and are assigned to `globalThis`: + +```swift +@JS enum PropertyNamespace { + @JS enum Nested { + @JS static var nestedConstant = "constant" + @JS static var nestedDouble = 3.14 + @JS static var nestedProperty = 100 + } +} +``` + +Generated TypeScript definitions: + +```typescript +declare global { + namespace PropertyNamespace { + namespace Nested { + var nestedConstant: string; + let nestedDouble: number; + let nestedProperty: number; + } + } +} +``` + +JavaScript usage: + +```typescript +// Direct access via global namespace (no exports needed) +console.log(PropertyNamespace.Nested.nestedConstant); // "constant" +console.log(PropertyNamespace.Nested.nestedDouble); // 3.14 +console.log(PropertyNamespace.Nested.nestedProperty); // 100 + +// Modify mutable properties +PropertyNamespace.Nested.nestedConstant = "updated"; +PropertyNamespace.Nested.nestedProperty = 200; + +// Type-safe access +const constant: string = PropertyNamespace.Nested.nestedConstant; +const value: number = PropertyNamespace.Nested.nestedProperty; +``` + +## Supported Features + +| Swift Static Property Feature | Status | +|:------------------------------|:-------| +| Class `static let` | ✅ | +| Class `static var` | ✅ | +| Class `class var` | ✅ | +| Enum static properties | ✅ | +| Namespace enum static properties | ✅ | +| Computed properties (get/set) | ✅ | +| Read-only computed properties | ✅ | +| All property types (primitives, objects, optionals) | ✅ | +| Property observers (`willSet`/`didSet`) | ❌ | +| Generic static properties | ❌ | +| Protocol static property requirements | ❌ | diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 7e2b586e..a2cd3c1a 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -672,6 +672,111 @@ enum APIOptionalResult { return "willSet:\(PropertyHolder.willSetCallCount),didSet:\(PropertyHolder.didSetCallCount),willSetOld:\(PropertyHolder.lastWillSetOldValue),willSetNew:\(PropertyHolder.lastWillSetNewValue),didSetOld:\(PropertyHolder.lastDidSetOldValue),didSetNew:\(PropertyHolder.lastDidSetNewValue)" } + +// MARK: - Static Functions +@JS class MathUtils { + @JS static func add(a: Int, b: Int) -> Int { + return a + b + } + @JS class func substract(a: Int, b: Int) -> Int { + return a - b + } +} + +@JS enum StaticCalculator { + case scientific + case basic + + @JS static func roundtrip(_ value: Int) -> Int { + return value + } +} + +@JS enum StaticUtils { + @JS enum Nested { + @JS static func roundtrip(_ value: String) -> String { + return value + } + } +} + +// MARK: - Static Properties + +@JS class StaticPropertyHolder { + @JS static let staticConstant: String = "constant" + @JS nonisolated(unsafe) static var staticVariable: Int = 42 + @JS nonisolated(unsafe) static var staticString: String = "initial" + @JS nonisolated(unsafe) static var staticBool: Bool = true + @JS nonisolated(unsafe) static var staticFloat: Float = 3.14 + @JS nonisolated(unsafe) static var staticDouble: Double = 2.718 + + @JS static var computedProperty: String { + get { return "computed: \(staticVariable)" } + set { + if let number = Int(newValue.replacingOccurrences(of: "computed: ", with: "")) { + staticVariable = number + } + } + } + + @JS static var readOnlyComputed: Int { + return staticVariable * 2 + } + + @JS nonisolated(unsafe) static var optionalString: String? = nil + @JS nonisolated(unsafe) static var optionalInt: Int? = nil + + @JS nonisolated(unsafe) static var jsObjectProperty: JSObject = JSObject() + + @JS init() {} + +} + +@JS enum StaticPropertyEnum { + case option1 + case option2 + + @JS nonisolated(unsafe) static var enumProperty: String = "enum value" + @JS static let enumConstant: Int = 42 + @JS nonisolated(unsafe) static var enumBool: Bool = false + + @JS nonisolated(unsafe) static var enumVariable: Int = 200 + + @JS static var computedReadonly: Int { + return enumVariable * 2 + } + + @JS static var computedReadWrite: String { + get { + return "Value: \(enumVariable)" + } + set { + if let range = newValue.range(of: "Value: "), + let number = Int(String(newValue[range.upperBound...])) + { + enumVariable = number + } + } + } +} + +@JS enum StaticPropertyNamespace { + @JS nonisolated(unsafe) static var namespaceProperty: String = "namespace" + @JS static let namespaceConstant: String = "constant" + + @JS enum NestedProperties { + @JS nonisolated(unsafe) static var nestedProperty: Int = 999 + @JS static let nestedConstant: String = "nested" + @JS nonisolated(unsafe) static var nestedDouble: Double = 1.414 + } +} + +// Test functions for static properties +@JS func getAllStaticPropertyValues() -> String { + return + "const:\(StaticPropertyHolder.staticConstant),var:\(StaticPropertyHolder.staticVariable),computed:\(StaticPropertyHolder.computedProperty),readonly:\(StaticPropertyHolder.readOnlyComputed)" +} + class ExportAPITests: XCTestCase { func testAll() { var hasDeinitGreeter = false diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift index b629cda4..3b5baabb 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.ExportSwift.swift @@ -488,6 +488,289 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { } } +extension StaticCalculator: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> StaticCalculator { + return StaticCalculator(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> StaticCalculator { + return StaticCalculator(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .scientific + case 1: + self = .basic + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .scientific: + return 0 + case .basic: + return 1 + } + } +} + +@_expose(wasm, "bjs_StaticCalculator_static_roundtrip") +@_cdecl("bjs_StaticCalculator_static_roundtrip") +public func _bjs_StaticCalculator_static_roundtrip(value: Int32) -> Int32 { + #if arch(wasm32) + let ret = StaticCalculator.roundtrip(_: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticUtils_Nested_static_roundtrip") +@_cdecl("bjs_StaticUtils_Nested_static_roundtrip") +public func _bjs_StaticUtils_Nested_static_roundtrip(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + let ret = StaticUtils.Nested.roundtrip(_: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension StaticPropertyEnum: _BridgedSwiftCaseEnum { + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { + return bridgeJSRawValue + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ value: Int32) -> StaticPropertyEnum { + return StaticPropertyEnum(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ value: Int32) -> StaticPropertyEnum { + return StaticPropertyEnum(bridgeJSRawValue: value)! + } + @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() -> Int32 { + return bridgeJSRawValue + } + + private init?(bridgeJSRawValue: Int32) { + switch bridgeJSRawValue { + case 0: + self = .option1 + case 1: + self = .option2 + default: + return nil + } + } + + private var bridgeJSRawValue: Int32 { + switch self { + case .option1: + return 0 + case .option2: + return 1 + } + } +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumProperty_get") +@_cdecl("bjs_StaticPropertyEnum_static_enumProperty_get") +public func _bjs_StaticPropertyEnum_static_enumProperty_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyEnum.enumProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumProperty_set") +@_cdecl("bjs_StaticPropertyEnum_static_enumProperty_set") +public func _bjs_StaticPropertyEnum_static_enumProperty_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyEnum.enumProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumConstant_get") +@_cdecl("bjs_StaticPropertyEnum_static_enumConstant_get") +public func _bjs_StaticPropertyEnum_static_enumConstant_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyEnum.enumConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumBool_get") +@_cdecl("bjs_StaticPropertyEnum_static_enumBool_get") +public func _bjs_StaticPropertyEnum_static_enumBool_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyEnum.enumBool + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumBool_set") +@_cdecl("bjs_StaticPropertyEnum_static_enumBool_set") +public func _bjs_StaticPropertyEnum_static_enumBool_set(value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyEnum.enumBool = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumVariable_get") +@_cdecl("bjs_StaticPropertyEnum_static_enumVariable_get") +public func _bjs_StaticPropertyEnum_static_enumVariable_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyEnum.enumVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_enumVariable_set") +@_cdecl("bjs_StaticPropertyEnum_static_enumVariable_set") +public func _bjs_StaticPropertyEnum_static_enumVariable_set(value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyEnum.enumVariable = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_computedReadonly_get") +@_cdecl("bjs_StaticPropertyEnum_static_computedReadonly_get") +public func _bjs_StaticPropertyEnum_static_computedReadonly_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyEnum.computedReadonly + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_computedReadWrite_get") +@_cdecl("bjs_StaticPropertyEnum_static_computedReadWrite_get") +public func _bjs_StaticPropertyEnum_static_computedReadWrite_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyEnum.computedReadWrite + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyEnum_static_computedReadWrite_set") +@_cdecl("bjs_StaticPropertyEnum_static_computedReadWrite_set") +public func _bjs_StaticPropertyEnum_static_computedReadWrite_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyEnum.computedReadWrite = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_static_namespaceProperty_get") +@_cdecl("bjs_StaticPropertyNamespace_static_namespaceProperty_get") +public func _bjs_StaticPropertyNamespace_static_namespaceProperty_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyNamespace.namespaceProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_static_namespaceProperty_set") +@_cdecl("bjs_StaticPropertyNamespace_static_namespaceProperty_set") +public func _bjs_StaticPropertyNamespace_static_namespaceProperty_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyNamespace.namespaceProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_static_namespaceConstant_get") +@_cdecl("bjs_StaticPropertyNamespace_static_namespaceConstant_get") +public func _bjs_StaticPropertyNamespace_static_namespaceConstant_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyNamespace.namespaceConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_get") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_get") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyNamespace.NestedProperties.nestedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_set") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_set") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedProperty_set(value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyNamespace.NestedProperties.nestedProperty = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedConstant_get") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedConstant_get") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedConstant_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyNamespace.NestedProperties.nestedConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_get") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_get") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_get() -> Float64 { + #if arch(wasm32) + let ret = StaticPropertyNamespace.NestedProperties.nestedDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_set") +@_cdecl("bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_set") +public func _bjs_StaticPropertyNamespace_NestedProperties_static_nestedDouble_set(value: Float64) -> Void { + #if arch(wasm32) + StaticPropertyNamespace.NestedProperties.nestedDouble = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_roundTripVoid") @_cdecl("bjs_roundTripVoid") public func _bjs_roundTripVoid() -> Void { @@ -1635,6 +1918,17 @@ public func _bjs_getObserverStats() -> Void { #endif } +@_expose(wasm, "bjs_getAllStaticPropertyValues") +@_cdecl("bjs_getAllStaticPropertyValues") +public func _bjs_getAllStaticPropertyValues() -> Void { + #if arch(wasm32) + let ret = getAllStaticPropertyValues() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_Greeter_init") @_cdecl("bjs_Greeter_init") public func _bjs_Greeter_init(nameBytes: Int32, nameLength: Int32) -> UnsafeMutableRawPointer { @@ -2407,4 +2701,288 @@ extension PropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { #endif return .object(JSObject(id: UInt32(bitPattern: _bjs_PropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) } +} + +@_expose(wasm, "bjs_MathUtils_static_add") +@_cdecl("bjs_MathUtils_static_add") +public func _bjs_MathUtils_static_add(a: Int32, b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.add(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_static_substract") +@_cdecl("bjs_MathUtils_static_substract") +public func _bjs_MathUtils_static_substract(a: Int32, b: Int32) -> Int32 { + #if arch(wasm32) + let ret = MathUtils.substract(a: Int.bridgeJSLiftParameter(a), b: Int.bridgeJSLiftParameter(b)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_MathUtils_deinit") +@_cdecl("bjs_MathUtils_deinit") +public func _bjs_MathUtils_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension MathUtils: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_MathUtils_wrap") + func _bjs_MathUtils_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_MathUtils_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_MathUtils_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +@_expose(wasm, "bjs_StaticPropertyHolder_init") +@_cdecl("bjs_StaticPropertyHolder_init") +public func _bjs_StaticPropertyHolder_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = StaticPropertyHolder() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticConstant_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticConstant_get") +public func _bjs_StaticPropertyHolder_static_staticConstant_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticConstant + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticVariable_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticVariable_get") +public func _bjs_StaticPropertyHolder_static_staticVariable_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticVariable + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticVariable_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticVariable_set") +public func _bjs_StaticPropertyHolder_static_staticVariable_set(value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticVariable = Int.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticString_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticString_get") +public func _bjs_StaticPropertyHolder_static_staticString_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticString + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticString_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticString_set") +public func _bjs_StaticPropertyHolder_static_staticString_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticString = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticBool_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticBool_get") +public func _bjs_StaticPropertyHolder_static_staticBool_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticBool + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticBool_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticBool_set") +public func _bjs_StaticPropertyHolder_static_staticBool_set(value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticBool = Bool.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticFloat_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticFloat_get") +public func _bjs_StaticPropertyHolder_static_staticFloat_get() -> Float32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticFloat + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticFloat_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticFloat_set") +public func _bjs_StaticPropertyHolder_static_staticFloat_set(value: Float32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticFloat = Float.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticDouble_get") +@_cdecl("bjs_StaticPropertyHolder_static_staticDouble_get") +public func _bjs_StaticPropertyHolder_static_staticDouble_get() -> Float64 { + #if arch(wasm32) + let ret = StaticPropertyHolder.staticDouble + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_staticDouble_set") +@_cdecl("bjs_StaticPropertyHolder_static_staticDouble_set") +public func _bjs_StaticPropertyHolder_static_staticDouble_set(value: Float64) -> Void { + #if arch(wasm32) + StaticPropertyHolder.staticDouble = Double.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_computedProperty_get") +@_cdecl("bjs_StaticPropertyHolder_static_computedProperty_get") +public func _bjs_StaticPropertyHolder_static_computedProperty_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.computedProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_computedProperty_set") +@_cdecl("bjs_StaticPropertyHolder_static_computedProperty_set") +public func _bjs_StaticPropertyHolder_static_computedProperty_set(valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.computedProperty = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_readOnlyComputed_get") +@_cdecl("bjs_StaticPropertyHolder_static_readOnlyComputed_get") +public func _bjs_StaticPropertyHolder_static_readOnlyComputed_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.readOnlyComputed + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_optionalString_get") +@_cdecl("bjs_StaticPropertyHolder_static_optionalString_get") +public func _bjs_StaticPropertyHolder_static_optionalString_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.optionalString + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_optionalString_set") +@_cdecl("bjs_StaticPropertyHolder_static_optionalString_set") +public func _bjs_StaticPropertyHolder_static_optionalString_set(valueIsSome: Int32, valueBytes: Int32, valueLength: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.optionalString = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_optionalInt_get") +@_cdecl("bjs_StaticPropertyHolder_static_optionalInt_get") +public func _bjs_StaticPropertyHolder_static_optionalInt_get() -> Void { + #if arch(wasm32) + let ret = StaticPropertyHolder.optionalInt + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_optionalInt_set") +@_cdecl("bjs_StaticPropertyHolder_static_optionalInt_set") +public func _bjs_StaticPropertyHolder_static_optionalInt_set(valueIsSome: Int32, valueValue: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.optionalInt = Optional.bridgeJSLiftParameter(valueIsSome, valueValue) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_jsObjectProperty_get") +@_cdecl("bjs_StaticPropertyHolder_static_jsObjectProperty_get") +public func _bjs_StaticPropertyHolder_static_jsObjectProperty_get() -> Int32 { + #if arch(wasm32) + let ret = StaticPropertyHolder.jsObjectProperty + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_static_jsObjectProperty_set") +@_cdecl("bjs_StaticPropertyHolder_static_jsObjectProperty_set") +public func _bjs_StaticPropertyHolder_static_jsObjectProperty_set(value: Int32) -> Void { + #if arch(wasm32) + StaticPropertyHolder.jsObjectProperty = JSObject.bridgeJSLiftParameter(value) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StaticPropertyHolder_deinit") +@_cdecl("bjs_StaticPropertyHolder_deinit") +public func _bjs_StaticPropertyHolder_deinit(pointer: UnsafeMutableRawPointer) { + Unmanaged.fromOpaque(pointer).release() +} + +extension StaticPropertyHolder: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + #if arch(wasm32) + @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StaticPropertyHolder_wrap") + func _bjs_StaticPropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 + #else + func _bjs_StaticPropertyHolder_wrap(_: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") + } + #endif + return .object(JSObject(id: UInt32(bitPattern: _bjs_StaticPropertyHolder_wrap(Unmanaged.passRetained(self).toOpaque())))) + } } \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json index def3e68d..15c5a3a7 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.ExportSwift.json @@ -5,6 +5,7 @@ "abiName" : "bjs_Greeter_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -24,6 +25,7 @@ "abiName" : "bjs_Greeter_greet", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "greet", @@ -40,6 +42,7 @@ "abiName" : "bjs_Greeter_changeName", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "changeName", @@ -65,6 +68,7 @@ "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "name", "type" : { "string" : { @@ -74,6 +78,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "prefix", "type" : { "string" : { @@ -90,6 +95,7 @@ "abiName" : "bjs_Calculator_square", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "square", @@ -114,6 +120,7 @@ "abiName" : "bjs_Calculator_add", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "add", @@ -188,6 +195,7 @@ "abiName" : "bjs_Converter_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -199,9 +207,13 @@ "abiName" : "bjs_Converter_toString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "toString", + "namespace" : [ + "Utils" + ], "parameters" : [ { "label" : "value", @@ -234,6 +246,7 @@ "abiName" : "bjs_HTTPServer_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -245,9 +258,14 @@ "abiName" : "bjs_HTTPServer_call", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "call", + "namespace" : [ + "Networking", + "API" + ], "parameters" : [ { "label" : "_", @@ -281,6 +299,7 @@ "abiName" : "bjs_TestServer_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -292,9 +311,15 @@ "abiName" : "bjs_TestServer_call", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "call", + "namespace" : [ + "Networking", + "APIV2", + "Internal" + ], "parameters" : [ { "label" : "_", @@ -329,6 +354,7 @@ "abiName" : "bjs_OptionalPropertyHolder_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -354,6 +380,7 @@ "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "optionalName", "type" : { "optional" : { @@ -367,6 +394,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "optionalAge", "type" : { "optional" : { @@ -380,6 +408,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "optionalGreeter", "type" : { "optional" : { @@ -399,6 +428,7 @@ "abiName" : "bjs_SimplePropertyHolder_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -420,6 +450,7 @@ "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "value", "type" : { "int" : { @@ -435,6 +466,7 @@ "abiName" : "bjs_PropertyHolder_init", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "parameters" : [ @@ -508,6 +540,7 @@ "abiName" : "bjs_PropertyHolder_getAllValues", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getAllValues", @@ -525,6 +558,7 @@ "properties" : [ { "isReadonly" : false, + "isStatic" : false, "name" : "intValue", "type" : { "int" : { @@ -534,6 +568,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "floatValue", "type" : { "float" : { @@ -543,6 +578,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "doubleValue", "type" : { "double" : { @@ -552,6 +588,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "boolValue", "type" : { "bool" : { @@ -561,6 +598,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "stringValue", "type" : { "string" : { @@ -570,6 +608,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyInt", "type" : { "int" : { @@ -579,6 +618,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyFloat", "type" : { "float" : { @@ -588,6 +628,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyDouble", "type" : { "double" : { @@ -597,6 +638,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyBool", "type" : { "bool" : { @@ -606,6 +648,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "readonlyString", "type" : { "string" : { @@ -615,6 +658,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "jsObject", "type" : { "jsObject" : { @@ -624,6 +668,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "sibling", "type" : { "swiftHeapObject" : { @@ -633,6 +678,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "lazyValue", "type" : { "string" : { @@ -642,6 +688,7 @@ }, { "isReadonly" : true, + "isStatic" : false, "name" : "computedReadonly", "type" : { "int" : { @@ -651,6 +698,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "computedReadWrite", "type" : { "string" : { @@ -660,6 +708,7 @@ }, { "isReadonly" : false, + "isStatic" : false, "name" : "observedProperty", "type" : { "int" : { @@ -669,6 +718,286 @@ } ], "swiftCallName" : "PropertyHolder" + }, + { + "methods" : [ + { + "abiName" : "bjs_MathUtils_static_add", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "add", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + }, + { + "abiName" : "bjs_MathUtils_static_substract", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "substract", + "parameters" : [ + { + "label" : "a", + "name" : "a", + "type" : { + "int" : { + + } + } + }, + { + "label" : "b", + "name" : "b", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "className" : { + "_0" : "MathUtils" + } + } + } + ], + "name" : "MathUtils", + "properties" : [ + + ], + "swiftCallName" : "MathUtils" + }, + { + "constructor" : { + "abiName" : "bjs_StaticPropertyHolder_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + + ], + "name" : "StaticPropertyHolder", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : true, + "name" : "staticConstant", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticVariable", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticString", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticBool", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "bool" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticFloat", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "float" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "staticDouble", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "double" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedProperty", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "readOnlyComputed", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "int" : { + + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "optionalString", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "optionalInt", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "isReadonly" : false, + "isStatic" : true, + "name" : "jsObjectProperty", + "staticContext" : { + "className" : { + "_0" : "StaticPropertyHolder" + } + }, + "type" : { + "jsObject" : { + + } + } + } + ], + "swiftCallName" : "StaticPropertyHolder" } ], "enums" : [ @@ -701,6 +1030,12 @@ ], "emitStyle" : "const", "name" : "Direction", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Direction" }, { @@ -726,6 +1061,12 @@ ], "emitStyle" : "const", "name" : "Status", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Status" }, { @@ -755,6 +1096,12 @@ "emitStyle" : "const", "name" : "Theme", "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Theme" }, { @@ -784,6 +1131,12 @@ "emitStyle" : "const", "name" : "HttpStatus", "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "HttpStatus" }, { @@ -815,6 +1168,12 @@ ], "emitStyle" : "tsEnum", "name" : "TSDirection", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "TSDirection" }, { @@ -844,6 +1203,12 @@ "emitStyle" : "tsEnum", "name" : "TSTheme", "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "TSTheme" }, { @@ -852,27 +1217,64 @@ ], "emitStyle" : "const", "name" : "Utils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Utils" }, { "cases" : [ - { - "associatedValues" : [ - ], - "name" : "get" - }, - { - "associatedValues" : [ + ], + "emitStyle" : "const", + "name" : "Networking", + "staticMethods" : [ - ], - "name" : "post" - }, - { - "associatedValues" : [ + ], + "staticProperties" : [ - ], - "name" : "put" + ], + "swiftCallName" : "Networking" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "API", + "namespace" : [ + "Networking" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Networking.API" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "get" + }, + { + "associatedValues" : [ + + ], + "name" : "post" + }, + { + "associatedValues" : [ + + ], + "name" : "put" }, { "associatedValues" : [ @@ -886,9 +1288,29 @@ "namespace" : [ "Networking", "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + ], "swiftCallName" : "Networking.API.Method" }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Configuration", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Configuration" + }, { "cases" : [ { @@ -926,6 +1348,12 @@ "Configuration" ], "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Configuration.LogLevel" }, { @@ -958,8 +1386,32 @@ "Configuration" ], "rawType" : "Int", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "Configuration.Port" }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Internal", + "namespace" : [ + "Networking", + "APIV2" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Internal" + }, { "cases" : [ { @@ -981,6 +1433,12 @@ "Networking", "APIV2", "Internal" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + ], "swiftCallName" : "Internal.SupportedMethod" }, @@ -1055,6 +1513,12 @@ ], "emitStyle" : "const", "name" : "APIResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], "swiftCallName" : "APIResult" }, { @@ -1230,218 +1694,624 @@ "type" : { "string" : { - } - } + } + } + } + ], + "name" : "comprehensive" + }, + { + "associatedValues" : [ + + ], + "name" : "info" + } + ], + "emitStyle" : "const", + "name" : "ComplexResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "ComplexResult" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Utilities", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utilities" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "bool" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + }, + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "Result", + "namespace" : [ + "Utilities" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Utilities.Result" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "API", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "API" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "string" : { + + } + } + }, + { + "type" : { + "int" : { + + } + } + } + ], + "name" : "failure" + } + ], + "emitStyle" : "const", + "name" : "NetworkingResult", + "namespace" : [ + "API" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "API.NetworkingResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "name" : "success" + }, + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + } + ], + "name" : "failure" + }, + { + "associatedValues" : [ + { + "type" : { + "optional" : { + "_0" : { + "bool" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "int" : { + + } + } + } + } + }, + { + "type" : { + "optional" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "name" : "status" + } + ], + "emitStyle" : "const", + "name" : "APIOptionalResult", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "APIOptionalResult" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "scientific" + }, + { + "associatedValues" : [ + + ], + "name" : "basic" + } + ], + "emitStyle" : "const", + "name" : "StaticCalculator", + "staticMethods" : [ + { + "abiName" : "bjs_StaticCalculator_static_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundtrip", + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "int" : { + + } + }, + "staticContext" : { + "enumName" : { + "_0" : "StaticCalculator" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "StaticCalculator" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "StaticUtils", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "StaticUtils" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "Nested", + "namespace" : [ + "StaticUtils" + ], + "staticMethods" : [ + { + "abiName" : "bjs_StaticUtils_Nested_static_roundtrip", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "roundtrip", + "namespace" : [ + "StaticUtils", + "Nested" + ], + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "StaticUtils.Nested" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "option1" + }, + { + "associatedValues" : [ + + ], + "name" : "option2" + } + ], + "emitStyle" : "const", + "name" : "StaticPropertyEnum", + "staticMethods" : [ + + ], + "staticProperties" : [ + { + "isReadonly" : false, + "isStatic" : true, + "name" : "enumProperty", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "enumConstant", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "int" : { + } - ], - "name" : "comprehensive" + } }, { - "associatedValues" : [ + "isReadonly" : false, + "isStatic" : true, + "name" : "enumBool", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "bool" : { - ], - "name" : "info" - } - ], - "emitStyle" : "const", - "name" : "ComplexResult", - "swiftCallName" : "ComplexResult" - }, - { - "cases" : [ + } + } + }, { - "associatedValues" : [ - { - "type" : { - "string" : { + "isReadonly" : false, + "isStatic" : true, + "name" : "enumVariable", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "int" : { - } - } } - ], - "name" : "success" + } }, { - "associatedValues" : [ - { - "type" : { - "string" : { - - } - } - }, - { - "type" : { - "int" : { + "isReadonly" : true, + "isStatic" : true, + "name" : "computedReadonly", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "int" : { - } - } } - ], - "name" : "failure" + } }, { - "associatedValues" : [ - { - "type" : { - "bool" : { - - } - } - }, - { - "type" : { - "int" : { - - } - } - }, - { - "type" : { - "string" : { + "isReadonly" : false, + "isStatic" : true, + "name" : "computedReadWrite", + "staticContext" : { + "enumName" : { + "_0" : "StaticPropertyEnum" + } + }, + "type" : { + "string" : { - } - } } - ], - "name" : "status" + } } ], - "emitStyle" : "const", - "name" : "Result", - "namespace" : [ - "Utilities" - ], - "swiftCallName" : "Utilities.Result" + "swiftCallName" : "StaticPropertyEnum" }, { "cases" : [ + + ], + "emitStyle" : "const", + "name" : "StaticPropertyNamespace", + "staticMethods" : [ + + ], + "staticProperties" : [ { - "associatedValues" : [ - { - "type" : { - "string" : { + "isReadonly" : false, + "isStatic" : true, + "name" : "namespaceProperty", + "namespace" : [ + "StaticPropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { - } - } } - ], - "name" : "success" + }, + "type" : { + "string" : { + + } + } }, { - "associatedValues" : [ - { - "type" : { - "string" : { + "isReadonly" : true, + "isStatic" : true, + "name" : "namespaceConstant", + "namespace" : [ + "StaticPropertyNamespace" + ], + "staticContext" : { + "namespaceEnum" : { - } - } - }, - { - "type" : { - "int" : { + } + }, + "type" : { + "string" : { - } - } } - ], - "name" : "failure" + } } ], - "emitStyle" : "const", - "name" : "NetworkingResult", - "namespace" : [ - "API" - ], - "swiftCallName" : "API.NetworkingResult" + "swiftCallName" : "StaticPropertyNamespace" }, { "cases" : [ + + ], + "emitStyle" : "const", + "name" : "NestedProperties", + "namespace" : [ + "StaticPropertyNamespace" + ], + "staticMethods" : [ + + ], + "staticProperties" : [ { - "associatedValues" : [ - { - "type" : { - "optional" : { - "_0" : { - "string" : { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedProperty", + "namespace" : [ + "StaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { - } - } - } - } } - ], - "name" : "success" + }, + "type" : { + "int" : { + + } + } }, { - "associatedValues" : [ - { - "type" : { - "optional" : { - "_0" : { - "int" : { + "isReadonly" : true, + "isStatic" : true, + "name" : "nestedConstant", + "namespace" : [ + "StaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { - } - } - } - } - }, - { - "type" : { - "optional" : { - "_0" : { - "bool" : { + } + }, + "type" : { + "string" : { - } - } - } - } } - ], - "name" : "failure" + } }, { - "associatedValues" : [ - { - "type" : { - "optional" : { - "_0" : { - "bool" : { - - } - } - } - } - }, - { - "type" : { - "optional" : { - "_0" : { - "int" : { + "isReadonly" : false, + "isStatic" : true, + "name" : "nestedDouble", + "namespace" : [ + "StaticPropertyNamespace", + "NestedProperties" + ], + "staticContext" : { + "namespaceEnum" : { - } - } - } - } - }, - { - "type" : { - "optional" : { - "_0" : { - "string" : { + } + }, + "type" : { + "double" : { - } - } - } - } } - ], - "name" : "status" + } } ], - "emitStyle" : "const", - "name" : "APIOptionalResult", - "swiftCallName" : "APIOptionalResult" + "swiftCallName" : "StaticPropertyNamespace.NestedProperties" } ], "functions" : [ @@ -1449,6 +2319,7 @@ "abiName" : "bjs_roundTripVoid", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripVoid", @@ -1465,6 +2336,7 @@ "abiName" : "bjs_roundTripInt", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripInt", @@ -1489,6 +2361,7 @@ "abiName" : "bjs_roundTripFloat", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripFloat", @@ -1513,6 +2386,7 @@ "abiName" : "bjs_roundTripDouble", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripDouble", @@ -1537,6 +2411,7 @@ "abiName" : "bjs_roundTripBool", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripBool", @@ -1561,6 +2436,7 @@ "abiName" : "bjs_roundTripString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripString", @@ -1585,6 +2461,7 @@ "abiName" : "bjs_roundTripSwiftHeapObject", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripSwiftHeapObject", @@ -1609,6 +2486,7 @@ "abiName" : "bjs_roundTripJSObject", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripJSObject", @@ -1633,6 +2511,7 @@ "abiName" : "bjs_throwsSwiftError", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsSwiftError", @@ -1657,6 +2536,7 @@ "abiName" : "bjs_throwsWithIntResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsWithIntResult", @@ -1673,6 +2553,7 @@ "abiName" : "bjs_throwsWithStringResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsWithStringResult", @@ -1689,6 +2570,7 @@ "abiName" : "bjs_throwsWithBoolResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsWithBoolResult", @@ -1705,6 +2587,7 @@ "abiName" : "bjs_throwsWithFloatResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsWithFloatResult", @@ -1721,6 +2604,7 @@ "abiName" : "bjs_throwsWithDoubleResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsWithDoubleResult", @@ -1737,6 +2621,7 @@ "abiName" : "bjs_throwsWithSwiftHeapObjectResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsWithSwiftHeapObjectResult", @@ -1753,6 +2638,7 @@ "abiName" : "bjs_throwsWithJSObjectResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : true }, "name" : "throwsWithJSObjectResult", @@ -1769,6 +2655,7 @@ "abiName" : "bjs_asyncRoundTripVoid", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripVoid", @@ -1785,6 +2672,7 @@ "abiName" : "bjs_asyncRoundTripInt", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripInt", @@ -1809,6 +2697,7 @@ "abiName" : "bjs_asyncRoundTripFloat", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripFloat", @@ -1833,6 +2722,7 @@ "abiName" : "bjs_asyncRoundTripDouble", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripDouble", @@ -1857,6 +2747,7 @@ "abiName" : "bjs_asyncRoundTripBool", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripBool", @@ -1881,6 +2772,7 @@ "abiName" : "bjs_asyncRoundTripString", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripString", @@ -1905,6 +2797,7 @@ "abiName" : "bjs_asyncRoundTripSwiftHeapObject", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripSwiftHeapObject", @@ -1929,6 +2822,7 @@ "abiName" : "bjs_asyncRoundTripJSObject", "effects" : { "isAsync" : true, + "isStatic" : false, "isThrows" : false }, "name" : "asyncRoundTripJSObject", @@ -1953,6 +2847,7 @@ "abiName" : "bjs_takeGreeter", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "takeGreeter", @@ -1986,6 +2881,7 @@ "abiName" : "bjs_createCalculator", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "createCalculator", @@ -2002,6 +2898,7 @@ "abiName" : "bjs_useCalculator", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "useCalculator", @@ -2044,6 +2941,7 @@ "abiName" : "bjs_testGreeterToJSValue", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "testGreeterToJSValue", @@ -2060,6 +2958,7 @@ "abiName" : "bjs_testCalculatorToJSValue", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "testCalculatorToJSValue", @@ -2076,6 +2975,7 @@ "abiName" : "bjs_testSwiftClassAsJSValue", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "testSwiftClassAsJSValue", @@ -2100,6 +3000,7 @@ "abiName" : "bjs_setDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setDirection", @@ -2124,6 +3025,7 @@ "abiName" : "bjs_getDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getDirection", @@ -2140,6 +3042,7 @@ "abiName" : "bjs_processDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "processDirection", @@ -2164,6 +3067,7 @@ "abiName" : "bjs_setTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setTheme", @@ -2190,6 +3094,7 @@ "abiName" : "bjs_getTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getTheme", @@ -2207,6 +3112,7 @@ "abiName" : "bjs_setHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setHttpStatus", @@ -2233,6 +3139,7 @@ "abiName" : "bjs_getHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getHttpStatus", @@ -2250,6 +3157,7 @@ "abiName" : "bjs_processTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "processTheme", @@ -2276,6 +3184,7 @@ "abiName" : "bjs_setTSDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setTSDirection", @@ -2300,6 +3209,7 @@ "abiName" : "bjs_getTSDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getTSDirection", @@ -2316,6 +3226,7 @@ "abiName" : "bjs_setTSTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "setTSTheme", @@ -2342,6 +3253,7 @@ "abiName" : "bjs_getTSTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getTSTheme", @@ -2359,6 +3271,7 @@ "abiName" : "bjs_roundtripNetworkingAPIMethod", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripNetworkingAPIMethod", @@ -2383,6 +3296,7 @@ "abiName" : "bjs_roundtripConfigurationLogLevel", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripConfigurationLogLevel", @@ -2409,6 +3323,7 @@ "abiName" : "bjs_roundtripConfigurationPort", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripConfigurationPort", @@ -2435,6 +3350,7 @@ "abiName" : "bjs_processConfigurationLogLevel", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "processConfigurationLogLevel", @@ -2461,6 +3377,7 @@ "abiName" : "bjs_roundtripInternalSupportedMethod", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripInternalSupportedMethod", @@ -2485,6 +3402,7 @@ "abiName" : "bjs_roundtripAPIResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripAPIResult", @@ -2509,6 +3427,7 @@ "abiName" : "bjs_makeAPIResultSuccess", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeAPIResultSuccess", @@ -2533,6 +3452,7 @@ "abiName" : "bjs_makeAPIResultFailure", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeAPIResultFailure", @@ -2557,6 +3477,7 @@ "abiName" : "bjs_makeAPIResultInfo", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeAPIResultInfo", @@ -2573,6 +3494,7 @@ "abiName" : "bjs_makeAPIResultFlag", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeAPIResultFlag", @@ -2597,6 +3519,7 @@ "abiName" : "bjs_makeAPIResultRate", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeAPIResultRate", @@ -2621,6 +3544,7 @@ "abiName" : "bjs_makeAPIResultPrecise", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeAPIResultPrecise", @@ -2645,6 +3569,7 @@ "abiName" : "bjs_roundtripComplexResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripComplexResult", @@ -2669,6 +3594,7 @@ "abiName" : "bjs_makeComplexResultSuccess", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeComplexResultSuccess", @@ -2693,6 +3619,7 @@ "abiName" : "bjs_makeComplexResultError", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeComplexResultError", @@ -2726,6 +3653,7 @@ "abiName" : "bjs_makeComplexResultLocation", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeComplexResultLocation", @@ -2768,6 +3696,7 @@ "abiName" : "bjs_makeComplexResultStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeComplexResultStatus", @@ -2810,6 +3739,7 @@ "abiName" : "bjs_makeComplexResultCoordinates", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeComplexResultCoordinates", @@ -2852,6 +3782,7 @@ "abiName" : "bjs_makeComplexResultComprehensive", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeComplexResultComprehensive", @@ -2948,6 +3879,7 @@ "abiName" : "bjs_makeComplexResultInfo", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeComplexResultInfo", @@ -2964,6 +3896,7 @@ "abiName" : "bjs_makeUtilitiesResultSuccess", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeUtilitiesResultSuccess", @@ -2988,6 +3921,7 @@ "abiName" : "bjs_makeUtilitiesResultFailure", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeUtilitiesResultFailure", @@ -3021,6 +3955,7 @@ "abiName" : "bjs_makeUtilitiesResultStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeUtilitiesResultStatus", @@ -3063,6 +3998,7 @@ "abiName" : "bjs_makeAPINetworkingResultSuccess", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeAPINetworkingResultSuccess", @@ -3087,6 +4023,7 @@ "abiName" : "bjs_makeAPINetworkingResultFailure", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "makeAPINetworkingResultFailure", @@ -3120,6 +4057,7 @@ "abiName" : "bjs_roundtripUtilitiesResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripUtilitiesResult", @@ -3144,6 +4082,7 @@ "abiName" : "bjs_roundtripAPINetworkingResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundtripAPINetworkingResult", @@ -3168,6 +4107,7 @@ "abiName" : "bjs_roundTripOptionalString", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalString", @@ -3200,6 +4140,7 @@ "abiName" : "bjs_roundTripOptionalInt", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalInt", @@ -3232,6 +4173,7 @@ "abiName" : "bjs_roundTripOptionalBool", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalBool", @@ -3264,6 +4206,7 @@ "abiName" : "bjs_roundTripOptionalFloat", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalFloat", @@ -3296,6 +4239,7 @@ "abiName" : "bjs_roundTripOptionalDouble", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalDouble", @@ -3328,6 +4272,7 @@ "abiName" : "bjs_roundTripOptionalSyntax", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalSyntax", @@ -3360,6 +4305,7 @@ "abiName" : "bjs_roundTripOptionalMixSyntax", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalMixSyntax", @@ -3392,6 +4338,7 @@ "abiName" : "bjs_roundTripOptionalSwiftSyntax", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalSwiftSyntax", @@ -3424,6 +4371,7 @@ "abiName" : "bjs_roundTripOptionalWithSpaces", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalWithSpaces", @@ -3456,6 +4404,7 @@ "abiName" : "bjs_roundTripOptionalTypeAlias", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalTypeAlias", @@ -3488,6 +4437,7 @@ "abiName" : "bjs_roundTripOptionalStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalStatus", @@ -3520,6 +4470,7 @@ "abiName" : "bjs_roundTripOptionalTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalTheme", @@ -3554,6 +4505,7 @@ "abiName" : "bjs_roundTripOptionalHttpStatus", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalHttpStatus", @@ -3588,6 +4540,7 @@ "abiName" : "bjs_roundTripOptionalTSDirection", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalTSDirection", @@ -3620,6 +4573,7 @@ "abiName" : "bjs_roundTripOptionalTSTheme", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalTSTheme", @@ -3654,6 +4608,7 @@ "abiName" : "bjs_roundTripOptionalNetworkingAPIMethod", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalNetworkingAPIMethod", @@ -3686,6 +4641,7 @@ "abiName" : "bjs_roundTripOptionalAPIResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalAPIResult", @@ -3718,6 +4674,7 @@ "abiName" : "bjs_roundTripOptionalComplexResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalComplexResult", @@ -3750,6 +4707,7 @@ "abiName" : "bjs_roundTripOptionalClass", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalClass", @@ -3782,6 +4740,7 @@ "abiName" : "bjs_roundTripOptionalAPIOptionalResult", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "roundTripOptionalAPIOptionalResult", @@ -3814,6 +4773,7 @@ "abiName" : "bjs_createPropertyHolder", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "createPropertyHolder", @@ -3883,6 +4843,7 @@ "abiName" : "bjs_testPropertyHolder", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "testPropertyHolder", @@ -3907,6 +4868,7 @@ "abiName" : "bjs_resetObserverCounts", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "resetObserverCounts", @@ -3923,11 +4885,29 @@ "abiName" : "bjs_getObserverStats", "effects" : { "isAsync" : false, + "isStatic" : false, "isThrows" : false }, "name" : "getObserverStats", "parameters" : [ + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_getAllStaticPropertyValues", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getAllStaticPropertyValues", + "parameters" : [ + ], "returnType" : { "string" : { diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 039c721e..6b877d3a 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -1,7 +1,7 @@ // @ts-check import { - Direction, Status, Theme, HttpStatus, TSDirection, TSTheme, APIResult, ComplexResult, APIOptionalResult + DirectionValues, StatusValues, ThemeValues, HttpStatusValues, TSDirection, TSTheme, APIResultValues, ComplexResultValues, APIOptionalResultValues, StaticCalculatorValues, StaticPropertyEnumValues } from '../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.js'; /** @type {import('../.build/plugins/PackageToJS/outputs/PackageTests/test.d.ts').SetupOptionsFn} */ @@ -274,6 +274,88 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { ph.release(); ph2.release(); + // Test static properties + assert.equal(exports.StaticPropertyHolder.staticConstant, "constant"); + assert.equal(exports.StaticPropertyHolder.staticVariable, 42); + assert.equal(exports.StaticPropertyHolder.staticString, "initial"); + assert.equal(exports.StaticPropertyHolder.staticBool, true); + assert.equal(exports.StaticPropertyHolder.staticFloat, 3.140000104904175); + assert.equal(exports.StaticPropertyHolder.staticDouble, 2.718); + assert.equal(exports.StaticPropertyHolder.readOnlyComputed, 84); // staticVariable * 2 = 42 * 2 + + // Test static primitive property setters + exports.StaticPropertyHolder.staticVariable = 200; + exports.StaticPropertyHolder.staticString = "updated"; + exports.StaticPropertyHolder.staticBool = false; + exports.StaticPropertyHolder.staticFloat = 6.28; + exports.StaticPropertyHolder.staticDouble = 1.414; + + assert.equal(exports.StaticPropertyHolder.staticVariable, 200); + assert.equal(exports.StaticPropertyHolder.staticString, "updated"); + assert.equal(exports.StaticPropertyHolder.staticBool, false); + assert.equal(exports.StaticPropertyHolder.staticFloat, 6.280000209808350); + assert.equal(exports.StaticPropertyHolder.staticDouble, 1.414); + + // Test static JSObject + const testStaticObj = { staticTest: "object" }; + exports.StaticPropertyHolder.jsObjectProperty = testStaticObj; + assert.equal(exports.StaticPropertyHolder.jsObjectProperty, testStaticObj); + + const newStaticObj = { newStaticProp: "new" }; + exports.StaticPropertyHolder.jsObjectProperty = newStaticObj; + assert.equal(exports.StaticPropertyHolder.jsObjectProperty, newStaticObj); + + // Test static optional properties + assert.equal(exports.StaticPropertyHolder.optionalString, null); + assert.equal(exports.StaticPropertyHolder.optionalInt, null); + exports.StaticPropertyHolder.optionalString = "optional value"; + exports.StaticPropertyHolder.optionalInt = 42; + assert.equal(exports.StaticPropertyHolder.optionalString, "optional value"); + assert.equal(exports.StaticPropertyHolder.optionalInt, 42); + exports.StaticPropertyHolder.optionalString = null; + exports.StaticPropertyHolder.optionalInt = null; + assert.equal(exports.StaticPropertyHolder.optionalString, null); + assert.equal(exports.StaticPropertyHolder.optionalInt, null); + + // Test static computed properties + assert.equal(exports.StaticPropertyHolder.computedProperty, "computed: 200"); + exports.StaticPropertyHolder.computedProperty = "computed: 300"; // Should have parsed and set staticVariable + assert.equal(exports.StaticPropertyHolder.staticVariable, 300); + assert.equal(exports.StaticPropertyHolder.computedProperty, "computed: 300"); + assert.equal(exports.StaticPropertyHolder.readOnlyComputed, 600); // staticVariable * 2 = 300 * 2 + + // Test static properties in enums + assert.equal(exports.StaticPropertyEnum.enumProperty, "enum value"); + assert.equal(exports.StaticPropertyEnum.enumConstant, 42); + assert.equal(exports.StaticPropertyEnum.enumBool, false); + + exports.StaticPropertyEnum.enumProperty = "modified enum"; + exports.StaticPropertyEnum.enumBool = true; + assert.equal(exports.StaticPropertyEnum.enumProperty, "modified enum"); + assert.equal(exports.StaticPropertyEnum.enumBool, true); + + assert.equal(exports.StaticPropertyEnum.enumVariable, 200); + assert.equal(exports.StaticPropertyEnum.computedReadonly, 400); + assert.equal(exports.StaticPropertyEnum.computedReadWrite, "Value: 200"); + exports.StaticPropertyEnum.computedReadWrite = "Value: 500"; + assert.equal(exports.StaticPropertyEnum.enumVariable, 500); + + // Namespace enum static properties + assert.equal(globalThis.StaticPropertyNamespace.namespaceProperty, "namespace"); + assert.equal(globalThis.StaticPropertyNamespace.namespaceConstant, "constant"); + + globalThis.StaticPropertyNamespace.namespaceProperty = "modified namespace"; + assert.equal(globalThis.StaticPropertyNamespace.namespaceProperty, "modified namespace"); + + assert.equal(globalThis.StaticPropertyNamespace.NestedProperties.nestedProperty, 999); + assert.equal(globalThis.StaticPropertyNamespace.NestedProperties.nestedConstant, "nested"); + assert.equal(globalThis.StaticPropertyNamespace.NestedProperties.nestedDouble, 1.414); + + globalThis.StaticPropertyNamespace.NestedProperties.nestedProperty = 1000; + globalThis.StaticPropertyNamespace.NestedProperties.nestedDouble = 2.828; + assert.equal(globalThis.StaticPropertyNamespace.NestedProperties.nestedProperty, 1000); + assert.equal(globalThis.StaticPropertyNamespace.NestedProperties.nestedDouble, 2.828); + // Test class without @JS init constructor const calc = exports.createCalculator(); assert.equal(calc.square(5), 25); @@ -298,34 +380,35 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.fail("Expected no error"); } - assert.equal(Direction.North, 0); - assert.equal(Direction.South, 1); - assert.equal(Direction.East, 2); - assert.equal(Direction.West, 3); - assert.equal(Status.Loading, 0); - assert.equal(Status.Success, 1); - assert.equal(Status.Error, 2); - - assert.equal(exports.setDirection(Direction.North), Direction.North); - assert.equal(exports.setDirection(Direction.South), Direction.South); - assert.equal(exports.getDirection(), Direction.North); - assert.equal(exports.processDirection(Direction.North), Status.Success); - assert.equal(exports.processDirection(Direction.East), Status.Loading); - - assert.equal(Theme.Light, "light"); - assert.equal(Theme.Dark, "dark"); - assert.equal(Theme.Auto, "auto"); - assert.equal(HttpStatus.Ok, 200); - assert.equal(HttpStatus.NotFound, 404); - assert.equal(HttpStatus.ServerError, 500); - - assert.equal(exports.setTheme(Theme.Light), Theme.Light); - assert.equal(exports.setTheme(Theme.Dark), Theme.Dark); - assert.equal(exports.getTheme(), Theme.Light); - assert.equal(exports.setHttpStatus(HttpStatus.Ok), HttpStatus.Ok); - assert.equal(exports.getHttpStatus(), HttpStatus.Ok); - assert.equal(exports.processTheme(Theme.Light), HttpStatus.Ok); - assert.equal(exports.processTheme(Theme.Dark), HttpStatus.NotFound); + // Test enums + assert.equal(exports.Direction.North, 0); + assert.equal(exports.Direction.South, 1); + assert.equal(exports.Direction.East, 2); + assert.equal(DirectionValues.West, 3); + assert.equal(exports.Status.Loading, 0); + assert.equal(exports.Status.Success, 1); + assert.equal(StatusValues.Error, 2); + + assert.equal(exports.setDirection(exports.Direction.North), DirectionValues.North); + assert.equal(exports.setDirection(exports.Direction.South), exports.Direction.South); + assert.equal(exports.getDirection(), exports.Direction.North); + assert.equal(exports.processDirection(exports.Direction.North), exports.Status.Success); + assert.equal(exports.processDirection(DirectionValues.East), StatusValues.Loading); + + assert.equal(exports.Theme.Light, "light"); + assert.equal(exports.Theme.Dark, "dark"); + assert.equal(ThemeValues.Auto, "auto"); + assert.equal(exports.HttpStatus.Ok, 200); + assert.equal(exports.HttpStatus.NotFound, 404); + assert.equal(HttpStatusValues.ServerError, 500); + + assert.equal(exports.setTheme(exports.Theme.Light), exports.Theme.Light); + assert.equal(exports.setTheme(exports.Theme.Dark), exports.Theme.Dark); + assert.equal(exports.getTheme(), ThemeValues.Light); + assert.equal(exports.setHttpStatus(exports.HttpStatus.Ok), HttpStatusValues.Ok); + assert.equal(exports.getHttpStatus(), exports.HttpStatus.Ok); + assert.equal(exports.processTheme(exports.Theme.Light), exports.HttpStatus.Ok); + assert.equal(exports.processTheme(exports.Theme.Dark), HttpStatusValues.NotFound); assert.equal(TSDirection.North, 0); assert.equal(TSDirection.South, 1); @@ -340,28 +423,28 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(exports.setTSTheme(TSTheme.Light), TSTheme.Light); assert.equal(exports.getTSTheme(), TSTheme.Light); - assert.equal(globalThis.Networking.API.Method.Get, 0); - assert.equal(globalThis.Networking.API.Method.Post, 1); - assert.equal(globalThis.Networking.API.Method.Put, 2); - assert.equal(globalThis.Networking.API.Method.Delete, 3); - assert.equal(globalThis.Configuration.LogLevel.Debug, "debug"); - assert.equal(globalThis.Configuration.LogLevel.Info, "info"); - assert.equal(globalThis.Configuration.LogLevel.Warning, "warning"); - assert.equal(globalThis.Configuration.LogLevel.Error, "error"); - assert.equal(globalThis.Configuration.Port.Http, 80); - assert.equal(globalThis.Configuration.Port.Https, 443); - assert.equal(globalThis.Configuration.Port.Development, 3000); - assert.equal(globalThis.Networking.APIV2.Internal.SupportedMethod.Get, 0); - assert.equal(globalThis.Networking.APIV2.Internal.SupportedMethod.Post, 1); - - assert.equal(exports.roundtripNetworkingAPIMethod(globalThis.Networking.API.Method.Get), globalThis.Networking.API.Method.Get); - assert.equal(exports.roundtripConfigurationLogLevel(globalThis.Configuration.LogLevel.Debug), globalThis.Configuration.LogLevel.Debug); - assert.equal(exports.roundtripConfigurationPort(globalThis.Configuration.Port.Http), globalThis.Configuration.Port.Http); - assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevel.Debug), globalThis.Configuration.Port.Development); - assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevel.Info), globalThis.Configuration.Port.Http); - assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevel.Warning), globalThis.Configuration.Port.Https); - assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevel.Error), globalThis.Configuration.Port.Development); - assert.equal(exports.roundtripInternalSupportedMethod(globalThis.Networking.APIV2.Internal.SupportedMethod.Get), globalThis.Networking.APIV2.Internal.SupportedMethod.Get); + assert.equal(globalThis.Networking.API.MethodValues.Get, 0); + assert.equal(globalThis.Networking.API.MethodValues.Post, 1); + assert.equal(globalThis.Networking.API.MethodValues.Put, 2); + assert.equal(globalThis.Networking.API.MethodValues.Delete, 3); + assert.equal(globalThis.Configuration.LogLevelValues.Debug, "debug"); + assert.equal(globalThis.Configuration.LogLevelValues.Info, "info"); + assert.equal(globalThis.Configuration.LogLevelValues.Warning, "warning"); + assert.equal(globalThis.Configuration.LogLevelValues.Error, "error"); + assert.equal(globalThis.Configuration.PortValues.Http, 80); + assert.equal(globalThis.Configuration.PortValues.Https, 443); + assert.equal(globalThis.Configuration.PortValues.Development, 3000); + assert.equal(globalThis.Networking.APIV2.Internal.SupportedMethodValues.Get, 0); + assert.equal(globalThis.Networking.APIV2.Internal.SupportedMethodValues.Post, 1); + + assert.equal(exports.roundtripNetworkingAPIMethod(globalThis.Networking.API.MethodValues.Get), globalThis.Networking.API.MethodValues.Get); + assert.equal(exports.roundtripConfigurationLogLevel(globalThis.Configuration.LogLevelValues.Debug), globalThis.Configuration.LogLevelValues.Debug); + assert.equal(exports.roundtripConfigurationPort(globalThis.Configuration.PortValues.Http), globalThis.Configuration.PortValues.Http); + assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevelValues.Debug), globalThis.Configuration.PortValues.Development); + assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevelValues.Info), globalThis.Configuration.PortValues.Http); + assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevelValues.Warning), globalThis.Configuration.PortValues.Https); + assert.equal(exports.processConfigurationLogLevel(globalThis.Configuration.LogLevelValues.Error), globalThis.Configuration.PortValues.Development); + assert.equal(exports.roundtripInternalSupportedMethod(globalThis.Networking.APIV2.Internal.SupportedMethodValues.Get), globalThis.Networking.APIV2.Internal.SupportedMethodValues.Get); const converter = new exports.Converter(); assert.equal(converter.toString(42), "42"); @@ -369,13 +452,13 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { converter.release(); const httpServer = new exports.HTTPServer(); - httpServer.call(globalThis.Networking.API.Method.Get); - httpServer.call(globalThis.Networking.API.Method.Post); + httpServer.call(globalThis.Networking.API.MethodValues.Get); + httpServer.call(globalThis.Networking.API.MethodValues.Post); httpServer.release(); const testServer = new exports.TestServer(); - testServer.call(globalThis.Networking.APIV2.Internal.SupportedMethod.Get); - testServer.call(globalThis.Networking.APIV2.Internal.SupportedMethod.Post); + testServer.call(globalThis.Networking.APIV2.Internal.SupportedMethodValues.Get); + testServer.call(globalThis.Networking.APIV2.Internal.SupportedMethodValues.Post); testServer.release(); const globalConverter = new globalThis.Utils.Converter(); @@ -383,48 +466,48 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { globalConverter.release(); const globalHttpServer = new globalThis.Networking.API.HTTPServer(); - globalHttpServer.call(globalThis.Networking.API.Method.Get); + globalHttpServer.call(globalThis.Networking.API.MethodValues.Get); globalHttpServer.release(); const globalTestServer = new globalThis.Networking.APIV2.Internal.TestServer(); - globalTestServer.call(globalThis.Networking.APIV2.Internal.SupportedMethod.Post); + globalTestServer.call(globalThis.Networking.APIV2.Internal.SupportedMethodValues.Post); globalTestServer.release(); - const s1 = { tag: APIResult.Tag.Success, param0: "Cześć 🙋‍♂️" }; - const f1 = { tag: APIResult.Tag.Failure, param0: 42 }; - const i1 = { tag: APIResult.Tag.Info }; + const s1 = { tag: exports.APIResult.Tag.Success, param0: "Cześć 🙋‍♂️" }; + const f1 = { tag: exports.APIResult.Tag.Failure, param0: 42 }; + const i1 = { tag: APIResultValues.Tag.Info }; assert.deepEqual(exports.roundtripAPIResult(s1), s1); assert.deepEqual(exports.roundtripAPIResult(f1), f1); assert.deepEqual(exports.roundtripAPIResult(i1), i1); - assert.deepEqual(exports.makeAPIResultSuccess("Test"), { tag: APIResult.Tag.Success, param0: "Test" }); - assert.deepEqual(exports.makeAPIResultSuccess("ok"), { tag: APIResult.Tag.Success, param0: "ok" }); - assert.deepEqual(exports.makeAPIResultFailure(123), { tag: APIResult.Tag.Failure, param0: 123 }); - assert.deepEqual(exports.makeAPIResultInfo(), { tag: APIResult.Tag.Info }); + assert.deepEqual(exports.makeAPIResultSuccess("Test"), { tag: exports.APIResult.Tag.Success, param0: "Test" }); + assert.deepEqual(exports.makeAPIResultSuccess("ok"), { tag: exports.APIResult.Tag.Success, param0: "ok" }); + assert.deepEqual(exports.makeAPIResultFailure(123), { tag: exports.APIResult.Tag.Failure, param0: 123 }); + assert.deepEqual(exports.makeAPIResultInfo(), { tag: APIResultValues.Tag.Info }); - const bTrue = { tag: APIResult.Tag.Flag, param0: true }; - const bFalse = { tag: APIResult.Tag.Flag, param0: false }; + const bTrue = { tag: exports.APIResult.Tag.Flag, param0: true }; + const bFalse = { tag: exports.APIResult.Tag.Flag, param0: false }; assert.deepEqual(exports.makeAPIResultFlag(true), bTrue); assert.deepEqual(exports.makeAPIResultFlag(false), bFalse); const rVal = 3.25; - const r1 = { tag: APIResult.Tag.Rate, param0: rVal }; + const r1 = { tag: exports.APIResult.Tag.Rate, param0: rVal }; assert.deepEqual(exports.roundtripAPIResult(r1), r1); assert.deepEqual(exports.makeAPIResultRate(rVal), r1); const pVal = 3.141592653589793; - const p1 = { tag: APIResult.Tag.Precise, param0: pVal }; + const p1 = { tag: APIResultValues.Tag.Precise, param0: pVal }; assert.deepEqual(exports.roundtripAPIResult(p1), p1); assert.deepEqual(exports.makeAPIResultPrecise(pVal), p1); - const cs1 = { tag: ComplexResult.Tag.Success, param0: "All good!" }; - const ce1 = { tag: ComplexResult.Tag.Error, param0: "Network error", param1: 503 }; - const cl1 = { tag: ComplexResult.Tag.Location, param0: 37.7749, param1: -122.4194, param2: "San Francisco" }; - const cst1 = { tag: ComplexResult.Tag.Status, param0: true, param1: 200, param2: "OK" }; - const cc1 = { tag: ComplexResult.Tag.Coordinates, param0: 10.5, param1: 20.3, param2: 30.7 }; - const ccomp1 = { tag: ComplexResult.Tag.Comprehensive, param0: true, param1: false, param2: 42, param3: 100, param4: 3.14, param5: 2.718, param6: "Hello", param7: "World", param8: "Test" }; - const ci1 = { tag: ComplexResult.Tag.Info }; + const cs1 = { tag: exports.ComplexResult.Tag.Success, param0: "All good!" }; + const ce1 = { tag: exports.ComplexResult.Tag.Error, param0: "Network error", param1: 503 }; + const cl1 = { tag: exports.ComplexResult.Tag.Location, param0: 37.7749, param1: -122.4194, param2: "San Francisco" }; + const cst1 = { tag: exports.ComplexResult.Tag.Status, param0: true, param1: 200, param2: "OK" }; + const cc1 = { tag: exports.ComplexResult.Tag.Coordinates, param0: 10.5, param1: 20.3, param2: 30.7 }; + const ccomp1 = { tag: ComplexResultValues.Tag.Comprehensive, param0: true, param1: false, param2: 42, param3: 100, param4: 3.14, param5: 2.718, param6: "Hello", param7: "World", param8: "Test" }; + const ci1 = { tag: ComplexResultValues.Tag.Info }; assert.deepEqual(exports.roundtripComplexResult(cs1), cs1); assert.deepEqual(exports.roundtripComplexResult(ce1), ce1); @@ -434,35 +517,35 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.deepEqual(exports.roundtripComplexResult(ccomp1), ccomp1); assert.deepEqual(exports.roundtripComplexResult(ci1), ci1); - assert.deepEqual(exports.makeComplexResultSuccess("Great!"), { tag: ComplexResult.Tag.Success, param0: "Great!" }); - assert.deepEqual(exports.makeComplexResultError("Timeout", 408), { tag: ComplexResult.Tag.Error, param0: "Timeout", param1: 408 }); - assert.deepEqual(exports.makeComplexResultLocation(40.7128, -74.0060, "New York"), { tag: ComplexResult.Tag.Location, param0: 40.7128, param1: -74.0060, param2: "New York" }); - assert.deepEqual(exports.makeComplexResultStatus(false, 500, "Internal Server Error"), { tag: ComplexResult.Tag.Status, param0: false, param1: 500, param2: "Internal Server Error" }); - assert.deepEqual(exports.makeComplexResultCoordinates(1.1, 2.2, 3.3), { tag: ComplexResult.Tag.Coordinates, param0: 1.1, param1: 2.2, param2: 3.3 }); - assert.deepEqual(exports.makeComplexResultComprehensive(true, false, 10, 20, 1.5, 2.5, "First", "Second", "Third"), { tag: ComplexResult.Tag.Comprehensive, param0: true, param1: false, param2: 10, param3: 20, param4: 1.5, param5: 2.5, param6: "First", param7: "Second", param8: "Third" }); - assert.deepEqual(exports.makeComplexResultInfo(), { tag: ComplexResult.Tag.Info }); + assert.deepEqual(exports.makeComplexResultSuccess("Great!"), { tag: exports.ComplexResult.Tag.Success, param0: "Great!" }); + assert.deepEqual(exports.makeComplexResultError("Timeout", 408), { tag: exports.ComplexResult.Tag.Error, param0: "Timeout", param1: 408 }); + assert.deepEqual(exports.makeComplexResultLocation(40.7128, -74.0060, "New York"), { tag: exports.ComplexResult.Tag.Location, param0: 40.7128, param1: -74.0060, param2: "New York" }); + assert.deepEqual(exports.makeComplexResultStatus(false, 500, "Internal Server Error"), { tag: exports.ComplexResult.Tag.Status, param0: false, param1: 500, param2: "Internal Server Error" }); + assert.deepEqual(exports.makeComplexResultCoordinates(1.1, 2.2, 3.3), { tag: exports.ComplexResult.Tag.Coordinates, param0: 1.1, param1: 2.2, param2: 3.3 }); + assert.deepEqual(exports.makeComplexResultComprehensive(true, false, 10, 20, 1.5, 2.5, "First", "Second", "Third"), { tag: exports.ComplexResult.Tag.Comprehensive, param0: true, param1: false, param2: 10, param3: 20, param4: 1.5, param5: 2.5, param6: "First", param7: "Second", param8: "Third" }); + assert.deepEqual(exports.makeComplexResultInfo(), { tag: exports.ComplexResult.Tag.Info }); - const urSuccess = { tag: globalThis.Utilities.Result.Tag.Success, param0: "Utility operation completed" }; - const urFailure = { tag: globalThis.Utilities.Result.Tag.Failure, param0: "Utility error occurred", param1: 500 }; - const urStatus = { tag: globalThis.Utilities.Result.Tag.Status, param0: true, param1: 200, param2: "Utility status OK" }; + const urSuccess = { tag: globalThis.Utilities.ResultValues.Tag.Success, param0: "Utility operation completed" }; + const urFailure = { tag: globalThis.Utilities.ResultValues.Tag.Failure, param0: "Utility error occurred", param1: 500 }; + const urStatus = { tag: globalThis.Utilities.ResultValues.Tag.Status, param0: true, param1: 200, param2: "Utility status OK" }; assert.deepEqual(exports.roundtripUtilitiesResult(urSuccess), urSuccess); assert.deepEqual(exports.roundtripUtilitiesResult(urFailure), urFailure); assert.deepEqual(exports.roundtripUtilitiesResult(urStatus), urStatus); - assert.deepEqual(exports.makeUtilitiesResultSuccess("Test"), { tag: globalThis.Utilities.Result.Tag.Success, param0: "Test" }); - assert.deepEqual(exports.makeUtilitiesResultSuccess("ok"), { tag: globalThis.Utilities.Result.Tag.Success, param0: "ok" }); - assert.deepEqual(exports.makeUtilitiesResultFailure("Error", 123), { tag: globalThis.Utilities.Result.Tag.Failure, param0: "Error", param1: 123 }); - assert.deepEqual(exports.makeUtilitiesResultStatus(true, 200, "OK"), { tag: globalThis.Utilities.Result.Tag.Status, param0: true, param1: 200, param2: "OK" }); + assert.deepEqual(exports.makeUtilitiesResultSuccess("Test"), { tag: globalThis.Utilities.ResultValues.Tag.Success, param0: "Test" }); + assert.deepEqual(exports.makeUtilitiesResultSuccess("ok"), { tag: globalThis.Utilities.ResultValues.Tag.Success, param0: "ok" }); + assert.deepEqual(exports.makeUtilitiesResultFailure("Error", 123), { tag: globalThis.Utilities.ResultValues.Tag.Failure, param0: "Error", param1: 123 }); + assert.deepEqual(exports.makeUtilitiesResultStatus(true, 200, "OK"), { tag: globalThis.Utilities.ResultValues.Tag.Status, param0: true, param1: 200, param2: "OK" }); - const nrSuccess = { tag: globalThis.API.NetworkingResult.Tag.Success, param0: "Network request successful" }; - const nrFailure = { tag: globalThis.API.NetworkingResult.Tag.Failure, param0: "Network timeout", param1: 408 }; + const nrSuccess = { tag: globalThis.API.NetworkingResultValues.Tag.Success, param0: "Network request successful" }; + const nrFailure = { tag: globalThis.API.NetworkingResultValues.Tag.Failure, param0: "Network timeout", param1: 408 }; assert.deepEqual(exports.roundtripAPINetworkingResult(nrSuccess), nrSuccess); assert.deepEqual(exports.roundtripAPINetworkingResult(nrFailure), nrFailure); - assert.deepEqual(exports.makeAPINetworkingResultSuccess("Connected"), { tag: globalThis.API.NetworkingResult.Tag.Success, param0: "Connected" }); - assert.deepEqual(exports.makeAPINetworkingResultFailure("Timeout", 408), { tag: globalThis.API.NetworkingResult.Tag.Failure, param0: "Timeout", param1: 408 }); + assert.deepEqual(exports.makeAPINetworkingResultSuccess("Connected"), { tag: globalThis.API.NetworkingResultValues.Tag.Success, param0: "Connected" }); + assert.deepEqual(exports.makeAPINetworkingResultFailure("Timeout", 408), { tag: globalThis.API.NetworkingResultValues.Tag.Failure, param0: "Timeout", param1: 408 }); assert.equal(exports.roundTripOptionalString(null), null); assert.equal(exports.roundTripOptionalInt(null), null); @@ -486,12 +569,12 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(exports.roundTripOptionalWithSpaces(1.618), 1.618); assert.equal(exports.roundTripOptionalTypeAlias(null), null); assert.equal(exports.roundTripOptionalTypeAlias(25), 25); - assert.equal(exports.roundTripOptionalStatus(Status.Success), Status.Success); - assert.equal(exports.roundTripOptionalTheme(Theme.Light), Theme.Light); - assert.equal(exports.roundTripOptionalHttpStatus(HttpStatus.Ok), HttpStatus.Ok); + assert.equal(exports.roundTripOptionalStatus(exports.Status.Success), StatusValues.Success); + assert.equal(exports.roundTripOptionalTheme(exports.Theme.Light), ThemeValues.Light); + assert.equal(exports.roundTripOptionalHttpStatus(exports.HttpStatus.Ok), HttpStatusValues.Ok); assert.equal(exports.roundTripOptionalTSDirection(TSDirection.North), TSDirection.North); assert.equal(exports.roundTripOptionalTSTheme(TSTheme.Light), TSTheme.Light); - assert.equal(exports.roundTripOptionalNetworkingAPIMethod(globalThis.Networking.API.Method.Get), globalThis.Networking.API.Method.Get); + assert.equal(exports.roundTripOptionalNetworkingAPIMethod(globalThis.Networking.API.MethodValues.Get), globalThis.Networking.API.MethodValues.Get); assert.deepEqual(exports.roundTripOptionalAPIResult(p1), p1); assert.deepEqual(exports.roundTripOptionalComplexResult(cl1), cl1); @@ -529,16 +612,16 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { testPropertyGreeter.release(); optionalsHolder.release(); - const aor1 = { tag: APIOptionalResult.Tag.Success, param0: "hello world" }; - const aor2 = { tag: APIOptionalResult.Tag.Success, param0: null }; - const aor3 = { tag: APIOptionalResult.Tag.Failure, param0: 404, param1: true }; - const aor4 = { tag: APIOptionalResult.Tag.Failure, param0: 404, param1: null }; - const aor5 = { tag: APIOptionalResult.Tag.Failure, param0: null, param1: null }; - const aor6 = { tag: APIOptionalResult.Tag.Status, param0: true, param1: 200, param2: "OK" }; - const aor7 = { tag: APIOptionalResult.Tag.Status, param0: true, param1: null, param2: "Partial" }; - const aor8 = { tag: APIOptionalResult.Tag.Status, param0: null, param1: null, param2: "Zero" }; - const aor9 = { tag: APIOptionalResult.Tag.Status, param0: false, param1: 500, param2: null }; - const aor10 = { tag: APIOptionalResult.Tag.Status, param0: null, param1: 0, param2: "Zero" }; + const aor1 = { tag: APIOptionalResultValues.Tag.Success, param0: "hello world" }; + const aor2 = { tag: APIOptionalResultValues.Tag.Success, param0: null }; + const aor3 = { tag: APIOptionalResultValues.Tag.Failure, param0: 404, param1: true }; + const aor4 = { tag: APIOptionalResultValues.Tag.Failure, param0: 404, param1: null }; + const aor5 = { tag: APIOptionalResultValues.Tag.Failure, param0: null, param1: null }; + const aor6 = { tag: APIOptionalResultValues.Tag.Status, param0: true, param1: 200, param2: "OK" }; + const aor7 = { tag: APIOptionalResultValues.Tag.Status, param0: true, param1: null, param2: "Partial" }; + const aor8 = { tag: APIOptionalResultValues.Tag.Status, param0: null, param1: null, param2: "Zero" }; + const aor9 = { tag: APIOptionalResultValues.Tag.Status, param0: false, param1: 500, param2: null }; + const aor10 = { tag: APIOptionalResultValues.Tag.Status, param0: null, param1: 0, param2: "Zero" }; assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor1), aor1); assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor2), aor2); @@ -551,6 +634,14 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor9), aor9); assert.deepEqual(exports.roundTripOptionalAPIOptionalResult(aor10), aor10); assert.equal(exports.roundTripOptionalAPIOptionalResult(null), null); + + assert.equal(exports.MathUtils.add(2147483647, 0), 2147483647); + assert.equal(exports.StaticCalculator.roundtrip(42), 42); + assert.equal(StaticCalculatorValues.Scientific, 0); + assert.equal(StaticCalculatorValues.Basic, 1); + assert.equal(StaticCalculatorValues.Scientific, exports.StaticCalculator.Scientific); + assert.equal(StaticCalculatorValues.Basic, exports.StaticCalculator.Basic); + assert.equal(globalThis.StaticUtils.Nested.roundtrip("hello world"), "hello world"); } /** @param {import('./../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} exports */