diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 6e5c17141..d6912bbd7 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -724,14 +724,12 @@ struct StackCodegen { switch type { case .string, .int, .uint, .bool, .float, .double, .jsObject(nil), .jsValue, .swiftStruct, .swiftHeapObject, .unsafePointer, - .swiftProtocol, .caseEnum, .associatedValueEnum, .rawValueEnum, .array: + .swiftProtocol, .caseEnum, .associatedValueEnum, .rawValueEnum, .array, .dictionary: return "\(raw: type.swiftType).bridgeJSStackPop()" case .jsObject(let className?): return "\(raw: className)(unsafelyWrapping: JSObject.bridgeJSStackPop())" case .nullable(let wrappedType, let kind): return liftNullableExpression(wrappedType: wrappedType, kind: kind) - case .dictionary(let valueType): - return liftDictionaryExpression(valueType: valueType) case .closure: return "JSObject.bridgeJSStackPop()" case .void, .namespaceEnum: @@ -739,42 +737,6 @@ struct StackCodegen { } } - func liftDictionaryExpression(valueType: BridgeType) -> ExprSyntax { - switch valueType { - case .jsObject(let className?) where className != "JSObject": - return """ - { - let __dict = [String: JSObject].bridgeJSStackPop() - return __dict.mapValues { \(raw: className)(unsafelyWrapping: $0) } - }() - """ - case .nullable, .closure: - return liftDictionaryExpressionInline(valueType: valueType) - case .void, .namespaceEnum: - fatalError("Invalid dictionary value type: \(valueType)") - default: - return "[String: \(raw: valueType.swiftType)].bridgeJSStackPop()" - } - } - - private func liftDictionaryExpressionInline(valueType: BridgeType) -> ExprSyntax { - let valueLift = liftExpression(for: valueType) - let swiftTypeName = valueType.swiftType - return """ - { - let __count = Int(_swift_js_pop_i32()) - var __result: [String: \(raw: swiftTypeName)] = [:] - __result.reserveCapacity(__count) - for _ in 0..<__count { - let __value = \(valueLift) - let __key = String.bridgeJSStackPop() - __result[__key] = __value - } - return __result - }() - """ - } - private func liftNullableExpression(wrappedType: BridgeType, kind: JSOptionalKind) -> ExprSyntax { let typeName = kind == .null ? "Optional" : "JSUndefinedOr" switch wrappedType { diff --git a/Tests/BridgeJSRuntimeTests/DictionarySupportTests.swift b/Tests/BridgeJSRuntimeTests/DictionarySupportTests.swift new file mode 100644 index 000000000..8f935da12 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/DictionarySupportTests.swift @@ -0,0 +1,54 @@ +@_spi(BridgeJS) import JavaScriptKit +import XCTest + +@JSClass struct DictionarySupportImports { + @JSFunction static func jsRoundTripDictionaryInt(_ values: [String: Int]) throws(JSException) -> [String: Int] + @JSFunction static func jsRoundTripDictionaryBool(_ values: [String: Bool]) throws(JSException) -> [String: Bool] + @JSFunction static func jsRoundTripDictionaryDouble( + _ values: [String: Double] + ) throws(JSException) -> [String: Double] + @JSFunction static func jsRoundTripDictionaryJSObject( + _ values: [String: JSObject] + ) throws(JSException) -> [String: JSObject] + @JSFunction static func jsRoundTripDictionaryJSValue( + _ values: [String: JSValue] + ) throws(JSException) -> [String: JSValue] + @JSFunction static func jsRoundTripDictionaryDoubleArray( + _ values: [String: [Double]] + ) throws(JSException) -> [String: [Double]] +} + +final class DictionarySupportTests: XCTestCase { + + private func roundTripTest(_ fn: ([String: T]) throws -> [String: T], _ input: [String: T]) throws { + let result = try fn(input) + XCTAssertEqual(result, input) + } + + func testRoundTripDictionaryInt() throws { + try roundTripTest(DictionarySupportImports.jsRoundTripDictionaryInt, ["a": 1, "b": 2]) + } + + func testRoundTripDictionaryBool() throws { + try roundTripTest(DictionarySupportImports.jsRoundTripDictionaryBool, ["yes": true, "no": false]) + } + + func testRoundTripDictionaryDouble() throws { + try roundTripTest(DictionarySupportImports.jsRoundTripDictionaryDouble, ["pi": 3.14, "tau": 6.28]) + } + + func testRoundTripDictionaryJSObject() throws { + try roundTripTest(DictionarySupportImports.jsRoundTripDictionaryJSObject, ["global": JSObject.global]) + } + + func testRoundTripDictionaryJSValue() throws { + try roundTripTest( + DictionarySupportImports.jsRoundTripDictionaryJSValue, + ["number": .number(123.5), "boolean": .boolean(true), "string": .string("hello"), "null": .null] + ) + } + + func testRoundTripDictionaryDoubleArray() throws { + try roundTripTest(DictionarySupportImports.jsRoundTripDictionaryDoubleArray, ["xs": [1.0, 2.5], "ys": []]) + } +} diff --git a/Tests/BridgeJSRuntimeTests/DictionaryTests.swift b/Tests/BridgeJSRuntimeTests/DictionaryTests.swift deleted file mode 100644 index 95f2706e6..000000000 --- a/Tests/BridgeJSRuntimeTests/DictionaryTests.swift +++ /dev/null @@ -1,96 +0,0 @@ -@_spi(BridgeJS) import JavaScriptKit -import XCTest - -final class DictionaryTests: XCTestCase { - func testRoundTripDictionary() throws { - let input: [String: Int] = ["a": 1, "b": 2] - let result = try jsRoundTripDictionary(input) - XCTAssertEqual(result, input) - } - - func testRoundTripDictionaryBool() throws { - let input: [String: Bool] = ["yes": true, "no": false] - let result = try jsRoundTripDictionaryBool(input) - XCTAssertEqual(result, input) - } - - func testRoundTripDictionaryDouble() throws { - let input: [String: Double] = ["pi": 3.14, "tau": 6.28] - let result = try jsRoundTripDictionaryDouble(input) - XCTAssertEqual(result, input) - } - - func testRoundTripDictionaryJSObject() throws { - let global = JSObject.global - let input: [String: JSObject] = [ - "global": global - ] - let result = try jsRoundTripDictionaryJSObject(input) - XCTAssertEqual(result, input) - } - - func testRoundTripDictionaryJSValue() throws { - let input: [String: JSValue] = [ - "number": .number(123.5), - "boolean": .boolean(true), - "string": .string("hello"), - "null": .null, - ] - let result = try jsRoundTripDictionaryJSValue(input) - XCTAssertEqual(result, input) - } - - func testRoundTripNestedDictionary() throws { - let input: [String: [Double]] = [ - "xs": [1.0, 2.5], - "ys": [], - ] - let result = try jsRoundTripNestedDictionary(input) - XCTAssertEqual(result, input) - } - - func testRoundTripOptionalDictionaryNull() throws { - let some: [String: String]? = ["k": "v"] - XCTAssertEqual(try jsRoundTripOptionalDictionary(some), some) - XCTAssertNil(try jsRoundTripOptionalDictionary(nil)) - } - - func testRoundTripOptionalDictionaryUndefined() throws { - let some: JSUndefinedOr<[String: Int]> = .value(["n": 42]) - let undefined: JSUndefinedOr<[String: Int]> = .undefined - - let returnedSome = try jsRoundTripUndefinedDictionary(some) - switch returnedSome { - case .value(let dict): - XCTAssertEqual(dict, ["n": 42]) - case .undefined: - XCTFail("Expected defined dictionary") - } - - let returnedUndefined = try jsRoundTripUndefinedDictionary(undefined) - switch returnedUndefined { - case .value: - XCTFail("Expected undefined") - case .undefined: - break - } - } -} - -@JSFunction func jsRoundTripDictionary(_ values: [String: Int]) throws(JSException) -> [String: Int] - -@JSFunction func jsRoundTripDictionaryBool(_ values: [String: Bool]) throws(JSException) -> [String: Bool] - -@JSFunction func jsRoundTripDictionaryDouble(_ values: [String: Double]) throws(JSException) -> [String: Double] - -@JSFunction func jsRoundTripDictionaryJSObject(_ values: [String: JSObject]) throws(JSException) -> [String: JSObject] - -@JSFunction func jsRoundTripDictionaryJSValue(_ values: [String: JSValue]) throws(JSException) -> [String: JSValue] - -@JSFunction func jsRoundTripNestedDictionary(_ values: [String: [Double]]) throws(JSException) -> [String: [Double]] - -@JSFunction func jsRoundTripOptionalDictionary(_ values: [String: String]?) throws(JSException) -> [String: String]? - -@JSFunction func jsRoundTripUndefinedDictionary( - _ values: JSUndefinedOr<[String: Int]> -) throws(JSException) -> JSUndefinedOr<[String: Int]> diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index e8a0b9476..7e63f8b98 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -10013,171 +10013,129 @@ func _$DefaultArgumentImports_runJsDefaultArgumentTests() throws(JSException) -> } #if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionary") -fileprivate func bjs_jsRoundTripDictionary_extern() -> Void +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DictionarySupportImports_jsRoundTripDictionaryInt_static") +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryInt_static_extern() -> Void #else -fileprivate func bjs_jsRoundTripDictionary_extern() -> Void { +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryInt_static_extern() -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsRoundTripDictionary() -> Void { - return bjs_jsRoundTripDictionary_extern() -} - -func _$jsRoundTripDictionary(_ values: [String: Int]) throws(JSException) -> [String: Int] { - let _ = values.bridgeJSLowerParameter() - bjs_jsRoundTripDictionary() - if let error = _swift_js_take_exception() { - throw error - } - return [String: Int].bridgeJSLiftReturn() +@inline(never) fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryInt_static() -> Void { + return bjs_DictionarySupportImports_jsRoundTripDictionaryInt_static_extern() } #if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionaryBool") -fileprivate func bjs_jsRoundTripDictionaryBool_extern() -> Void +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DictionarySupportImports_jsRoundTripDictionaryBool_static") +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryBool_static_extern() -> Void #else -fileprivate func bjs_jsRoundTripDictionaryBool_extern() -> Void { +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryBool_static_extern() -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsRoundTripDictionaryBool() -> Void { - return bjs_jsRoundTripDictionaryBool_extern() -} - -func _$jsRoundTripDictionaryBool(_ values: [String: Bool]) throws(JSException) -> [String: Bool] { - let _ = values.bridgeJSLowerParameter() - bjs_jsRoundTripDictionaryBool() - if let error = _swift_js_take_exception() { - throw error - } - return [String: Bool].bridgeJSLiftReturn() +@inline(never) fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryBool_static() -> Void { + return bjs_DictionarySupportImports_jsRoundTripDictionaryBool_static_extern() } #if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionaryDouble") -fileprivate func bjs_jsRoundTripDictionaryDouble_extern() -> Void +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DictionarySupportImports_jsRoundTripDictionaryDouble_static") +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryDouble_static_extern() -> Void #else -fileprivate func bjs_jsRoundTripDictionaryDouble_extern() -> Void { +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryDouble_static_extern() -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsRoundTripDictionaryDouble() -> Void { - return bjs_jsRoundTripDictionaryDouble_extern() -} - -func _$jsRoundTripDictionaryDouble(_ values: [String: Double]) throws(JSException) -> [String: Double] { - let _ = values.bridgeJSLowerParameter() - bjs_jsRoundTripDictionaryDouble() - if let error = _swift_js_take_exception() { - throw error - } - return [String: Double].bridgeJSLiftReturn() +@inline(never) fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryDouble_static() -> Void { + return bjs_DictionarySupportImports_jsRoundTripDictionaryDouble_static_extern() } #if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionaryJSObject") -fileprivate func bjs_jsRoundTripDictionaryJSObject_extern() -> Void +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DictionarySupportImports_jsRoundTripDictionaryJSObject_static") +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryJSObject_static_extern() -> Void #else -fileprivate func bjs_jsRoundTripDictionaryJSObject_extern() -> Void { +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryJSObject_static_extern() -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsRoundTripDictionaryJSObject() -> Void { - return bjs_jsRoundTripDictionaryJSObject_extern() -} - -func _$jsRoundTripDictionaryJSObject(_ values: [String: JSObject]) throws(JSException) -> [String: JSObject] { - let _ = values.bridgeJSLowerParameter() - bjs_jsRoundTripDictionaryJSObject() - if let error = _swift_js_take_exception() { - throw error - } - return [String: JSObject].bridgeJSLiftReturn() +@inline(never) fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryJSObject_static() -> Void { + return bjs_DictionarySupportImports_jsRoundTripDictionaryJSObject_static_extern() } #if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripDictionaryJSValue") -fileprivate func bjs_jsRoundTripDictionaryJSValue_extern() -> Void +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DictionarySupportImports_jsRoundTripDictionaryJSValue_static") +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryJSValue_static_extern() -> Void #else -fileprivate func bjs_jsRoundTripDictionaryJSValue_extern() -> Void { +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryJSValue_static_extern() -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsRoundTripDictionaryJSValue() -> Void { - return bjs_jsRoundTripDictionaryJSValue_extern() -} - -func _$jsRoundTripDictionaryJSValue(_ values: [String: JSValue]) throws(JSException) -> [String: JSValue] { - let _ = values.bridgeJSLowerParameter() - bjs_jsRoundTripDictionaryJSValue() - if let error = _swift_js_take_exception() { - throw error - } - return [String: JSValue].bridgeJSLiftReturn() +@inline(never) fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryJSValue_static() -> Void { + return bjs_DictionarySupportImports_jsRoundTripDictionaryJSValue_static_extern() } #if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripNestedDictionary") -fileprivate func bjs_jsRoundTripNestedDictionary_extern() -> Void +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DictionarySupportImports_jsRoundTripDictionaryDoubleArray_static") +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryDoubleArray_static_extern() -> Void #else -fileprivate func bjs_jsRoundTripNestedDictionary_extern() -> Void { +fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryDoubleArray_static_extern() -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsRoundTripNestedDictionary() -> Void { - return bjs_jsRoundTripNestedDictionary_extern() +@inline(never) fileprivate func bjs_DictionarySupportImports_jsRoundTripDictionaryDoubleArray_static() -> Void { + return bjs_DictionarySupportImports_jsRoundTripDictionaryDoubleArray_static_extern() } -func _$jsRoundTripNestedDictionary(_ values: [String: [Double]]) throws(JSException) -> [String: [Double]] { +func _$DictionarySupportImports_jsRoundTripDictionaryInt(_ values: [String: Int]) throws(JSException) -> [String: Int] { let _ = values.bridgeJSLowerParameter() - bjs_jsRoundTripNestedDictionary() + bjs_DictionarySupportImports_jsRoundTripDictionaryInt_static() if let error = _swift_js_take_exception() { throw error } - return [String: [Double]].bridgeJSLiftReturn() + return [String: Int].bridgeJSLiftReturn() } -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripOptionalDictionary") -fileprivate func bjs_jsRoundTripOptionalDictionary_extern(_ values: Int32) -> Void -#else -fileprivate func bjs_jsRoundTripOptionalDictionary_extern(_ values: Int32) -> Void { - fatalError("Only available on WebAssembly") -} -#endif -@inline(never) fileprivate func bjs_jsRoundTripOptionalDictionary(_ values: Int32) -> Void { - return bjs_jsRoundTripOptionalDictionary_extern(values) +func _$DictionarySupportImports_jsRoundTripDictionaryBool(_ values: [String: Bool]) throws(JSException) -> [String: Bool] { + let _ = values.bridgeJSLowerParameter() + bjs_DictionarySupportImports_jsRoundTripDictionaryBool_static() + if let error = _swift_js_take_exception() { + throw error + } + return [String: Bool].bridgeJSLiftReturn() } -func _$jsRoundTripOptionalDictionary(_ values: Optional<[String: String]>) throws(JSException) -> Optional<[String: String]> { - let valuesIsSome = values.bridgeJSLowerParameter() - bjs_jsRoundTripOptionalDictionary(valuesIsSome) +func _$DictionarySupportImports_jsRoundTripDictionaryDouble(_ values: [String: Double]) throws(JSException) -> [String: Double] { + let _ = values.bridgeJSLowerParameter() + bjs_DictionarySupportImports_jsRoundTripDictionaryDouble_static() if let error = _swift_js_take_exception() { throw error } - return Optional<[String: String]>.bridgeJSLiftReturn() + return [String: Double].bridgeJSLiftReturn() } -#if arch(wasm32) -@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripUndefinedDictionary") -fileprivate func bjs_jsRoundTripUndefinedDictionary_extern(_ values: Int32) -> Void -#else -fileprivate func bjs_jsRoundTripUndefinedDictionary_extern(_ values: Int32) -> Void { - fatalError("Only available on WebAssembly") +func _$DictionarySupportImports_jsRoundTripDictionaryJSObject(_ values: [String: JSObject]) throws(JSException) -> [String: JSObject] { + let _ = values.bridgeJSLowerParameter() + bjs_DictionarySupportImports_jsRoundTripDictionaryJSObject_static() + if let error = _swift_js_take_exception() { + throw error + } + return [String: JSObject].bridgeJSLiftReturn() } -#endif -@inline(never) fileprivate func bjs_jsRoundTripUndefinedDictionary(_ values: Int32) -> Void { - return bjs_jsRoundTripUndefinedDictionary_extern(values) + +func _$DictionarySupportImports_jsRoundTripDictionaryJSValue(_ values: [String: JSValue]) throws(JSException) -> [String: JSValue] { + let _ = values.bridgeJSLowerParameter() + bjs_DictionarySupportImports_jsRoundTripDictionaryJSValue_static() + if let error = _swift_js_take_exception() { + throw error + } + return [String: JSValue].bridgeJSLiftReturn() } -func _$jsRoundTripUndefinedDictionary(_ values: JSUndefinedOr<[String: Int]>) throws(JSException) -> JSUndefinedOr<[String: Int]> { - let valuesIsSome = values.bridgeJSLowerParameter() - bjs_jsRoundTripUndefinedDictionary(valuesIsSome) +func _$DictionarySupportImports_jsRoundTripDictionaryDoubleArray(_ values: [String: [Double]]) throws(JSException) -> [String: [Double]] { + let _ = values.bridgeJSLowerParameter() + bjs_DictionarySupportImports_jsRoundTripDictionaryDoubleArray_static() if let error = _swift_js_take_exception() { throw error } - return JSUndefinedOr<[String: Int]>.bridgeJSLiftReturn() + return [String: [Double]].bridgeJSLiftReturn() } #if arch(wasm32) @@ -11424,6 +11382,18 @@ fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSValueArrayNull_ return bjs_OptionalSupportImports_jsRoundTripOptionalJSValueArrayNull_static_extern(v) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalJSValueArrayUndefined_static") +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSValueArrayUndefined_static_extern(_ v: Int32) -> Void +#else +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSValueArrayUndefined_static_extern(_ v: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSValueArrayUndefined_static(_ v: Int32) -> Void { + return bjs_OptionalSupportImports_jsRoundTripOptionalJSValueArrayUndefined_static_extern(v) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryNull_static") fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryNull_static_extern(_ v: Int32) -> Void @@ -11436,6 +11406,18 @@ fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDic return bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryNull_static_extern(v) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined_static") +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined_static_extern(_ v: Int32) -> Void +#else +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined_static_extern(_ v: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined_static(_ v: Int32) -> Void { + return bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined_static_extern(v) +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_runJsOptionalSupportTests_static") fileprivate func bjs_OptionalSupportImports_runJsOptionalSupportTests_static_extern() -> Void @@ -11493,6 +11475,15 @@ func _$OptionalSupportImports_jsRoundTripOptionalJSValueArrayNull(_ v: Optional< return Optional<[JSValue]>.bridgeJSLiftReturn() } +func _$OptionalSupportImports_jsRoundTripOptionalJSValueArrayUndefined(_ v: JSUndefinedOr<[JSValue]>) throws(JSException) -> JSUndefinedOr<[JSValue]> { + let vIsSome = v.bridgeJSLowerParameter() + bjs_OptionalSupportImports_jsRoundTripOptionalJSValueArrayUndefined_static(vIsSome) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr<[JSValue]>.bridgeJSLiftReturn() +} + func _$OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryNull(_ v: Optional<[String: String]>) throws(JSException) -> Optional<[String: String]> { let vIsSome = v.bridgeJSLowerParameter() bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryNull_static(vIsSome) @@ -11502,6 +11493,15 @@ func _$OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryNull(_ return Optional<[String: String]>.bridgeJSLiftReturn() } +func _$OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined(_ v: JSUndefinedOr<[String: String]>) throws(JSException) -> JSUndefinedOr<[String: String]> { + let vIsSome = v.bridgeJSLowerParameter() + bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined_static(vIsSome) + if let error = _swift_js_take_exception() { + throw error + } + return JSUndefinedOr<[String: String]>.bridgeJSLiftReturn() +} + func _$OptionalSupportImports_runJsOptionalSupportTests() throws(JSException) -> Void { bjs_OptionalSupportImports_runJsOptionalSupportTests_static() if let error = _swift_js_take_exception() { diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index 66027d719..4b0617e3a 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -15706,245 +15706,187 @@ }, { "functions" : [ + + ], + "types" : [ { - "name" : "jsRoundTripDictionary", - "parameters" : [ - { - "name" : "values", - "type" : { - "dictionary" : { - "_0" : { - "int" : { + "getters" : [ - } - } - } - } - } ], - "returnType" : { - "dictionary" : { - "_0" : { - "int" : { + "methods" : [ - } - } - } - } - }, - { - "name" : "jsRoundTripDictionaryBool", - "parameters" : [ + ], + "name" : "DictionarySupportImports", + "setters" : [ + + ], + "staticMethods" : [ { - "name" : "values", - "type" : { - "dictionary" : { - "_0" : { - "bool" : { + "name" : "jsRoundTripDictionaryInt", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "int" : { + } + } } } } - } - } - ], - "returnType" : { - "dictionary" : { - "_0" : { - "bool" : { - - } - } - } - } - }, - { - "name" : "jsRoundTripDictionaryDouble", - "parameters" : [ - { - "name" : "values", - "type" : { + ], + "returnType" : { "dictionary" : { "_0" : { - "double" : { + "int" : { } } } } - } - ], - "returnType" : { - "dictionary" : { - "_0" : { - "double" : { + }, + { + "name" : "jsRoundTripDictionaryBool", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "bool" : { + } + } + } + } } - } - } - } - }, - { - "name" : "jsRoundTripDictionaryJSObject", - "parameters" : [ - { - "name" : "values", - "type" : { + ], + "returnType" : { "dictionary" : { "_0" : { - "jsObject" : { + "bool" : { } } } } - } - ], - "returnType" : { - "dictionary" : { - "_0" : { - "jsObject" : { + }, + { + "name" : "jsRoundTripDictionaryDouble", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { + "_0" : { + "double" : { + } + } + } + } } - } - } - } - }, - { - "name" : "jsRoundTripDictionaryJSValue", - "parameters" : [ - { - "name" : "values", - "type" : { + ], + "returnType" : { "dictionary" : { "_0" : { - "jsValue" : { + "double" : { } } } } - } - ], - "returnType" : { - "dictionary" : { - "_0" : { - "jsValue" : { - - } - } - } - } - }, - { - "name" : "jsRoundTripNestedDictionary", - "parameters" : [ + }, { - "name" : "values", - "type" : { - "dictionary" : { - "_0" : { - "array" : { + "name" : "jsRoundTripDictionaryJSObject", + "parameters" : [ + { + "name" : "values", + "type" : { + "dictionary" : { "_0" : { - "double" : { + "jsObject" : { } } } } } - } - } - ], - "returnType" : { - "dictionary" : { - "_0" : { - "array" : { + ], + "returnType" : { + "dictionary" : { "_0" : { - "double" : { + "jsObject" : { } } } } - } - } - }, - { - "name" : "jsRoundTripOptionalDictionary", - "parameters" : [ + }, { - "name" : "values", - "type" : { - "nullable" : { - "_0" : { + "name" : "jsRoundTripDictionaryJSValue", + "parameters" : [ + { + "name" : "values", + "type" : { "dictionary" : { "_0" : { - "string" : { + "jsValue" : { } } } - }, - "_1" : "null" + } } - } - } - ], - "returnType" : { - "nullable" : { - "_0" : { + ], + "returnType" : { "dictionary" : { "_0" : { - "string" : { + "jsValue" : { } } } - }, - "_1" : "null" - } - } - }, - { - "name" : "jsRoundTripUndefinedDictionary", - "parameters" : [ + } + }, { - "name" : "values", - "type" : { - "nullable" : { - "_0" : { + "name" : "jsRoundTripDictionaryDoubleArray", + "parameters" : [ + { + "name" : "values", + "type" : { "dictionary" : { "_0" : { - "int" : { + "array" : { + "_0" : { + "double" : { + } + } } } } - }, - "_1" : "undefined" + } } - } - } - ], - "returnType" : { - "nullable" : { - "_0" : { + ], + "returnType" : { "dictionary" : { "_0" : { - "int" : { + "array" : { + "_0" : { + "double" : { + } + } } } } - }, - "_1" : "undefined" + } } - } + ] } - ], - "types" : [ - ] }, { @@ -17099,6 +17041,42 @@ } } }, + { + "name" : "jsRoundTripOptionalJSValueArrayUndefined", + "parameters" : [ + { + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "array" : { + "_0" : { + "jsValue" : { + + } + } + } + }, + "_1" : "undefined" + } + } + }, { "name" : "jsRoundTripOptionalStringToStringDictionaryNull", "parameters" : [ @@ -17135,6 +17113,42 @@ } } }, + { + "name" : "jsRoundTripOptionalStringToStringDictionaryUndefined", + "parameters" : [ + { + "name" : "v", + "type" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "undefined" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "dictionary" : { + "_0" : { + "string" : { + + } + } + } + }, + "_1" : "undefined" + } + } + }, { "name" : "runJsOptionalSupportTests", "parameters" : [ diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/DictionarySupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/DictionarySupportTests.mjs new file mode 100644 index 000000000..09956341c --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/DictionarySupportTests.mjs @@ -0,0 +1,26 @@ + +/** + * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["DictionarySupportImports"]} + */ +export function getImports(importsContext) { + return { + "jsRoundTripDictionaryInt": (dict) => { + return { ...dict }; + }, + "jsRoundTripDictionaryBool": (dict) => { + return { ...dict }; + }, + "jsRoundTripDictionaryDouble": (dict) => { + return { ...dict }; + }, + "jsRoundTripDictionaryJSObject": (dict) => { + return dict; + }, + "jsRoundTripDictionaryJSValue": (dict) => { + return dict; + }, + "jsRoundTripDictionaryDoubleArray": (dict) => { + return Object.fromEntries(Object.entries(dict).map(([k, v]) => [k, [...v]])); + }, + } +} \ No newline at end of file diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs index aaa05a70a..f9fa397f6 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs @@ -35,9 +35,15 @@ export function getImports(importsContext) { jsRoundTripOptionalJSValueArrayNull: (v) => { return v ?? null; }, + jsRoundTripOptionalJSValueArrayUndefined: (v) => { + return v === undefined ? undefined : v; + }, jsRoundTripOptionalStringToStringDictionaryNull: (v) => { return v ?? null; }, + jsRoundTripOptionalStringToStringDictionaryUndefined: (v) => { + return v === undefined ? undefined : v; + }, runJsOptionalSupportTests: () => { const exports = importsContext.getExports(); if (!exports) { throw new Error("No exports!?"); } diff --git a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift index 520a608ad..7f9708f57 100644 --- a/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift +++ b/Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift @@ -13,16 +13,16 @@ import JavaScriptEventLoop @JSFunction static func jsRoundTripOptionalJSValueArrayNull( _ v: Optional<[JSValue]> ) throws(JSException) -> Optional<[JSValue]> - // @JSFunction static func jsRoundTripOptionalJSValueArrayUndefined( - // _ v: JSUndefinedOr<[JSValue]> - // ) throws(JSException) -> JSUndefinedOr<[JSValue]> + @JSFunction static func jsRoundTripOptionalJSValueArrayUndefined( + _ v: JSUndefinedOr<[JSValue]> + ) throws(JSException) -> JSUndefinedOr<[JSValue]> @JSFunction static func jsRoundTripOptionalStringToStringDictionaryNull( _ v: Optional<[String: String]> ) throws(JSException) -> Optional<[String: String]> - // @JSFunction static func jsRoundTripOptionalStringToStringDictionaryUndefined( - // _ v: JSUndefinedOr<[String: String]> - // ) throws(JSException) -> JSUndefinedOr<[String: String]> + @JSFunction static func jsRoundTripOptionalStringToStringDictionaryUndefined( + _ v: JSUndefinedOr<[String: String]> + ) throws(JSException) -> JSUndefinedOr<[String: String]> @JSFunction static func runJsOptionalSupportTests() throws(JSException) } @@ -70,17 +70,20 @@ final class OptionalSupportTests: XCTestCase { try roundTripTest(OptionalSupportImports.jsRoundTripOptionalJSValueArrayNull, [.number(1), .undefined, .null]) } - // func testRoundTripOptionalJSValueArrayUndefined() throws { - // try roundTripTest(OptionalSupportImports.jsRoundTripOptionalJSValueArrayUndefined, [.number(1), .undefined, .null]) - // } + func testRoundTripOptionalJSValueArrayUndefined() throws { + try roundTripTest( + OptionalSupportImports.jsRoundTripOptionalJSValueArrayUndefined, + [.number(1), .undefined, .null] + ) + } func testRoundTripOptionalStringToStringDictionaryNull() throws { try roundTripTest(OptionalSupportImports.jsRoundTripOptionalStringToStringDictionaryNull, ["key": "value"]) } - // func testRoundTripOptionalStringToStringDictionaryUndefined() throws { - // try roundTripTest(OptionalSupportImports.jsRoundTripOptionalStringToStringDictionaryUndefined, ["key": "value"]) - // } + func testRoundTripOptionalStringToStringDictionaryUndefined() throws { + try roundTripTest(OptionalSupportImports.jsRoundTripOptionalStringToStringDictionaryUndefined, ["key": "value"]) + } } @JS enum OptionalSupportExports { diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 3aeb10a8b..e6cc960cd 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -9,6 +9,7 @@ import { getImports as getClosureSupportImports } from './BridgeJSRuntimeTests/J import { getImports as getSwiftClassSupportImports } from './BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs'; import { getImports as getOptionalSupportImports } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs'; import { getImports as getArraySupportImports, ArrayElementObject } from './BridgeJSRuntimeTests/JavaScript/ArraySupportTests.mjs'; +import { getImports as getDictionarySupportImports } from './BridgeJSRuntimeTests/JavaScript/DictionarySupportTests.mjs'; import { getImports as getDefaultArgumentImports } from './BridgeJSRuntimeTests/JavaScript/DefaultArgumentTests.mjs'; import { getImports as getJSClassSupportImports, JSClassWithArrayMembers } from './BridgeJSRuntimeTests/JavaScript/JSClassSupportTests.mjs'; @@ -54,30 +55,6 @@ export async function setupOptions(options, context) { "jsRoundTripString": (v) => { return v; }, - "jsRoundTripDictionary": (dict) => { - return { ...dict }; - }, - "jsRoundTripDictionaryBool": (dict) => { - return { ...dict }; - }, - "jsRoundTripDictionaryDouble": (dict) => { - return { ...dict }; - }, - "jsRoundTripDictionaryJSObject": (dict) => { - return dict; - }, - "jsRoundTripDictionaryJSValue": (dict) => { - return dict; - }, - "jsRoundTripNestedDictionary": (dict) => { - return Object.fromEntries(Object.entries(dict).map(([k, v]) => [k, [...v]])); - }, - "jsRoundTripOptionalDictionary": (dict) => { - return dict ?? null; - }, - "jsRoundTripUndefinedDictionary": (dict) => { - return dict; - }, "jsRoundTripJSValue": (v) => { return v; }, @@ -164,6 +141,7 @@ export async function setupOptions(options, context) { SwiftClassSupportImports: getSwiftClassSupportImports(importsContext), OptionalSupportImports: getOptionalSupportImports(importsContext), ArraySupportImports: getArraySupportImports(importsContext), + DictionarySupportImports: getDictionarySupportImports(importsContext), DefaultArgumentImports: getDefaultArgumentImports(importsContext), JSClassSupportImports: getJSClassSupportImports(importsContext), };