Skip to content

Commit

Permalink
rn | Improve bridging, allowing implicit conversion of jsi types wrap…
Browse files Browse the repository at this point in the history
…ped in SyncCallback/AsyncCallback/AsyncPromise.

Summary:
`toJs()` resolution trips up on converting the plain old jsi values.
In order to help it - remove the automatic inference of template types, since we already know that `T` in this case is going to be the concrete jsi type.
This allows using implicit conversions on Sync/Async Callback types, as well as AsyncPromise.

Without it - AsyncPromise/Callback trip up on trying to convert Convertor<T> to jsi type.

Changelog:
[General][Added] SyncCallback/AsyncCallback/AsyncPromise bridging types in C++ now allow wrapping JSI types.

Reviewed By: JoshuaGross

Differential Revision: D38529799

fbshipit-source-id: 860de2d771899f331bf1a4ff0dade4eccc875618
  • Loading branch information
nlutsenko authored and facebook-github-bot committed Aug 9, 2022
1 parent 647542c commit 610bb7f
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 2 deletions.
3 changes: 1 addition & 2 deletions ReactCommon/react/bridging/Base.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ template <typename T, std::enable_if_t<is_jsi_v<T>, int> = 0>
auto toJs(
jsi::Runtime &rt,
T &&value,
const std::shared_ptr<CallInvoker> & = nullptr)
-> decltype(convert(rt, std::forward<T>(value))) {
const std::shared_ptr<CallInvoker> & = nullptr) -> remove_cvref_t<T> {
return convert(rt, std::forward<T>(value));
}

Expand Down
107 changes: 107 additions & 0 deletions ReactCommon/react/bridging/tests/BridgingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,51 @@ TEST_F(BridgingTest, syncCallbackTest) {
EXPECT_TRUE(fn.isFunction(rt)); // Ensure the function wasn't invalidated.
}

TEST_F(BridgingTest, syncCallbackImplicitBridgingTest) {
{ // Value
auto fn = function("(a, b) => a + b");
auto cb = bridging::fromJs<SyncCallback<std::string(jsi::Value, int)>>(
rt, fn, invoker);
jsi::Value foo(jsi::String::createFromAscii(rt, "foo"));

EXPECT_EQ(cb(std::move(foo), 1), "foo1");
EXPECT_EQ(cb(jsi::String::createFromAscii(rt, "bar"), 2), "bar2");
EXPECT_TRUE(fn.isFunction(rt));
}
{ // Object
auto fn = function("(a, b) => a.obj + b");
auto cb = bridging::fromJs<SyncCallback<std::string(jsi::Object, int)>>(
rt, fn, invoker);

jsi::Object foo(rt);
foo.setProperty(rt, "obj", "foo");

EXPECT_EQ(cb(std::move(foo), 1), "foo1");
EXPECT_TRUE(fn.isFunction(rt));
}
{ // String
auto fn = function("(a, b) => a + b");
auto cb = bridging::fromJs<SyncCallback<std::string(jsi::String, int)>>(
rt, fn, invoker);
jsi::String foo(jsi::String::createFromAscii(rt, "foo"));

EXPECT_EQ(cb(std::move(foo), 1), "foo1");
EXPECT_EQ(cb(jsi::String::createFromAscii(rt, "bar"), 2), "bar2");
EXPECT_TRUE(fn.isFunction(rt));
}
{ // Array
auto fn = function("(a, b) => a[0] + b");
auto cb = bridging::fromJs<SyncCallback<std::string(jsi::Array, int)>>(
rt, fn, invoker);

jsi::Array foo(rt, 1);
foo.setValueAtIndex(rt, 0, jsi::String::createFromAscii(rt, "foo"));

EXPECT_EQ(cb(std::move(foo), 1), "foo1");
EXPECT_TRUE(fn.isFunction(rt));
}
}

TEST_F(BridgingTest, asyncCallbackTest) {
std::string output;

Expand All @@ -230,6 +275,68 @@ TEST_F(BridgingTest, asyncCallbackTest) {
EXPECT_EQ("hello"s, output);
}

TEST_F(BridgingTest, asyncCallbackImplicitBridgingTest) {
std::string output;
auto func = std::function<void(std::string)>([&](auto str) { output = str; });
{ // Value
auto cb = bridging::fromJs<AsyncCallback<decltype(func), jsi::Value, int>>(
rt, function("(func, a, b) => func(a + b)"), invoker);
jsi::Value foo(jsi::String::createFromAscii(rt, "foo"));

cb(func, std::move(foo), 1);
flushQueue();
EXPECT_EQ(output, "foo1");

cb(func, jsi::String::createFromAscii(rt, "bar"), 2);
flushQueue();
EXPECT_EQ(output, "bar2");

output.clear();
}
{ // Object
auto cb = bridging::fromJs<AsyncCallback<decltype(func), jsi::Object, int>>(
rt, function("(func, a, b) => func(a.obj + b)"), invoker);

jsi::Object foo(rt);
foo.setProperty(rt, "obj", "foo");

cb(func, std::move(foo), 1);
flushQueue();
EXPECT_EQ(output, "foo1");

output.clear();
}
{ // String
auto cb = bridging::fromJs<AsyncCallback<decltype(func), jsi::String, int>>(
rt, function("(func, a, b) => func(a + b)"), invoker);
jsi::String foo(jsi::String::createFromAscii(rt, "foo"));

cb(func, std::move(foo), 1);
flushQueue();
EXPECT_EQ(output, "foo1");

cb(func, jsi::String::createFromAscii(rt, "bar"), 2);
flushQueue();
EXPECT_EQ(output, "bar2");

output.clear();
}
{ // Array
auto fn = function("(func, a, b) => func(a[0] + b)");
auto cb = bridging::fromJs<AsyncCallback<decltype(func), jsi::Array, int>>(
rt, fn, invoker);

jsi::Array foo(rt, 1);
foo.setValueAtIndex(rt, 0, jsi::String::createFromAscii(rt, "foo"));

cb(func, std::move(foo), 1);
flushQueue();
EXPECT_EQ(output, "foo1");

output.clear();
}
}

TEST_F(BridgingTest, promiseTest) {
auto func = function(
"(promise, obj) => {"
Expand Down

0 comments on commit 610bb7f

Please sign in to comment.