Skip to content

Commit e870935

Browse files
C++ Turbo Module > Allow Promise<void> types (#52388)
Summary: Pull Request resolved: #52388 Changelog: [Internal] Similar to `AsyncCallback<>` (the foundation of `AsyncPromise`) we should allow `void` Promise types in C++ such as `AsyncPromise<>` Reviewed By: rbergerjr Differential Revision: D77712020 fbshipit-source-id: d7360df5cc1b77f1e03e5fb73b0b468f6e3a415b
1 parent 255977a commit e870935

5 files changed

Lines changed: 33 additions & 15 deletions

File tree

packages/react-native/ReactCommon/react/bridging/Promise.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616

1717
namespace facebook::react {
1818

19-
template <typename T>
19+
template <typename... T>
2020
class AsyncPromise {
21+
static_assert(
22+
sizeof...(T) <= 1,
23+
"AsyncPromise must have at most one argument");
24+
2125
public:
2226
AsyncPromise(jsi::Runtime& rt, const std::shared_ptr<CallInvoker>& jsInvoker)
2327
: state_(std::make_shared<SharedState>()) {
@@ -28,7 +32,9 @@ class AsyncPromise {
2832
bridging::toJs(
2933
rt,
3034
// Safe to capture this since this is called synchronously.
31-
[this](AsyncCallback<T> resolve, AsyncCallback<Error> reject) {
35+
[this](
36+
AsyncCallback<T...> resolve,
37+
const AsyncCallback<Error>& reject) {
3238
state_->resolve = std::move(resolve);
3339
state_->reject = std::move(reject);
3440
},
@@ -42,11 +48,11 @@ class AsyncPromise {
4248
state_->promiseHolder = promiseHolder;
4349
}
4450

45-
void resolve(T value) {
51+
void resolve(T... value) {
4652
std::lock_guard<std::mutex> lock(state_->mutex);
4753

4854
if (state_->resolve) {
49-
state_->resolve->call(std::move(value));
55+
state_->resolve->call(std::forward<T>(value)...);
5056
state_->resolve.reset();
5157
state_->reject.reset();
5258
}
@@ -87,16 +93,16 @@ class AsyncPromise {
8793

8894
std::mutex mutex;
8995
std::weak_ptr<PromiseHolder> promiseHolder;
90-
std::optional<AsyncCallback<T>> resolve;
96+
std::optional<AsyncCallback<T...>> resolve;
9197
std::optional<AsyncCallback<Error>> reject;
9298
};
9399

94100
std::shared_ptr<SharedState> state_;
95101
};
96102

97-
template <typename T>
98-
struct Bridging<AsyncPromise<T>> {
99-
static jsi::Object toJs(jsi::Runtime& rt, const AsyncPromise<T>& promise) {
103+
template <typename... T>
104+
struct Bridging<AsyncPromise<T...>> {
105+
static jsi::Object toJs(jsi::Runtime& rt, const AsyncPromise<T...>& promise) {
100106
return promise.get(rt);
101107
}
102108
};

packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ void NativeCxxModuleExample::voidFunc(jsi::Runtime& rt) {
177177
emitOnEvent(NativeCxxModuleExampleEnumNone::NA);
178178
}
179179

180+
AsyncPromise<> NativeCxxModuleExample::voidPromise(jsi::Runtime& rt) {
181+
AsyncPromise<> promise(rt, jsInvoker_);
182+
promise.resolve();
183+
return promise;
184+
}
185+
180186
void NativeCxxModuleExample::setMenu(jsi::Runtime& rt, MenuItem menuItem) {
181187
menuItem.onPress("value", true);
182188
if (menuItem.items) {
@@ -213,8 +219,7 @@ ObjectStruct NativeCxxModuleExample::getObjectThrows(
213219
throw std::runtime_error("Intentional exception from Cxx getObjectThrows");
214220
};
215221

216-
AsyncPromise<jsi::Value> NativeCxxModuleExample::promiseThrows(
217-
jsi::Runtime& rt) {
222+
AsyncPromise<> NativeCxxModuleExample::promiseThrows(jsi::Runtime& rt) {
218223
throw std::runtime_error("Intentional exception from Cxx promiseThrows");
219224
};
220225

@@ -231,12 +236,11 @@ ObjectStruct NativeCxxModuleExample::getObjectAssert(
231236
return {};
232237
};
233238

234-
AsyncPromise<jsi::Value> NativeCxxModuleExample::promiseAssert(
235-
jsi::Runtime& rt) {
239+
AsyncPromise<> NativeCxxModuleExample::promiseAssert(jsi::Runtime& rt) {
236240
react_native_assert(false && "Intentional assert from Cxx promiseAssert");
237241

238242
// Asserts disabled
239-
auto promise = AsyncPromise<jsi::Value>(rt, jsInvoker_);
243+
auto promise = AsyncPromise<>(rt, jsInvoker_);
240244
promise.reject("Asserts disabled");
241245
return promise;
242246
};

packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ class NativeCxxModuleExample
193193

194194
void voidFunc(jsi::Runtime& rt);
195195

196+
AsyncPromise<> voidPromise(jsi::Runtime& rt);
197+
196198
void setMenu(jsi::Runtime& rt, MenuItem menuItem);
197199

198200
void emitCustomDeviceEvent(jsi::Runtime& rt, const std::string& eventName);
@@ -201,13 +203,13 @@ class NativeCxxModuleExample
201203

202204
ObjectStruct getObjectThrows(jsi::Runtime& rt, ObjectStruct arg);
203205

204-
AsyncPromise<jsi::Value> promiseThrows(jsi::Runtime& rt);
206+
AsyncPromise<> promiseThrows(jsi::Runtime& rt);
205207

206208
void voidFuncAssert(jsi::Runtime& rt);
207209

208210
ObjectStruct getObjectAssert(jsi::Runtime& rt, ObjectStruct arg);
209211

210-
AsyncPromise<jsi::Value> promiseAssert(jsi::Runtime& rt);
212+
AsyncPromise<> promiseAssert(jsi::Runtime& rt);
211213

212214
private:
213215
std::optional<AsyncCallback<std::string>> valueCallback_;

packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export interface Spec extends TurboModule {
105105
+getValueWithPromise: (error: boolean) => Promise<string>;
106106
+getWithWithOptionalArgs: (optionalArg?: boolean) => ?boolean;
107107
+voidFunc: () => void;
108+
+voidPromise: () => Promise<void>;
108109
+setMenu: (menuItem: MenuItem) => void;
109110
+emitCustomDeviceEvent: (eventName: string) => void;
110111
+voidFuncThrows: () => void;

packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type Examples =
5858
| 'promise'
5959
| 'rejectPromise'
6060
| 'voidFunc'
61+
| 'voidPromise'
6162
| 'setMenuItem'
6263
| 'optionalArgs'
6364
| 'emitDeviceEvent';
@@ -138,6 +139,10 @@ class NativeCxxModuleExampleExample extends React.Component<{}, State> {
138139
.then(() => {})
139140
.catch(e => this._setResult('rejectPromise', e.message)),
140141
voidFunc: () => NativeCxxModuleExample?.voidFunc(),
142+
voidPromise: () =>
143+
NativeCxxModuleExample?.voidPromise().then(valuePromise =>
144+
this._setResult('voidPromise', valuePromise),
145+
),
141146
setMenuItem: () => {
142147
let curValue = '';
143148
NativeCxxModuleExample?.setMenu({

0 commit comments

Comments
 (0)