From a181c615b9187de5eb58f3c9121fd569b64794b3 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Fri, 23 Oct 2026 20:05:25 +0200 Subject: [PATCH] perf(android): build nested UInt64 arrays directly in JNI UInt64[][] is an Array in Kotlin, and its JVM class names kotlin.ULongArray, which JNI cannot name. It crossed as an Array, so Kotlin mapped it on every crossing and created a ULongArray box for each row. JNI now creates the ULongArray[] itself with the class from ULongBox, puts each row's long[] in a box with AllocObject and the box's field, and reads rows the same way. JNI signatures declare the array as an Object[], so Kotlin bridges take an Array<*> and cast it back without copying. Struct getters return the field as it is. Structs compared these fields through the JNI conversion, which is now a cast. Types give structs an equality value instead, so the generated equals() and hashCode() are unchanged. Arrays nested more than two levels deep still map their outer levels in Kotlin. New TestObject methods pass UInt64[][] as a Promise result and through a callback. --- .../src/main/cpp/core/JNIConverter+Array.hpp | 27 +++++ .../cpp/core/JSIConverter+JPrimitiveArray.hpp | 27 +++++ .../android/src/main/cpp/core/JUInt64.hpp | 13 +++ .../src/syntax/kotlin/KotlinStruct.ts | 5 +- .../syntax/kotlin/types/KotlinArrayType.ts | 39 ++++++- .../syntax/kotlin/types/KotlinNamedType.ts | 4 +- .../syntax/kotlin/types/KotlinOptionalType.ts | 6 +- .../src/syntax/kotlin/types/KotlinType.ts | 6 +- .../nitro/test/HybridTestObjectKotlin.kt | 13 +++ .../apple/HybridTestObjectSwift.swift | 12 +++ .../nitro-test/cpp/HybridTestObjectCpp.cpp | 11 ++ .../nitro-test/cpp/HybridTestObjectCpp.hpp | 4 + .../android/NitroTest+autolinking.cmake | 1 + .../generated/android/NitroTestOnLoad.cpp | 2 + .../c++/HybridTestObjectCppSpecClass.cpp | 2 + ...t___std__vector_std__vector_uint64_t__.cpp | 60 +++++++++++ .../c++/JHybridTestObjectSwiftKotlinSpec.cpp | 17 ++- .../generated/android/c++/JUnsignedValues.cpp | 8 +- ...t___std__vector_std__vector_uint64_t__.hpp | 55 ++++++++++ .../JHybridTestObjectSwiftKotlinSpec.hpp | 5 +- .../NitroTest/private/JUnsignedValues.hpp | 10 +- ..._t___std__vector_std__vector_uint64_t__.kt | 97 +++++++++++++++++ .../test/HybridTestObjectSwiftKotlinSpec.kt | 24 ++++- .../com/margelo/nitro/test/UnsignedValues.kt | 8 +- .../apple/NitroTest-Swift-Cxx-Bridge.cpp | 49 +++++++++ .../NitroTestAppleCxx/NitroTestAppleCxx.h | 11 ++ .../c++/HybridTestObjectCppSpecClass.cpp | 2 + .../HybridTestObjectSwiftKotlinSpecSwift.cpp | 24 +++++ .../HybridTestObjectSwiftKotlinSpecSwift.hpp | 2 + ...swift__Array_swift__Array_uint64_t__.swift | 71 ++++++++++++ .../HybridTestObjectSwiftKotlinSpec.swift | 2 + .../HybridTestObjectSwiftKotlinSpec_cxx.swift | 20 ++++ ...swift__Array_swift__Array_uint64_t__.swift | 102 ++++++++++++++++++ .../NitroTest/HybridTestObjectCppSpec.hpp | 2 + .../nitro-test/specs/TestObject.nitro.ts | 4 + tests/standalone/test-runner/js/data.test.ts | 16 +++ 36 files changed, 727 insertions(+), 34 deletions(-) create mode 100644 tests/standalone/nitro-test/nitrogen/generated/android/c++/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.cpp create mode 100644 tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.hpp create mode 100644 tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.kt create mode 100644 tests/standalone/nitro-test/nitrogen/generated/apple/swift/Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__.swift create mode 100644 tests/standalone/nitro-test/nitrogen/generated/apple/swift/Promise_swift__Array_swift__Array_uint64_t__.swift diff --git a/packages/nitro-core/native/android/src/main/cpp/core/JNIConverter+Array.hpp b/packages/nitro-core/native/android/src/main/cpp/core/JNIConverter+Array.hpp index a2dbe99209..921e8a954f 100644 --- a/packages/nitro-core/native/android/src/main/cpp/core/JNIConverter+Array.hpp +++ b/packages/nitro-core/native/android/src/main/cpp/core/JNIConverter+Array.hpp @@ -75,6 +75,33 @@ struct JNIConverter, jni::local_ref> } }; +template <> +struct JNIConverter>, jni::local_ref> { + using JavaArray = jni::local_ref; + + static jni::local_ref toJNI(const std::vector>& value) { + const jsize size = static_cast(value.size()); + auto arrays = JULongBox::newArrays(size); + for (jsize i = 0; i < size; ++i) { + auto array = JNIConverter, JavaArray>::toJNI(value[i]); + auto box = JULongBox::boxArray(array); + arrays->setElement(i, *box); + } + return arrays; + } + static std::vector> fromJNI(jni::alias_ref value) { + const jsize size = static_cast(value->size()); + std::vector> result; + result.reserve(size); + for (jsize i = 0; i < size; ++i) { + auto box = jni::static_ref_cast(value->getElement(i)); + auto array = JULongBox::unboxArray(box); + result.push_back(JNIConverter, JavaArray>::fromJNI(array)); + } + return result; + } +}; + template struct JNIConverter, jni::local_ref>> { using JavaArray = jni::JArrayClass; diff --git a/packages/nitro-core/native/android/src/main/cpp/core/JSIConverter+JPrimitiveArray.hpp b/packages/nitro-core/native/android/src/main/cpp/core/JSIConverter+JPrimitiveArray.hpp index 44028b5754..4280ac354a 100644 --- a/packages/nitro-core/native/android/src/main/cpp/core/JSIConverter+JPrimitiveArray.hpp +++ b/packages/nitro-core/native/android/src/main/cpp/core/JSIConverter+JPrimitiveArray.hpp @@ -82,4 +82,31 @@ struct JSIConverter> { } }; +template <> +struct JSIConverter> { + using JavaArray = jni::local_ref; + + static jni::local_ref fromJSI(jsi::Runtime& runtime, const jsi::Value& value) { + auto array = value.asObject(runtime).asArray(runtime); + const jsize size = static_cast(array.size(runtime)); + auto result = JULongBox::newArrays(size); + for (jsize i = 0; i < size; ++i) { + auto element = JSIConverter::fromJSI(runtime, array.getValueAtIndex(runtime, i)); + auto box = JULongBox::boxArray(element); + result->setElement(i, *box); + } + return result; + } + static jsi::Array toJSI(jsi::Runtime& runtime, jni::alias_ref value) { + return createJSIArray(runtime, value->size(), [&](size_t i) { + auto box = jni::static_ref_cast(value->getElement(i)); + return JSIConverter::toJSI(runtime, JULongBox::unboxArray(box)); + }); + } + static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + return canConvertJSIArray(runtime, value, + [&](const jsi::Value& element) { return JSIConverter::canConvert(runtime, element); }); + } +}; + } // namespace margelo::nitro diff --git a/packages/nitro-core/native/android/src/main/cpp/core/JUInt64.hpp b/packages/nitro-core/native/android/src/main/cpp/core/JUInt64.hpp index 7307fd801a..a5dd9334e1 100644 --- a/packages/nitro-core/native/android/src/main/cpp/core/JUInt64.hpp +++ b/packages/nitro-core/native/android/src/main/cpp/core/JUInt64.hpp @@ -36,6 +36,14 @@ struct JULongArray : jni::JavaClass { static constexpr auto kJavaDescriptor = "Ljava/lang/Object;"; }; +/** + * A Kotlin Array, whose JVM class names kotlin.ULongArray. JNI only sees an Object[], + * creates it with JULongBox, and creates or reads each element's ULongArray box itself. + */ +struct JULongArrays : jni::JavaClass> { + static constexpr const char* kJavaDescriptor = nullptr; +}; + /** * Creates and reads JULong and JULongArray boxes without calling into Kotlin. nitro-core's ULongBox * gives JNI their classes and value fields once, since JNI cannot name them. @@ -66,6 +74,11 @@ struct JULongBox : jni::JavaClass { jobject array = jni::Environment::current()->GetObjectField(value.get(), getULongArrayLayout().field); return jni::adopt_local(static_cast(array)); } + static jni::local_ref newArrays(jsize size) { + jobjectArray arrays = jni::Environment::current()->NewObjectArray(size, getULongArrayLayout().clazz, nullptr); + FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); + return jni::adopt_local(static_cast(arrays)); + } private: struct Layout { diff --git a/packages/nitrogen/src/syntax/kotlin/KotlinStruct.ts b/packages/nitrogen/src/syntax/kotlin/KotlinStruct.ts index 27cb4cb565..0ef9a46608 100644 --- a/packages/nitrogen/src/syntax/kotlin/KotlinStruct.ts +++ b/packages/nitrogen/src/syntax/kotlin/KotlinStruct.ts @@ -51,10 +51,9 @@ private fun get${name}_cxx(): ${type} { }) .join('\n\n') - // Values whose boxes compare by identity, such as `ULongArray`, compare by their JNI representation. + // Values whose boxes compare by identity, such as `ULongArray`, compare by their contents. const getEqualityValue = (property: KotlinNamedType, value: string): string => { - if (property.isKotlinEqualityCompatible) return value - return property.convert(value, { from: 'kotlin', to: 'c++', in: 'kotlin' }) + return property.getKotlinEqualityValue(value) ?? value } const equalityComparators = structType.properties.map((property) => { const value = getEqualityValue(property, `this.${property.escapedName}`) diff --git a/packages/nitrogen/src/syntax/kotlin/types/KotlinArrayType.ts b/packages/nitrogen/src/syntax/kotlin/types/KotlinArrayType.ts index 466f6c32da..73471904f8 100644 --- a/packages/nitrogen/src/syntax/kotlin/types/KotlinArrayType.ts +++ b/packages/nitrogen/src/syntax/kotlin/types/KotlinArrayType.ts @@ -29,20 +29,31 @@ export class KotlinArrayType extends ArrayType implements KotlinType { } get needsKotlinConversion(): boolean { - if (this.isULongArray && this.erasedToObject) return false + if (this.erasedToObject && (this.isULongArray || this.isULongArrays)) return false return this.itemType.needsKotlinConversion } /** `ULongArray` is a value class, so its field holds the `long[]` JNI uses. */ get isKotlinFieldCompatible(): boolean { return this.isULongArray || !this.needsKotlinConversion } - /** `ULongArray` boxes compare by identity, so compare their `long[]`s instead. */ - get isKotlinEqualityCompatible(): boolean { - return !this.isULongArray && (this.itemType.isKotlinEqualityCompatible ?? true) + /** `ULongArray` boxes compare by identity, so structs compare their `long[]`s instead. */ + getKotlinEqualityValue(value: string): string | undefined { + if (this.isULongArray) return `${value}.asLongArray()` + const item = this.itemType.getKotlinEqualityValue?.('__item') + if (item == null) return undefined + const sourceCode = this.type.itemType.getCode('kotlin', { context: 'type-argument' }) + const resultCode = this.itemType.getCode('kotlin', { context: 'type-argument' }) + return ` +${value}.mapToArray<${sourceCode}, ${resultCode}> { __item -> ${item} } +`.trim() } private get isULongArray(): boolean { return this.itemType.kind === 'uint64' } + /** `Array`, which JNI creates and reads itself since its JVM class names `kotlin.ULongArray`. */ + private get isULongArrays(): boolean { + return this.itemType instanceof KotlinArrayType && this.itemType.isULongArray + } convert(value: string, conversion: KotlinConversion): string { switch (conversion.in) { case 'kotlin': { @@ -51,6 +62,12 @@ export class KotlinArrayType extends ArrayType implements KotlinType { // Both reinterpret the same array without copying it. return conversion.from === 'kotlin' ? `${value}.asLongArray()` : `${value}.asULongArray()` } + if (this.isULongArrays) { + // JNI creates a `ULongArray[]` and only declares it as an `Object[]`, so the cast always holds. + if (conversion.from === 'kotlin') return value + const publicType = this.type.getCode('kotlin', { context: 'type-argument' }) + return `(@Suppress("UNCHECKED_CAST") (${value} as ${publicType}))` + } const item = this.itemType.convert('__item', conversion) const sourceType = conversion.from === 'c++' ? this.itemType : this.type.itemType const resultType = conversion.from === 'c++' ? this.type.itemType : this.itemType @@ -92,6 +109,10 @@ ${value}.mapToArray<${sourceCode}, ${resultCode}> { __item -> ${item} } jniType = this.erasedToObject ? 'JULongArray' : 'JArrayUInt64' break default: { + if (this.isULongArrays) { + jniType = 'JULongArrays' + break + } const item = this.itemType.getCode(language, { ...options, context: 'type-argument' }) jniType = `jni::JArrayClass<${item}>` break @@ -110,6 +131,11 @@ ${value}.mapToArray<${sourceCode}, ${resultCode}> { __item -> ${item} } case 'uint64': return this.erasedToObject ? 'ULongArray' : 'LongArray' default: { + if (this.isULongArrays) { + // JNI only declares it as an `Object[]`, see `JULongArrays`. + if (this.erasedToObject) return this.type.getCode(language, options) + return 'Array<*>' + } const item = this.itemType.getCode(language, { ...options, context: 'type-argument' }) return `Array<${item}>` } @@ -132,7 +158,10 @@ ${value}.mapToArray<${sourceCode}, ${resultCode}> { __item -> ${item} } jsiConverterHeader = 'NitroModules/JSIConverter+JPrimitiveArray.hpp' break default: - jsiConverterHeader = 'NitroModules/JSIConverter+JArrayClass.hpp' + // `JULongArrays` converts its `JArrayUInt64` elements. + jsiConverterHeader = this.isULongArrays + ? 'NitroModules/JSIConverter+JPrimitiveArray.hpp' + : 'NitroModules/JSIConverter+JArrayClass.hpp' break } imports.push( diff --git a/packages/nitrogen/src/syntax/kotlin/types/KotlinNamedType.ts b/packages/nitrogen/src/syntax/kotlin/types/KotlinNamedType.ts index c0839d6d03..1296db33c1 100644 --- a/packages/nitrogen/src/syntax/kotlin/types/KotlinNamedType.ts +++ b/packages/nitrogen/src/syntax/kotlin/types/KotlinNamedType.ts @@ -22,8 +22,8 @@ export class KotlinNamedType extends NamedWrappingType implements Ko get isKotlinFieldCompatible(): boolean { return this.type.isKotlinFieldCompatible ?? !this.type.needsKotlinConversion } - get isKotlinEqualityCompatible(): boolean { - return this.type.isKotlinEqualityCompatible ?? true + getKotlinEqualityValue(value: string): string | undefined { + return this.type.getKotlinEqualityValue?.(value) } get needsKotlinConversion(): boolean { diff --git a/packages/nitrogen/src/syntax/kotlin/types/KotlinOptionalType.ts b/packages/nitrogen/src/syntax/kotlin/types/KotlinOptionalType.ts index 7c3730439a..c7fd15a638 100644 --- a/packages/nitrogen/src/syntax/kotlin/types/KotlinOptionalType.ts +++ b/packages/nitrogen/src/syntax/kotlin/types/KotlinOptionalType.ts @@ -29,8 +29,10 @@ export class KotlinOptionalType extends OptionalType implements KotlinType { return this.wrappingType.jniValueKind } - get isKotlinEqualityCompatible(): boolean { - return this.wrappingType.isKotlinEqualityCompatible ?? true + getKotlinEqualityValue(value: string): string | undefined { + const wrappedValue = this.wrappingType.getKotlinEqualityValue?.('it') + if (wrappedValue == null) return undefined + return `${value}?.let { ${wrappedValue} }` } getCppConverter(cppType: Type): KotlinCppConverter { diff --git a/packages/nitrogen/src/syntax/kotlin/types/KotlinType.ts b/packages/nitrogen/src/syntax/kotlin/types/KotlinType.ts index adaf8cc206..204d883230 100644 --- a/packages/nitrogen/src/syntax/kotlin/types/KotlinType.ts +++ b/packages/nitrogen/src/syntax/kotlin/types/KotlinType.ts @@ -73,10 +73,10 @@ export interface KotlinType extends Type { /** Whether a generated Kotlin backing field already has this JNI representation. */ readonly isKotlinFieldCompatible?: boolean /** - * Whether `Objects.deepEquals` and `contentDeepHashCode` compare the public Kotlin value - * by its contents. Otherwise, generated structs compare its JNI representation. + * A Kotlin expression that `Objects.deepEquals` and `contentDeepHashCode` compare by contents, + * for public values whose boxes compare by identity, e.g. `ULongArray`. Otherwise `undefined`. */ - readonly isKotlinEqualityCompatible?: boolean + getKotlinEqualityValue?(value: string): string | undefined /** Overrides a native value's printer only when its JVM signature differs. */ getJniCode?(options: GetKotlinCodeOptions): string /** Adapts a native scalar at the JNI boundary when its JVM ABI differs. */ diff --git a/tests/standalone/nitro-test/android/src/main/java/com/margelo/nitro/test/HybridTestObjectKotlin.kt b/tests/standalone/nitro-test/android/src/main/java/com/margelo/nitro/test/HybridTestObjectKotlin.kt index 98d4076b3a..d98b5c9108 100644 --- a/tests/standalone/nitro-test/android/src/main/java/com/margelo/nitro/test/HybridTestObjectKotlin.kt +++ b/tests/standalone/nitro-test/android/src/main/java/com/margelo/nitro/test/HybridTestObjectKotlin.kt @@ -269,6 +269,19 @@ class HybridTestObjectKotlin : HybridTestObjectSwiftKotlinSpec() { return callback.callAsync(array) } + override fun bounceNestedUnsignedArrayAsync(array: Array): Promise> { + return Promise.async { + return@async array + } + } + + override fun callNestedUnsignedArrayCallback( + array: Array, + callback: Callback<(array: Array) -> Array>, + ): Array { + return callback.callSync(array) + } + override fun bounceHybridObjects(array: Array): Array { return array } diff --git a/tests/standalone/nitro-test/apple/HybridTestObjectSwift.swift b/tests/standalone/nitro-test/apple/HybridTestObjectSwift.swift index d9edff87ac..8e9682a842 100644 --- a/tests/standalone/nitro-test/apple/HybridTestObjectSwift.swift +++ b/tests/standalone/nitro-test/apple/HybridTestObjectSwift.swift @@ -421,6 +421,18 @@ class HybridTestObjectSwift: HybridTestObjectSwiftKotlinSpec { return callback.callAsync(array) } + func bounceNestedUnsignedArrayAsync(array: [[UInt64]]) throws -> any Promise<[[UInt64]]> { + return .async { + return array + } + } + + func callNestedUnsignedArrayCallback( + array: [[UInt64]], callback: any Callback<[[UInt64]], [[UInt64]]> + ) throws -> [[UInt64]] { + return try callback.callSync(array) + } + func bounceHybridObjects(array: [(any HybridChildSpec)]) throws -> [(any HybridChildSpec)] { return array } diff --git a/tests/standalone/nitro-test/cpp/HybridTestObjectCpp.cpp b/tests/standalone/nitro-test/cpp/HybridTestObjectCpp.cpp index 2643cbe09c..88c9e60c69 100644 --- a/tests/standalone/nitro-test/cpp/HybridTestObjectCpp.cpp +++ b/tests/standalone/nitro-test/cpp/HybridTestObjectCpp.cpp @@ -414,6 +414,17 @@ HybridTestObjectCpp::callUnsignedArrayCallbackAsync(const std::vector& return callback.callAsync(array); } +Promise>> +HybridTestObjectCpp::bounceNestedUnsignedArrayAsync(const std::vector>& array) { + return Promise>>::async([=]() { return array; }); +} + +std::vector> HybridTestObjectCpp::callNestedUnsignedArrayCallback( + const std::vector>& array, + const Callback>(const std::vector>&)>& callback) { + return callback.callSync(array); +} + std::vector HybridTestObjectCpp::bounceHybridObjects(const std::vector& array) { return array; } diff --git a/tests/standalone/nitro-test/cpp/HybridTestObjectCpp.hpp b/tests/standalone/nitro-test/cpp/HybridTestObjectCpp.hpp index 502d104cb6..0f11a7ede7 100644 --- a/tests/standalone/nitro-test/cpp/HybridTestObjectCpp.hpp +++ b/tests/standalone/nitro-test/cpp/HybridTestObjectCpp.hpp @@ -196,6 +196,10 @@ class HybridTestObjectCpp : public HybridTestObjectCppSpec { Promise> callUnsignedArrayCallbackAsync(const std::vector& array, const Callback(const std::vector&)>& callback) override; + Promise>> bounceNestedUnsignedArrayAsync(const std::vector>& array) override; + std::vector> callNestedUnsignedArrayCallback( + const std::vector>& array, + const Callback>(const std::vector>&)>& callback) override; std::vector bounceHybridObjects(const std::vector& array) override; std::vector> bounceFunctions(const std::vector>& functions) override; diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/NitroTest+autolinking.cmake b/tests/standalone/nitro-test/nitrogen/generated/android/NitroTest+autolinking.cmake index 4dac02a556..feecdc247f 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/NitroTest+autolinking.cmake +++ b/tests/standalone/nitro-test/nitrogen/generated/android/NitroTest+autolinking.cmake @@ -41,6 +41,7 @@ target_sources(NitroTest PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JCallback_std__string.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JCallback_std__vector_Powertrain__std__vector_Powertrain_.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JCallback_std__vector_std__vector_std__optional_Person____std__vector_std__vector_std__optional_Person___.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JCallback_std__vector_uint64_t__std__vector_uint64_t_.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JCallback_uint64_t_uint64_t.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JCallback_void.cpp" diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/NitroTestOnLoad.cpp b/tests/standalone/nitro-test/nitrogen/generated/android/NitroTestOnLoad.cpp index 7c94a0b726..4cf82e5c5b 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/NitroTestOnLoad.cpp +++ b/tests/standalone/nitro-test/nitrogen/generated/android/NitroTestOnLoad.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ namespace margelo::nitro::test { margelo::nitro::test::JCallback_Promise_std__vector_Powertrain__::registerNatives(); margelo::nitro::test::JCallback_std__vector_std__vector_std__optional_Person____std__vector_std__vector_std__optional_Person___::registerNatives(); margelo::nitro::test::JCallback_std__vector_uint64_t__std__vector_uint64_t_::registerNatives(); + margelo::nitro::test::JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::registerNatives(); margelo::nitro::test::JCallback_double_double::registerNatives(); margelo::nitro::test::JCallback_Promise_void_::registerNatives(); margelo::nitro::test::JCallback_void_std__optional_double_::registerNatives(); diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/c++/HybridTestObjectCppSpecClass.cpp b/tests/standalone/nitro-test/nitrogen/generated/android/c++/HybridTestObjectCppSpecClass.cpp index d9643b5958..3f4a63cab0 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/c++/HybridTestObjectCppSpecClass.cpp +++ b/tests/standalone/nitro-test/nitrogen/generated/android/c++/HybridTestObjectCppSpecClass.cpp @@ -159,6 +159,8 @@ namespace margelo::nitro::test { clazz.registerHybridMethod("bounceUnsignedAsync", &HybridTestObjectCppSpec::bounceUnsignedAsync); clazz.registerHybridMethod("callUnsignedCallbackAsync", &HybridTestObjectCppSpec::callUnsignedCallbackAsync); clazz.registerHybridMethod("callUnsignedArrayCallbackAsync", &HybridTestObjectCppSpec::callUnsignedArrayCallbackAsync); + clazz.registerHybridMethod("bounceNestedUnsignedArrayAsync", &HybridTestObjectCppSpec::bounceNestedUnsignedArrayAsync); + clazz.registerHybridMethod("callNestedUnsignedArrayCallback", &HybridTestObjectCppSpec::callNestedUnsignedArrayCallback); clazz.registerHybridMethod("bounceHybridObjects", &HybridTestObjectCppSpec::bounceHybridObjects); clazz.registerHybridMethod("bounceFunctions", &HybridTestObjectCppSpec::bounceFunctions); clazz.registerHybridMethod("bounceMaps", &HybridTestObjectCppSpec::bounceMaps); diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/c++/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.cpp b/tests/standalone/nitro-test/nitrogen/generated/android/c++/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.cpp new file mode 100644 index 0000000000..e18e31d4bb --- /dev/null +++ b/tests/standalone/nitro-test/nitrogen/generated/android/c++/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.cpp @@ -0,0 +1,60 @@ +/// +/// JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include +#include +#include + +namespace margelo::nitro::test { + + JNIRetainedValue>::Type JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::JFunction_cxx::invoke(JNIRetainedValue>::Type array) const { + static const auto __method = javaClassStatic()->getMethod(jni::alias_ref)>("call"); + auto result = __method(self(), JNIRetainedValue>::borrow(array)); + return JNIRetainedValue>::retain(result); + } + + jni::local_ref JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::create(CallbackType callback) { + return newObjectCxxArgs(std::move(callback)); + } + + jni::local_ref JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::callSync_cxx(jni::alias_ref array) { + return callSync(array); + } + + jni::local_ref>> JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::callAsync_cxx(jni::alias_ref array) { + return callAsync>>(array); + } + + void JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::callAndForget_cxx(jni::alias_ref array) { + callAndForget(array); + } + + jni::local_ref JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::fromCxx_cxx(jni::alias_ref, jni::alias_ref callback) { + return create(getCallback(callback)); + } + + jni::local_ref JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::fromFunction_cxx(jni::alias_ref, jni::alias_ref function) { + return create(CallbackType::make(JNICallable(jni::make_global(function)))); + } + + void JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::registerNatives() { + registerHybrid({ + makeNativeMethod("callSync_cxx", JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::callSync_cxx), + makeNativeMethod("callAsync_cxx", JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::callAsync_cxx), + makeNativeMethod("callAndForget_cxx", JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::callAndForget_cxx), + makeNativeMethod("fromCxx_cxx", JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::fromCxx_cxx), + makeNativeMethod("fromFunction_cxx", JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::fromFunction_cxx), + }); + } + + JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__::JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__(CallbackType callback) : HybridBase(std::move(callback)) {} + +} // namespace margelo::nitro::test diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/c++/JHybridTestObjectSwiftKotlinSpec.cpp b/tests/standalone/nitro-test/nitrogen/generated/android/c++/JHybridTestObjectSwiftKotlinSpec.cpp index d0dabb2a36..c982d65064 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/c++/JHybridTestObjectSwiftKotlinSpec.cpp +++ b/tests/standalone/nitro-test/nitrogen/generated/android/c++/JHybridTestObjectSwiftKotlinSpec.cpp @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -209,6 +210,8 @@ namespace margelo::nitro::test { clazz.registerHybridMethod("bounceUnsignedAsync", &JHybridTestObjectSwiftKotlinSpec::bounceUnsignedAsync); clazz.registerHybridMethod("callUnsignedCallbackAsync", &JHybridTestObjectSwiftKotlinSpec::callUnsignedCallbackAsync); clazz.registerHybridMethod("callUnsignedArrayCallbackAsync", &JHybridTestObjectSwiftKotlinSpec::callUnsignedArrayCallbackAsync); + clazz.registerHybridMethod("bounceNestedUnsignedArrayAsync", &JHybridTestObjectSwiftKotlinSpec::bounceNestedUnsignedArrayAsync); + clazz.registerHybridMethod("callNestedUnsignedArrayCallback", &JHybridTestObjectSwiftKotlinSpec::callNestedUnsignedArrayCallback); clazz.registerHybridMethod("bounceHybridObjects", &JHybridTestObjectSwiftKotlinSpec::bounceHybridObjects); clazz.registerHybridMethod("bounceFunctions", &JHybridTestObjectSwiftKotlinSpec::bounceFunctions); clazz.registerHybridMethod("bounceMaps", &JHybridTestObjectSwiftKotlinSpec::bounceMaps); @@ -670,8 +673,8 @@ namespace margelo::nitro::test { auto __result = __method(_javaPart, CxxPart::getClass(), array); return __result; } - jni::local_ref> JHybridTestObjectSwiftKotlinSpec::bounceNestedUnsignedArray(const jni::local_ref>& array) { - static const auto __method = CxxPart::getClass()->getNonvirtualMethod>(jni::alias_ref> /* array */)>("bounceNestedUnsignedArray_cxx"); + jni::local_ref JHybridTestObjectSwiftKotlinSpec::bounceNestedUnsignedArray(const jni::local_ref& array) { + static const auto __method = CxxPart::getClass()->getNonvirtualMethod(jni::alias_ref /* array */)>("bounceNestedUnsignedArray_cxx"); auto __result = __method(_javaPart, CxxPart::getClass(), array); return __result; } @@ -725,6 +728,16 @@ namespace margelo::nitro::test { auto __result = __method(_javaPart, CxxPart::getClass(), array, callback); return __result; } + jni::local_ref>> JHybridTestObjectSwiftKotlinSpec::bounceNestedUnsignedArrayAsync(const jni::local_ref& array) { + static const auto __method = CxxPart::getClass()->getNonvirtualMethod>>(jni::alias_ref /* array */)>("bounceNestedUnsignedArrayAsync_cxx"); + auto __result = __method(_javaPart, CxxPart::getClass(), array); + return __result; + } + jni::local_ref JHybridTestObjectSwiftKotlinSpec::callNestedUnsignedArrayCallback(const jni::local_ref& array, const jni::local_ref& callback) { + static const auto __method = CxxPart::getClass()->getNonvirtualMethod(jni::alias_ref /* array */, jni::alias_ref /* callback */)>("callNestedUnsignedArrayCallback_cxx"); + auto __result = __method(_javaPart, CxxPart::getClass(), array, callback); + return __result; + } jni::local_ref> JHybridTestObjectSwiftKotlinSpec::bounceHybridObjects(const jni::local_ref>& array) { static const auto __method = CxxPart::getClass()->getNonvirtualMethod>(jni::alias_ref> /* array */)>("bounceHybridObjects"); auto __result = __method(_javaPart, CxxPart::getClass(), array); diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/c++/JUnsignedValues.cpp b/tests/standalone/nitro-test/nitrogen/generated/android/c++/JUnsignedValues.cpp index a534816e6f..f5d653e602 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/c++/JUnsignedValues.cpp +++ b/tests/standalone/nitro-test/nitrogen/generated/android/c++/JUnsignedValues.cpp @@ -13,13 +13,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include @@ -27,7 +27,7 @@ namespace margelo::nitro { jni::local_ref JSIConverter>::fromJSI(jsi::Runtime& runtime, const jsi::Value& value) { auto object = value.asObject(runtime); - return margelo::nitro::test::JUnsignedValues::create(JSIConverter::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "unsignedValue"))), JSIConverter>>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "optionalUnsigned"))), JSIConverter>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "values"))), JSIConverter>>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "nested"))), JSIConverter>>>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "record"))), JSIConverter>>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "callbacks")))); + return margelo::nitro::test::JUnsignedValues::create(JSIConverter::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "unsignedValue"))), JSIConverter>>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "optionalUnsigned"))), JSIConverter>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "values"))), JSIConverter>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "nested"))), JSIConverter>>>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "record"))), JSIConverter>>::fromJSI(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "callbacks")))); } jsi::Value JSIConverter>::toJSI(jsi::Runtime& runtime, jni::alias_ref value) { @@ -35,7 +35,7 @@ namespace margelo::nitro { object.setProperty(runtime, PropNameIDCache::get(runtime, "unsignedValue"), JSIConverter::toJSI(runtime, value->getUnsignedValue())); object.setProperty(runtime, PropNameIDCache::get(runtime, "optionalUnsigned"), JSIConverter>>::toJSI(runtime, value->getOptionalUnsigned())); object.setProperty(runtime, PropNameIDCache::get(runtime, "values"), JSIConverter>::toJSI(runtime, value->getValues())); - object.setProperty(runtime, PropNameIDCache::get(runtime, "nested"), JSIConverter>>::toJSI(runtime, value->getNested())); + object.setProperty(runtime, PropNameIDCache::get(runtime, "nested"), JSIConverter>::toJSI(runtime, value->getNested())); object.setProperty(runtime, PropNameIDCache::get(runtime, "record"), JSIConverter>>>::toJSI(runtime, value->getRecord())); object.setProperty(runtime, PropNameIDCache::get(runtime, "callbacks"), JSIConverter>>::toJSI(runtime, value->getCallbacks())); return object; @@ -45,7 +45,7 @@ namespace margelo::nitro { if (!value.isObject()) return false; auto object = value.getObject(runtime); if (!isPlainObject(runtime, object)) return false; - return JSIConverter::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "unsignedValue"))) && JSIConverter>>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "optionalUnsigned"))) && JSIConverter>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "values"))) && JSIConverter>>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "nested"))) && JSIConverter>>>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "record"))) && JSIConverter>>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "callbacks"))); + return JSIConverter::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "unsignedValue"))) && JSIConverter>>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "optionalUnsigned"))) && JSIConverter>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "values"))) && JSIConverter>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "nested"))) && JSIConverter>>>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "record"))) && JSIConverter>>::canConvert(runtime, object.getProperty(runtime, PropNameIDCache::get(runtime, "callbacks"))); } } // namespace margelo::nitro diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.hpp b/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.hpp new file mode 100644 index 0000000000..16abbc0758 --- /dev/null +++ b/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.hpp @@ -0,0 +1,55 @@ +/// +/// JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace margelo::nitro::test { + + namespace jni = facebook::jni; + + /** + * The C++ part of the Kotlin `Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__`, which holds a `Callback<...>` in `JNICallback`. + */ + class JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__ final : public jni::HybridClass(jni::local_ref)>> { + public: + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/test/Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__;"; + + /** + * The Kotlin `Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.Function_cxx`, which calls a Kotlin callback. + */ + struct JFunction_cxx : jni::JavaClass { + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/test/Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__$Function_cxx;"; + JNIRetainedValue>::Type invoke(JNIRetainedValue>::Type array) const; + }; + + public: + static jni::local_ref create(CallbackType callback); + static void registerNatives(); + + private: + jni::local_ref callSync_cxx(jni::alias_ref array); + jni::local_ref>> callAsync_cxx(jni::alias_ref array); + void callAndForget_cxx(jni::alias_ref array); + static jni::local_ref fromCxx_cxx(jni::alias_ref, jni::alias_ref callback); + static jni::local_ref fromFunction_cxx(jni::alias_ref, jni::alias_ref function); + + private: + friend HybridBase; + explicit JCallback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__(CallbackType callback); + }; + +} // namespace margelo::nitro::test diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JHybridTestObjectSwiftKotlinSpec.hpp b/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JHybridTestObjectSwiftKotlinSpec.hpp index feef03612c..e208c1535e 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JHybridTestObjectSwiftKotlinSpec.hpp +++ b/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JHybridTestObjectSwiftKotlinSpec.hpp @@ -83,6 +83,7 @@ #include #include #include +#include #include #include #include @@ -217,7 +218,7 @@ namespace margelo::nitro::test { jni::local_ref>>> awaitEnumArrayPromise(const jni::local_ref>>>& promise); jni::local_ref>>> callNestedStructCallback(const jni::local_ref>>>& value, const jni::local_ref& callback); jni::local_ref bounceUnsignedArray(const jni::local_ref& array); - jni::local_ref> bounceNestedUnsignedArray(const jni::local_ref>& array); + jni::local_ref bounceNestedUnsignedArray(const jni::local_ref& array); jni::local_ref> bounceOptionalUnsignedArray(const jni::local_ref>& array); jni::local_ref>> bounceUnsignedArrayAsync(const jni::local_ref& array); jni::local_ref callUnsignedArrayCallback(const jni::local_ref& array, const jni::local_ref& callback); @@ -228,6 +229,8 @@ namespace margelo::nitro::test { jni::local_ref>> bounceUnsignedAsync(uint64_t value); jni::local_ref>> callUnsignedCallbackAsync(uint64_t value, const jni::local_ref& callback); jni::local_ref>> callUnsignedArrayCallbackAsync(const jni::local_ref& array, const jni::local_ref& callback); + jni::local_ref>> bounceNestedUnsignedArrayAsync(const jni::local_ref& array); + jni::local_ref callNestedUnsignedArrayCallback(const jni::local_ref& array, const jni::local_ref& callback); jni::local_ref> bounceHybridObjects(const jni::local_ref>& array); jni::local_ref> bounceFunctions(const jni::local_ref>& functions); jni::local_ref> bounceMaps(const jni::local_ref>& maps); diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JUnsignedValues.hpp b/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JUnsignedValues.hpp index 6a8adc80e6..77a6152e02 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JUnsignedValues.hpp +++ b/tests/standalone/nitro-test/nitrogen/generated/android/c++/include/NitroTest/private/JUnsignedValues.hpp @@ -16,13 +16,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include namespace margelo::nitro::test { @@ -32,9 +32,9 @@ namespace margelo::nitro::test { struct JUnsignedValues final : public jni::JavaClass { static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/test/UnsignedValues;"; - static jni::local_ref create(uint64_t unsignedValue, jni::alias_ref> optionalUnsigned, jni::alias_ref values, jni::alias_ref> nested, jni::alias_ref>> record, jni::alias_ref> callbacks) { + static jni::local_ref create(uint64_t unsignedValue, jni::alias_ref> optionalUnsigned, jni::alias_ref values, jni::alias_ref nested, jni::alias_ref>> record, jni::alias_ref> callbacks) { static const auto clazz = javaClassStatic(); - static const auto create = clazz->getStaticMethod>, jni::alias_ref, jni::alias_ref>, jni::alias_ref>>, jni::alias_ref>)>("fromCpp"); + static const auto create = clazz->getStaticMethod>, jni::alias_ref, jni::alias_ref, jni::alias_ref>>, jni::alias_ref>)>("fromCpp"); return create(clazz, JNIConverter::toJNI(unsignedValue), optionalUnsigned, values, nested, record, callbacks); } @@ -54,9 +54,9 @@ namespace margelo::nitro::test { return getFieldValue(field); } - jni::local_ref> getNested() const { + jni::local_ref getNested() const { static const auto clazz = javaClassStatic(); - static const auto method = clazz->getNonvirtualMethod()>("getNested_cxx"); + static const auto method = clazz->getNonvirtualMethod("getNested_cxx"); return method(this->self(), clazz); } diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.kt b/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.kt new file mode 100644 index 0000000000..ea5140c49c --- /dev/null +++ b/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.kt @@ -0,0 +1,97 @@ +/// +/// Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.test + +import androidx.annotation.Keep +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.Callback +import com.margelo.nitro.core.Promise +import com.margelo.nitro.utils.mapToArray +import com.margelo.nitro.core.CxxCallback +import com.margelo.nitro.core.callSync + +/** + * The JNI representation of `Callback<(array: Array) -> Array>`, for the JavaScript callback `(array: array) => std::vector>`. + * It holds a C++ `Callback<...>`, which calls either a JS function or a native function. + * Use `Callback<(array: Array) -> Array>` instead of this class in your code. + */ +@DoNotStrip +@Keep +@Suppress( + "KotlinJniMissingFunction", "unused", + "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", + "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", + "PARAMETER_NAME_CHANGED_ON_OVERRIDE", +) +class Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__ @DoNotStrip @Keep private constructor(hybridData: HybridData): CxxCallback(hybridData), Callback.Arity1, Array> { + override fun callSync(array: Array): Array { + val __result = callSync_cxx(array) + return (@Suppress("UNCHECKED_CAST") (__result as Array)) + } + + override fun callAsync(array: Array): Promise> { + return callAsync_cxx(array) + } + + override fun callAndForget(array: Array): Unit { + callAndForget_cxx(array) + } + + /** + * Lets C++ call a Kotlin callback with JNI types, e.g. `Long` instead of `ULong`. + */ + @DoNotStrip + @Keep + private class Function_cxx(private val callback: Callback<(array: Array) -> Array>) { + @DoNotStrip + @Keep + fun call(array: Array<*>): Array<*> { + val __result = this.callback.callSync((@Suppress("UNCHECKED_CAST") (array as Array))) + return __result + } + } + + @DoNotStrip + @Keep + private external fun callSync_cxx(array: Array<*>): Array<*> + + @DoNotStrip + @Keep + private external fun callAsync_cxx(array: Array<*>): Promise> + + @DoNotStrip + @Keep + private external fun callAndForget_cxx(array: Array<*>): Unit + + companion object { + /** + * Returns the given [callback] as its JNI representation. + * A callback from another module keeps its C++ `Callback<...>`, and + * a callback created in Kotlin is wrapped in a C++ `Callback<...>` that calls it. + */ + @JvmStatic + fun fromKotlin(callback: Callback<(array: Array) -> Array>): Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__ { + return when (callback) { + is Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__ -> callback + is CxxCallback -> fromCxx_cxx(callback) + else -> fromFunction_cxx(Function_cxx(callback)) + } + } + + @JvmStatic + @DoNotStrip + @Keep + private external fun fromCxx_cxx(callback: CxxCallback): Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__ + + @JvmStatic + @DoNotStrip + @Keep + private external fun fromFunction_cxx(function: Function_cxx): Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__ + } +} diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/HybridTestObjectSwiftKotlinSpec.kt b/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/HybridTestObjectSwiftKotlinSpec.kt index ef9d19c97d..37b620bf0b 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/HybridTestObjectSwiftKotlinSpec.kt +++ b/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/HybridTestObjectSwiftKotlinSpec.kt @@ -299,9 +299,9 @@ abstract class HybridTestObjectSwiftKotlinSpec: HybridObject() { @DoNotStrip @Keep - private fun bounceNestedUnsignedArray_cxx(array: Array): Array { - val __result = bounceNestedUnsignedArray(array.mapToArray { __item -> __item.asULongArray() }) - return __result.mapToArray { __item -> __item.asLongArray() } + private fun bounceNestedUnsignedArray_cxx(array: Array<*>): Array<*> { + val __result = bounceNestedUnsignedArray((@Suppress("UNCHECKED_CAST") (array as Array))) + return __result } abstract fun bounceOptionalUnsignedArray(array: ULongArray?): ULongArray? @@ -374,6 +374,24 @@ abstract class HybridTestObjectSwiftKotlinSpec: HybridObject() { return __result } + abstract fun bounceNestedUnsignedArrayAsync(array: Array): Promise> + + @DoNotStrip + @Keep + private fun bounceNestedUnsignedArrayAsync_cxx(array: Array<*>): Promise> { + val __result = bounceNestedUnsignedArrayAsync((@Suppress("UNCHECKED_CAST") (array as Array))) + return __result + } + + abstract fun callNestedUnsignedArrayCallback(array: Array, callback: Callback<(array: Array) -> Array>): Array + + @DoNotStrip + @Keep + private fun callNestedUnsignedArrayCallback_cxx(array: Array<*>, callback: Callback_std__vector_std__vector_uint64_t___std__vector_std__vector_uint64_t__): Array<*> { + val __result = callNestedUnsignedArrayCallback((@Suppress("UNCHECKED_CAST") (array as Array)), callback) + return __result + } + @DoNotStrip @Keep abstract fun bounceHybridObjects(array: Array): Array diff --git a/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/UnsignedValues.kt b/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/UnsignedValues.kt index 206d64288f..530280395c 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/UnsignedValues.kt +++ b/tests/standalone/nitro-test/nitrogen/generated/android/kotlin/com/margelo/nitro/test/UnsignedValues.kt @@ -48,8 +48,8 @@ data class UnsignedValues( @DoNotStrip @Keep @Suppress("unused", "FunctionName") - private fun getNested_cxx(): Array { - return nested.mapToArray { __item -> __item.asLongArray() } + private fun getNested_cxx(): Array<*> { + return nested } @DoNotStrip @@ -89,8 +89,8 @@ data class UnsignedValues( @Keep @Suppress("unused") @JvmStatic - private fun fromCpp(unsignedValue: Long, optionalUnsigned: Long?, values: LongArray, nested: Array, record: Map, callbacks: Array): UnsignedValues { - return UnsignedValues(unsignedValue.toULong(), optionalUnsigned?.let { it.toULong() }, values.asULongArray(), nested.mapToArray { __item -> __item.asULongArray() }, record, callbacks.mapToArray ULong>> { __item -> __item }) + private fun fromCpp(unsignedValue: Long, optionalUnsigned: Long?, values: LongArray, nested: Array<*>, record: Map, callbacks: Array): UnsignedValues { + return UnsignedValues(unsignedValue.toULong(), optionalUnsigned?.let { it.toULong() }, values.asULongArray(), (@Suppress("UNCHECKED_CAST") (nested as Array)), record, callbacks.mapToArray ULong>> { __item -> __item }) } } } diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/NitroTest-Swift-Cxx-Bridge.cpp b/tests/standalone/nitro-test/nitrogen/generated/apple/NitroTest-Swift-Cxx-Bridge.cpp index 4f0801744f..fba073a4a5 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/apple/NitroTest-Swift-Cxx-Bridge.cpp +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/NitroTest-Swift-Cxx-Bridge.cpp @@ -249,6 +249,24 @@ namespace margelo::nitro::test::swift_bridge { }); } + Promise_swift__Array_swift__Array_uint64_t__ create_Promise_swift__Array_swift__Array_uint64_t__() { return Promise_swift__Array_swift__Array_uint64_t__::pending(); } + + void reject_Promise_swift__Array_swift__Array_uint64_t__(const Promise_swift__Array_swift__Array_uint64_t__& promise, std::exception_ptr error) { promise.reject(std::move(error)); } + + void listenRejected_Promise_swift__Array_swift__Array_uint64_t__(const Promise_swift__Array_swift__Array_uint64_t__& promise, std::function listener) { promise.addOnRejectedListener(std::move(listener)); } + + void resolve_Promise_swift__Array_swift__Array_uint64_t__(const Promise_swift__Array_swift__Array_uint64_t__& promise, const void* NON_NULL value) { + promise.resolve(NitroModules::copySwiftValue>>(value)); + } + + void listen_Promise_swift__Array_swift__Array_uint64_t__(const Promise_swift__Array_swift__Array_uint64_t__& promise, std::function listener) { + promise.addOnResolvedListener([listener = std::move(listener)](const swift::Array>& value) { + NitroModules::withSwiftValue(value, [&](const void* pointer) { + listener(pointer); + }); + }); + } + Result callSync_Callback_void(const Callback_void& callback) noexcept { try { callback.callSync(); @@ -509,6 +527,37 @@ namespace margelo::nitro::test::swift_bridge { }); } + Result callSync_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(const Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__& callback, const void* NON_NULL param0, void* NON_NULL __outResult) noexcept { + try { + NitroModules::initializeSwiftValue(__outResult, callback.callSync(NitroModules::copySwiftValue>>(param0))); + return Result::withValue(); + } catch (...) { + return Result::withError(std::current_exception()); + } + } + + Promise>> callAsync_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(const Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__& callback, const void* NON_NULL param0) { + return callback.callAsync(NitroModules::copySwiftValue>>(param0)); + } + + void callAndForget_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(const Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__& callback, const void* NON_NULL param0) { + callback.callAndForget(NitroModules::copySwiftValue>>(param0)); + } + + Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ create_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(std::function(const void* NON_NULL param0, void* NON_NULL __outResult)> closure) { + return Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__::make([closure = std::move(closure)](const swift::Array>& param0) -> swift::Array> { + auto __result = borrowSwiftValue(param0, [&](const void* param0) { + return withSwiftResult>>([&](void* __outResult) { + return closure(param0, __outResult); + }); + }); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + return std::move(__result.value()); + }); + } + Callback_void InlineCallback_void::escape() const { return get().escape(); } diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/NitroTestAppleCxx/include/NitroTestAppleCxx/NitroTestAppleCxx.h b/tests/standalone/nitro-test/nitrogen/generated/apple/NitroTestAppleCxx/include/NitroTestAppleCxx/NitroTestAppleCxx.h index d1362fdd2c..f30f27cc76 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/apple/NitroTestAppleCxx/include/NitroTestAppleCxx/NitroTestAppleCxx.h +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/NitroTestAppleCxx/include/NitroTestAppleCxx/NitroTestAppleCxx.h @@ -253,6 +253,12 @@ namespace margelo::nitro::test::swift_bridge { void resolve_Promise_swift__Array_uint64_t_(const Promise_swift__Array_uint64_t_& promise, const void* NON_NULL value); void listen_Promise_swift__Array_uint64_t_(const Promise_swift__Array_uint64_t_& promise, std::function listener); using Promise_uint64_t = Promise; + using Promise_swift__Array_swift__Array_uint64_t__ = Promise>>; + Promise_swift__Array_swift__Array_uint64_t__ create_Promise_swift__Array_swift__Array_uint64_t__(); + void reject_Promise_swift__Array_swift__Array_uint64_t__(const Promise_swift__Array_swift__Array_uint64_t__& promise, std::exception_ptr error); + void listenRejected_Promise_swift__Array_swift__Array_uint64_t__(const Promise_swift__Array_swift__Array_uint64_t__& promise, std::function listener); + void resolve_Promise_swift__Array_swift__Array_uint64_t__(const Promise_swift__Array_swift__Array_uint64_t__& promise, const void* NON_NULL value); + void listen_Promise_swift__Array_swift__Array_uint64_t__(const Promise_swift__Array_swift__Array_uint64_t__& promise, std::function listener); using Callback_void = Callback; Result callSync_Callback_void(const Callback_void& callback) noexcept; Callback_void create_Callback_void(std::function()> closure); @@ -318,6 +324,11 @@ namespace margelo::nitro::test::swift_bridge { Promise> callAsync_Callback_swift__Array_uint64_t__swift__Array_uint64_t_(const Callback_swift__Array_uint64_t__swift__Array_uint64_t_& callback, const void* NON_NULL param0); void callAndForget_Callback_swift__Array_uint64_t__swift__Array_uint64_t_(const Callback_swift__Array_uint64_t__swift__Array_uint64_t_& callback, const void* NON_NULL param0); Callback_swift__Array_uint64_t__swift__Array_uint64_t_ create_Callback_swift__Array_uint64_t__swift__Array_uint64_t_(std::function(const void* NON_NULL param0, void* NON_NULL __outResult)> closure); + using Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ = Callback>(const swift::Array>&)>; + Result callSync_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(const Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__& callback, const void* NON_NULL param0, void* NON_NULL __outResult) noexcept; + Promise>> callAsync_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(const Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__& callback, const void* NON_NULL param0); + void callAndForget_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(const Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__& callback, const void* NON_NULL param0); + Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ create_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(std::function(const void* NON_NULL param0, void* NON_NULL __outResult)> closure); // TODO: Replace this borrowing facade with a typealias once our minimum Xcode includes // https://github.com/swiftlang/swift/pull/93321, which fixes https://github.com/swiftlang/swift/issues/93318. // Exporting the same imported InlineCallback specialization from two Swift headers duplicates its traits. diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/c++/HybridTestObjectCppSpecClass.cpp b/tests/standalone/nitro-test/nitrogen/generated/apple/c++/HybridTestObjectCppSpecClass.cpp index d9643b5958..3f4a63cab0 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/apple/c++/HybridTestObjectCppSpecClass.cpp +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/c++/HybridTestObjectCppSpecClass.cpp @@ -159,6 +159,8 @@ namespace margelo::nitro::test { clazz.registerHybridMethod("bounceUnsignedAsync", &HybridTestObjectCppSpec::bounceUnsignedAsync); clazz.registerHybridMethod("callUnsignedCallbackAsync", &HybridTestObjectCppSpec::callUnsignedCallbackAsync); clazz.registerHybridMethod("callUnsignedArrayCallbackAsync", &HybridTestObjectCppSpec::callUnsignedArrayCallbackAsync); + clazz.registerHybridMethod("bounceNestedUnsignedArrayAsync", &HybridTestObjectCppSpec::bounceNestedUnsignedArrayAsync); + clazz.registerHybridMethod("callNestedUnsignedArrayCallback", &HybridTestObjectCppSpec::callNestedUnsignedArrayCallback); clazz.registerHybridMethod("bounceHybridObjects", &HybridTestObjectCppSpec::bounceHybridObjects); clazz.registerHybridMethod("bounceFunctions", &HybridTestObjectCppSpec::bounceFunctions); clazz.registerHybridMethod("bounceMaps", &HybridTestObjectCppSpec::bounceMaps); diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/c++/HybridTestObjectSwiftKotlinSpecSwift.cpp b/tests/standalone/nitro-test/nitrogen/generated/apple/c++/HybridTestObjectSwiftKotlinSpecSwift.cpp index 8a301547ed..ad5a6996a0 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/apple/c++/HybridTestObjectSwiftKotlinSpecSwift.cpp +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/c++/HybridTestObjectSwiftKotlinSpecSwift.cpp @@ -503,6 +503,28 @@ namespace margelo::nitro::test { return std::move(__result.value()); } + Promise>> HybridTestObjectSwiftKotlinSpecSwift::bounceNestedUnsignedArrayAsync(const swift::Array>& array) { + auto __result = withCxxResult>>>([&](void* __outResult) { + return _swiftPart.bounceNestedUnsignedArrayAsync(array, __outResult); + }); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + return std::move(__result.value()); + } + + swift::Array> HybridTestObjectSwiftKotlinSpecSwift::callNestedUnsignedArrayCallback(const swift::Array>& array, const Callback>(const swift::Array>&)>& callback) { + auto __result = ([&](const void* callback) { + return withSwiftResult>>([&](void* __outResult) { + return _swiftPart.callNestedUnsignedArrayCallback(array, callback, __outResult); + }); + })(std::addressof(callback)); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + return std::move(__result.value()); + } + swift::Array<::NitroTest::HybridChildSpec_cxx> HybridTestObjectSwiftKotlinSpecSwift::bounceHybridObjects(const swift::Array<::NitroTest::HybridChildSpec_cxx>& array) { auto __result = withSwiftResult>([&](void* __outResult) { return _swiftPart.bounceHybridObjects(array, __outResult); @@ -1757,6 +1779,8 @@ namespace margelo::nitro::test { clazz.registerHybridMethod("bounceUnsignedAsync", &HybridTestObjectSwiftKotlinSpecSwift::bounceUnsignedAsync); clazz.registerHybridMethod("callUnsignedCallbackAsync", &HybridTestObjectSwiftKotlinSpecSwift::callUnsignedCallbackAsync); clazz.registerHybridMethod("callUnsignedArrayCallbackAsync", &HybridTestObjectSwiftKotlinSpecSwift::callUnsignedArrayCallbackAsync); + clazz.registerHybridMethod("bounceNestedUnsignedArrayAsync", &HybridTestObjectSwiftKotlinSpecSwift::bounceNestedUnsignedArrayAsync); + clazz.registerHybridMethod("callNestedUnsignedArrayCallback", &HybridTestObjectSwiftKotlinSpecSwift::callNestedUnsignedArrayCallback); clazz.registerHybridMethod("bounceHybridObjects", &HybridTestObjectSwiftKotlinSpecSwift::bounceHybridObjects); clazz.registerHybridMethod("bounceFunctions", &HybridTestObjectSwiftKotlinSpecSwift::bounceFunctions); clazz.registerHybridMethod("bounceMaps", &HybridTestObjectSwiftKotlinSpecSwift::bounceMaps); diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/c++/include/NitroTest/private/HybridTestObjectSwiftKotlinSpecSwift.hpp b/tests/standalone/nitro-test/nitrogen/generated/apple/c++/include/NitroTest/private/HybridTestObjectSwiftKotlinSpecSwift.hpp index 4b4d0e31fa..6475285632 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/apple/c++/include/NitroTest/private/HybridTestObjectSwiftKotlinSpecSwift.hpp +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/c++/include/NitroTest/private/HybridTestObjectSwiftKotlinSpecSwift.hpp @@ -132,6 +132,8 @@ namespace margelo::nitro::test { Promise bounceUnsignedAsync(uint64_t value); Promise callUnsignedCallbackAsync(uint64_t value, const Callback& callback); Promise> callUnsignedArrayCallbackAsync(const swift::Array& array, const Callback(const swift::Array&)>& callback); + Promise>> bounceNestedUnsignedArrayAsync(const swift::Array>& array); + swift::Array> callNestedUnsignedArrayCallback(const swift::Array>& array, const Callback>(const swift::Array>&)>& callback); swift::Array<::NitroTest::HybridChildSpec_cxx> bounceHybridObjects(const swift::Array<::NitroTest::HybridChildSpec_cxx>& array); swift::Array> bounceFunctions(const swift::Array>& functions); swift::Array bounceMaps(const swift::Array& maps); diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/swift/Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__.swift b/tests/standalone/nitro-test/nitrogen/generated/apple/swift/Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__.swift new file mode 100644 index 0000000000..6f5971543a --- /dev/null +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/swift/Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__.swift @@ -0,0 +1,71 @@ +/// +/// Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +public import NitroModules +internal import CxxStdlib +internal import NitroTestAppleCxx + +public typealias Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ = margelo.nitro.test.swift_bridge.Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ + +extension Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ { + public typealias Arguments = ([[UInt64]]) + public typealias Return = [[UInt64]] + public typealias AsyncResult = margelo.nitro.test.swift_bridge.Promise_swift__Array_swift__Array_uint64_t__ + private typealias bridge = margelo.nitro.test.swift_bridge + + public func __nitroCallSync(_ arguments: Arguments) throws -> Return { + return try withUnsafePointer(to: arguments) { (param0: UnsafePointer<[[UInt64]]>) -> Return in + return try withUnsafeTemporaryAllocation(of: [[UInt64]].self, capacity: 1) { (result: UnsafeMutableBufferPointer<[[UInt64]]>) -> Return in + let __result = bridge.callSync_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(self, param0, result.baseAddress!) + if __result.hasError() { + throw RuntimeError.from(cppError: __result.error()) + } + let value = result.baseAddress!.move() + return value + } + } + } + public func __nitroCallAsync(_ arguments: Arguments) -> AsyncResult { + return withUnsafePointer(to: arguments) { (param0: UnsafePointer<[[UInt64]]>) -> AsyncResult in + return bridge.callAsync_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(self, param0) + } + } + public func __nitroCallAndForget(_ arguments: Arguments) { + return withUnsafePointer(to: arguments) { (param0: UnsafePointer<[[UInt64]]>) -> Void in + bridge.callAndForget_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(self, param0) + } + } + public init(_ closure: @escaping @Sendable ([[UInt64]]) throws -> Return) { + self = bridge.create_Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__(.init { (param0: UnsafeRawPointer!, __outResult: UnsafeMutableRawPointer!) -> bridge.Result_void in + do { + let value = try closure(param0.load(as: [[UInt64]].self)) + __outResult.assumingMemoryBound(to: [[UInt64]].self).initialize(to: value) + return bridge.Result_void.withValue() + } catch { + return bridge.Result_void.withError(error.toCpp()) + } + }) + } +} + +extension Callback<([[UInt64]]), [[UInt64]]> where Self == Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ { + /// Creates a native callback from an escaping Swift closure. + public static func native(_ closure: @escaping @Sendable ([[UInt64]]) throws -> [[UInt64]]) -> Self { + return Self(closure) + } +} + +extension Callback<([[UInt64]]), [[UInt64]]> { + func toCpp() -> Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ { + if let value = self as? Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ { + return value + } + return Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__ { (param0: [[UInt64]]) -> [[UInt64]] in + try self.callSync((param0)) + } + } +} diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/swift/HybridTestObjectSwiftKotlinSpec.swift b/tests/standalone/nitro-test/nitrogen/generated/apple/swift/HybridTestObjectSwiftKotlinSpec.swift index 70ac997eb9..ae1d3a67ad 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/apple/swift/HybridTestObjectSwiftKotlinSpec.swift +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/swift/HybridTestObjectSwiftKotlinSpec.swift @@ -70,6 +70,8 @@ public protocol HybridTestObjectSwiftKotlinSpec_protocol: HybridTestObjectSwiftK func bounceUnsignedAsync(value: UInt64) throws -> any Promise func callUnsignedCallbackAsync(value: UInt64, callback: any Callback<(/* value */ UInt64), UInt64>) throws -> any Promise func callUnsignedArrayCallbackAsync(array: [UInt64], callback: any Callback<(/* array */ [UInt64]), [UInt64]>) throws -> any Promise<[UInt64]> + func bounceNestedUnsignedArrayAsync(array: [[UInt64]]) throws -> any Promise<[[UInt64]]> + func callNestedUnsignedArrayCallback(array: [[UInt64]], callback: any Callback<(/* array */ [[UInt64]]), [[UInt64]]>) throws -> [[UInt64]] func bounceHybridObjects(array: [(any HybridChildSpec)]) throws -> [(any HybridChildSpec)] func bounceFunctions(functions: [any Callback<(), Void>]) throws -> [any Callback<(), Void>] func bounceMaps(maps: [AnyJSON]) throws -> [AnyJSON] diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/swift/HybridTestObjectSwiftKotlinSpec_cxx.swift b/tests/standalone/nitro-test/nitrogen/generated/apple/swift/HybridTestObjectSwiftKotlinSpec_cxx.swift index db9742887b..3e6894fae3 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/apple/swift/HybridTestObjectSwiftKotlinSpec_cxx.swift +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/swift/HybridTestObjectSwiftKotlinSpec_cxx.swift @@ -629,6 +629,26 @@ public final class HybridTestObjectSwiftKotlinSpec_cxx { } } + public final func bounceNestedUnsignedArrayAsync(array: [[UInt64]], __outResult: UnsafeMutableRawPointer) -> bridge.Result_void { + do { + let value = try __implementation.bounceNestedUnsignedArrayAsync(array: array) + __outResult.initializeMemory(as: margelo.nitro.test.swift_bridge.Promise_swift__Array_swift__Array_uint64_t__.self, repeating: value.toCpp(), count: 1) + return bridge.Result_void.withValue() + } catch { + return bridge.Result_void.withError(error.toCpp()) + } + } + + public final func callNestedUnsignedArrayCallback(array: [[UInt64]], callback: UnsafeRawPointer, __outResult: UnsafeMutableRawPointer) -> bridge.Result_void { + do { + let value = try __implementation.callNestedUnsignedArrayCallback(array: array, callback: callback.load(as: margelo.nitro.test.swift_bridge.Callback_swift__Array_swift__Array_uint64_t___swift__Array_swift__Array_uint64_t__.self)) + __outResult.assumingMemoryBound(to: [[UInt64]].self).initialize(to: value) + return bridge.Result_void.withValue() + } catch { + return bridge.Result_void.withError(error.toCpp()) + } + } + public final func bounceHybridObjects(array: [HybridChildSpec_cxx], __outResult: UnsafeMutableRawPointer) -> bridge.Result_void { do { let value = try __implementation.bounceHybridObjects(array: array.map { $0.getHybridChildSpec() }) diff --git a/tests/standalone/nitro-test/nitrogen/generated/apple/swift/Promise_swift__Array_swift__Array_uint64_t__.swift b/tests/standalone/nitro-test/nitrogen/generated/apple/swift/Promise_swift__Array_swift__Array_uint64_t__.swift new file mode 100644 index 0000000000..11fc35942c --- /dev/null +++ b/tests/standalone/nitro-test/nitrogen/generated/apple/swift/Promise_swift__Array_swift__Array_uint64_t__.swift @@ -0,0 +1,102 @@ +/// +/// Promise_swift__Array_swift__Array_uint64_t__.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +public import NitroModules +internal import CxxStdlib +public import Dispatch +internal import NitroTestAppleCxx + +public typealias Promise_swift__Array_swift__Array_uint64_t__ = margelo.nitro.test.swift_bridge.Promise_swift__Array_swift__Array_uint64_t__ + +extension Promise_swift__Array_swift__Array_uint64_t__ { + public typealias T = [[UInt64]] + private typealias bridge = margelo.nitro.test.swift_bridge + + public func __nitroResolve(result: [[UInt64]]) { + withUnsafePointer(to: result) { (pointer: UnsafePointer<[[UInt64]]>) -> Void in + bridge.resolve_Promise_swift__Array_swift__Array_uint64_t__(self, pointer) + } + } + public func __nitroReject(error: any Error) { + bridge.reject_Promise_swift__Array_swift__Array_uint64_t__(self, error.toCpp()) + } + + public func __nitroAddOnResolvedListener(_ listener: @escaping @Sendable ([[UInt64]]) -> Void) { + bridge.listen_Promise_swift__Array_swift__Array_uint64_t__(self, .init { (value: UnsafeRawPointer!) -> Void in + listener(value.load(as: [[UInt64]].self)) + }) + } + public func __nitroAddOnRejectedListener(_ listener: @escaping @Sendable (any Error) -> Void) { + bridge.listenRejected_Promise_swift__Array_swift__Array_uint64_t__(self, .init { (exceptionPtr: std.exception_ptr) -> Void in + listener(RuntimeError.from(cppError: exceptionPtr)) + }) + } +} + +extension Promise<[[UInt64]]> where Self == Promise_swift__Array_swift__Array_uint64_t__ { + public static func pending() -> Self { + return margelo.nitro.test.swift_bridge.create_Promise_swift__Array_swift__Array_uint64_t__() + } + + public static func resolved(with result: [[UInt64]]) -> Self { + let promise = Promise_swift__Array_swift__Array_uint64_t__.pending() + promise.resolve(result: result) + return promise + } + public static func rejected(with error: any Error) -> Self { + let promise = Promise_swift__Array_swift__Array_uint64_t__.pending() + promise.reject(error: error) + return promise + } + + public static func `async`( + _ priority: TaskPriority? = nil, + _ run: sending @escaping @isolated(any) () async throws -> sending [[UInt64]] + ) -> Self { + let promise = Promise_swift__Array_swift__Array_uint64_t__.pending() + Task(priority: priority) { () async -> Void in + do { + promise.resolve(result: try await run()) + } catch { + promise.reject(error: error) + } + } + return promise + } + + public static func parallel( + _ queue: DispatchQueue = .global(), + _ run: @escaping @Sendable () throws -> [[UInt64]] + ) -> Self { + let promise = Promise_swift__Array_swift__Array_uint64_t__.pending() + queue.async { () -> Void in + do { + promise.resolve(result: try run()) + } catch { + promise.reject(error: error) + } + } + return promise + } +} + +extension Promise<[[UInt64]]> { + func toCpp() -> Promise_swift__Array_swift__Array_uint64_t__ { + if let self = self as? Promise_swift__Array_swift__Array_uint64_t__ { + return self + } else { + let promise = Promise_swift__Array_swift__Array_uint64_t__.pending() + self.addOnResolvedListener { (result: [[UInt64]]) -> Void in + promise.resolve(result: result) + } + self.addOnRejectedListener { (error: any Error) -> Void in + promise.reject(error: error) + } + return promise + } + } +} diff --git a/tests/standalone/nitro-test/nitrogen/generated/shared/c++/include/NitroTest/HybridTestObjectCppSpec.hpp b/tests/standalone/nitro-test/nitrogen/generated/shared/c++/include/NitroTest/HybridTestObjectCppSpec.hpp index b785111664..761462cbb7 100644 --- a/tests/standalone/nitro-test/nitrogen/generated/shared/c++/include/NitroTest/HybridTestObjectCppSpec.hpp +++ b/tests/standalone/nitro-test/nitrogen/generated/shared/c++/include/NitroTest/HybridTestObjectCppSpec.hpp @@ -178,6 +178,8 @@ namespace margelo::nitro::test { virtual Promise bounceUnsignedAsync(uint64_t value) = 0; virtual Promise callUnsignedCallbackAsync(uint64_t value, const Callback& callback) = 0; virtual Promise> callUnsignedArrayCallbackAsync(const std::vector& array, const Callback(const std::vector& /* array */)>& callback) = 0; + virtual Promise>> bounceNestedUnsignedArrayAsync(const std::vector>& array) = 0; + virtual std::vector> callNestedUnsignedArrayCallback(const std::vector>& array, const Callback>(const std::vector>& /* array */)>& callback) = 0; virtual std::vector bounceHybridObjects(const std::vector& array) = 0; virtual std::vector> bounceFunctions(const std::vector>& functions) = 0; virtual std::vector bounceMaps(const std::vector& maps) = 0; diff --git a/tests/standalone/nitro-test/specs/TestObject.nitro.ts b/tests/standalone/nitro-test/specs/TestObject.nitro.ts index 86cdc38b70..a1fd8e6031 100644 --- a/tests/standalone/nitro-test/specs/TestObject.nitro.ts +++ b/tests/standalone/nitro-test/specs/TestObject.nitro.ts @@ -244,6 +244,8 @@ export declare class TestObjectCpp extends HybridObject { bounceUnsignedAsync(value: UInt64): Promise callUnsignedCallbackAsync(value: UInt64, callback: (value: UInt64) => UInt64): Promise callUnsignedArrayCallbackAsync(array: UInt64[], callback: (array: UInt64[]) => UInt64[]): Promise + bounceNestedUnsignedArrayAsync(array: UInt64[][]): Promise + callNestedUnsignedArrayCallback(array: UInt64[][], callback: (array: UInt64[][]) => UInt64[][]): UInt64[][] // Arrays (complex) bounceHybridObjects(array: Child[]): Child[] @@ -542,6 +544,8 @@ export declare class TestObjectSwiftKotlin extends HybridObject { bounceUnsignedAsync(value: UInt64): Promise callUnsignedCallbackAsync(value: UInt64, callback: (value: UInt64) => UInt64): Promise callUnsignedArrayCallbackAsync(array: UInt64[], callback: (array: UInt64[]) => UInt64[]): Promise + bounceNestedUnsignedArrayAsync(array: UInt64[][]): Promise + callNestedUnsignedArrayCallback(array: UInt64[][], callback: (array: UInt64[][]) => UInt64[][]): UInt64[][] // Arrays (complex) bounceHybridObjects(array: Child[]): Child[] diff --git a/tests/standalone/test-runner/js/data.test.ts b/tests/standalone/test-runner/js/data.test.ts index 59a8a7af6a..bf071d4816 100644 --- a/tests/standalone/test-runner/js/data.test.ts +++ b/tests/standalone/test-runner/js/data.test.ts @@ -220,6 +220,22 @@ export const cases = { expect(result).to.equal(18446744073709551615n) }, + 'bounceNestedUnsignedArrayAsync(...) resolves every level': async (testObject) => { + const nested = [[], UNSIGNED_BOUNDARIES, [18446744073709551615n]] + expect(await withTimeout(testObject.bounceNestedUnsignedArrayAsync(nested))).to.deep.equal(nested) + }, + + 'callNestedUnsignedArrayCallback(...) passes every level to JS and back': (testObject) => { + const nested = [[], UNSIGNED_BOUNDARIES] + const received: bigint[][][] = [] + const result = testObject.callNestedUnsignedArrayCallback(nested, (array) => { + received.push(array) + return [...array].reverse() + }) + expect(received).to.deep.equal([nested]) + expect(result).to.deep.equal([...nested].reverse()) + }, + 'callUnsignedArrayCallbackAsync(...) resolves the JS array': async (testObject) => { const result = await withTimeout(testObject.callUnsignedArrayCallbackAsync(UNSIGNED_BOUNDARIES, (array) => [...array].reverse())) expect(result).to.deep.equal([...UNSIGNED_BOUNDARIES].reverse())