Skip to content

Commit

Permalink
fix: Add test with complex callback that returns complex return type …
Browse files Browse the repository at this point in the history
…(ArrayBuffer) (#441)

* fix: Add test with complex callback that returns complex return type (ArrayBuffer)

* Update HybridTestObjectCpp.cpp

* fix: Don't use `borrowing` when copying
  • Loading branch information
mrousavy authored Dec 20, 2024
1 parent ba3d947 commit 7c0807d
Show file tree
Hide file tree
Showing 24 changed files with 515 additions and 52 deletions.
19 changes: 19 additions & 0 deletions example/src/getTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,25 @@ export function getTests(
.didNotThrow()
.equals(13)
),
createTest(
'Async callback can be awaited and returned on native side: callbackAsyncPromiseBuffer(...)',
async () =>
(
await it(async () => {
return timeoutedPromise<ArrayBuffer>(async (complete) => {
const result = await testObject.callbackAsyncPromiseBuffer(
async () => {
return await testObject.createArrayBufferAsync()
}
)
complete(result)
})
})
)
.didNotThrow()
.didReturn('object')
.toContain('byteLength')
),

// Objects
createTest('getCar()', () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,14 @@ class HybridTestObjectKotlin: HybridTestObjectSwiftKotlinSpec() {
}
}

override fun callbackAsyncPromiseBuffer(callback: () -> Promise<Promise<ArrayBuffer>>): Promise<ArrayBuffer> {
return Promise.async {
val promise = callback().await()
val result = promise.await()
return@async result
}
}

override fun getCar(): Car {
return Car(2018.0, "Lamborghini", "Huracán", 640.0, Powertrain.GAS, null, true)
}
Expand Down
11 changes: 11 additions & 0 deletions packages/react-native-nitro-image/cpp/HybridTestObjectCpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,17 @@ HybridTestObjectCpp::callbackAsyncPromise(const std::function<std::shared_ptr<Pr
});
}

std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridTestObjectCpp::callbackAsyncPromiseBuffer(
const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>()>& callback) {
return Promise<std::shared_ptr<ArrayBuffer>>::async([=]() {
std::future<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>> future = callback()->await();
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> promise = future.get();
std::future<std::shared_ptr<ArrayBuffer>> innerFuture = promise->await();
std::shared_ptr<ArrayBuffer> innerResult = innerFuture.get();
return innerResult;
});
}

std::shared_ptr<Promise<double>>
HybridTestObjectCpp::getValueFromJSCallbackAndWait(const std::function<std::shared_ptr<Promise<double>>()>& getValue) {
return Promise<double>::async([=]() -> double {
Expand Down
2 changes: 2 additions & 0 deletions packages/react-native-nitro-image/cpp/HybridTestObjectCpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class HybridTestObjectCpp : public HybridTestObjectCppSpec {
std::shared_ptr<Promise<double>> callSumUpNTimes(const std::function<std::shared_ptr<Promise<double>>()>& callback, double n) override;
std::shared_ptr<Promise<double>>
callbackAsyncPromise(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<double>>>>()>& callback) override;
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> callbackAsyncPromiseBuffer(
const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>()>& callback) override;
std::shared_ptr<Promise<void>>
getValueFromJsCallback(const std::function<std::shared_ptr<Promise<std::string>>()>& callback,
const std::function<void(const std::string& /* valueFromJs */)>& andThenCall) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ class HybridTestObjectSwift : HybridTestObjectSwiftKotlinSpec {
}
}

func callbackAsyncPromiseBuffer(callback: @escaping (() -> Promise<Promise<ArrayBufferHolder>>)) throws -> Promise<ArrayBufferHolder> {
return Promise.async {
let promise = try await callback().await()
let result = try await promise.await()
return result
}
}


func bounceStrings(array: [String]) throws -> [String] {
return array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "JFunc_void_std__optional_double_.hpp"
#include "JFunc_std__shared_ptr_Promise_double__.hpp"
#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_double____.hpp"
#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____.hpp"
#include "JFunc_std__shared_ptr_Promise_std__string__.hpp"
#include "JHybridBaseSpec.hpp"
#include "JHybridChildSpec.hpp"
Expand Down Expand Up @@ -48,6 +49,7 @@ int initialize(JavaVM* vm) {
margelo::nitro::image::JFunc_void_std__optional_double_::registerNatives();
margelo::nitro::image::JFunc_std__shared_ptr_Promise_double__::registerNatives();
margelo::nitro::image::JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_double____::registerNatives();
margelo::nitro::image::JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____::registerNatives();
margelo::nitro::image::JFunc_std__shared_ptr_Promise_double__::registerNatives();
margelo::nitro::image::JFunc_std__shared_ptr_Promise_std__string__::registerNatives();
margelo::nitro::image::JFunc_void_std__string::registerNatives();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
///
/// JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____.hpp
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
/// https://github.com/mrousavy/nitro
/// Copyright © 2024 Marc Rousavy @ Margelo
///

#pragma once

#include <fbjni/fbjni.h>
#include <functional>

#include <functional>
#include <NitroModules/Promise.hpp>
#include <NitroModules/ArrayBuffer.hpp>
#include <NitroModules/JPromise.hpp>
#include <NitroModules/JArrayBuffer.hpp>
#include <NitroModules/JUnit.hpp>

namespace margelo::nitro::image {

using namespace facebook;

/**
* C++ representation of the callback Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____.
* This is a Kotlin `() -> Promise<Promise<ArrayBuffer>>`, backed by a `std::function<...>`.
*/
struct JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____ final: public jni::HybridClass<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____> {
public:
static jni::local_ref<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____::javaobject> fromCpp(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>()>& func) {
return JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____::newObjectCxxArgs(func);
}

public:
jni::local_ref<JPromise::javaobject> call() {
std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>> __result = _func();
return [&]() {
jni::local_ref<JPromise::javaobject> __localPromise = JPromise::create();
jni::global_ref<JPromise::javaobject> __promise = jni::make_global(__localPromise);
__result->addOnResolvedListener([=](const std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>& __result) {
__promise->cthis()->resolve([&]() {
jni::local_ref<JPromise::javaobject> __localPromise = JPromise::create();
jni::global_ref<JPromise::javaobject> __promise = jni::make_global(__localPromise);
__result->addOnResolvedListener([=](const std::shared_ptr<ArrayBuffer>& __result) {
__promise->cthis()->resolve(JArrayBuffer::wrap(__result));
});
__result->addOnRejectedListener([=](const std::exception_ptr& __error) {
auto __jniError = jni::getJavaExceptionForCppException(__error);
__promise->cthis()->reject(__jniError);
});
return __localPromise;
}());
});
__result->addOnRejectedListener([=](const std::exception_ptr& __error) {
auto __jniError = jni::getJavaExceptionForCppException(__error);
__promise->cthis()->reject(__jniError);
});
return __localPromise;
}();
}

public:
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/image/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____;";
static void registerNatives() {
registerHybrid({makeNativeMethod("call", JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____::call)});
}

private:
explicit JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>()>& func): _func(func) { }

private:
friend HybridBase;
std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>()> _func;
};

} // namespace margelo::nitro::image
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ namespace margelo::nitro::image { class HybridBaseSpec; }
#include "JFunc_void_std__optional_double_.hpp"
#include "JFunc_std__shared_ptr_Promise_double__.hpp"
#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_double____.hpp"
#include "JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____.hpp"
#include "JFunc_std__shared_ptr_Promise_std__string__.hpp"
#include "JFunc_void_std__string.hpp"

Expand Down Expand Up @@ -554,6 +555,22 @@ namespace margelo::nitro::image {
return __promise;
}();
}
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> JHybridTestObjectSwiftKotlinSpec::callbackAsyncPromiseBuffer(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>()>& callback) {
static const auto method = _javaPart->getClass()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____::javaobject> /* callback */)>("callbackAsyncPromiseBuffer");
auto __result = method(_javaPart, JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____::fromCpp(callback));
return [&]() {
auto __promise = Promise<std::shared_ptr<ArrayBuffer>>::create();
__result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
auto __result = jni::static_ref_cast<JArrayBuffer::javaobject>(__boxedResult);
__promise->resolve(__result->cthis()->getArrayBuffer());
});
__result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
jni::JniException __jniError(__throwable);
__promise->reject(std::make_exception_ptr(__jniError));
});
return __promise;
}();
}
std::shared_ptr<Promise<double>> JHybridTestObjectSwiftKotlinSpec::getValueFromJSCallbackAndWait(const std::function<std::shared_ptr<Promise<double>>()>& getValue) {
static const auto method = _javaPart->getClass()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<JFunc_std__shared_ptr_Promise_double__::javaobject> /* getValue */)>("getValueFromJSCallbackAndWait");
auto __result = method(_javaPart, JFunc_std__shared_ptr_Promise_double__::fromCpp(getValue));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ namespace margelo::nitro::image {
void callWithOptional(std::optional<double> value, const std::function<void(std::optional<double> /* maybe */)>& callback) override;
std::shared_ptr<Promise<double>> callSumUpNTimes(const std::function<std::shared_ptr<Promise<double>>()>& callback, double n) override;
std::shared_ptr<Promise<double>> callbackAsyncPromise(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<double>>>>()>& callback) override;
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> callbackAsyncPromiseBuffer(const std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>()>& callback) override;
std::shared_ptr<Promise<double>> getValueFromJSCallbackAndWait(const std::function<std::shared_ptr<Promise<double>>()>& getValue) override;
std::shared_ptr<Promise<void>> getValueFromJsCallback(const std::function<std::shared_ptr<Promise<std::string>>()>& callback, const std::function<void(const std::string& /* valueFromJs */)>& andThenCall) override;
Car getCar() override;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
///
/// Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____.kt
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
/// https://github.com/mrousavy/nitro
/// Copyright © 2024 Marc Rousavy @ Margelo
///

package com.margelo.nitro.image

import androidx.annotation.Keep
import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStrip
import com.margelo.nitro.core.*
import dalvik.annotation.optimization.FastNative

/**
* Represents the JavaScript callback `() => std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>`.
* This is implemented in C++, via a `std::function<...>`.
*/
@DoNotStrip
@Keep
@Suppress("RedundantSuppression", "ConvertSecondaryConstructorToPrimary", "RedundantUnitReturnType", "KotlinJniMissingFunction", "ClassName", "unused")
class Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____ {
@DoNotStrip
@Keep
private val mHybridData: HybridData

@DoNotStrip
@Keep
private constructor(hybridData: HybridData) {
mHybridData = hybridData
}

/**
* Converts this function to a Kotlin Lambda.
* This exists purely as syntactic sugar, and has minimal runtime overhead.
*/
fun toLambda(): () -> Promise<Promise<ArrayBuffer>> = this::call

/**
* Call the given JS callback.
* @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted.
*/
@FastNative
external fun call(): Promise<Promise<ArrayBuffer>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,17 @@ abstract class HybridTestObjectSwiftKotlinSpec: HybridObject() {
return __result
}

@DoNotStrip
@Keep
abstract fun callbackAsyncPromiseBuffer(callback: () -> Promise<Promise<ArrayBuffer>>): Promise<ArrayBuffer>

@DoNotStrip
@Keep
private fun callbackAsyncPromiseBuffer(callback: Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____): Promise<ArrayBuffer> {
val __result = callbackAsyncPromiseBuffer(callback.toLambda())
return __result
}

@DoNotStrip
@Keep
abstract fun getValueFromJSCallbackAndWait(getValue: () -> Promise<Double>): Promise<Double>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,31 @@ namespace margelo::nitro::image::bridge::swift {
};
}

// pragma MARK: std::function<void(const std::shared_ptr<ArrayBuffer>& /* result */)>
Func_void_std__shared_ptr_ArrayBuffer_ create_Func_void_std__shared_ptr_ArrayBuffer_(void* _Nonnull swiftClosureWrapper) {
auto swiftClosure = NitroImage::Func_void_std__shared_ptr_ArrayBuffer_::fromUnsafe(swiftClosureWrapper);
return [swiftClosure = std::move(swiftClosure)](const std::shared_ptr<ArrayBuffer>& result) mutable -> void {
swiftClosure.call(ArrayBufferHolder(result));
};
}

// pragma MARK: std::function<std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>>()>
Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____ create_Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____(void* _Nonnull swiftClosureWrapper) {
auto swiftClosure = NitroImage::Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer_____::fromUnsafe(swiftClosureWrapper);
return [swiftClosure = std::move(swiftClosure)]() mutable -> std::shared_ptr<Promise<std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>>> {
auto __result = swiftClosure.call();
return __result;
};
}

// pragma MARK: std::function<void(const std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>& /* result */)>
Func_void_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer___ create_Func_void_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer___(void* _Nonnull swiftClosureWrapper) {
auto swiftClosure = NitroImage::Func_void_std__shared_ptr_Promise_std__shared_ptr_ArrayBuffer___::fromUnsafe(swiftClosureWrapper);
return [swiftClosure = std::move(swiftClosure)](const std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>>& result) mutable -> void {
swiftClosure.call(result);
};
}

// pragma MARK: std::function<std::shared_ptr<Promise<std::string>>()>
Func_std__shared_ptr_Promise_std__string__ create_Func_std__shared_ptr_Promise_std__string__(void* _Nonnull swiftClosureWrapper) {
auto swiftClosure = NitroImage::Func_std__shared_ptr_Promise_std__string__::fromUnsafe(swiftClosureWrapper);
Expand All @@ -164,14 +189,6 @@ namespace margelo::nitro::image::bridge::swift {
};
}

// pragma MARK: std::function<void(const std::shared_ptr<ArrayBuffer>& /* result */)>
Func_void_std__shared_ptr_ArrayBuffer_ create_Func_void_std__shared_ptr_ArrayBuffer_(void* _Nonnull swiftClosureWrapper) {
auto swiftClosure = NitroImage::Func_void_std__shared_ptr_ArrayBuffer_::fromUnsafe(swiftClosureWrapper);
return [swiftClosure = std::move(swiftClosure)](const std::shared_ptr<ArrayBuffer>& result) mutable -> void {
swiftClosure.call(ArrayBufferHolder(result));
};
}

// pragma MARK: std::shared_ptr<margelo::nitro::image::HybridBaseSpec>
std::shared_ptr<margelo::nitro::image::HybridBaseSpec> create_std__shared_ptr_margelo__nitro__image__HybridBaseSpec_(void* _Nonnull swiftUnsafePointer) {
NitroImage::HybridBaseSpec_cxx swiftPart = NitroImage::HybridBaseSpec_cxx::fromUnsafe(swiftUnsafePointer);
Expand Down
Loading

0 comments on commit 7c0807d

Please sign in to comment.