From 8ebcc227a0f900ff8c155579eff136a5d001dac4 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Fri, 20 Feb 2026 11:42:55 +0100 Subject: [PATCH] BridgeJS: fix _exports access for namespaced classes in JS codegen --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 28 ++- .../Sources/BridgeJSLink/JSGlueGen.swift | 39 +++- .../BridgeJSLink/JSIntrinsicRegistry.swift | 2 + .../Inputs/MacroSwift/Namespaces.swift | 16 ++ .../Namespaces.Global.json | 69 ++++++ .../Namespaces.Global.swift | 60 +++++ .../BridgeJSCodegenTests/Namespaces.json | 69 ++++++ .../BridgeJSCodegenTests/Namespaces.swift | 60 +++++ .../BridgeJSLinkTests/ArrayTypes.js | 4 +- .../BridgeJSLinkTests/DictionaryTypes.js | 4 +- .../BridgeJSLinkTests/EnumNamespace.Global.js | 6 +- .../BridgeJSLinkTests/EnumNamespace.js | 6 +- .../BridgeJSLinkTests/MixedGlobal.js | 2 +- .../BridgeJSLinkTests/MixedModules.js | 4 +- .../BridgeJSLinkTests/MixedPrivate.js | 2 +- .../BridgeJSLinkTests/Namespaces.Global.d.ts | 16 ++ .../BridgeJSLinkTests/Namespaces.Global.js | 42 +++- .../BridgeJSLinkTests/Namespaces.d.ts | 9 + .../BridgeJSLinkTests/Namespaces.js | 38 ++- .../BridgeJSRuntimeTests/ExportAPITests.swift | 37 +++ .../Generated/BridgeJS.swift | 137 +++++++++++ .../Generated/JavaScript/BridgeJS.json | 218 ++++++++++++++++++ .../JavaScript/SwiftClassSupportTests.mjs | 3 + .../SwiftClassSupportTests.swift | 6 + Tests/prelude.mjs | 26 +++ 25 files changed, 870 insertions(+), 33 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index ddd54a333..ce9d4bb67 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -978,7 +978,9 @@ public struct BridgeJSLink { [structDef.name], IntrinsicJSFragment.PrintCodeContext( scope: structScope, - printer: structPrinter + printer: structPrinter, + hasDirectAccessToSwiftClass: false, + classNamespaces: intrinsicRegistry.classNamespaces ) ) bodyPrinter.write(lines: structPrinter.lines) @@ -995,7 +997,9 @@ public struct BridgeJSLink { [enumDef.valuesName], IntrinsicJSFragment.PrintCodeContext( scope: enumScope, - printer: enumPrinter + printer: enumPrinter, + hasDirectAccessToSwiftClass: false, + classNamespaces: intrinsicRegistry.classNamespaces ) ) bodyPrinter.write(lines: enumPrinter.lines) @@ -1079,6 +1083,14 @@ public struct BridgeJSLink { public func link() throws -> (outputJs: String, outputDts: String) { intrinsicRegistry.reset() + intrinsicRegistry.classNamespaces = skeletons.reduce(into: [:]) { result, unified in + guard let skeleton = unified.exported else { return } + for klass in skeleton.classes { + if let namespace = klass.namespace { + result[klass.name] = namespace + } + } + } let data = try collectLinkData() let outputJs = try generateJavaScript(data: data) let outputDts = generateTypeScript(data: data) @@ -1144,8 +1156,11 @@ public struct BridgeJSLink { for klass in classes.sorted(by: { $0.name < $1.name }) { let wrapperFunctionName = "bjs_\(klass.name)_wrap" + let namespacePath = (klass.namespace ?? []).map { ".\($0)" }.joined() + let exportsPath = + namespacePath.isEmpty ? "_exports['\(klass.name)']" : "_exports\(namespacePath).\(klass.name)" wrapperLines.append("importObject[\"\(moduleName)\"][\"\(wrapperFunctionName)\"] = function(pointer) {") - wrapperLines.append(" const obj = _exports['\(klass.name)'].__construct(pointer);") + wrapperLines.append(" const obj = \(exportsPath).__construct(pointer);") wrapperLines.append(" return \(JSGlueVariableScope.reservedSwift).memory.retain(obj);") wrapperLines.append("};") } @@ -1252,7 +1267,8 @@ public struct BridgeJSLink { self.context = IntrinsicJSFragment.PrintCodeContext( scope: scope, printer: body, - hasDirectAccessToSwiftClass: hasDirectAccessToSwiftClass + hasDirectAccessToSwiftClass: hasDirectAccessToSwiftClass, + classNamespaces: intrinsicRegistry.classNamespaces ) } @@ -2147,7 +2163,9 @@ extension BridgeJSLink { self.context = context self.printContext = IntrinsicJSFragment.PrintCodeContext( scope: scope, - printer: body + printer: body, + hasDirectAccessToSwiftClass: false, + classNamespaces: intrinsicRegistry.classNamespaces ) } diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 6f848eb05..63eb6cc0b 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -137,14 +137,36 @@ struct IntrinsicJSFragment: Sendable { /// The printer to print the main fragment code. var printer: CodeFragmentPrinter /// Whether the fragment has direct access to the SwiftHeapObject classes. - /// If false, the fragment needs to use `_exports[""]` to access the class. + /// If false, the fragment needs to use `_exports` to access the class. var hasDirectAccessToSwiftClass: Bool = true + /// Maps class names to their namespace path components for resolving `_exports` access. + var classNamespaces: [String: [String]] = [:] func with(_ keyPath: WritableKeyPath, _ value: T) -> PrintCodeContext { var new = self new[keyPath: keyPath] = value return new } + + private func unqualifiedClassName(for qualifiedName: String) -> String { + qualifiedName.split(separator: ".").last.map(String.init) ?? qualifiedName + } + + private func exportsAccess(forClass name: String) -> String { + if let namespace = classNamespaces[name], !namespace.isEmpty { + let path = namespace.map { ".\($0)" }.joined() + return "_exports\(path).\(name)" + } + return "_exports['\(name)']" + } + + func classReference(forQualifiedName qualifiedName: String) -> String { + if hasDirectAccessToSwiftClass { + return unqualifiedClassName(for: qualifiedName) + } + let unqualified = unqualifiedClassName(for: qualifiedName) + return exportsAccess(forClass: unqualified) + } } /// A function that prints the fragment code. @@ -555,8 +577,9 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["value"], printCode: { arguments, context in + let classRef = context.classReference(forQualifiedName: name) return [ - "\(context.hasDirectAccessToSwiftClass ? name : "_exports['\(name)']").__construct(\(arguments[0]))" + "\(classRef).__construct(\(arguments[0]))" ] } ) @@ -565,7 +588,8 @@ struct IntrinsicJSFragment: Sendable { return IntrinsicJSFragment( parameters: ["pointer"], printCode: { arguments, context in - return ["_exports['\(name)'].__construct(\(arguments[0]))"] + let classRef = context.classReference(forQualifiedName: name) + return ["\(classRef).__construct(\(arguments[0]))"] } ) } @@ -874,10 +898,8 @@ struct IntrinsicJSFragment: Sendable { printer.write( "\(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject) = undefined;" ) - let constructExpr = - context.hasDirectAccessToSwiftClass - ? "\(className).__construct(\(pointerVar))" - : "_exports['\(className)'].__construct(\(pointerVar))" + let classRef = context.classReference(forQualifiedName: className) + let constructExpr = "\(classRef).__construct(\(pointerVar))" printer.write( "const \(resultVar) = \(pointerVar) === null ? \(absenceLiteral) : \(constructExpr);" ) @@ -2075,8 +2097,9 @@ struct IntrinsicJSFragment: Sendable { let (scope, printer) = (context.scope, context.printer) let ptrVar = scope.variable("ptr") let objVar = scope.variable("obj") + let classRef = context.classReference(forQualifiedName: className) printer.write("const \(ptrVar) = \(scope.popPointer());") - printer.write("const \(objVar) = _exports['\(className)'].__construct(\(ptrVar));") + printer.write("const \(objVar) = \(classRef).__construct(\(ptrVar));") return [objVar] } ) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift index c3e77d83f..e3654e89f 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSIntrinsicRegistry.swift @@ -5,6 +5,7 @@ import BridgeJSUtilities /// Registry for JS helper intrinsics used during code generation. final class JSIntrinsicRegistry { private var entries: [String: [String]] = [:] + var classNamespaces: [String: [String]] = [:] var isEmpty: Bool { entries.isEmpty @@ -19,6 +20,7 @@ final class JSIntrinsicRegistry { func reset() { entries.removeAll() + classNamespaces.removeAll() } func emitLines() -> [String] { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Namespaces.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Namespaces.swift index 32ea9791f..cbe146ff5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Namespaces.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Namespaces.swift @@ -32,3 +32,19 @@ class UUID { Foundation.UUID().uuidString } } + +@JS(namespace: "Collections") class Container { + var items: [Greeter] + + @JS init() { + self.items = [] + } + + @JS func getItems() -> [Greeter] { + return items + } + + @JS func addItem(_ item: Greeter) { + items.append(item) + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json index a87bffa6b..0ef46ac72 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.json @@ -128,6 +128,75 @@ ], "swiftCallName" : "UUID" + }, + { + "constructor" : { + "abiName" : "bjs_Container_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_Container_getItems", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getItems", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + }, + { + "abiName" : "bjs_Container_addItem", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "addItem", + "parameters" : [ + { + "label" : "_", + "name" : "item", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "Container", + "namespace" : [ + "Collections" + ], + "properties" : [ + + ], + "swiftCallName" : "Container" } ], "enums" : [ diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.swift index c4db9f0fb..4b9ecd10a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.Global.swift @@ -157,4 +157,64 @@ fileprivate func _bjs_UUID_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> In #endif @inline(never) fileprivate func _bjs_UUID_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { return _bjs_UUID_wrap_extern(pointer) +} + +@_expose(wasm, "bjs_Container_init") +@_cdecl("bjs_Container_init") +public func _bjs_Container_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Container() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_getItems") +@_cdecl("bjs_Container_getItems") +public func _bjs_Container_getItems(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Container.bridgeJSLiftParameter(_self).getItems() + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_addItem") +@_cdecl("bjs_Container_addItem") +public func _bjs_Container_addItem(_ _self: UnsafeMutableRawPointer, _ item: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Container.bridgeJSLiftParameter(_self).addItem(_: Greeter.bridgeJSLiftParameter(item)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_deinit") +@_cdecl("bjs_Container_deinit") +public func _bjs_Container_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Container: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Container_wrap") +fileprivate func _bjs_Container_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Container_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_Container_wrap_extern(pointer) } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json index 766d93a5d..1bca1dc5d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.json @@ -128,6 +128,75 @@ ], "swiftCallName" : "UUID" + }, + { + "constructor" : { + "abiName" : "bjs_Container_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + + ] + }, + "methods" : [ + { + "abiName" : "bjs_Container_getItems", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "getItems", + "parameters" : [ + + ], + "returnType" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + } + }, + { + "abiName" : "bjs_Container_addItem", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "addItem", + "parameters" : [ + { + "label" : "_", + "name" : "item", + "type" : { + "swiftHeapObject" : { + "_0" : "Greeter" + } + } + } + ], + "returnType" : { + "void" : { + + } + } + } + ], + "name" : "Container", + "namespace" : [ + "Collections" + ], + "properties" : [ + + ], + "swiftCallName" : "Container" } ], "enums" : [ diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.swift index c4db9f0fb..4b9ecd10a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Namespaces.swift @@ -157,4 +157,64 @@ fileprivate func _bjs_UUID_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> In #endif @inline(never) fileprivate func _bjs_UUID_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { return _bjs_UUID_wrap_extern(pointer) +} + +@_expose(wasm, "bjs_Container_init") +@_cdecl("bjs_Container_init") +public func _bjs_Container_init() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = Container() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_getItems") +@_cdecl("bjs_Container_getItems") +public func _bjs_Container_getItems(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = Container.bridgeJSLiftParameter(_self).getItems() + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_addItem") +@_cdecl("bjs_Container_addItem") +public func _bjs_Container_addItem(_ _self: UnsafeMutableRawPointer, _ item: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Container.bridgeJSLiftParameter(_self).addItem(_: Greeter.bridgeJSLiftParameter(item)) + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_Container_deinit") +@_cdecl("bjs_Container_deinit") +public func _bjs_Container_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension Container: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_Container_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "TestModule", name: "bjs_Container_wrap") +fileprivate func _bjs_Container_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_Container_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_Container_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_Container_wrap_extern(pointer) } \ No newline at end of file diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index b206b9a9f..47db4d410 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -798,7 +798,7 @@ export async function createInstantiator(options, swift) { const arrayResult = []; for (let i = 0; i < arrayLen; i++) { const ptr = ptrStack.pop(); - const obj = _exports['Item'].__construct(ptr); + const obj = Item.__construct(ptr); arrayResult.push(obj); } arrayResult.reverse(); @@ -820,7 +820,7 @@ export async function createInstantiator(options, swift) { const arrayResult1 = []; for (let i1 = 0; i1 < arrayLen1; i1++) { const ptr = ptrStack.pop(); - const obj = _exports['Item'].__construct(ptr); + const obj = Item.__construct(ptr); arrayResult1.push(obj); } arrayResult1.reverse(); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index efbd9b09e..268caf407 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -369,7 +369,7 @@ export async function createInstantiator(options, swift) { const dictResult = {}; for (let i = 0; i < dictLen; i++) { const ptr = ptrStack.pop(); - const obj = _exports['Box'].__construct(ptr); + const obj = Box.__construct(ptr); const string = strStack.pop(); dictResult[string] = obj; } @@ -402,7 +402,7 @@ export async function createInstantiator(options, swift) { optValue = null; } else { const ptr = ptrStack.pop(); - const obj = _exports['Box'].__construct(ptr); + const obj = Box.__construct(ptr); optValue = obj; } const string = strStack.pop(); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js index a5f97641c..ca44d2382 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -233,15 +233,15 @@ export async function createInstantiator(options, swift) { importObject["TestModule"] = {}; } importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { - const obj = _exports['Converter'].__construct(pointer); + const obj = _exports.Utils.Converter.__construct(pointer); return swift.memory.retain(obj); }; importObject["TestModule"]["bjs_HTTPServer_wrap"] = function(pointer) { - const obj = _exports['HTTPServer'].__construct(pointer); + const obj = _exports.Networking.API.HTTPServer.__construct(pointer); return swift.memory.retain(obj); }; importObject["TestModule"]["bjs_TestServer_wrap"] = function(pointer) { - const obj = _exports['TestServer'].__construct(pointer); + const obj = _exports.Networking.APIV2.Internal.TestServer.__construct(pointer); return swift.memory.retain(obj); }; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index a30709cbb..8484951f3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -214,15 +214,15 @@ export async function createInstantiator(options, swift) { importObject["TestModule"] = {}; } importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { - const obj = _exports['Converter'].__construct(pointer); + const obj = _exports.Utils.Converter.__construct(pointer); return swift.memory.retain(obj); }; importObject["TestModule"]["bjs_HTTPServer_wrap"] = function(pointer) { - const obj = _exports['HTTPServer'].__construct(pointer); + const obj = _exports.Networking.API.HTTPServer.__construct(pointer); return swift.memory.retain(obj); }; importObject["TestModule"]["bjs_TestServer_wrap"] = function(pointer) { - const obj = _exports['TestServer'].__construct(pointer); + const obj = _exports.Networking.APIV2.Internal.TestServer.__construct(pointer); return swift.memory.retain(obj); }; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index 457661b6c..9460ed45e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -189,7 +189,7 @@ export async function createInstantiator(options, swift) { importObject["TestModule"] = {}; } importObject["TestModule"]["bjs_GlobalClass_wrap"] = function(pointer) { - const obj = _exports['GlobalClass'].__construct(pointer); + const obj = _exports.GlobalAPI.GlobalClass.__construct(pointer); return swift.memory.retain(obj); }; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index 6c0c5ad9c..5b99112ab 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -189,7 +189,7 @@ export async function createInstantiator(options, swift) { importObject["GlobalModule"] = {}; } importObject["GlobalModule"]["bjs_GlobalClass_wrap"] = function(pointer) { - const obj = _exports['GlobalClass'].__construct(pointer); + const obj = _exports.GlobalAPI.GlobalClass.__construct(pointer); return swift.memory.retain(obj); }; // Wrapper functions for module: PrivateModule @@ -197,7 +197,7 @@ export async function createInstantiator(options, swift) { importObject["PrivateModule"] = {}; } importObject["PrivateModule"]["bjs_PrivateClass_wrap"] = function(pointer) { - const obj = _exports['PrivateClass'].__construct(pointer); + const obj = _exports.PrivateAPI.PrivateClass.__construct(pointer); return swift.memory.retain(obj); }; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index a576e82b6..e600c1eb9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -189,7 +189,7 @@ export async function createInstantiator(options, swift) { importObject["TestModule"] = {}; } importObject["TestModule"]["bjs_PrivateClass_wrap"] = function(pointer) { - const obj = _exports['PrivateClass'].__construct(pointer); + const obj = _exports.PrivateAPI.PrivateClass.__construct(pointer); return swift.memory.retain(obj); }; }, 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 77d9cc0e9..25ac1ac6d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.d.ts @@ -7,6 +7,13 @@ export {}; declare global { + namespace Collections { + class Container { + constructor(); + addItem(item: Greeter): void; + getItems(): Greeter[]; + } + } namespace MyModule { namespace Utils { function namespacedFunction(): string; @@ -49,8 +56,17 @@ export interface Converter extends SwiftHeapObject { export interface UUID extends SwiftHeapObject { uuidString(): string; } +export interface Container extends SwiftHeapObject { + getItems(): Greeter[]; + addItem(item: Greeter): void; +} export type Exports = { plainFunction(): string; + Collections: { + Container: { + new(): Container; + } + }, MyModule: { Utils: { namespacedFunction(): string; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js index 806697af2..303dd5274 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -188,16 +188,20 @@ export async function createInstantiator(options, swift) { if (!importObject["TestModule"]) { importObject["TestModule"] = {}; } + importObject["TestModule"]["bjs_Container_wrap"] = function(pointer) { + const obj = _exports.Collections.Container.__construct(pointer); + return swift.memory.retain(obj); + }; importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { - const obj = _exports['Converter'].__construct(pointer); + const obj = _exports.Utils.Converters.Converter.__construct(pointer); return swift.memory.retain(obj); }; importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { - const obj = _exports['Greeter'].__construct(pointer); + const obj = _exports.__Swift.Foundation.Greeter.__construct(pointer); return swift.memory.retain(obj); }; importObject["TestModule"]["bjs_UUID_wrap"] = function(pointer) { - const obj = _exports['UUID'].__construct(pointer); + const obj = _exports.__Swift.Foundation.UUID.__construct(pointer); return swift.memory.retain(obj); }; }, @@ -287,6 +291,34 @@ export async function createInstantiator(options, swift) { return ret; } } + class Container extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Container_deinit, Container.prototype); + } + + constructor() { + const ret = instance.exports.bjs_Container_init(); + return Container.__construct(ret); + } + getItems() { + instance.exports.bjs_Container_getItems(this.pointer); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = ptrStack.pop(); + const obj = Greeter.__construct(ptr); + arrayResult.push(obj); + } + arrayResult.reverse(); + return arrayResult; + } + addItem(item) { + instance.exports.bjs_Container_addItem(this.pointer, item.pointer); + } + } + if (typeof globalThis.Collections === 'undefined') { + globalThis.Collections = {}; + } if (typeof globalThis.MyModule === 'undefined') { globalThis.MyModule = {}; } @@ -312,6 +344,9 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }, + Collections: { + Container, + }, MyModule: { Utils: { namespacedFunction: function bjs_MyModule_Utils_namespacedFunction() { @@ -338,6 +373,7 @@ export async function createInstantiator(options, swift) { globalThis.__Swift.Foundation.Greeter = exports.__Swift.Foundation.Greeter; globalThis.Utils.Converters.Converter = exports.Utils.Converters.Converter; globalThis.__Swift.Foundation.UUID = exports.__Swift.Foundation.UUID; + globalThis.Collections.Container = exports.Collections.Container; globalThis.MyModule.Utils.namespacedFunction = exports.MyModule.Utils.namespacedFunction; return exports; }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts index 67a89533a..fff65ce6d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.d.ts @@ -20,8 +20,17 @@ export interface Converter extends SwiftHeapObject { export interface UUID extends SwiftHeapObject { uuidString(): string; } +export interface Container extends SwiftHeapObject { + getItems(): Greeter[]; + addItem(item: Greeter): void; +} export type Exports = { plainFunction(): string; + Collections: { + Container: { + new(): Container; + } + }, MyModule: { Utils: { namespacedFunction(): string; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js index 1f5366828..85c45665d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -188,16 +188,20 @@ export async function createInstantiator(options, swift) { if (!importObject["TestModule"]) { importObject["TestModule"] = {}; } + importObject["TestModule"]["bjs_Container_wrap"] = function(pointer) { + const obj = _exports.Collections.Container.__construct(pointer); + return swift.memory.retain(obj); + }; importObject["TestModule"]["bjs_Converter_wrap"] = function(pointer) { - const obj = _exports['Converter'].__construct(pointer); + const obj = _exports.Utils.Converters.Converter.__construct(pointer); return swift.memory.retain(obj); }; importObject["TestModule"]["bjs_Greeter_wrap"] = function(pointer) { - const obj = _exports['Greeter'].__construct(pointer); + const obj = _exports.__Swift.Foundation.Greeter.__construct(pointer); return swift.memory.retain(obj); }; importObject["TestModule"]["bjs_UUID_wrap"] = function(pointer) { - const obj = _exports['UUID'].__construct(pointer); + const obj = _exports.__Swift.Foundation.UUID.__construct(pointer); return swift.memory.retain(obj); }; }, @@ -287,6 +291,31 @@ export async function createInstantiator(options, swift) { return ret; } } + class Container extends SwiftHeapObject { + static __construct(ptr) { + return SwiftHeapObject.__wrap(ptr, instance.exports.bjs_Container_deinit, Container.prototype); + } + + constructor() { + const ret = instance.exports.bjs_Container_init(); + return Container.__construct(ret); + } + getItems() { + instance.exports.bjs_Container_getItems(this.pointer); + const arrayLen = i32Stack.pop(); + const arrayResult = []; + for (let i = 0; i < arrayLen; i++) { + const ptr = ptrStack.pop(); + const obj = Greeter.__construct(ptr); + arrayResult.push(obj); + } + arrayResult.reverse(); + return arrayResult; + } + addItem(item) { + instance.exports.bjs_Container_addItem(this.pointer, item.pointer); + } + } const exports = { plainFunction: function bjs_plainFunction() { instance.exports.bjs_plainFunction(); @@ -294,6 +323,9 @@ export async function createInstantiator(options, swift) { tmpRetString = undefined; return ret; }, + Collections: { + Container, + }, MyModule: { Utils: { namespacedFunction: function bjs_MyModule_Utils_namespacedFunction() { diff --git a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift index 97c2d5fbf..fe24ef42d 100644 --- a/Tests/BridgeJSRuntimeTests/ExportAPITests.swift +++ b/Tests/BridgeJSRuntimeTests/ExportAPITests.swift @@ -361,6 +361,43 @@ struct TestError: Error { } } +@JS func createConverter() -> Utils.Converter { + return Utils.Converter() +} + +@JS func useConverter(converter: Utils.Converter, value: Int) -> String { + return converter.toString(value: value) +} + +@JS func roundTripConverterArray(_ converters: [Utils.Converter]) -> [Utils.Converter] { + return converters +} + +@JS func createHTTPServer() -> Networking.API.HTTPServer { + return Networking.API.HTTPServer() +} + +@JS(namespace: "__Swift.Foundation") +class UUID { + let value: String + + @JS init(value: String) { + self.value = value + } + + @JS func uuidString() -> String { + return value + } +} + +@JS func createUUID(value: String) -> UUID { + return UUID(value: value) +} + +@JS func roundTripUUID(_ uuid: UUID) -> UUID { + return uuid +} + @JS(namespace: "Networking.APIV2") enum Internal { @JS enum SupportedMethod { diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 90f2e76b6..63d55c265 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -5086,6 +5086,72 @@ public func _bjs_getTSTheme() -> Void { #endif } +@_expose(wasm, "bjs_createConverter") +@_cdecl("bjs_createConverter") +public func _bjs_createConverter() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = createConverter() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_useConverter") +@_cdecl("bjs_useConverter") +public func _bjs_useConverter(_ converter: UnsafeMutableRawPointer, _ value: Int32) -> Void { + #if arch(wasm32) + let ret = useConverter(converter: Utils.Converter.bridgeJSLiftParameter(converter), value: Int.bridgeJSLiftParameter(value)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripConverterArray") +@_cdecl("bjs_roundTripConverterArray") +public func _bjs_roundTripConverterArray() -> Void { + #if arch(wasm32) + let ret = roundTripConverterArray(_: [Utils.Converter].bridgeJSStackPop()) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_createHTTPServer") +@_cdecl("bjs_createHTTPServer") +public func _bjs_createHTTPServer() -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = createHTTPServer() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_createUUID") +@_cdecl("bjs_createUUID") +public func _bjs_createUUID(_ valueBytes: Int32, _ valueLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = createUUID(value: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_roundTripUUID") +@_cdecl("bjs_roundTripUUID") +public func _bjs_roundTripUUID(_ uuid: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = roundTripUUID(_: UUID.bridgeJSLiftParameter(uuid)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_roundtripNetworkingAPIMethod") @_cdecl("bjs_roundtripNetworkingAPIMethod") public func _bjs_roundtripNetworkingAPIMethod(_ method: Int32) -> Int32 { @@ -7126,6 +7192,56 @@ fileprivate func _bjs_HTTPServer_wrap_extern(_ pointer: UnsafeMutableRawPointer) return _bjs_HTTPServer_wrap_extern(pointer) } +@_expose(wasm, "bjs_UUID_init") +@_cdecl("bjs_UUID_init") +public func _bjs_UUID_init(_ valueBytes: Int32, _ valueLength: Int32) -> UnsafeMutableRawPointer { + #if arch(wasm32) + let ret = UUID(value: String.bridgeJSLiftParameter(valueBytes, valueLength)) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_UUID_uuidString") +@_cdecl("bjs_UUID_uuidString") +public func _bjs_UUID_uuidString(_ _self: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + let ret = UUID.bridgeJSLiftParameter(_self).uuidString() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_UUID_deinit") +@_cdecl("bjs_UUID_deinit") +public func _bjs_UUID_deinit(_ pointer: UnsafeMutableRawPointer) -> Void { + #if arch(wasm32) + Unmanaged.fromOpaque(pointer).release() + #else + fatalError("Only available on WebAssembly") + #endif +} + +extension UUID: ConvertibleToJSValue, _BridgedSwiftHeapObject { + var jsValue: JSValue { + return .object(JSObject(id: UInt32(bitPattern: _bjs_UUID_wrap(Unmanaged.passRetained(self).toOpaque())))) + } +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_UUID_wrap") +fileprivate func _bjs_UUID_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 +#else +fileprivate func _bjs_UUID_wrap_extern(_ pointer: UnsafeMutableRawPointer) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func _bjs_UUID_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 { + return _bjs_UUID_wrap_extern(pointer) +} + @_expose(wasm, "bjs_TestServer_init") @_cdecl("bjs_TestServer_init") public func _bjs_TestServer_init() -> UnsafeMutableRawPointer { @@ -11363,6 +11479,18 @@ fileprivate func bjs_SwiftClassSupportImports_jsRoundTripGreeter_static_extern(_ return bjs_SwiftClassSupportImports_jsRoundTripGreeter_static_extern(greeter) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SwiftClassSupportImports_jsRoundTripUUID_static") +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripUUID_static_extern(_ uuid: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer +#else +fileprivate func bjs_SwiftClassSupportImports_jsRoundTripUUID_static_extern(_ uuid: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_SwiftClassSupportImports_jsRoundTripUUID_static(_ uuid: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { + return bjs_SwiftClassSupportImports_jsRoundTripUUID_static_extern(uuid) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static") fileprivate func bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static_extern(_ greeterIsSome: Int32, _ greeterPointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer @@ -11408,6 +11536,15 @@ func _$SwiftClassSupportImports_jsRoundTripGreeter(_ greeter: Greeter) throws(JS return Greeter.bridgeJSLiftReturn(ret) } +func _$SwiftClassSupportImports_jsRoundTripUUID(_ uuid: UUID) throws(JSException) -> UUID { + let uuidPointer = uuid.bridgeJSLowerParameter() + let ret = bjs_SwiftClassSupportImports_jsRoundTripUUID_static(uuidPointer) + if let error = _swift_js_take_exception() { + throw error + } + return UUID.bridgeJSLiftReturn(ret) +} + func _$SwiftClassSupportImports_jsRoundTripOptionalGreeter(_ greeter: Optional) throws(JSException) -> Optional { let (greeterIsSome, greeterPointer) = greeter.bridgeJSLowerParameter() let ret = bjs_SwiftClassSupportImports_jsRoundTripOptionalGreeter_static(greeterIsSome, greeterPointer) diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index e682dffd3..2c2d3dc0f 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -771,6 +771,55 @@ ], "swiftCallName" : "Networking.API.HTTPServer" }, + { + "constructor" : { + "abiName" : "bjs_UUID_init", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ] + }, + "methods" : [ + { + "abiName" : "bjs_UUID_uuidString", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "uuidString", + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + } + } + ], + "name" : "UUID", + "namespace" : [ + "__Swift", + "Foundation" + ], + "properties" : [ + + ], + "swiftCallName" : "UUID" + }, { "constructor" : { "abiName" : "bjs_TestServer_init", @@ -6917,6 +6966,157 @@ } } }, + { + "abiName" : "bjs_createConverter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createConverter", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Utils.Converter" + } + } + }, + { + "abiName" : "bjs_useConverter", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "useConverter", + "parameters" : [ + { + "label" : "converter", + "name" : "converter", + "type" : { + "swiftHeapObject" : { + "_0" : "Utils.Converter" + } + } + }, + { + "label" : "value", + "name" : "value", + "type" : { + "int" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "abiName" : "bjs_roundTripConverterArray", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripConverterArray", + "parameters" : [ + { + "label" : "_", + "name" : "converters", + "type" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Utils.Converter" + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "swiftHeapObject" : { + "_0" : "Utils.Converter" + } + } + } + } + }, + { + "abiName" : "bjs_createHTTPServer", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createHTTPServer", + "parameters" : [ + + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "Networking.API.HTTPServer" + } + } + }, + { + "abiName" : "bjs_createUUID", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "createUUID", + "parameters" : [ + { + "label" : "value", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "UUID" + } + } + }, + { + "abiName" : "bjs_roundTripUUID", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : false + }, + "name" : "roundTripUUID", + "parameters" : [ + { + "label" : "_", + "name" : "uuid", + "type" : { + "swiftHeapObject" : { + "_0" : "UUID" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "UUID" + } + } + }, { "abiName" : "bjs_roundtripNetworkingAPIMethod", "effects" : { @@ -15760,6 +15960,24 @@ } } }, + { + "name" : "jsRoundTripUUID", + "parameters" : [ + { + "name" : "uuid", + "type" : { + "swiftHeapObject" : { + "_0" : "UUID" + } + } + } + ], + "returnType" : { + "swiftHeapObject" : { + "_0" : "UUID" + } + } + }, { "name" : "jsRoundTripOptionalGreeter", "parameters" : [ diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs index bd3b40f26..8e808efd6 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs @@ -6,6 +6,9 @@ export function getImports(importsContext) { jsRoundTripGreeter: (greeter) => { return greeter; }, + jsRoundTripUUID: (uuid) => { + return uuid; + }, jsRoundTripOptionalGreeter: (greeter) => { return greeter; }, diff --git a/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift index fa13de468..01e64bfe3 100644 --- a/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift +++ b/Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift @@ -3,6 +3,7 @@ import JavaScriptKit @JSClass struct SwiftClassSupportImports { @JSFunction static func jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter + @JSFunction static func jsRoundTripUUID(_ uuid: UUID) throws(JSException) -> UUID @JSFunction static func jsRoundTripOptionalGreeter(_ greeter: Greeter?) throws(JSException) -> Greeter? @JSFunction static func jsConsumeLeakCheck(_ value: LeakCheck) throws(JSException) -> Void @JSFunction static func jsConsumeOptionalLeakCheck(_ value: LeakCheck?) throws(JSException) -> Void @@ -24,6 +25,11 @@ final class SwiftClassSupportTests: XCTestCase { XCTAssertEqual(greeter2?.name, "Hello") } + func testRoundTripUUID() throws { + let uuid = try SwiftClassSupportImports.jsRoundTripUUID(UUID(value: "11111111-2222-3333-4444-555555555555")) + XCTAssertEqual(uuid.uuidString(), "11111111-2222-3333-4444-555555555555") + } + func testSwiftClassToJSObject() throws { let greeter = Greeter(name: "BridgeJS") let jsGreeter = try XCTUnwrap(greeter.jsValue.object) diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 030ec270d..86a5fe04f 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -611,6 +611,32 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(converter.toString(123), "123"); converter.release(); + const createdConverter = exports.createConverter(); + assert.equal(createdConverter.toString(99), "99"); + assert.equal(exports.useConverter(createdConverter, 55), "55"); + createdConverter.release(); + + const c1 = exports.createConverter(); + const c2 = exports.createConverter(); + const converterArray = exports.roundTripConverterArray([c1, c2]); + assert.equal(converterArray.length, 2); + assert.equal(converterArray[0].toString(10), "10"); + assert.equal(converterArray[1].toString(20), "20"); + c1.release(); + c2.release(); + converterArray.forEach((c) => c.release()); + + const uuid = exports.createUUID("11111111-2222-3333-4444-555555555555"); + assert.equal(uuid.uuidString(), "11111111-2222-3333-4444-555555555555"); + const roundTrippedUUID = exports.roundTripUUID(uuid); + assert.equal(roundTrippedUUID.uuidString(), "11111111-2222-3333-4444-555555555555"); + roundTrippedUUID.release(); + uuid.release(); + + const createdServer = exports.createHTTPServer(); + createdServer.call(exports.Networking.API.Method.Get); + createdServer.release(); + assert.equal(exports.Utils.StringUtils.uppercase("hello"), "HELLO"); assert.equal(exports.Utils.StringUtils.uppercase(""), ""); assert.equal(exports.Utils.StringUtils.lowercase("WORLD"), "world");