From 84624af11aa737e607a0ae1369865f76925a0167 Mon Sep 17 00:00:00 2001 From: William Taylor Date: Tue, 30 Jun 2026 09:55:30 +1000 Subject: [PATCH 1/3] BridgeJS: Merge nested types correctly --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 565 ++++++++++-------- .../MacroSwift/ClassWithNestedTypes.swift | 34 ++ .../MacroSwift/StructWithNestedTypes.swift | 52 ++ .../ClassWithNestedTypes.json | 218 +++++++ .../ClassWithNestedTypes.swift | 177 ++++++ .../StructWithNestedTypes.json | 337 +++++++++++ .../StructWithNestedTypes.swift | 249 ++++++++ .../BridgeJSLinkTests/Alias.d.ts | 14 +- .../__Snapshots__/BridgeJSLinkTests/Alias.js | 4 +- .../BridgeJSLinkTests/AliasInClosure.d.ts | 6 +- .../BridgeJSLinkTests/AliasInClosure.js | 2 +- .../BridgeJSLinkTests/ArrayTypes.d.ts | 10 +- .../BridgeJSLinkTests/ArrayTypes.js | 4 +- .../ClassWithNestedTypes.d.ts | 51 ++ .../BridgeJSLinkTests/ClassWithNestedTypes.js | 375 ++++++++++++ .../BridgeJSLinkTests/DefaultParameters.d.ts | 34 +- .../BridgeJSLinkTests/DefaultParameters.js | 6 +- .../BridgeJSLinkTests/DictionaryTypes.d.ts | 4 +- .../BridgeJSLinkTests/DictionaryTypes.js | 2 +- .../BridgeJSLinkTests/DocComments.d.ts | 14 +- .../BridgeJSLinkTests/DocComments.js | 2 +- .../BridgeJSLinkTests/EnumAlias.d.ts | 4 +- .../BridgeJSLinkTests/EnumAlias.js | 2 +- .../EnumAssociatedValue.d.ts | 4 +- .../BridgeJSLinkTests/EnumAssociatedValue.js | 2 +- .../EnumNamespace.Global.d.ts | 32 +- .../BridgeJSLinkTests/EnumNamespace.Global.js | 4 +- .../BridgeJSLinkTests/EnumNamespace.d.ts | 12 +- .../BridgeJSLinkTests/EnumNamespace.js | 4 +- .../IdentityModeClass.ConfigPointer.d.ts | 10 +- .../IdentityModeClass.ConfigPointer.js | 2 +- .../IdentityModeClass.PerClass.d.ts | 10 +- .../IdentityModeClass.PerClass.js | 2 +- .../BridgeJSLinkTests/IdentityModeClass.d.ts | 10 +- .../BridgeJSLinkTests/IdentityModeClass.js | 2 +- .../BridgeJSLinkTests/JSValue.d.ts | 6 +- .../BridgeJSLinkTests/JSValue.js | 2 +- .../BridgeJSLinkTests/MixedGlobal.d.ts | 4 +- .../BridgeJSLinkTests/MixedGlobal.js | 2 +- .../BridgeJSLinkTests/MixedModules.d.ts | 10 +- .../BridgeJSLinkTests/MixedModules.js | 4 +- .../BridgeJSLinkTests/MixedPrivate.d.ts | 4 +- .../BridgeJSLinkTests/MixedPrivate.js | 2 +- .../BridgeJSLinkTests/Namespaces.Global.d.ts | 8 +- .../BridgeJSLinkTests/Namespaces.d.ts | 8 +- .../BridgeJSLinkTests/NestedType.d.ts | 6 +- .../BridgeJSLinkTests/NestedType.js | 6 +- .../BridgeJSLinkTests/Optionals.d.ts | 12 +- .../BridgeJSLinkTests/Optionals.js | 4 +- .../BridgeJSLinkTests/PropertyTypes.d.ts | 6 +- .../BridgeJSLinkTests/PropertyTypes.js | 2 +- .../BridgeJSLinkTests/Protocol.d.ts | 18 +- .../BridgeJSLinkTests/Protocol.js | 6 +- .../BridgeJSLinkTests/ProtocolInClosure.d.ts | 6 +- .../BridgeJSLinkTests/ProtocolInClosure.js | 2 +- .../StaticFunctions.Global.d.ts | 6 +- .../StaticFunctions.Global.js | 2 +- .../BridgeJSLinkTests/StaticFunctions.d.ts | 6 +- .../BridgeJSLinkTests/StaticFunctions.js | 2 +- .../StaticProperties.Global.d.ts | 4 +- .../StaticProperties.Global.js | 2 +- .../BridgeJSLinkTests/StaticProperties.d.ts | 4 +- .../BridgeJSLinkTests/StaticProperties.js | 2 +- .../StructWithNestedTypes.d.ts | 73 +++ .../StructWithNestedTypes.js | 364 +++++++++++ .../BridgeJSLinkTests/SwiftClass.d.ts | 10 +- .../BridgeJSLinkTests/SwiftClass.js | 6 +- .../BridgeJSLinkTests/SwiftClosure.d.ts | 14 +- .../BridgeJSLinkTests/SwiftClosure.js | 4 +- .../BridgeJSLinkTests/SwiftStruct.d.ts | 18 +- .../BridgeJSLinkTests/SwiftStruct.js | 42 +- .../BridgeJSLinkTests/UnsafePointer.d.ts | 2 +- .../BridgeJSRuntimeTests/ExportAPITests.swift | 21 + .../Generated/BridgeJS.swift | 113 ++++ .../Generated/JavaScript/BridgeJS.json | 111 ++++ Tests/prelude.mjs | 8 + 76 files changed, 2706 insertions(+), 486 deletions(-) create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ClassWithNestedTypes.swift create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StructWithNestedTypes.swift create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.json create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.swift create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.json create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.swift create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.d.ts create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.d.ts create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index ed9eb950f..4706b14a4 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -168,7 +168,6 @@ public struct BridgeJSLink { var classLines: [String] = [] var dtsExportLines: [String] = [] var dtsClassLines: [String] = [] - var namespacedClassDtsExportEntries: [String: [String]] = [:] var topLevelTypeLines: [String] = [] var topLevelDtsTypeLines: [String] = [] var importObjectBuilders: [ImportObjectBuilder] = [] @@ -198,16 +197,9 @@ public struct BridgeJSLink { guard let skeleton = unified.exported else { continue } // Process classes for klass in skeleton.classes { - let (jsType, dtsType, dtsExportEntry) = try renderExportedClass(klass) + let (jsType, dtsType) = try renderExportedClass(klass) data.classLines.append(contentsOf: jsType) data.dtsClassLines.append(contentsOf: dtsType) - - if klass.namespace == nil { - data.exportsLines.append("\(klass.name),") - data.dtsExportLines.append(contentsOf: dtsExportEntry) - } else { - data.namespacedClassDtsExportEntries[klass.name] = dtsExportEntry - } } // Process enums - collect top-level definitions and export entries @@ -230,16 +222,10 @@ public struct BridgeJSLink { } } - var structExportEntries: [(js: [String], dts: [String])] = [] - for structDefinition in skeleton.structs { - let (jsStruct, dtsType, dtsExportEntry) = try renderExportedStruct(structDefinition) - if structDefinition.namespace == nil { - data.topLevelDtsTypeLines.append(contentsOf: dtsType) - } - - if structDefinition.namespace == nil && (!jsStruct.isEmpty || !dtsExportEntry.isEmpty) { - structExportEntries.append((js: jsStruct, dts: dtsExportEntry)) - } + for structDefinition in skeleton.structs where structDefinition.namespace == nil { + data.topLevelDtsTypeLines.append( + contentsOf: renderExportedStructInterface(structDefinition) + ) } // Process functions @@ -257,11 +243,6 @@ public struct BridgeJSLink { data.exportsLines.append(contentsOf: entry.js) data.dtsExportLines.append(contentsOf: entry.dts) } - - for entry in structExportEntries { - data.exportsLines.append(contentsOf: entry.js) - data.dtsExportLines.append(contentsOf: entry.dts) - } } // Process imported skeletons @@ -1014,6 +995,12 @@ public struct BridgeJSLink { }, renderDocCallback: { documentation, parameters in self.renderJSDoc(documentation: documentation, parameters: parameters) + }, + renderStructInterface: { structDef in + self.renderExportedStructInterface(structDef) + }, + renderClassDeclaration: { klass in + self.renderExportedClassDeclaration(klass) } ) printer.write(lines: namespaceDeclarationsLines) @@ -1027,7 +1014,10 @@ public struct BridgeJSLink { let hierarchicalExportLines = namespaceBuilder.buildHierarchicalExportsType( exportedSkeletons: exportedSkeletons, renderClassEntry: { klass in - data.namespacedClassDtsExportEntries[klass.name] ?? [] + self.renderExportedClassExportEntryBody(klass) + }, + renderStructEntry: { structDef in + self.renderExportedStructExportEntry(structDef) }, renderFunctionEntry: { function in self.renderJSDoc(documentation: function.documentation, parameters: function.parameters) @@ -1341,6 +1331,9 @@ public struct BridgeJSLink { renderFunctionImpl: { function in let (js, _) = try self.renderExportedFunction(function: function) return js + }, + renderStructImpl: { structDef in + try self.renderExportedStructJsBody(structDef) } ) printer.write(lines: hierarchicalLines) @@ -1599,22 +1592,16 @@ public struct BridgeJSLink { .replacingOccurrences(of: "\"", with: "\\\"") } - func renderExportedStruct( + func renderExportedStructInterface( _ structDefinition: ExportedStruct - ) throws -> (js: [String], dtsType: [String], dtsExportEntry: [String]) { - let structName = structDefinition.name - let hasConstructor = structDefinition.constructor != nil - let staticMethods = structDefinition.methods.filter { $0.effects.isStatic } - let staticProperties = structDefinition.properties.filter { $0.isStatic } - + ) -> [String] { let dtsTypePrinter = CodeFragmentPrinter() for line in renderJSDoc(documentation: structDefinition.documentation, parameters: []) { dtsTypePrinter.write(line) } - dtsTypePrinter.write("export interface \(structName) {") - let instanceProps = structDefinition.properties.filter { !$0.isStatic } + dtsTypePrinter.write("export interface \(structDefinition.name) {") dtsTypePrinter.indent { - for property in instanceProps { + for property in structDefinition.properties where !property.isStatic { let tsType = resolveTypeScriptType(property.type) for line in renderJSDoc(documentation: property.documentation, parameters: []) { dtsTypePrinter.write(line) @@ -1636,87 +1623,78 @@ public struct BridgeJSLink { } } dtsTypePrinter.write("}") + return dtsTypePrinter.lines + } - guard hasConstructor || !staticMethods.isEmpty || !staticProperties.isEmpty else { - return (js: [], dtsType: dtsTypePrinter.lines, dtsExportEntry: []) + func renderExportedStructExportEntry( + _ structDefinition: ExportedStruct + ) -> [String] { + let dtsExportEntryPrinter = CodeFragmentPrinter() + if let constructor = structDefinition.constructor { + let jsDocLines = renderJSDoc(documentation: constructor.documentation, parameters: constructor.parameters) + dtsExportEntryPrinter.write(lines: jsDocLines) + dtsExportEntryPrinter.write( + "init\(renderTSSignature(parameters: constructor.parameters, returnType: .swiftStruct(structDefinition.swiftCallName), effects: constructor.effects));" + ) + } + for property in structDefinition.properties where property.isStatic { + let readonly = property.isReadonly ? "readonly " : "" + dtsExportEntryPrinter.write(lines: renderJSDoc(documentation: property.documentation, parameters: [])) + dtsExportEntryPrinter.write("\(readonly)\(property.name): \(resolveTypeScriptType(property.type));") + } + for method in structDefinition.methods where method.effects.isStatic { + let jsDocLines = renderJSDoc(documentation: method.documentation, parameters: method.parameters) + dtsExportEntryPrinter.write(lines: jsDocLines) + dtsExportEntryPrinter.write( + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) } - let jsPrinter = CodeFragmentPrinter() - jsPrinter.write("\(structName): {") - try jsPrinter.indent { - // Constructor as 'init' function - if let constructor = structDefinition.constructor { - let thunkBuilder = ExportedThunkBuilder( - effects: constructor.effects, - intrinsicRegistry: intrinsicRegistry - ) - for param in constructor.parameters { - try thunkBuilder.lowerParameter(param: param) - } - let returnExpr = try thunkBuilder.call( - abiName: constructor.abiName, - returnType: .swiftStruct(structDefinition.swiftCallName) - ) + return dtsExportEntryPrinter.lines + } - let constructorPrinter = CodeFragmentPrinter() - let paramList = DefaultValueUtils.formatParameterList(constructor.parameters) - constructorPrinter.write("init: function(\(paramList)) {") - constructorPrinter.indent { - thunkBuilder.renderFunctionBody(into: constructorPrinter, returnExpr: returnExpr) - } - constructorPrinter.write("},") - jsPrinter.write(lines: constructorPrinter.lines) + func renderExportedStructJsBody( + _ structDefinition: ExportedStruct + ) throws -> [String] { + let jsPrinter = CodeFragmentPrinter() + // Constructor as 'init' function + if let constructor = structDefinition.constructor { + let thunkBuilder = ExportedThunkBuilder( + effects: constructor.effects, + intrinsicRegistry: intrinsicRegistry + ) + for param in constructor.parameters { + try thunkBuilder.lowerParameter(param: param) } + let returnExpr = try thunkBuilder.call( + abiName: constructor.abiName, + returnType: .swiftStruct(structDefinition.swiftCallName) + ) - for property in staticProperties { - let propertyLines = try renderStaticPropertyForExportObject( - property: property, - className: structName - ) - jsPrinter.write(lines: propertyLines) + let constructorPrinter = CodeFragmentPrinter() + let paramList = DefaultValueUtils.formatParameterList(constructor.parameters) + constructorPrinter.write("init: function(\(paramList)) {") + constructorPrinter.indent { + thunkBuilder.renderFunctionBody(into: constructorPrinter, returnExpr: returnExpr) } + constructorPrinter.write("},") + jsPrinter.write(lines: constructorPrinter.lines) + } - for method in staticMethods { - let methodLines = try renderStaticMethodForExportObject(method: method) - jsPrinter.write(lines: methodLines) - } + for property in structDefinition.properties where property.isStatic { + let propertyLines = try renderStaticPropertyForExportObject( + property: property, + className: structDefinition.name + ) + jsPrinter.write(lines: propertyLines) } - jsPrinter.write("},") - let dtsExportEntryPrinter = CodeFragmentPrinter() - dtsExportEntryPrinter.write("\(structName): {") - dtsExportEntryPrinter.indent { - if let constructor = structDefinition.constructor { - let jsDocLines = renderJSDoc( - documentation: constructor.documentation, - parameters: constructor.parameters - ) - dtsExportEntryPrinter.write(lines: jsDocLines) - dtsExportEntryPrinter.write( - "init\(renderTSSignature(parameters: constructor.parameters, returnType: .swiftStruct(structDefinition.swiftCallName), effects: constructor.effects));" - ) - } - for property in staticProperties { - let readonly = property.isReadonly ? "readonly " : "" - for line in renderJSDoc(documentation: property.documentation, parameters: []) { - dtsExportEntryPrinter.write(line) - } - dtsExportEntryPrinter.write("\(readonly)\(property.name): \(resolveTypeScriptType(property.type));") - } - for method in staticMethods { - let jsDocLines = renderJSDoc( - documentation: method.documentation, - parameters: method.parameters - ) - dtsExportEntryPrinter.write(lines: jsDocLines) - dtsExportEntryPrinter.write( - "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" - ) - } + for method in structDefinition.methods where method.effects.isStatic { + let methodLines = try renderStaticMethodForExportObject(method: method) + jsPrinter.write(lines: methodLines) } - dtsExportEntryPrinter.write("}") - return (js: jsPrinter.lines, dtsType: dtsTypePrinter.lines, dtsExportEntry: dtsExportEntryPrinter.lines) + return jsPrinter.lines } func renderExportedEnum( @@ -2118,16 +2096,14 @@ extension BridgeJSLink { func renderExportedClass( _ klass: ExportedClass - ) throws -> (js: [String], dtsType: [String], dtsExportEntry: [String]) { + ) throws -> (js: [String], dtsType: [String]) { let jsPrinter = CodeFragmentPrinter() let dtsTypePrinter = CodeFragmentPrinter() - let dtsExportEntryPrinter = CodeFragmentPrinter() for line in renderJSDoc(documentation: klass.documentation, parameters: []) { dtsTypePrinter.write(line) } dtsTypePrinter.write("export interface \(klass.name) extends SwiftHeapObject {") - dtsExportEntryPrinter.write("\(klass.name): {") jsPrinter.write("class \(klass.name) extends SwiftHeapObject {") // Per-class identity mode: determine at codegen time whether this class uses identity caching @@ -2176,19 +2152,6 @@ extension BridgeJSLink { } jsPrinter.write("}") } - - dtsExportEntryPrinter.indent { - let jsDocLines = renderJSDoc( - documentation: constructor.documentation, - parameters: constructor.parameters - ) - for line in jsDocLines { - dtsExportEntryPrinter.write(line) - } - dtsExportEntryPrinter.write( - "new\(renderTSSignature(parameters: constructor.parameters, returnType: .swiftHeapObject(klass.name), effects: constructor.effects));" - ) - } } for method in klass.methods { @@ -2212,18 +2175,6 @@ extension BridgeJSLink { ) ) } - - dtsExportEntryPrinter.indent { - for line in renderJSDoc( - documentation: method.documentation, - parameters: method.parameters - ) { - dtsExportEntryPrinter.write(line) - } - dtsExportEntryPrinter.write( - "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" - ) - } } else { let thunkBuilder = ExportedThunkBuilder( effects: method.effects, @@ -2267,15 +2218,76 @@ extension BridgeJSLink { className: klass.abiName, isStatic: property.isStatic, jsPrinter: jsPrinter, - dtsPrinter: property.isStatic ? dtsExportEntryPrinter : dtsTypePrinter + dtsPrinter: dtsTypePrinter ) } jsPrinter.write("}") dtsTypePrinter.write("}") - dtsExportEntryPrinter.write("}") - return (jsPrinter.lines, dtsTypePrinter.lines, dtsExportEntryPrinter.lines) + return (jsPrinter.lines, dtsTypePrinter.lines) + } + + func renderExportedClassExportEntryBody( + _ klass: ExportedClass + ) -> [String] { + let printer = CodeFragmentPrinter() + if let constructor = klass.constructor { + printer.write( + lines: renderJSDoc(documentation: constructor.documentation, parameters: constructor.parameters) + ) + printer.write( + "new\(renderTSSignature(parameters: constructor.parameters, returnType: .swiftHeapObject(klass.name), effects: constructor.effects));" + ) + } + for method in klass.methods where method.effects.isStatic { + printer.write(lines: renderJSDoc(documentation: method.documentation, parameters: method.parameters)) + printer.write( + "\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) + } + for property in klass.properties where property.isStatic { + let readonly = property.isReadonly ? "readonly " : "" + printer.write(lines: renderJSDoc(documentation: property.documentation, parameters: [])) + printer.write("\(readonly)\(property.name): \(resolveTypeScriptType(property.type));") + } + return printer.lines + } + + func renderExportedClassDeclaration( + _ klass: ExportedClass + ) -> [String] { + let printer = CodeFragmentPrinter() + printer.write(lines: renderJSDoc(documentation: klass.documentation, parameters: [])) + printer.write("class \(klass.name) {") + printer.indent { + if let constructor = klass.constructor { + let paramSignatures = constructor.parameters.map { param in + let optional = param.hasDefault ? "?" : "" + return "\(param.name)\(optional): \(param.type.tsType)" + } + printer.write( + lines: renderJSDoc(documentation: constructor.documentation, parameters: constructor.parameters) + ) + printer.write("constructor(\(paramSignatures.joined(separator: ", ")));") + } + for method in klass.methods.sorted(by: { $0.name < $1.name }) { + let staticKeyword = method.effects.isStatic ? "static " : "" + printer.write(lines: renderJSDoc(documentation: method.documentation, parameters: method.parameters)) + printer.write( + "\(staticKeyword)\(method.name)\(renderTSSignature(parameters: method.parameters, returnType: method.returnType, effects: method.effects));" + ) + } + for property in klass.properties.sorted(by: { $0.name < $1.name }) { + let staticKeyword = property.isStatic ? "static " : "" + let readonly = property.isReadonly ? "readonly " : "" + printer.write(lines: renderJSDoc(documentation: property.documentation, parameters: [])) + printer.write("\(staticKeyword)\(readonly)\(property.name): \(resolveTypeScriptType(property.type));") + } + printer.write("release(): void;") + } + printer.write("}") + return printer.lines } private func renderClassProperty( @@ -2338,12 +2350,14 @@ extension BridgeJSLink { } // Add instance property to TypeScript interface definition - let readonly = property.isReadonly ? "readonly " : "" - dtsPrinter.indent { - for line in renderJSDoc(documentation: property.documentation, parameters: []) { - dtsPrinter.write(line) + if !isStatic { + let readonly = property.isReadonly ? "readonly " : "" + dtsPrinter.indent { + for line in renderJSDoc(documentation: property.documentation, parameters: []) { + dtsPrinter.write(line) + } + dtsPrinter.write("\(readonly)\(property.name): \(resolveTypeScriptType(property.type));") } - dtsPrinter.write("\(readonly)\(property.name): \(property.type.tsType);") } } @@ -2760,17 +2774,27 @@ extension BridgeJSLink { return printer.lines } + private enum NodeDeclaration { + case classType(ExportedClass) + case structType(ExportedStruct) + } + private struct NamespaceContent { + // The declaration this node represents + var declaration: NodeDeclaration? + + // Contents var functions: [ExportedFunction] = [] - var classes: [ExportedClass] = [] var enums: [ExportedEnum] = [] - var structs: [ExportedStruct] = [] var staticProperties: [ExportedProperty] = [] + + // Output var functionJsLines: [(name: String, lines: [String])] = [] var functionDtsLines: [(name: String, lines: [String])] = [] - var classDtsLines: [(name: String, lines: [String])] = [] + var declarationDtsLines: [String] = [] var enumDtsLines: [(name: String, line: String)] = [] var staticPropertyDtsLines: [(name: String, lines: [String])] = [] + var structJsLines: [String] = [] var propertyJsLines: [String] = [] } @@ -2791,6 +2815,16 @@ extension BridgeJSLink { children[childName] = newChild return newChild } + + var classDeclaration: ExportedClass? { + if case .classType(let klass) = content.declaration { return klass } + return nil + } + + var structDeclaration: ExportedStruct? { + if case .structType(let structDef) = content.declaration { return structDef } + return nil + } } private func buildExportsTree( @@ -2806,20 +2840,20 @@ extension BridgeJSLink { currentNode.content.functions.append(function) } - for klass in skeleton.classes where klass.namespace != nil { + for klass in skeleton.classes { var currentNode = rootNode - for part in klass.namespace! { + for part in (klass.namespace ?? []) + [klass.name] { currentNode = currentNode.addChild(part) } - currentNode.content.classes.append(klass) + currentNode.content.declaration = .classType(klass) } - for structDef in skeleton.structs where structDef.namespace != nil { + for structDef in skeleton.structs { var currentNode = rootNode - for part in structDef.namespace! { + for part in (structDef.namespace ?? []) + [structDef.name] { currentNode = currentNode.addChild(part) } - currentNode.content.structs.append(structDef) + currentNode.content.declaration = .structType(structDef) } for enumDef in skeleton.enums where enumDef.namespace != nil && enumDef.enumType != .namespace { @@ -2854,6 +2888,7 @@ extension BridgeJSLink { fileprivate func buildHierarchicalExportsType( exportedSkeletons: [ExportedSkeleton], renderClassEntry: (ExportedClass) -> [String], + renderStructEntry: (ExportedStruct) -> [String], renderFunctionEntry: (ExportedFunction) -> [String], renderPropertyEntry: (ExportedProperty) -> [String] ) -> [String] { @@ -2866,6 +2901,7 @@ extension BridgeJSLink { populateTypeScriptExportLines( node: node, renderClassEntry: renderClassEntry, + renderStructEntry: renderStructEntry, renderFunctionEntry: renderFunctionEntry, renderPropertyEntry: renderPropertyEntry ) @@ -2879,6 +2915,7 @@ extension BridgeJSLink { private func populateTypeScriptExportLines( node: NamespaceNode, renderClassEntry: (ExportedClass) -> [String], + renderStructEntry: (ExportedStruct) -> [String], renderFunctionEntry: (ExportedFunction) -> [String], renderPropertyEntry: (ExportedProperty) -> [String] ) { @@ -2886,9 +2923,13 @@ extension BridgeJSLink { node.content.functionDtsLines.append((function.name, renderFunctionEntry(function))) } - for klass in node.content.classes { - let entry = renderClassEntry(klass) - node.content.classDtsLines.append((klass.name, entry)) + switch node.content.declaration { + case .classType(let klass): + node.content.declarationDtsLines = renderClassEntry(klass) + case .structType(let structDef): + node.content.declarationDtsLines = renderStructEntry(structDef) + case nil: + break } for property in node.content.staticProperties { @@ -2903,6 +2944,7 @@ extension BridgeJSLink { populateTypeScriptExportLines( node: childNode, renderClassEntry: renderClassEntry, + renderStructEntry: renderStructEntry, renderFunctionEntry: renderFunctionEntry, renderPropertyEntry: renderPropertyEntry ) @@ -2912,36 +2954,52 @@ extension BridgeJSLink { fileprivate func buildHierarchicalExportsObject( exportedSkeletons: [ExportedSkeleton], intrinsicRegistry: JSIntrinsicRegistry, - renderFunctionImpl: (ExportedFunction) throws -> [String] + renderFunctionImpl: (ExportedFunction) throws -> [String], + renderStructImpl: (ExportedStruct) throws -> [String] ) throws -> [String] { let printer = CodeFragmentPrinter() let rootNode = NamespaceNode(name: "") buildExportsTree(rootNode: rootNode, exportedSkeletons: exportedSkeletons) - try populateJavaScriptExportLines(node: rootNode, renderFunctionImpl: renderFunctionImpl) + try populateJavaScriptExportLines( + node: rootNode, + renderFunctionImpl: renderFunctionImpl, + renderStructImpl: renderStructImpl + ) try populatePropertyImplementations( node: rootNode, intrinsicRegistry: intrinsicRegistry ) - printExportsObjectHierarchy(node: rootNode, printer: printer, currentPath: []) + printExportsObjectHierarchy(node: rootNode, printer: printer) return printer.lines } private func populateJavaScriptExportLines( node: NamespaceNode, - renderFunctionImpl: (ExportedFunction) throws -> [String] + renderFunctionImpl: (ExportedFunction) throws -> [String], + renderStructImpl: (ExportedStruct) throws -> [String] ) throws { for function in node.content.functions { let impl = try renderFunctionImpl(function) node.content.functionJsLines.append((function.name, impl)) } + switch node.content.declaration { + case .structType(let structDef): + node.content.structJsLines = try renderStructImpl(structDef) + case .classType, nil: break + } + for (_, childNode) in node.children { - try populateJavaScriptExportLines(node: childNode, renderFunctionImpl: renderFunctionImpl) + try populateJavaScriptExportLines( + node: childNode, + renderFunctionImpl: renderFunctionImpl, + renderStructImpl: renderStructImpl + ) } } @@ -3011,9 +3069,21 @@ extension BridgeJSLink { } private func hasExportContent(node: NamespaceNode) -> Bool { - if !node.content.classDtsLines.isEmpty || !node.content.enumDtsLines.isEmpty - || !node.content.functionDtsLines.isEmpty || !node.content.staticProperties.isEmpty - { + let content = node.content + switch content.declaration { + case .classType: + return true + case .structType(let structDef): + if structDef.constructor != nil + || structDef.properties.contains(where: \.isStatic) + || structDef.methods.contains(where: \.effects.isStatic) + { + return true + } + case nil: + break + } + if !content.enums.isEmpty || !content.functions.isEmpty || !content.staticProperties.isEmpty { return true } return node.children.values.contains(where: { hasExportContent(node: $0) }) @@ -3024,9 +3094,7 @@ extension BridgeJSLink { guard hasExportContent(node: childNode) else { continue } printer.write("\(childName): {") printer.indent { - for (_, lines) in childNode.content.classDtsLines.sorted(by: { $0.name < $1.name }) { - printer.write(lines: lines) - } + printer.write(lines: childNode.content.declarationDtsLines) for (_, line) in childNode.content.enumDtsLines.sorted(by: { $0.name < $1.name }) { printer.write(line) @@ -3050,36 +3118,51 @@ extension BridgeJSLink { private func printExportsObjectHierarchy( node: NamespaceNode, - printer: CodeFragmentPrinter, - currentPath: [String] = [] + printer: CodeFragmentPrinter ) { for (childName, childNode) in node.children.sorted(by: { $0.key < $1.key }) { - let newPath = currentPath + [childName] - printer.write("\(childName): {") - printer.indent { - for klass in childNode.content.classes.sorted(by: { $0.name < $1.name }) { - printer.write("\(klass.name),") + guard hasExportContent(node: childNode) else { continue } + if case .classType = childNode.content.declaration { + let body = CodeFragmentPrinter() + writeExportsObjectBody(node: childNode, into: body) + if body.lines.isEmpty { + printer.write("\(childName),") + } else { + printer.write("\(childName): Object.assign(\(childName), {") + printer.indent { + printer.write(lines: body.lines) + } + printer.write("}),") } - - for enumDef in childNode.content.enums.sorted(by: { $0.name < $1.name }) { - printer.write("\(enumDef.name): \(enumDef.valuesName),") + } else { + printer.write("\(childName): {") + printer.indent { + writeExportsObjectBody(node: childNode, into: printer) } + printer.write("},") + } + } + } - // Print function and property implementations - printer.write(lines: childNode.content.propertyJsLines) - for (name, lines) in childNode.content.functionJsLines.sorted(by: { $0.name < $1.name }) { - var modifiedLines = lines - if !modifiedLines.isEmpty { - modifiedLines[0] = "\(name): " + modifiedLines[0] - modifiedLines[modifiedLines.count - 1] += "," - } - printer.write(lines: modifiedLines) - } + private func writeExportsObjectBody(node: NamespaceNode, into printer: CodeFragmentPrinter) { + printer.write(lines: node.content.structJsLines) + + for enumDef in node.content.enums.sorted(by: { $0.name < $1.name }) { + printer.write("\(enumDef.name): \(enumDef.valuesName),") + } - printExportsObjectHierarchy(node: childNode, printer: printer, currentPath: newPath) + // Print function and property implementations + printer.write(lines: node.content.propertyJsLines) + for (name, lines) in node.content.functionJsLines.sorted(by: { $0.name < $1.name }) { + var modifiedLines = lines + if !modifiedLines.isEmpty { + modifiedLines[0] = "\(name): " + modifiedLines[0] + modifiedLines[modifiedLines.count - 1] += "," } - printer.write("},") + printer.write(lines: modifiedLines) } + + printExportsObjectHierarchy(node: node, printer: printer) } /// Generates TypeScript declarations for all namespaces @@ -3100,7 +3183,9 @@ extension BridgeJSLink { func namespaceDeclarations( exportedSkeletons: [ExportedSkeleton], renderTSSignatureCallback: @escaping ([Parameter], BridgeType, Effects) -> String, - renderDocCallback: @escaping (String?, [Parameter]) -> [String] + renderDocCallback: @escaping (String?, [Parameter]) -> [String], + renderStructInterface: @escaping (ExportedStruct) -> [String], + renderClassDeclaration: @escaping (ExportedClass) -> [String] ) -> [String] { let printer = CodeFragmentPrinter() @@ -3118,12 +3203,14 @@ extension BridgeJSLink { printer.indent() generateNamespaceDeclarationsForNode( node: globalRootNode, - depth: 1, + inNamespaceScope: false, printer: printer, exposeToGlobal: true, exportedSkeletons: exportedSkeletons, renderTSSignatureCallback: renderTSSignatureCallback, - renderDocCallback: renderDocCallback + renderDocCallback: renderDocCallback, + renderStructInterface: renderStructInterface, + renderClassDeclaration: renderClassDeclaration ) printer.unindent() printer.write("}") @@ -3138,12 +3225,14 @@ extension BridgeJSLink { if !localRootNode.children.isEmpty { generateNamespaceDeclarationsForNode( node: localRootNode, - depth: 1, + inNamespaceScope: false, printer: printer, exposeToGlobal: false, exportedSkeletons: exportedSkeletons, renderTSSignatureCallback: renderTSSignatureCallback, - renderDocCallback: renderDocCallback + renderDocCallback: renderDocCallback, + renderStructInterface: renderStructInterface, + renderClassDeclaration: renderClassDeclaration ) } } @@ -3153,22 +3242,27 @@ extension BridgeJSLink { private func generateNamespaceDeclarationsForNode( node: NamespaceNode, - depth: Int, + inNamespaceScope: Bool, printer: CodeFragmentPrinter, exposeToGlobal: Bool, exportedSkeletons: [ExportedSkeleton], renderTSSignatureCallback: @escaping ([Parameter], BridgeType, Effects) -> String, - renderDocCallback: @escaping (String?, [Parameter]) -> [String] + renderDocCallback: @escaping (String?, [Parameter]) -> [String], + renderStructInterface: @escaping (ExportedStruct) -> [String], + renderClassDeclaration: @escaping (ExportedClass) -> [String] ) { func hasContent(node: NamespaceNode) -> Bool { // Enums and structs are always included - if !node.content.enums.isEmpty || !node.content.structs.isEmpty { + if !node.content.enums.isEmpty + || node.children.values.contains(where: { $0.structDeclaration != nil }) + { return true } // When exposeToGlobal is true, classes, functions, and properties are included if exposeToGlobal { - if !node.content.classes.isEmpty || !node.content.functions.isEmpty + if node.children.values.contains(where: { $0.classDeclaration != nil }) + || !node.content.functions.isEmpty || !node.content.staticProperties.isEmpty { return true @@ -3185,10 +3279,19 @@ extension BridgeJSLink { return false } - func generateNamespaceDeclarations(node: NamespaceNode, depth: Int) { + func generateNamespaceDeclarations(node: NamespaceNode) { let sortedChildren = node.children.sorted { $0.key < $1.key } for (childName, childNode) in sortedChildren { + if inNamespaceScope { + if exposeToGlobal, let klass = childNode.classDeclaration { + printer.write(lines: renderClassDeclaration(klass)) + } + if let structDef = childNode.structDeclaration { + printer.write(lines: renderStructInterface(structDef)) + } + } + // Skip empty namespaces guard hasContent(node: childNode) else { continue @@ -3198,51 +3301,6 @@ extension BridgeJSLink { printer.write("\(exportKeyword)namespace \(childName) {") printer.indent() - // Only include classes when exposeToGlobal is true - if exposeToGlobal { - let sortedClasses = childNode.content.classes.sorted { $0.name < $1.name } - for klass in sortedClasses { - printer.write(lines: renderDocCallback(klass.documentation, [])) - printer.write("class \(klass.name) {") - printer.indent { - if let constructor = klass.constructor { - let paramSignatures = constructor.parameters.map { param in - let optional = param.hasDefault ? "?" : "" - return "\(param.name)\(optional): \(param.type.tsType)" - } - let constructorSignature = - "constructor(\(paramSignatures.joined(separator: ", ")));" - printer.write( - lines: renderDocCallback(constructor.documentation, constructor.parameters) - ) - printer.write(constructorSignature) - } - - let sortedMethods = klass.methods.sorted { $0.name < $1.name } - for method in sortedMethods { - let staticKeyword = method.effects.isStatic ? "static " : "" - let methodSignature = - "\(staticKeyword)\(method.name)\(renderTSSignatureCallback(method.parameters, method.returnType, method.effects));" - printer.write(lines: renderDocCallback(method.documentation, method.parameters)) - printer.write(methodSignature) - } - - let sortedProperties = klass.properties.sorted { $0.name < $1.name } - for property in sortedProperties { - let staticKeyword = property.isStatic ? "static " : "" - let readonly = property.isReadonly ? "readonly " : "" - printer.write(lines: renderDocCallback(property.documentation, [])) - printer.write( - "\(staticKeyword)\(readonly)\(property.name): \(property.type.tsType);" - ) - } - - printer.write("release(): void;") - } - printer.write("}") - } - } - // Generate enum definitions within declare global namespace let sortedEnums = childNode.content.enums.sorted { $0.name < $1.name } for enumDefinition in sortedEnums { @@ -3351,25 +3409,6 @@ extension BridgeJSLink { } } - // Generate struct interface definitions - let sortedStructs = childNode.content.structs.sorted { $0.name < $1.name } - for structDef in sortedStructs { - let instanceProps = structDef.properties.filter { !$0.isStatic } - printer.write(lines: renderDocCallback(structDef.documentation, [])) - printer.write("export interface \(structDef.name) {") - printer.indent { - for property in instanceProps { - let tsType = BridgeJSLink.resolveTypeScriptType( - property.type, - exportedSkeletons: exportedSkeletons - ) - printer.write(lines: renderDocCallback(property.documentation, [])) - printer.write("\(property.name): \(tsType);") - } - } - printer.write("}") - } - // Only include functions and properties when exposeToGlobal is true if exposeToGlobal { let sortedFunctions = childNode.content.functions.sorted { $0.name < $1.name } @@ -3389,12 +3428,14 @@ extension BridgeJSLink { generateNamespaceDeclarationsForNode( node: childNode, - depth: depth + 1, + inNamespaceScope: true, printer: printer, exposeToGlobal: exposeToGlobal, exportedSkeletons: exportedSkeletons, renderTSSignatureCallback: renderTSSignatureCallback, - renderDocCallback: renderDocCallback + renderDocCallback: renderDocCallback, + renderStructInterface: renderStructInterface, + renderClassDeclaration: renderClassDeclaration ) printer.unindent() @@ -3402,7 +3443,7 @@ extension BridgeJSLink { } } - generateNamespaceDeclarations(node: node, depth: depth) + generateNamespaceDeclarations(node: node) } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ClassWithNestedTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ClassWithNestedTypes.swift new file mode 100644 index 000000000..7971283d2 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/ClassWithNestedTypes.swift @@ -0,0 +1,34 @@ +@JS class Account { + @JS enum Role: String { + case admin + case guest + } + + @JS struct Credentials { + var token: String + + @JS init(token: String) { + self.token = token + } + + @JS static var maxLength: Int { 64 } + + @JS static func empty() -> Credentials { + Credentials(token: "") + } + } + + @JS var name: String + + @JS var role: Role { .admin } + + @JS static var defaultRole: Role { .guest } + + @JS init(name: String) { + self.name = name + } + + @JS func describe() -> String { + name + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StructWithNestedTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StructWithNestedTypes.swift new file mode 100644 index 000000000..d8e5973c1 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/StructWithNestedTypes.swift @@ -0,0 +1,52 @@ +@JS struct Shape { + @JS enum Kind: String { + case circle + case square + } + + var label: String + + @JS init(label: String) { + self.label = label + } +} + +@JS struct Widget { + @JS enum Variant: String { + case button + case slider + } + + @JS struct Layout { + @JS enum Alignment: String { + case leading + case trailing + } + + var padding: Int + } + + @JS struct Bounds { + var width: Int + var height: Int + + @JS init(width: Int, height: Int) { + self.width = width + self.height = height + } + + @JS static var dimensions: Int { + 2 + } + + @JS static func zero() -> Bounds { + Bounds(width: 0, height: 0) + } + } + + var name: String + + @JS init(name: String) { + self.name = name + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.json new file mode 100644 index 000000000..0aa78c471 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.json @@ -0,0 +1,218 @@ +{ + "exported" : { + "aliases" : [ + + ], + "classes" : [ + { + "constructor" : { + "abiName" : "bjs_Account_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Account_describe", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "describe", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "Account", + "properties" : [ + { + "isReadonly" : false, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "role", + "type" : { + "rawValueEnum" : { + "_0" : "Account.Role", + "_1" : "String" + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "defaultRole", + "staticContext" : { + "className" : { + "_0" : "Account" + } + }, + "type" : { + "rawValueEnum" : { + "_0" : "Account.Role", + "_1" : "String" + } + } + } + ], + "swiftCallName" : "Account" + } + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "admin" + }, + { + "associatedValues" : [ + + ], + "name" : "guest" + } + ], + "emitStyle" : "const", + "name" : "Role", + "namespace" : [ + "Account" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Account.Role", + "tsFullPath" : "Account.Role" + } + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + { + "constructor" : { + "abiName" : "bjs_Account_Credentials_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "token", + "name" : "token", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Account_Credentials_static_empty", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "empty", + "parameters" : [ + + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Account.Credentials" + } + }, + "staticContext" : { + "structName" : { + "_0" : "Account_Credentials" + } + } + } + ], + "name" : "Credentials", + "namespace" : [ + "Account" + ], + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "token", + "namespace" : [ + "Account" + ], + "type" : { + "string" : { + + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "maxLength", + "staticContext" : { + "structName" : { + "_0" : "Account_Credentials" + } + }, + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "swiftCallName" : "Account.Credentials" + } + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.swift new file mode 100644 index 000000000..3ae08e13a --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.swift @@ -0,0 +1,177 @@ +extension Account.Role: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Account.Credentials: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Account.Credentials { + let token = String.bridgeJSStackPop() + return Account.Credentials(token: token) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.token.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_Account_Credentials(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Account_Credentials())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Account_Credentials") +fileprivate func _bjs_struct_lower_Account_Credentials_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_Account_Credentials_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_Account_Credentials(_ objectId: Int32) -> Void { + return _bjs_struct_lower_Account_Credentials_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Account_Credentials") +fileprivate func _bjs_struct_lift_Account_Credentials_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_Account_Credentials_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_Account_Credentials() -> Int32 { + return _bjs_struct_lift_Account_Credentials_extern() +} + +@_expose(wasm, "bjs_Account_Credentials_init") +@_cdecl("bjs_Account_Credentials_init") +public func _bjs_Account_Credentials_init(_ tokenBytes: Int32, _ tokenLength: Int32) -> Void { + #if arch(wasm32) + let ret = Account.Credentials(token: String.bridgeJSLiftParameter(tokenBytes, tokenLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_Credentials_static_maxLength_get") +@_cdecl("bjs_Account_Credentials_static_maxLength_get") +public func _bjs_Account_Credentials_static_maxLength_get() -> Int32 { + #if arch(wasm32) + let ret = Account_Credentials.maxLength + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_Credentials_static_empty") +@_cdecl("bjs_Account_Credentials_static_empty") +public func _bjs_Account_Credentials_static_empty() -> Void { + #if arch(wasm32) + let ret = Account.Credentials.empty() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_init") +@_cdecl("bjs_Account_init") +public func _bjs_Account_init(_ nameBytes: Int32, _ nameLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Account(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_describe") +@_cdecl("bjs_Account_describe") +public func _bjs_Account_describe(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Account.bridgeJSLiftParameter(_self).describe() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_name_get") +@_cdecl("bjs_Account_name_get") +public func _bjs_Account_name_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Account.bridgeJSLiftParameter(_self).name + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_name_set") +@_cdecl("bjs_Account_name_set") +public func _bjs_Account_name_set(_ _self: UnsafeMutableRawPointer, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + Account.bridgeJSLiftParameter(_self).name = String.bridgeJSLiftParameter(valueBytes, valueLength) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_role_get") +@_cdecl("bjs_Account_role_get") +public func _bjs_Account_role_get(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Account.bridgeJSLiftParameter(_self).role + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_static_defaultRole_get") +@_cdecl("bjs_Account_static_defaultRole_get") +public func _bjs_Account_static_defaultRole_get() -> Void { + #if arch(wasm32) + let ret = Account.defaultRole + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Account_deinit") +@_cdecl("bjs_Account_deinit") +public func _bjs_Account_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Account: ConvertibleToJSValue, _BridgedSwiftHeapObject, _BridgedSwiftProtocolExportable { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Account_wrap(Unmanaged.passRetained(self).toOpaque())))) + } + consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { + _bjs_Account_wrap(Unmanaged.passRetained(self).toOpaque()) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Account_wrap") +fileprivate func _bjs_Account_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Account_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_Account_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_Account_wrap_extern(pointer) +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.json new file mode 100644 index 000000000..ec470b65f --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.json @@ -0,0 +1,337 @@ +{ + "exported" : { + "aliases" : [ + + ], + "classes" : [ + + ], + "enums" : [ + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "circle" + }, + { + "associatedValues" : [ + + ], + "name" : "square" + } + ], + "emitStyle" : "const", + "name" : "Kind", + "namespace" : [ + "Shape" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Shape.Kind", + "tsFullPath" : "Shape.Kind" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "button" + }, + { + "associatedValues" : [ + + ], + "name" : "slider" + } + ], + "emitStyle" : "const", + "name" : "Variant", + "namespace" : [ + "Widget" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Widget.Variant", + "tsFullPath" : "Widget.Variant" + }, + { + "cases" : [ + { + "associatedValues" : [ + + ], + "name" : "leading" + }, + { + "associatedValues" : [ + + ], + "name" : "trailing" + } + ], + "emitStyle" : "const", + "name" : "Alignment", + "namespace" : [ + "Widget", + "Layout" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "Widget.Layout.Alignment", + "tsFullPath" : "Widget.Layout.Alignment" + } + ], + "exposeToGlobal" : false, + "functions" : [ + + ], + "protocols" : [ + + ], + "structs" : [ + { + "constructor" : { + "abiName" : "bjs_Shape_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "label", + "name" : "label", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "Shape", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "label", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "Shape" + }, + { + "constructor" : { + "abiName" : "bjs_Widget_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "name", + "name" : "name", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "Widget", + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "name", + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "Widget" + }, + { + "methods" : [ + + ], + "name" : "Layout", + "namespace" : [ + "Widget" + ], + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "padding", + "namespace" : [ + "Widget" + ], + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "swiftCallName" : "Widget.Layout" + }, + { + "constructor" : { + "abiName" : "bjs_Widget_Bounds_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "width", + "name" : "width", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "label" : "height", + "name" : "height", + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_Widget_Bounds_static_zero", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "zero", + "parameters" : [ + + ], + "returnType" : { + "swiftStruct" : { + "_0" : "Widget.Bounds" + } + }, + "staticContext" : { + "structName" : { + "_0" : "Widget_Bounds" + } + } + } + ], + "name" : "Bounds", + "namespace" : [ + "Widget" + ], + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "width", + "namespace" : [ + "Widget" + ], + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : false, + "name" : "height", + "namespace" : [ + "Widget" + ], + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "dimensions", + "staticContext" : { + "structName" : { + "_0" : "Widget_Bounds" + } + }, + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } + } + ], + "swiftCallName" : "Widget.Bounds" + } + ] + }, + "moduleName" : "TestModule", + "usedExternalModules" : [ + + ] +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.swift new file mode 100644 index 000000000..f8843b7cd --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.swift @@ -0,0 +1,249 @@ +extension Shape.Kind: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Widget.Variant: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Widget.Layout.Alignment: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + +extension Shape: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Shape { + let label = String.bridgeJSStackPop() + return Shape(label: label) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.label.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_Shape(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Shape())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Shape") +fileprivate func _bjs_struct_lower_Shape_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_Shape_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_Shape(_ objectId: Int32) -> Void { + return _bjs_struct_lower_Shape_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Shape") +fileprivate func _bjs_struct_lift_Shape_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_Shape_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_Shape() -> Int32 { + return _bjs_struct_lift_Shape_extern() +} + +@_expose(wasm, "bjs_Shape_init") +@_cdecl("bjs_Shape_init") +public func _bjs_Shape_init(_ labelBytes: Int32, _ labelLength: Int32) -> Void { + #if arch(wasm32) + let ret = Shape(label: String.bridgeJSLiftParameter(labelBytes, labelLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Widget: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Widget { + let name = String.bridgeJSStackPop() + return Widget(name: name) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.name.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_Widget(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Widget())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Widget") +fileprivate func _bjs_struct_lower_Widget_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_Widget_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_Widget(_ objectId: Int32) -> Void { + return _bjs_struct_lower_Widget_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Widget") +fileprivate func _bjs_struct_lift_Widget_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_Widget_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_Widget() -> Int32 { + return _bjs_struct_lift_Widget_extern() +} + +@_expose(wasm, "bjs_Widget_init") +@_cdecl("bjs_Widget_init") +public func _bjs_Widget_init(_ nameBytes: Int32, _ nameLength: Int32) -> Void { + #if arch(wasm32) + let ret = Widget(name: String.bridgeJSLiftParameter(nameBytes, nameLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Widget.Layout: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Widget.Layout { + let padding = Int.bridgeJSStackPop() + return Widget.Layout(padding: padding) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.padding.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_Widget_Layout(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Widget_Layout())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Widget_Layout") +fileprivate func _bjs_struct_lower_Widget_Layout_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_Widget_Layout_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_Widget_Layout(_ objectId: Int32) -> Void { + return _bjs_struct_lower_Widget_Layout_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Widget_Layout") +fileprivate func _bjs_struct_lift_Widget_Layout_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_Widget_Layout_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_Widget_Layout() -> Int32 { + return _bjs_struct_lift_Widget_Layout_extern() +} + +extension Widget.Bounds: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Widget.Bounds { + let height = Int.bridgeJSStackPop() + let width = Int.bridgeJSStackPop() + return Widget.Bounds(width: width, height: height) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.width.bridgeJSStackPush() + self.height.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_Widget_Bounds(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_Widget_Bounds())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Widget_Bounds") +fileprivate func _bjs_struct_lower_Widget_Bounds_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_Widget_Bounds_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_Widget_Bounds(_ objectId: Int32) -> Void { + return _bjs_struct_lower_Widget_Bounds_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_Widget_Bounds") +fileprivate func _bjs_struct_lift_Widget_Bounds_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_Widget_Bounds_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_Widget_Bounds() -> Int32 { + return _bjs_struct_lift_Widget_Bounds_extern() +} + +@_expose(wasm, "bjs_Widget_Bounds_init") +@_cdecl("bjs_Widget_Bounds_init") +public func _bjs_Widget_Bounds_init(_ width: Int32, _ height: Int32) -> Void { + #if arch(wasm32) + let ret = Widget.Bounds(width: Int.bridgeJSLiftParameter(width), height: Int.bridgeJSLiftParameter(height)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Widget_Bounds_static_dimensions_get") +@_cdecl("bjs_Widget_Bounds_static_dimensions_get") +public func _bjs_Widget_Bounds_static_dimensions_get() -> Int32 { + #if arch(wasm32) + let ret = Widget_Bounds.dimensions + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Widget_Bounds_static_zero") +@_cdecl("bjs_Widget_Bounds_static_zero") +public func _bjs_Widget_Bounds_static_zero() -> Void { + #if arch(wasm32) + let ret = Widget.Bounds.zero() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.d.ts index 3ee338254..e3092afb3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.d.ts @@ -37,13 +37,6 @@ export interface Surface { readonly label: string; } export type Exports = { - PolygonReference: { - new(underlying: PolygonReference): PolygonReference; - origin(): PolygonReference; - } - TagReference: { - new(underlying: TagReference): TagReference; - } roundtripPolygon(polygon: PolygonReference): PolygonReference; optionalPolygon(polygon: PolygonReference | null): PolygonReference | null; polygonArray(polygons: PolygonReference[]): PolygonReference[]; @@ -52,6 +45,13 @@ export type Exports = { roundtripTags(xs: (InnerTagTag | null)[]): (InnerTagTag | null)[]; describeUser(owner: HasOptionalUserId): HasOptionalUserId; InnerTag: InnerTagObject + PolygonReference: { + new(underlying: PolygonReference): PolygonReference; + origin(): PolygonReference; + }, + TagReference: { + new(underlying: TagReference): TagReference; + }, } export type Imports = { acceptTagged(tagged: string): void; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js index 8f9511e86..0b922111b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js @@ -421,8 +421,6 @@ export async function createInstantiator(options, swift) { enumHelpers.InnerTag = InnerTagHelpers; const exports = { - PolygonReference, - TagReference, roundtripPolygon: function bjs_roundtripPolygon(polygon) { const ret = instance.exports.bjs_roundtripPolygon(polygon.pointer); return PolygonReference.__construct(ret); @@ -517,6 +515,8 @@ export async function createInstantiator(options, swift) { return ret1; }, InnerTag: InnerTagValues, + PolygonReference, + TagReference, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.d.ts index f1d5d5fa9..73ea3b570 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.d.ts @@ -14,11 +14,11 @@ export interface SwiftHeapObject { export interface PolygonReference extends SwiftHeapObject { } export type Exports = { - PolygonReference: { - new(sides: number): PolygonReference; - } makePolygonFactory(): () => PolygonReference; makePolygonInspector(): (arg0: PolygonReference) => number; + PolygonReference: { + new(sides: number): PolygonReference; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js index bc7575fbc..a38fa118e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js @@ -363,7 +363,6 @@ export async function createInstantiator(options, swift) { } } const exports = { - PolygonReference, makePolygonFactory: function bjs_makePolygonFactory() { const ret = instance.exports.bjs_makePolygonFactory(); return swift.memory.getObject(ret); @@ -372,6 +371,7 @@ export async function createInstantiator(options, swift) { const ret = instance.exports.bjs_makePolygonInspector(); return swift.memory.getObject(ret); }, + PolygonReference, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.d.ts index 255249eef..f48189956 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.d.ts @@ -41,11 +41,6 @@ export interface MultiArrayContainer extends SwiftHeapObject { readonly strings: string[]; } export type Exports = { - Item: { - } - MultiArrayContainer: { - new(nums: number[], strs: string[]): MultiArrayContainer; - } processIntArray(values: number[]): number[]; processStringArray(values: string[]): string[]; processDoubleArray(values: number[]): number[]; @@ -76,6 +71,11 @@ export type Exports = { multiOptionalArrayParams(a: number[] | null, b: string[] | null): number; Direction: DirectionObject Status: StatusObject + Item: { + }, + MultiArrayContainer: { + new(nums: number[], strs: string[]): MultiArrayContainer; + }, } export type Imports = { checkArray(a: any): void; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index 7978d1522..419cf15d5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -493,8 +493,6 @@ export async function createInstantiator(options, swift) { structHelpers.Point = PointHelpers; const exports = { - Item, - MultiArrayContainer, processIntArray: function bjs_processIntArray(values) { for (const elem of values) { i32Stack.push((elem | 0)); @@ -1201,6 +1199,8 @@ export async function createInstantiator(options, swift) { }, Direction: DirectionValues, Status: StatusValues, + Item, + MultiArrayContainer, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.d.ts new file mode 100644 index 000000000..5537696c4 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.d.ts @@ -0,0 +1,51 @@ +// 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 type RoleObject = typeof Account.RoleValues; + +export namespace Account { + const RoleValues: { + readonly Admin: "admin"; + readonly Guest: "guest"; + }; + type RoleTag = typeof RoleValues[keyof typeof RoleValues]; + export interface Credentials { + token: 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 Account extends SwiftHeapObject { + describe(): string; + name: string; + readonly role: Account.RoleTag; +} +export type Exports = { + Account: { + new(name: string): Account; + readonly defaultRole: Account.RoleTag; + Role: RoleObject + Credentials: { + init(token: string): Account.Credentials; + readonly maxLength: number; + empty(): Account.Credentials; + }, + }, +} +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/ClassWithNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js new file mode 100644 index 000000000..272bb8c49 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js @@ -0,0 +1,375 @@ +// 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 RoleValues = { + Admin: "admin", + Guest: "guest", +}; + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + let decodeString; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let strStack = []; + let i32Stack = []; + let i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createAccount_CredentialsHelpers = () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.token); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + }, + lift: () => { + const string = strStack.pop(); + return { token: string }; + } + }); + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + tmpRetString = decodeString(ptr, len); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + swift.memory.release(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + return swift.memory.retain(decodeString(ptr, len)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const value = decodeString(ptr, len); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + bjs["swift_js_struct_lower_Account_Credentials"] = function(objectId) { + structHelpers.Account_Credentials.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_Account_Credentials"] = function() { + const value = structHelpers.Account_Credentials.lift(); + return swift.memory.retain(value); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = decodeString(ptr, len); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + // Wrapper functions for module: TestModule + if (!importObject["TestModule"]) { + importObject["TestModule"] = {}; + } + importObject["TestModule"]["bjs_Account_wrap"] = function(pointer) { + const obj = _exports['Account'].__construct(pointer); + return swift.memory.retain(obj); + }; + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => { + if (state.hasReleased) { + return; + } + state.hasReleased = true; + state.identityMap?.delete(state.pointer); + state.deinit(state.pointer); + }); + + /// Represents a Swift heap object like a class instance or an actor instance. + class SwiftHeapObject { + static __wrap(pointer, deinit, prototype, identityCache) { + pointer = pointer >>> 0; + const makeFresh = (identityMap) => { + const obj = Object.create(prototype); + const state = { pointer, deinit, hasReleased: false, identityMap }; + obj.pointer = pointer; + obj.__swiftHeapObjectState = state; + swiftHeapObjectFinalizationRegistry.register(obj, state, state); + if (identityMap) { + identityMap.set(pointer, new WeakRef(obj)); + } + return obj; + }; + + if (!identityCache) { + return makeFresh(null); + } + + const cached = identityCache.get(pointer)?.deref(); + if (cached && !cached.__swiftHeapObjectState.hasReleased) { + deinit(pointer); + return cached; + } + if (identityCache.has(pointer)) { + identityCache.delete(pointer); + } + + return makeFresh(identityCache); + } + + release() { + const state = this.__swiftHeapObjectState; + if (state.hasReleased) { + return; + } + state.hasReleased = true; + swiftHeapObjectFinalizationRegistry.unregister(state); + state.identityMap?.delete(state.pointer); + state.deinit(state.pointer); + } + } + class Account extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Account_deinit, Account.prototype, null); + } + + constructor(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + const ret = instance.exports.bjs_Account_init(nameId, nameBytes.length); + return Account.__construct(ret); + } + describe() { + instance.exports.bjs_Account_describe(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + get name() { + instance.exports.bjs_Account_name_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + set name(value) { + const valueBytes = textEncoder.encode(value); + const valueId = swift.memory.retain(valueBytes); + instance.exports.bjs_Account_name_set(this.pointer, valueId, valueBytes.length); + } + get role() { + instance.exports.bjs_Account_role_get(this.pointer); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + static get defaultRole() { + instance.exports.bjs_Account_static_defaultRole_get(); + const ret = tmpRetString; + tmpRetString = undefined; + return ret; + } + } + const Account_CredentialsHelpers = __bjs_createAccount_CredentialsHelpers(); + structHelpers.Account_Credentials = Account_CredentialsHelpers; + + const exports = { + Account: Object.assign(Account, { + Role: RoleValues, + Credentials: { + init: function(token) { + const tokenBytes = textEncoder.encode(token); + const tokenId = swift.memory.retain(tokenBytes); + instance.exports.bjs_Account_Credentials_init(tokenId, tokenBytes.length); + const structValue = structHelpers.Account_Credentials.lift(); + return structValue; + }, + get maxLength() { + const ret = instance.exports.bjs_Account_Credentials_static_maxLength_get(); + return ret; + }, + empty: function() { + instance.exports.bjs_Account_Credentials_static_empty(); + const structValue = structHelpers.Account_Credentials.lift(); + return structValue; + }, + }, + }), + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.d.ts index ac5658eb3..961b9fa5b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.d.ts @@ -46,22 +46,6 @@ export interface ConstructorDefaults extends SwiftHeapObject { tag: string | null; } export type Exports = { - DefaultGreeter: { - new(name: string): DefaultGreeter; - } - EmptyGreeter: { - new(): EmptyGreeter; - } - ConstructorDefaults: { - /** - * @param name - Optional parameter (default: "Default") - * @param count - Optional parameter (default: 42) - * @param enabled - Optional parameter (default: true) - * @param status - Optional parameter (default: Status.Active) - * @param tag - Optional parameter (default: null) - */ - new(name?: string, count?: number, enabled?: boolean, status?: StatusTag, tag?: string | null): ConstructorDefaults; - } /** * @param message - Optional parameter (default: "Hello World") */ @@ -143,6 +127,22 @@ export type Exports = { */ testMixedWithArrayDefault(name?: string, values?: number[], enabled?: boolean): string; Status: StatusObject + ConstructorDefaults: { + /** + * @param name - Optional parameter (default: "Default") + * @param count - Optional parameter (default: 42) + * @param enabled - Optional parameter (default: true) + * @param status - Optional parameter (default: Status.Active) + * @param tag - Optional parameter (default: null) + */ + new(name?: string, count?: number, enabled?: boolean, status?: StatusTag, tag?: string | null): ConstructorDefaults; + }, + DefaultGreeter: { + new(name: string): DefaultGreeter; + }, + EmptyGreeter: { + new(): EmptyGreeter; + }, MathOperations: { /** * @param baseValue - Optional parameter (default: 0.0) @@ -152,7 +152,7 @@ export type Exports = { * @param b - Optional parameter (default: 5.0) */ subtract(a: number, b?: number): number; - } + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index 0c6bfbec8..b7f67fe15 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -456,9 +456,6 @@ export async function createInstantiator(options, swift) { structHelpers.MathOperations = MathOperationsHelpers; const exports = { - DefaultGreeter, - EmptyGreeter, - ConstructorDefaults, testStringDefault: function bjs_testStringDefault(message = "Hello World") { const messageBytes = textEncoder.encode(message); const messageId = swift.memory.retain(messageBytes); @@ -675,6 +672,9 @@ export async function createInstantiator(options, swift) { return ret; }, Status: StatusValues, + ConstructorDefaults, + DefaultGreeter, + EmptyGreeter, MathOperations: { init: function(baseValue = 0.0) { instance.exports.bjs_MathOperations_init(baseValue); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.d.ts index f14b29aa4..652177cd8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.d.ts @@ -18,14 +18,14 @@ export interface SwiftHeapObject { export interface Box extends SwiftHeapObject { } export type Exports = { - Box: { - } mirrorDictionary(values: Record): Record; optionalDictionary(values: Record | null): Record | null; nestedDictionary(values: Record): Record; boxDictionary(boxes: Record): Record; optionalBoxDictionary(boxes: Record): Record; roundtripCounters(counters: Counters): Counters; + Box: { + }, } export type Imports = { importMirrorDictionary(values: Record): Record; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index 104472a02..d0ac5307f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -360,7 +360,6 @@ export async function createInstantiator(options, swift) { structHelpers.Counters = CountersHelpers; const exports = { - Box, mirrorDictionary: function bjs_mirrorDictionary(values) { const entries = Object.entries(values); for (const entry of entries) { @@ -513,6 +512,7 @@ export async function createInstantiator(options, swift) { const structValue = structHelpers.Counters.lift(); return structValue; }, + Box, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.d.ts index 359d719d1..196ef73fe 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.d.ts @@ -77,13 +77,6 @@ export interface Greeter extends SwiftHeapObject { name: string; } export type Exports = { - Greeter: { - /** - * Create a greeter. - * @param name The name to greet. - */ - new(name: string): Greeter; - } /** * Returns a greeting for a user. * @param name The user's name. @@ -120,6 +113,13 @@ export type Exports = { */ terminator(): string; Color: ColorObject + Greeter: { + /** + * Create a greeter. + * @param name The name to greet. + */ + new(name: string): Greeter; + }, MathUtils: { /** * Doubles a value, in a namespace. diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js index 07e8673bf..f29814675 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js @@ -351,7 +351,6 @@ export async function createInstantiator(options, swift) { structHelpers.Point = PointHelpers; const exports = { - Greeter, greet: function bjs_greet(name, greeting = "Hello") { const nameBytes = textEncoder.encode(name); const nameId = swift.memory.retain(nameBytes); @@ -407,6 +406,7 @@ export async function createInstantiator(options, swift) { return ret; } }, + Greeter, MathUtils: { double: function bjs_MathUtils_double(value) { const ret = instance.exports.bjs_MathUtils_double(value); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.d.ts index 9525038e6..d2772fa8b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.d.ts @@ -14,10 +14,10 @@ export interface SwiftHeapObject { export interface ColorBox extends SwiftHeapObject { } export type Exports = { + roundtripColor(color: ColorBox): ColorBox; ColorBox: { new(name: string): ColorBox; - } - roundtripColor(color: ColorBox): ColorBox; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js index ccf57601b..42f3fd958 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js @@ -290,11 +290,11 @@ export async function createInstantiator(options, swift) { } } const exports = { - ColorBox, roundtripColor: function bjs_roundtripColor(color) { const ret = instance.exports.bjs_roundtripColor(color.pointer); return ColorBox.__construct(ret); }, + ColorBox, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts index 13f77ae08..36fc92474 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.d.ts @@ -153,8 +153,6 @@ export interface SwiftHeapObject { export interface User extends SwiftHeapObject { } export type Exports = { - User: { - } handle(result: APIResultTag): void; getResult(): APIResultTag; roundtripAPIResult(result: APIResultTag): APIResultTag; @@ -184,6 +182,8 @@ export type Exports = { API: { NetworkingResult: NetworkingResultObject }, + User: { + }, Utilities: { Result: ResultObject }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js index 35b05fe61..8ff3dd90d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -1061,7 +1061,6 @@ export async function createInstantiator(options, swift) { enumHelpers.OptionalAllTypesResult = OptionalAllTypesResultHelpers; const exports = { - User, handle: function bjs_handle(result) { const resultCaseId = enumHelpers.APIResult.lower(result); instance.exports.bjs_handle(resultCaseId); @@ -1255,6 +1254,7 @@ export async function createInstantiator(options, swift) { API: { NetworkingResult: NetworkingResultValues, }, + User, Utilities: { Result: ResultValues, }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.d.ts index b78f0cecd..0ca8b16b9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.d.ts @@ -39,11 +39,6 @@ declare global { } namespace Networking { namespace API { - class HTTPServer { - constructor(); - call(method: Networking.API.MethodTag): void; - release(): void; - } const MethodValues: { readonly Get: 0; readonly Post: 1; @@ -51,19 +46,24 @@ declare global { readonly Delete: 3; }; type MethodTag = typeof MethodValues[keyof typeof MethodValues]; + class HTTPServer { + constructor(); + call(method: Networking.API.MethodTag): void; + release(): void; + } } namespace APIV2 { namespace Internal { - class TestServer { - constructor(); - call(method: Networking.APIV2.Internal.SupportedMethodTag): void; - release(): void; - } const SupportedMethodValues: { readonly Get: 0; readonly Post: 1; }; type SupportedMethodTag = typeof SupportedMethodValues[keyof typeof SupportedMethodValues]; + class TestServer { + constructor(); + call(method: Networking.APIV2.Internal.SupportedMethodTag): void; + release(): void; + } } } } @@ -114,21 +114,21 @@ export type Exports = { Formatting: { Converter: { new(): Converter; - } + }, }, Networking: { API: { + Method: MethodObject HTTPServer: { new(): HTTPServer; - } - Method: MethodObject + }, }, APIV2: { Internal: { + SupportedMethod: SupportedMethodObject TestServer: { new(): TestServer; - } - SupportedMethod: SupportedMethodObject + }, }, }, }, @@ -144,7 +144,7 @@ export type Exports = { Utils: { Converter: { new(): Converter; - } + }, }, } export type Imports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js index 1a8f5662f..6c45f0333 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -438,13 +438,13 @@ export async function createInstantiator(options, swift) { }, Networking: { API: { - HTTPServer, Method: MethodValues, + HTTPServer, }, APIV2: { Internal: { - TestServer, SupportedMethod: SupportedMethodValues, + TestServer, }, }, }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.d.ts index 23d872d27..b5a85a082 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.d.ts @@ -75,21 +75,21 @@ export type Exports = { Formatting: { Converter: { new(): Converter; - } + }, }, Networking: { API: { + Method: MethodObject HTTPServer: { new(): HTTPServer; - } - Method: MethodObject + }, }, APIV2: { Internal: { + SupportedMethod: SupportedMethodObject TestServer: { new(): TestServer; - } - SupportedMethod: SupportedMethodObject + }, }, }, }, @@ -105,7 +105,7 @@ export type Exports = { Utils: { Converter: { new(): Converter; - } + }, }, } export type Imports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index 9196e99b3..2a9e7948a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -389,13 +389,13 @@ export async function createInstantiator(options, swift) { }, Networking: { API: { - HTTPServer, Method: MethodValues, + HTTPServer, }, APIV2: { Internal: { - TestServer, SupportedMethod: SupportedMethodValues, + TestServer, }, }, }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.d.ts index e5e2a3a84..02d17c011 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.d.ts @@ -23,13 +23,13 @@ export interface ExplicitlyUncachedModel extends SwiftHeapObject { export type Exports = { CachedModel: { new(name: string): CachedModel; - } - UncachedModel: { - new(value: number): UncachedModel; - } + }, ExplicitlyUncachedModel: { new(count: number): ExplicitlyUncachedModel; - } + }, + UncachedModel: { + new(value: number): UncachedModel; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js index 36728f890..83f53d8a6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js @@ -348,8 +348,8 @@ export async function createInstantiator(options, swift) { } const exports = { CachedModel, - UncachedModel, ExplicitlyUncachedModel, + UncachedModel, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.d.ts index e5e2a3a84..02d17c011 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.d.ts @@ -23,13 +23,13 @@ export interface ExplicitlyUncachedModel extends SwiftHeapObject { export type Exports = { CachedModel: { new(name: string): CachedModel; - } - UncachedModel: { - new(value: number): UncachedModel; - } + }, ExplicitlyUncachedModel: { new(count: number): ExplicitlyUncachedModel; - } + }, + UncachedModel: { + new(value: number): UncachedModel; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js index ed180c1c8..bb6f36902 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js @@ -346,8 +346,8 @@ export async function createInstantiator(options, swift) { } const exports = { CachedModel, - UncachedModel, ExplicitlyUncachedModel, + UncachedModel, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.d.ts index e5e2a3a84..02d17c011 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.d.ts @@ -23,13 +23,13 @@ export interface ExplicitlyUncachedModel extends SwiftHeapObject { export type Exports = { CachedModel: { new(name: string): CachedModel; - } - UncachedModel: { - new(value: number): UncachedModel; - } + }, ExplicitlyUncachedModel: { new(count: number): ExplicitlyUncachedModel; - } + }, + UncachedModel: { + new(value: number): UncachedModel; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js index ed180c1c8..bb6f36902 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js @@ -346,8 +346,8 @@ export async function createInstantiator(options, swift) { } const exports = { CachedModel, - UncachedModel, ExplicitlyUncachedModel, + UncachedModel, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.d.ts index f4c13c610..85109479e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.d.ts @@ -19,13 +19,13 @@ export interface JSValueHolder extends SwiftHeapObject { optionalValue: any | null; } export type Exports = { - JSValueHolder: { - new(value: any, optionalValue: any | null): JSValueHolder; - } roundTripJSValue(value: any): any; roundTripOptionalJSValue(value: any | null): any | null; roundTripJSValueArray(values: any[]): any[]; roundTripOptionalJSValueArray(values: any[] | null): any[] | null; + JSValueHolder: { + new(value: any, optionalValue: any | null): JSValueHolder; + }, } export type Imports = { jsEchoJSValue(value: any): any; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index d47fd3e85..ae59008ba 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -527,7 +527,6 @@ export async function createInstantiator(options, swift) { } } const exports = { - JSValueHolder, roundTripJSValue: function bjs_roundTripJSValue(value) { const [valueKind, valuePayload1, valuePayload2] = __bjs_jsValueLower(value); instance.exports.bjs_roundTripJSValue(valueKind, valuePayload1, valuePayload2); @@ -627,6 +626,7 @@ export async function createInstantiator(options, swift) { } return optResult; }, + JSValueHolder, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.d.ts index 7b4cc95e6..c7ff9a39c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.d.ts @@ -16,10 +16,10 @@ export interface GlobalClass extends SwiftHeapObject { } export type Exports = { GlobalAPI: { + globalFunction(): string; GlobalClass: { new(): GlobalClass; - } - globalFunction(): string; + }, }, } export type Imports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index 577fa0ca7..39ecf8d99 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -295,13 +295,13 @@ export async function createInstantiator(options, swift) { } const exports = { GlobalAPI: { - GlobalClass, globalFunction: function bjs_GlobalAPI_globalFunction() { instance.exports.bjs_GlobalAPI_globalFunction(); const ret = tmpRetString; tmpRetString = undefined; return ret; }, + GlobalClass, }, }; _exports = exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.d.ts index 88485232e..01a392e91 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.d.ts @@ -8,12 +8,12 @@ export {}; declare global { namespace GlobalAPI { + function globalFunction(): string; class GlobalClass { constructor(); greet(): string; release(): void; } - function globalFunction(): string; } } @@ -32,16 +32,16 @@ export interface PrivateClass extends SwiftHeapObject { } export type Exports = { GlobalAPI: { + globalFunction(): string; GlobalClass: { new(): GlobalClass; - } - globalFunction(): string; + }, }, PrivateAPI: { + privateFunction(): string; PrivateClass: { new(): PrivateClass; - } - privateFunction(): string; + }, }, } export type Imports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index e15c7bcfb..62d7651e8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -322,22 +322,22 @@ export async function createInstantiator(options, swift) { } const exports = { GlobalAPI: { - GlobalClass, globalFunction: function bjs_GlobalAPI_globalFunction() { instance.exports.bjs_GlobalAPI_globalFunction(); const ret = tmpRetString; tmpRetString = undefined; return ret; }, + GlobalClass, }, PrivateAPI: { - PrivateClass, privateFunction: function bjs_PrivateAPI_privateFunction() { instance.exports.bjs_PrivateAPI_privateFunction(); const ret = tmpRetString; tmpRetString = undefined; return ret; }, + PrivateClass, }, }; _exports = exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.d.ts index 193857072..89aad5c32 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.d.ts @@ -16,10 +16,10 @@ export interface PrivateClass extends SwiftHeapObject { } export type Exports = { PrivateAPI: { + privateFunction(): string; PrivateClass: { new(): PrivateClass; - } - privateFunction(): string; + }, }, } export type Imports = { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index e1605fb10..69bfe5ff1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -295,13 +295,13 @@ export async function createInstantiator(options, swift) { } const exports = { PrivateAPI: { - PrivateClass, privateFunction: function bjs_PrivateAPI_privateFunction() { instance.exports.bjs_PrivateAPI_privateFunction(); const ret = tmpRetString; tmpRetString = undefined; return ret; }, + PrivateClass, }, }; _exports = exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts index ae792be4c..ac9ea13c4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts @@ -89,7 +89,7 @@ export type Exports = { Collections: { Container: { new(): Container; - } + }, }, MyModule: { Utils: { @@ -104,7 +104,7 @@ export type Exports = { Converters: { Converter: { new(): Converter; - } + }, }, }, __Swift: { @@ -113,9 +113,9 @@ export type Exports = { new(name: string): Greeter; makeDefault(): Greeter; readonly defaultGreeting: string; - } + }, UUID: { - } + }, }, }, } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts index 4c02c18b3..debd3ffcf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts @@ -36,7 +36,7 @@ export type Exports = { Collections: { Container: { new(): Container; - } + }, }, MyModule: { Utils: { @@ -51,7 +51,7 @@ export type Exports = { Converters: { Converter: { new(): Converter; - } + }, }, }, __Swift: { @@ -60,9 +60,9 @@ export type Exports = { new(name: string): Greeter; makeDefault(): Greeter; readonly defaultGreeting: string; - } + }, UUID: { - } + }, }, }, } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.d.ts index 4e966661e..c418ed8a5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.d.ts @@ -30,10 +30,10 @@ export interface Player extends SwiftHeapObject { getTag(): string; } export type Exports = { - User: { - } Player: { - } + }, + User: { + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js index 1fb339f32..972f9ae74 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js @@ -351,12 +351,8 @@ export async function createInstantiator(options, swift) { structHelpers.Player_Stats = Player_StatsHelpers; const exports = { - User, Player, - Player: { - }, - User: { - }, + User, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.d.ts index c4a22ac0c..0f64324cd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.d.ts @@ -42,12 +42,6 @@ export interface WithOptionalJSClass { childOrNull: WithOptionalJSClass | null; } export type Exports = { - Greeter: { - new(name: string | null): Greeter; - } - OptionalPropertyHolder: { - new(): OptionalPropertyHolder; - } roundTripOptionalClass(value: Greeter | null): Greeter | null; testOptionalPropertyRoundtrip(holder: OptionalPropertyHolder | null): OptionalPropertyHolder | null; roundTripExportedOptionalJSObject(value: any | null): any | null; @@ -71,6 +65,12 @@ export type Exports = { roundTripAlias(age: number | null): number | null; roundTripOptionalAlias(name: string | null): string | null; testMixedOptionals(firstName: string | null, lastName: string | null, age: number | null, active: boolean): string | null; + Greeter: { + new(name: string | null): Greeter; + }, + OptionalPropertyHolder: { + new(): OptionalPropertyHolder; + }, } export type Imports = { WithOptionalJSClass: { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js index 956582377..5a253cdc0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -685,8 +685,6 @@ export async function createInstantiator(options, swift) { } } const exports = { - Greeter, - OptionalPropertyHolder, roundTripOptionalClass: function bjs_roundTripOptionalClass(value) { const isSome = value != null; let result; @@ -972,6 +970,8 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return optResult; }, + Greeter, + OptionalPropertyHolder, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.d.ts index 8f65849ab..5872a3020 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.d.ts @@ -31,11 +31,11 @@ export interface PropertyHolder extends SwiftHeapObject { observedProperty: number; } export type Exports = { - PropertyHolder: { - new(intValue: number, floatValue: number, doubleValue: number, boolValue: boolean, stringValue: string, jsObject: any): PropertyHolder; - } createPropertyHolder(intValue: number, floatValue: number, doubleValue: number, boolValue: boolean, stringValue: string, jsObject: any): PropertyHolder; testPropertyHolder(holder: PropertyHolder): string; + PropertyHolder: { + new(intValue: number, floatValue: number, doubleValue: number, boolValue: boolean, stringValue: string, jsObject: any): PropertyHolder; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js index 0070d0dbe..61560134a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -406,7 +406,6 @@ export async function createInstantiator(options, swift) { } } const exports = { - PropertyHolder, createPropertyHolder: function bjs_createPropertyHolder(intValue, floatValue, doubleValue, boolValue, stringValue, jsObject) { const stringValueBytes = textEncoder.encode(stringValue); const stringValueId = swift.memory.retain(stringValueBytes); @@ -419,6 +418,7 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }, + PropertyHolder, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.d.ts index 27cd9212b..a413fa500 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.d.ts @@ -96,21 +96,21 @@ export interface DelegateManager extends SwiftHeapObject { delegatesByName: Record; } export type Exports = { - Helper: { - new(value: number): Helper; - } - MyViewController: { - new(delegate: MyViewControllerDelegate): MyViewController; - } - DelegateManager: { - new(delegates: MyViewControllerDelegate[]): DelegateManager; - } processDelegates(delegates: MyViewControllerDelegate[]): MyViewControllerDelegate[]; processDelegatesByName(delegates: Record): Record; Direction: DirectionObject ExampleEnum: ExampleEnumObject Result: ResultObject Priority: PriorityObject + DelegateManager: { + new(delegates: MyViewControllerDelegate[]): DelegateManager; + }, + Helper: { + new(value: number): Helper; + }, + MyViewController: { + new(delegate: MyViewControllerDelegate): MyViewController; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 999210eb5..b2a894ffa 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -793,9 +793,6 @@ export async function createInstantiator(options, swift) { enumHelpers.Result = ResultHelpers; const exports = { - Helper, - MyViewController, - DelegateManager, processDelegates: function bjs_processDelegates(delegates) { for (const elem of delegates) { const objId = swift.memory.retain(elem); @@ -847,6 +844,9 @@ export async function createInstantiator(options, swift) { ExampleEnum: ExampleEnumValues, Result: ResultValues, Priority: PriorityValues, + DelegateManager, + Helper, + MyViewController, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.d.ts index 6b7a9d28d..7d5a3c9aa 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.d.ts @@ -19,13 +19,13 @@ export interface Widget extends SwiftHeapObject { name: string; } export type Exports = { - Widget: { - new(name: string): Widget; - } processRenderable(item: Renderable, transform: (arg0: Renderable) => string): string; makeRenderableFactory(defaultName: string): () => Renderable; roundtripRenderable(callback: (arg0: Renderable) => Renderable): (arg0: Renderable) => Renderable; processOptionalRenderable(callback: (arg0: Renderable | null) => string): string; + Widget: { + new(name: string): Widget; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js index d9c31ed1d..01f9fe0e1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js @@ -447,7 +447,6 @@ export async function createInstantiator(options, swift) { } } const exports = { - Widget, processRenderable: function bjs_processRenderable(item, transform) { const callbackId = swift.memory.retain(transform); instance.exports.bjs_processRenderable(swift.memory.retain(item), callbackId); @@ -473,6 +472,7 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }, + Widget, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.d.ts index 5916e1648..e5602e42d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.d.ts @@ -51,15 +51,15 @@ export interface MathUtils extends SwiftHeapObject { multiply(x: number, y: number): number; } export type Exports = { + Calculator: CalculatorObject + APIResult: APIResultObject MathUtils: { new(): MathUtils; subtract(a: number, b: number): number; add(a: number, b: number): number; divide(a: number, b: number): number; readonly pi: number; - } - Calculator: CalculatorObject - APIResult: APIResultObject + }, Utils: { String: { uppercase(text: string): string; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js index d626e9adf..25f989a00 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -361,7 +361,6 @@ export async function createInstantiator(options, swift) { globalThis.Utils.String = {}; } const exports = { - MathUtils, Calculator: { ...CalculatorValues, square: function(value) { @@ -388,6 +387,7 @@ export async function createInstantiator(options, swift) { return ret; } }, + MathUtils, Utils: { String: { uppercase: function bjs_Utils_String_static_uppercase(text) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.d.ts index c9cb26910..a168f3ad1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.d.ts @@ -41,15 +41,15 @@ export interface MathUtils extends SwiftHeapObject { multiply(x: number, y: number): number; } export type Exports = { + Calculator: CalculatorObject + APIResult: APIResultObject MathUtils: { new(): MathUtils; subtract(a: number, b: number): number; add(a: number, b: number): number; divide(a: number, b: number): number; readonly pi: number; - } - Calculator: CalculatorObject - APIResult: APIResultObject + }, Utils: { String: { uppercase(text: string): string; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js index 93f1e7ec7..ca4093992 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -355,7 +355,6 @@ export async function createInstantiator(options, swift) { enumHelpers.APIResult = APIResultHelpers; const exports = { - MathUtils, Calculator: { ...CalculatorValues, square: function(value) { @@ -382,6 +381,7 @@ export async function createInstantiator(options, swift) { return ret; } }, + MathUtils, Utils: { String: { uppercase: function bjs_Utils_String_static_uppercase(text) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.d.ts index fea3c4b59..b54e14def 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.d.ts @@ -40,6 +40,7 @@ export interface SwiftHeapObject { export interface PropertyClass extends SwiftHeapObject { } export type Exports = { + PropertyEnum: PropertyEnumObject PropertyClass: { new(): PropertyClass; readonly staticConstant: string; @@ -49,8 +50,7 @@ export type Exports = { computedProperty: string; readonly readOnlyComputed: number; optionalProperty: string | null; - } - PropertyEnum: PropertyEnumObject + }, PropertyNamespace: { readonly namespaceConstant: string; namespaceProperty: string; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js index edf069178..63dd9cba5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -367,7 +367,6 @@ export async function createInstantiator(options, swift) { globalThis.PropertyNamespace.Nested = {}; } const exports = { - PropertyClass, PropertyEnum: { ...PropertyEnumValues, get enumProperty() { @@ -397,6 +396,7 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_PropertyEnum_static_computedEnum_set(valueId, valueBytes.length); } }, + PropertyClass, PropertyNamespace: { get namespaceProperty() { instance.exports.bjs_PropertyNamespace_static_namespaceProperty_get(); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.d.ts index 4ce689edb..aea927c79 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.d.ts @@ -26,6 +26,7 @@ export interface SwiftHeapObject { export interface PropertyClass extends SwiftHeapObject { } export type Exports = { + PropertyEnum: PropertyEnumObject PropertyClass: { new(): PropertyClass; readonly staticConstant: string; @@ -35,8 +36,7 @@ export type Exports = { computedProperty: string; readonly readOnlyComputed: number; optionalProperty: string | null; - } - PropertyEnum: PropertyEnumObject + }, PropertyNamespace: { readonly namespaceConstant: string; namespaceProperty: string; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js index 64132a3c2..b5680b9b0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -361,7 +361,6 @@ export async function createInstantiator(options, swift) { } } const exports = { - PropertyClass, PropertyEnum: { ...PropertyEnumValues, get enumProperty() { @@ -391,6 +390,7 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_PropertyEnum_static_computedEnum_set(valueId, valueBytes.length); } }, + PropertyClass, PropertyNamespace: { get namespaceProperty() { instance.exports.bjs_PropertyNamespace_static_namespaceProperty_get(); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.d.ts new file mode 100644 index 000000000..fe4708fd8 --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.d.ts @@ -0,0 +1,73 @@ +// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit, +// DO NOT EDIT. +// +// To update this file, just rebuild your project or run +// `swift package bridge-js`. + +export interface Shape { + label: string; +} +export interface Widget { + name: string; +} +export type KindObject = typeof Shape.KindValues; + +export type VariantObject = typeof Widget.VariantValues; + +export type AlignmentObject = typeof Widget.Layout.AlignmentValues; + +export namespace Shape { + const KindValues: { + readonly Circle: "circle"; + readonly Square: "square"; + }; + type KindTag = typeof KindValues[keyof typeof KindValues]; +} +export namespace Widget { + const VariantValues: { + readonly Button: "button"; + readonly Slider: "slider"; + }; + type VariantTag = typeof VariantValues[keyof typeof VariantValues]; + export interface Bounds { + width: number; + height: number; + } + export interface Layout { + padding: number; + } + export namespace Layout { + const AlignmentValues: { + readonly Leading: "leading"; + readonly Trailing: "trailing"; + }; + type AlignmentTag = typeof AlignmentValues[keyof typeof AlignmentValues]; + } +} +export type Exports = { + Shape: { + init(label: string): Shape; + Kind: KindObject + }, + Widget: { + init(name: string): Widget; + Variant: VariantObject + Bounds: { + init(width: number, height: number): Widget.Bounds; + readonly dimensions: number; + zero(): Widget.Bounds; + }, + Layout: { + Alignment: AlignmentObject + }, + }, +} +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/StructWithNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js new file mode 100644 index 000000000..ee5cc0a3e --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js @@ -0,0 +1,364 @@ +// 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 KindValues = { + Circle: "circle", + Square: "square", +}; + +export const VariantValues = { + Button: "button", + Slider: "slider", +}; + +export const AlignmentValues = { + Leading: "leading", + Trailing: "trailing", +}; + +export async function createInstantiator(options, swift) { + let instance; + let memory; + let setException; + let decodeString; + const textDecoder = new TextDecoder("utf-8"); + const textEncoder = new TextEncoder("utf-8"); + let tmpRetString; + let tmpRetBytes; + let tmpRetException; + let tmpRetOptionalBool; + let tmpRetOptionalInt; + let tmpRetOptionalFloat; + let tmpRetOptionalDouble; + let tmpRetOptionalHeapObject; + let strStack = []; + let i32Stack = []; + let i64Stack = []; + let f32Stack = []; + let f64Stack = []; + let ptrStack = []; + let taStack = []; + const enumHelpers = {}; + const structHelpers = {}; + + let _exports = null; + let bjs = null; + const __bjs_createShapeHelpers = () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.label); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + }, + lift: () => { + const string = strStack.pop(); + return { label: string }; + } + }); + const __bjs_createWidgetHelpers = () => ({ + lower: (value) => { + const bytes = textEncoder.encode(value.name); + const id = swift.memory.retain(bytes); + i32Stack.push(bytes.length); + i32Stack.push(id); + }, + lift: () => { + const string = strStack.pop(); + return { name: string }; + } + }); + const __bjs_createWidget_LayoutHelpers = () => ({ + lower: (value) => { + i32Stack.push((value.padding | 0)); + }, + lift: () => { + const int = i32Stack.pop(); + return { padding: int }; + } + }); + const __bjs_createWidget_BoundsHelpers = () => ({ + lower: (value) => { + i32Stack.push((value.width | 0)); + i32Stack.push((value.height | 0)); + }, + lift: () => { + const int = i32Stack.pop(); + const int1 = i32Stack.pop(); + return { width: int1, height: int }; + } + }); + + return { + /** + * @param {WebAssembly.Imports} importObject + */ + addImports: (importObject, importsContext) => { + bjs = {}; + importObject["bjs"] = bjs; + bjs["swift_js_return_string"] = function(ptr, len) { + tmpRetString = decodeString(ptr, len); + } + bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { + const source = swift.memory.getObject(sourceId); + swift.memory.release(sourceId); + const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); + bytes.set(source); + } + bjs["swift_js_make_js_string"] = function(ptr, len) { + return swift.memory.retain(decodeString(ptr, len)); + } + bjs["swift_js_init_memory_with_result"] = function(ptr, len) { + const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); + target.set(tmpRetBytes); + tmpRetBytes = undefined; + } + bjs["swift_js_throw"] = function(id) { + tmpRetException = swift.memory.retainByRef(id); + } + bjs["swift_js_retain"] = function(id) { + return swift.memory.retainByRef(id); + } + bjs["swift_js_release"] = function(id) { + swift.memory.release(id); + } + bjs["swift_js_push_i32"] = function(v) { + i32Stack.push(v | 0); + } + bjs["swift_js_push_f32"] = function(v) { + f32Stack.push(Math.fround(v)); + } + bjs["swift_js_push_f64"] = function(v) { + f64Stack.push(v); + } + bjs["swift_js_push_string"] = function(ptr, len) { + const value = decodeString(ptr, len); + strStack.push(value); + } + bjs["swift_js_pop_i32"] = function() { + return i32Stack.pop(); + } + bjs["swift_js_pop_f32"] = function() { + return f32Stack.pop(); + } + bjs["swift_js_pop_f64"] = function() { + return f64Stack.pop(); + } + bjs["swift_js_push_pointer"] = function(pointer) { + ptrStack.push(pointer); + } + bjs["swift_js_pop_pointer"] = function() { + return ptrStack.pop(); + } + bjs["swift_js_push_i64"] = function(v) { + i64Stack.push(v); + } + bjs["swift_js_pop_i64"] = function() { + return i64Stack.pop(); + } + const taCtors = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]; + bjs["swift_js_push_typed_array"] = function(kind, ptr, count) { + const Ctor = taCtors[kind]; + const byteLen = count * Ctor.BYTES_PER_ELEMENT; + const copy = memory.buffer.slice(ptr, ptr + byteLen); + taStack.push(Array.from(new Ctor(copy))); + } + bjs["swift_js_struct_lower_Shape"] = function(objectId) { + structHelpers.Shape.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_Shape"] = function() { + const value = structHelpers.Shape.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Widget"] = function(objectId) { + structHelpers.Widget.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_Widget"] = function() { + const value = structHelpers.Widget.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Widget_Layout"] = function(objectId) { + structHelpers.Widget_Layout.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_Widget_Layout"] = function() { + const value = structHelpers.Widget_Layout.lift(); + return swift.memory.retain(value); + } + bjs["swift_js_struct_lower_Widget_Bounds"] = function(objectId) { + structHelpers.Widget_Bounds.lower(swift.memory.getObject(objectId)); + } + bjs["swift_js_struct_lift_Widget_Bounds"] = function() { + const value = structHelpers.Widget_Bounds.lift(); + return swift.memory.retain(value); + } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } + bjs["swift_js_return_optional_bool"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalBool = null; + } else { + tmpRetOptionalBool = value !== 0; + } + } + bjs["swift_js_return_optional_int"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalInt = null; + } else { + tmpRetOptionalInt = value | 0; + } + } + bjs["swift_js_return_optional_float"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalFloat = null; + } else { + tmpRetOptionalFloat = Math.fround(value); + } + } + bjs["swift_js_return_optional_double"] = function(isSome, value) { + if (isSome === 0) { + tmpRetOptionalDouble = null; + } else { + tmpRetOptionalDouble = value; + } + } + bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = decodeString(ptr, len); + } + } + bjs["swift_js_return_optional_object"] = function(isSome, objectId) { + if (isSome === 0) { + tmpRetString = null; + } else { + tmpRetString = swift.memory.getObject(objectId); + } + } + bjs["swift_js_return_optional_heap_object"] = function(isSome, pointer) { + if (isSome === 0) { + tmpRetOptionalHeapObject = null; + } else { + tmpRetOptionalHeapObject = pointer; + } + } + bjs["swift_js_get_optional_int_presence"] = function() { + return tmpRetOptionalInt != null ? 1 : 0; + } + bjs["swift_js_get_optional_int_value"] = function() { + const value = tmpRetOptionalInt; + tmpRetOptionalInt = undefined; + return value; + } + bjs["swift_js_get_optional_string"] = function() { + const str = tmpRetString; + tmpRetString = undefined; + if (str == null) { + return -1; + } else { + const bytes = textEncoder.encode(str); + tmpRetBytes = bytes; + return bytes.length; + } + } + bjs["swift_js_get_optional_float_presence"] = function() { + return tmpRetOptionalFloat != null ? 1 : 0; + } + bjs["swift_js_get_optional_float_value"] = function() { + const value = tmpRetOptionalFloat; + tmpRetOptionalFloat = undefined; + return value; + } + bjs["swift_js_get_optional_double_presence"] = function() { + return tmpRetOptionalDouble != null ? 1 : 0; + } + bjs["swift_js_get_optional_double_value"] = function() { + const value = tmpRetOptionalDouble; + tmpRetOptionalDouble = undefined; + return value; + } + bjs["swift_js_get_optional_heap_object_pointer"] = function() { + const pointer = tmpRetOptionalHeapObject; + tmpRetOptionalHeapObject = undefined; + return pointer || 0; + } + bjs["swift_js_closure_unregister"] = function(funcRef) {} + }, + setInstance: (i) => { + instance = i; + memory = instance.exports.memory; + + decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + + setException = (error) => { + instance.exports._swift_js_exception.value = swift.memory.retain(error) + } + }, + /** @param {WebAssembly.Instance} instance */ + createExports: (instance) => { + const js = swift.memory.heap; + const ShapeHelpers = __bjs_createShapeHelpers(); + structHelpers.Shape = ShapeHelpers; + + const WidgetHelpers = __bjs_createWidgetHelpers(); + structHelpers.Widget = WidgetHelpers; + + const Widget_LayoutHelpers = __bjs_createWidget_LayoutHelpers(); + structHelpers.Widget_Layout = Widget_LayoutHelpers; + + const Widget_BoundsHelpers = __bjs_createWidget_BoundsHelpers(); + structHelpers.Widget_Bounds = Widget_BoundsHelpers; + + const exports = { + Shape: { + init: function(label) { + const labelBytes = textEncoder.encode(label); + const labelId = swift.memory.retain(labelBytes); + instance.exports.bjs_Shape_init(labelId, labelBytes.length); + const structValue = structHelpers.Shape.lift(); + return structValue; + }, + Kind: KindValues, + }, + Widget: { + init: function(name) { + const nameBytes = textEncoder.encode(name); + const nameId = swift.memory.retain(nameBytes); + instance.exports.bjs_Widget_init(nameId, nameBytes.length); + const structValue = structHelpers.Widget.lift(); + return structValue; + }, + Variant: VariantValues, + Bounds: { + init: function(width, height) { + instance.exports.bjs_Widget_Bounds_init(width, height); + const structValue = structHelpers.Widget_Bounds.lift(); + return structValue; + }, + get dimensions() { + const ret = instance.exports.bjs_Widget_Bounds_static_dimensions_get(); + return ret; + }, + zero: function() { + instance.exports.bjs_Widget_Bounds_static_zero(); + const structValue = structHelpers.Widget_Bounds.lift(); + return structValue; + }, + }, + Layout: { + Alignment: AlignmentValues, + }, + }, + }; + _exports = exports; + return exports; + }, + } +} \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts index 6d590950c..2f56a1cb8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.d.ts @@ -23,16 +23,16 @@ export interface PublicGreeter extends SwiftHeapObject { export interface PackageGreeter extends SwiftHeapObject { } export type Exports = { + takeGreeter(greeter: Greeter): void; Greeter: { new(name: string): Greeter; greetAnonymously(): string; readonly defaultGreeting: string; - } - PublicGreeter: { - } + }, PackageGreeter: { - } - takeGreeter(greeter: Greeter): void; + }, + PublicGreeter: { + }, } export type Imports = { jsRoundTripGreeter(greeter: Greeter): Greeter; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 7f9fb8a20..be63f59be 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -374,12 +374,12 @@ export async function createInstantiator(options, swift) { } const exports = { - Greeter, - PublicGreeter, - PackageGreeter, takeGreeter: function bjs_takeGreeter(greeter) { instance.exports.bjs_takeGreeter(greeter.pointer); }, + Greeter, + PackageGreeter, + PublicGreeter, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts index be62eeedd..70f23c11a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.d.ts @@ -64,12 +64,6 @@ export interface Person extends SwiftHeapObject { export interface TestProcessor extends SwiftHeapObject { } export type Exports = { - Person: { - new(name: string): Person; - } - TestProcessor: { - new(transform: (arg0: string) => string): TestProcessor; - } roundtripAnimal(animalClosure: (arg0: Animal) => Animal): (arg0: Animal) => Animal; roundtripOptionalAnimal(animalClosure: (arg0: Animal | null) => Animal | null): (arg0: Animal | null) => Animal | null; roundtripString(stringClosure: (arg0: string) => string): (arg0: string) => string; @@ -105,7 +99,13 @@ export type Exports = { APIResult: APIResultObject Animal: { init(type: string): Animal; - } + }, + Person: { + new(name: string): Person; + }, + TestProcessor: { + new(transform: (arg0: string) => string): TestProcessor; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index f5912b3f5..f3b9d987c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -1422,8 +1422,6 @@ export async function createInstantiator(options, swift) { enumHelpers.APIResult = APIResultHelpers; const exports = { - Person, - TestProcessor, roundtripAnimal: function bjs_roundtripAnimal(animalClosure) { const callbackId = swift.memory.retain(animalClosure); const ret = instance.exports.bjs_roundtripAnimal(callbackId); @@ -1576,6 +1574,8 @@ export async function createInstantiator(options, swift) { return structValue; }, }, + Person, + TestProcessor, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.d.ts index bf4ebc71f..14ddf714e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.d.ts @@ -63,24 +63,24 @@ export interface Greeter extends SwiftHeapObject { name: string; } export type Exports = { - Greeter: { - new(name: string): Greeter; - } roundtrip(session: Person): Person; roundtripContainer(container: Container): Container; Precision: PrecisionObject - DataPoint: { - init(x: number, y: number, label: string, optCount: number | null, optFlag: boolean | null): DataPoint; - readonly dimensions: number; - origin(): DataPoint; - } ConfigStruct: { readonly maxRetries: number; defaultConfig: string; timeout: number; readonly computedSetting: string; update(timeout: number): number; - } + }, + DataPoint: { + init(x: number, y: number, label: string, optCount: number | null, optFlag: boolean | null): DataPoint; + readonly dimensions: number; + origin(): DataPoint; + }, + Greeter: { + new(name: string): Greeter; + }, } export type Imports = { } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js index b25010a23..44ae8a39d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -600,7 +600,6 @@ export async function createInstantiator(options, swift) { structHelpers.Vector2D = Vector2DHelpers; const exports = { - Greeter, roundtrip: function bjs_roundtrip(session) { structHelpers.Person.lower(session); instance.exports.bjs_roundtrip(); @@ -614,26 +613,6 @@ export async function createInstantiator(options, swift) { return structValue; }, Precision: PrecisionValues, - DataPoint: { - init: function(x, y, label, optCount, optFlag) { - const labelBytes = textEncoder.encode(label); - const labelId = swift.memory.retain(labelBytes); - const isSome = optCount != null; - const isSome1 = optFlag != null; - instance.exports.bjs_DataPoint_init(x, y, labelId, labelBytes.length, +isSome, isSome ? optCount : 0, +isSome1, isSome1 ? optFlag ? 1 : 0 : 0); - const structValue = structHelpers.DataPoint.lift(); - return structValue; - }, - get dimensions() { - const ret = instance.exports.bjs_DataPoint_static_dimensions_get(); - return ret; - }, - origin: function() { - instance.exports.bjs_DataPoint_static_origin(); - const structValue = structHelpers.DataPoint.lift(); - return structValue; - }, - }, ConfigStruct: { get maxRetries() { const ret = instance.exports.bjs_ConfigStruct_static_maxRetries_get(); @@ -668,6 +647,27 @@ export async function createInstantiator(options, swift) { return ret; }, }, + DataPoint: { + init: function(x, y, label, optCount, optFlag) { + const labelBytes = textEncoder.encode(label); + const labelId = swift.memory.retain(labelBytes); + const isSome = optCount != null; + const isSome1 = optFlag != null; + instance.exports.bjs_DataPoint_init(x, y, labelId, labelBytes.length, +isSome, isSome ? optCount : 0, +isSome1, isSome1 ? optFlag ? 1 : 0 : 0); + const structValue = structHelpers.DataPoint.lift(); + return structValue; + }, + get dimensions() { + const ret = instance.exports.bjs_DataPoint_static_dimensions_get(); + return ret; + }, + origin: function() { + instance.exports.bjs_DataPoint_static_origin(); + const structValue = structHelpers.DataPoint.lift(); + return structValue; + }, + }, + Greeter, }; _exports = exports; return exports; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.d.ts index 4f9aa4e4a..5a4ee78ce 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.d.ts @@ -25,7 +25,7 @@ export type Exports = { roundTripPointerFields(value: PointerFields): PointerFields; PointerFields: { init(raw: number, mutRaw: number, opaque: number, ptr: number, mutPtr: number): PointerFields; - } + }, } export type Imports = { } diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 282b7cc60..92bf7ff68 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -1359,6 +1359,27 @@ enum GraphOperations { @JS static func roundtripMetadata(_ m: Metadata) -> Metadata { m } } +@JS class NestedTypeHost { + @JS enum Variant: String { + case primary + case secondary + } + + @JS struct Label { + var text: String + + @JS init(text: String) { + self.text = text + } + } + + @JS init() {} + + @JS func describe() -> String { + "host" + } +} + class ExportAPITests: XCTestCase { func testAll() { var hasDeinitGreeter = false diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 8968773a4..ff22e7fbe 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -5797,6 +5797,9 @@ public func _bjs_NestedStructGroupB_static_roundtripMetadata() -> Void { #endif } +extension NestedTypeHost.Variant: _BridgedSwiftEnumNoPayload, _BridgedSwiftRawValueEnum { +} + extension LightColor: _BridgedSwiftCaseEnum { @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 { return bridgeJSRawValue @@ -6573,6 +6576,63 @@ fileprivate func _bjs_struct_lift_NestedStructGroupB_Metadata_extern() -> Int32 return _bjs_struct_lift_NestedStructGroupB_Metadata_extern() } +extension NestedTypeHost.Label: _BridgedSwiftStruct { + @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> NestedTypeHost.Label { + let text = String.bridgeJSStackPop() + return NestedTypeHost.Label(text: text) + } + + @_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPush() { + self.text.bridgeJSStackPush() + } + + init(unsafelyCopying jsObject: JSObject) { + _bjs_struct_lower_NestedTypeHost_Label(jsObject.bridgeJSLowerParameter()) + self = Self.bridgeJSStackPop() + } + + func toJSObject() -> JSObject { + let __bjs_self = self + __bjs_self.bridgeJSStackPush() + return JSObject(id: UInt32(bitPattern: _bjs_struct_lift_NestedTypeHost_Label())) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_NestedTypeHost_Label") +fileprivate func _bjs_struct_lower_NestedTypeHost_Label_extern(_ objectId: Int32) -> Void +#else +fileprivate func _bjs_struct_lower_NestedTypeHost_Label_extern(_ objectId: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lower_NestedTypeHost_Label(_ objectId: Int32) -> Void { + return _bjs_struct_lower_NestedTypeHost_Label_extern(objectId) +} + +#if arch(wasm32) +@_extern(wasm, module: "bjs", name: "swift_js_struct_lift_NestedTypeHost_Label") +fileprivate func _bjs_struct_lift_NestedTypeHost_Label_extern() -> Int32 +#else +fileprivate func _bjs_struct_lift_NestedTypeHost_Label_extern() -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_struct_lift_NestedTypeHost_Label() -> Int32 { + return _bjs_struct_lift_NestedTypeHost_Label_extern() +} + +@_expose(wasm, "bjs_NestedTypeHost_Label_init") +@_cdecl("bjs_NestedTypeHost_Label_init") +public func _bjs_NestedTypeHost_Label_init(_ textBytes: Int32, _ textLength: Int32) -> Void { + #if arch(wasm32) + let ret = NestedTypeHost.Label(text: String.bridgeJSLiftParameter(textBytes, textLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + extension Point: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Point { let y = Int.bridgeJSStackPop() @@ -12882,6 +12942,59 @@ fileprivate func _bjs_TextProcessor_wrap_extern(_ pointer: UnsafeMutableRawPoint return _bjs_TextProcessor_wrap_extern(pointer) } +@_expose(wasm, "bjs_NestedTypeHost_init") +@_cdecl("bjs_NestedTypeHost_init") +public func _bjs_NestedTypeHost_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = NestedTypeHost() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_NestedTypeHost_describe") +@_cdecl("bjs_NestedTypeHost_describe") +public func _bjs_NestedTypeHost_describe(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = NestedTypeHost.bridgeJSLiftParameter(_self).describe() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_NestedTypeHost_deinit") +@_cdecl("bjs_NestedTypeHost_deinit") +public func _bjs_NestedTypeHost_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension NestedTypeHost: ConvertibleToJSValue, _BridgedSwiftHeapObject, _BridgedSwiftProtocolExportable { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_NestedTypeHost_wrap(Unmanaged.passRetained(self).toOpaque())))) + } + consuming func bridgeJSLowerAsProtocolReturn() -> Int32 { + _bjs_NestedTypeHost_wrap(Unmanaged.passRetained(self).toOpaque()) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_NestedTypeHost_wrap") +fileprivate func _bjs_NestedTypeHost_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_NestedTypeHost_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_NestedTypeHost_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_NestedTypeHost_wrap_extern(pointer) +} + @_expose(wasm, "bjs_OptionalHolder_init") @_cdecl("bjs_OptionalHolder_init") public func _bjs_OptionalHolder_init(_ nullableGreeterIsSome: Int32, _ nullableGreeterValue: UnsafeMutableRawPointer, _ undefinedNumberIsSome: Int32, _ undefinedNumberValue: Float64) -> UnsafeMutableRawPointer { diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index 25fd27d9f..018eceded 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -4705,6 +4705,43 @@ ], "swiftCallName" : "TextProcessor" }, + { + "constructor" : { + "abiName" : "bjs_NestedTypeHost_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_NestedTypeHost_describe", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "describe", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "NestedTypeHost", + "properties" : [ + + ], + "swiftCallName" : "NestedTypeHost" + }, { "constructor" : { "abiName" : "bjs_OptionalHolder_init", @@ -10002,6 +10039,36 @@ { "associatedValues" : [ + ], + "name" : "primary" + }, + { + "associatedValues" : [ + + ], + "name" : "secondary" + } + ], + "emitStyle" : "const", + "name" : "Variant", + "namespace" : [ + "NestedTypeHost" + ], + "rawType" : "String", + "staticMethods" : [ + + ], + "staticProperties" : [ + + ], + "swiftCallName" : "NestedTypeHost.Variant", + "tsFullPath" : "NestedTypeHost.Variant" + }, + { + "cases" : [ + { + "associatedValues" : [ + ], "name" : "red" }, @@ -18037,6 +18104,50 @@ ], "swiftCallName" : "NestedStructGroupB.Metadata" }, + { + "constructor" : { + "abiName" : "bjs_NestedTypeHost_Label_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "text", + "name" : "text", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + + ], + "name" : "Label", + "namespace" : [ + "NestedTypeHost" + ], + "properties" : [ + { + "isReadonly" : true, + "isStatic" : false, + "name" : "text", + "namespace" : [ + "NestedTypeHost" + ], + "type" : { + "string" : { + + } + } + } + ], + "swiftCallName" : "NestedTypeHost.Label" + }, { "methods" : [ diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index f431209dd..1bd824da5 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -683,6 +683,14 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { testServer.call(exports.Networking.APIV2.Internal.SupportedMethod.Post); testServer.release(); + const nestedHost = new exports.NestedTypeHost(); + assert.equal(nestedHost.describe(), "host"); + assert.equal(exports.NestedTypeHost.Variant.Primary, "primary"); + assert.equal(exports.NestedTypeHost.Variant.Secondary, "secondary"); + const hostLabel = exports.NestedTypeHost.Label.init("Save"); + assert.equal(hostLabel.text, "Save"); + nestedHost.release(); + const s1 = { tag: exports.APIResult.Tag.Success, param0: "Cześć 🙋‍♂️" }; const f1 = { tag: exports.APIResult.Tag.Failure, param0: 42 }; const i1 = { tag: APIResultValues.Tag.Info }; From 86097064bb078276cbd314e56141655465e9ddf9 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Wed, 1 Jul 2026 23:46:02 +0200 Subject: [PATCH 2/3] BridgeJS: Fix static property call expression for nested structs and enums --- Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift | 4 ++-- .../BridgeJSCodegenTests/ClassWithNestedTypes.swift | 2 +- .../BridgeJSCodegenTests/StructWithNestedTypes.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 663c2362e..2cc551857 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -560,7 +560,7 @@ public class ExportSwift { func callName(for property: ExportedProperty) -> String { switch self { case .enumStatic(let enumDef): - return property.callName(prefix: enumDef.swiftCallName) + return "\(enumDef.swiftCallName).\(property.name)" case .classStatic(let klass): // property.callName() would use staticContext (the ABI name) as prefix; // use swiftCallName directly so the emitted expression is valid Swift. @@ -568,7 +568,7 @@ public class ExportSwift { case .classInstance: return property.callName() case .structStatic(let structDef): - return property.callName(prefix: structDef.swiftCallName) + return "\(structDef.swiftCallName).\(property.name)" } } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.swift index 3ae08e13a..52c633045 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ClassWithNestedTypes.swift @@ -62,7 +62,7 @@ public func _bjs_Account_Credentials_init(_ tokenBytes: Int32, _ tokenLength: In @_cdecl("bjs_Account_Credentials_static_maxLength_get") public func _bjs_Account_Credentials_static_maxLength_get() -> Int32 { #if arch(wasm32) - let ret = Account_Credentials.maxLength + let ret = Account.Credentials.maxLength return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.swift index f8843b7cd..ad99f0a03 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StructWithNestedTypes.swift @@ -230,7 +230,7 @@ public func _bjs_Widget_Bounds_init(_ width: Int32, _ height: Int32) -> Void { @_cdecl("bjs_Widget_Bounds_static_dimensions_get") public func _bjs_Widget_Bounds_static_dimensions_get() -> Int32 { #if arch(wasm32) - let ret = Widget_Bounds.dimensions + let ret = Widget.Bounds.dimensions return ret.bridgeJSLowerReturn() #else fatalError("Only available on WebAssembly") From 79a58f210b6a66e1e171f3d7d564d8faafb9b099 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Wed, 1 Jul 2026 23:46:02 +0200 Subject: [PATCH 3/3] BridgeJS: Add runtime coverage for nested static members --- .../BridgeJSRuntimeTests/ExportAPITests.swift | 6 +++ .../Generated/BridgeJS.swift | 22 +++++++++++ .../Generated/JavaScript/BridgeJS.json | 39 +++++++++++++++++++ Tests/prelude.mjs | 2 + 4 files changed, 69 insertions(+) diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 92bf7ff68..5a852a23d 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -1371,6 +1371,12 @@ enum GraphOperations { @JS init(text: String) { self.text = text } + + @JS static var maxLength: Int { 64 } + + @JS static func untitled() -> Label { + Label(text: "untitled") + } } @JS init() {} diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index ff22e7fbe..a3104e685 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -6633,6 +6633,28 @@ public func _bjs_NestedTypeHost_Label_init(_ textBytes: Int32, _ textLength: Int #endif } +@_expose(wasm, "bjs_NestedTypeHost_Label_static_maxLength_get") +@_cdecl("bjs_NestedTypeHost_Label_static_maxLength_get") +public func _bjs_NestedTypeHost_Label_static_maxLength_get() -> Int32 { + #if arch(wasm32) + let ret = NestedTypeHost.Label.maxLength + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_NestedTypeHost_Label_static_untitled") +@_cdecl("bjs_NestedTypeHost_Label_static_untitled") +public func _bjs_NestedTypeHost_Label_static_untitled() -> Void { + #if arch(wasm32) + let ret = NestedTypeHost.Label.untitled() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + extension Point: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> Point { let y = Int.bridgeJSStackPop() diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index 018eceded..451a3213d 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -18125,7 +18125,28 @@ ] }, "methods" : [ + { + "abiName" : "bjs_NestedTypeHost_Label_static_untitled", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "untitled", + "parameters" : [ + ], + "returnType" : { + "swiftStruct" : { + "_0" : "NestedTypeHost.Label" + } + }, + "staticContext" : { + "structName" : { + "_0" : "NestedTypeHost_Label" + } + } + } ], "name" : "Label", "namespace" : [ @@ -18144,6 +18165,24 @@ } } + }, + { + "isReadonly" : true, + "isStatic" : true, + "name" : "maxLength", + "staticContext" : { + "structName" : { + "_0" : "NestedTypeHost_Label" + } + }, + "type" : { + "integer" : { + "_0" : { + "isSigned" : true, + "width" : "word" + } + } + } } ], "swiftCallName" : "NestedTypeHost.Label" diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 1bd824da5..887510e65 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -689,6 +689,8 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(exports.NestedTypeHost.Variant.Secondary, "secondary"); const hostLabel = exports.NestedTypeHost.Label.init("Save"); assert.equal(hostLabel.text, "Save"); + assert.equal(exports.NestedTypeHost.Label.maxLength, 64); + assert.equal(exports.NestedTypeHost.Label.untitled().text, "untitled"); nestedHost.release(); const s1 = { tag: exports.APIResult.Tag.Success, param0: "Cześć 🙋‍♂️" };