66 */
77
88#import " RCTTurboModule.h"
9- #import " RCTBlockGuard.h"
10-
11- #import < cxxreact/SystraceSection.h>
12- #import < glog/logging.h>
13- #import < objc/message.h>
14- #import < objc/runtime.h>
15- #import < atomic>
16- #import < iostream>
17- #import < sstream>
18- #import < vector>
199
2010#import < React/RCTBridgeModule.h>
2111#import < React/RCTConvert.h>
2717#import < ReactCommon/LongLivedObject.h>
2818#import < ReactCommon/TurboModule.h>
2919#import < ReactCommon/TurboModulePerfLogger.h>
30- #import < ReactCommon/TurboModuleUtils.h>
20+ #import < cxxreact/SystraceSection.h>
21+ #import < react/bridging/Bridging.h>
22+
23+ #include < glog/logging.h>
24+
25+ #import < objc/message.h>
26+ #import < objc/runtime.h>
27+ #import < atomic>
28+ #import < iostream>
29+ #import < sstream>
30+ #import < vector>
3131
3232using namespace facebook ;
3333using namespace facebook ::react;
@@ -143,7 +143,23 @@ static int32_t getUniqueId()
143143}
144144
145145static RCTResponseSenderBlock
146- convertJSIFunctionToCallback (jsi::Runtime &runtime, const jsi::Function &value, std::shared_ptr<CallInvoker> jsInvoker);
146+ convertJSIFunctionToCallback (jsi::Runtime &rt, jsi::Function &&function, std::shared_ptr<CallInvoker> jsInvoker)
147+ {
148+ __block std::optional<AsyncCallback<>> callback ({rt, std::move (function), std::move (jsInvoker)});
149+ return ^(NSArray *args) {
150+ if (!callback) {
151+ LOG (FATAL) << " Callback arg cannot be called more than once" ;
152+ return ;
153+ }
154+
155+ callback->call ([args](jsi::Runtime &rt, jsi::Function &jsFunction) {
156+ auto jsArgs = convertNSArrayToStdVector (rt, args);
157+ jsFunction.call (rt, (const jsi::Value *)jsArgs.data (), jsArgs.size ());
158+ });
159+ callback = std::nullopt ;
160+ };
161+ }
162+
147163id convertJSIValueToObjCObject (jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker)
148164{
149165 if (value.isUndefined () || value.isNull ()) {
@@ -164,56 +180,14 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s
164180 return convertJSIArrayToNSArray (runtime, o.getArray (runtime), jsInvoker);
165181 }
166182 if (o.isFunction (runtime)) {
167- return convertJSIFunctionToCallback (runtime, std::move ( o.getFunction (runtime) ), jsInvoker);
183+ return convertJSIFunctionToCallback (runtime, o.getFunction (runtime), jsInvoker);
168184 }
169185 return convertJSIObjectToNSDictionary (runtime, o, jsInvoker);
170186 }
171187
172188 throw std::runtime_error (" Unsupported jsi::jsi::Value kind" );
173189}
174190
175- static RCTResponseSenderBlock
176- convertJSIFunctionToCallback (jsi::Runtime &runtime, const jsi::Function &value, std::shared_ptr<CallInvoker> jsInvoker)
177- {
178- auto weakWrapper = CallbackWrapper::createWeak (value.getFunction (runtime), runtime, jsInvoker);
179- RCTBlockGuard *blockGuard = [[RCTBlockGuard alloc ] initWithCleanup: ^() {
180- auto strongWrapper = weakWrapper.lock ();
181- if (strongWrapper) {
182- strongWrapper->destroy ();
183- }
184- }];
185-
186- BOOL __block wrapperWasCalled = NO ;
187- RCTResponseSenderBlock callback = ^(NSArray *responses) {
188- if (wrapperWasCalled) {
189- LOG (FATAL) << " callback arg cannot be called more than once" ;
190- }
191-
192- auto strongWrapper = weakWrapper.lock ();
193- if (!strongWrapper) {
194- return ;
195- }
196-
197- strongWrapper->jsInvoker ().invokeAsync ([weakWrapper, responses, blockGuard]() {
198- auto strongWrapper2 = weakWrapper.lock ();
199- if (!strongWrapper2) {
200- return ;
201- }
202-
203- std::vector<jsi::Value> args = convertNSArrayToStdVector (strongWrapper2->runtime (), responses);
204- strongWrapper2->callback ().call (strongWrapper2->runtime (), (const jsi::Value *)args.data (), args.size ());
205- strongWrapper2->destroy ();
206-
207- // Delete the CallbackWrapper when the block gets dealloced without being invoked.
208- (void )blockGuard;
209- });
210-
211- wrapperWasCalled = YES ;
212- };
213-
214- return [callback copy ];
215- }
216-
217191static jsi::Value createJSRuntimeError (jsi::Runtime &runtime, const std::string &message)
218192{
219193 return runtime.global ().getPropertyAsFunction (runtime, " Error" ).call (runtime, message);
@@ -247,124 +221,78 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s
247221 }
248222
249223 jsi::Function Promise = runtime.global ().getPropertyAsFunction (runtime, " Promise" );
250- std::string moduleName = name_;
251224
252225 // Note: the passed invoke() block is not retained by default, so let's retain it here to help keep it longer.
253226 // Otherwise, there's a risk of it getting released before the promise function below executes.
254227 PromiseInvocationBlock invokeCopy = [invoke copy ];
255- jsi::Function fn = jsi::Function::createFromHostFunction (
228+ return Promise. callAsConstructor (
256229 runtime,
257- jsi::PropNameID::forAscii (runtime, " fn" ),
258- 2 ,
259- [invokeCopy, jsInvoker = jsInvoker_, moduleName, methodName](
260- jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) {
261- std::string moduleMethod = moduleName + " ." + methodName + " ()" ;
262-
263- if (count != 2 ) {
264- throw std::invalid_argument (
265- moduleMethod + " : Promise must pass constructor function two args. Passed " + std::to_string (count) +
266- " args." );
267- }
268- if (!invokeCopy) {
269- return jsi::Value::undefined ();
270- }
271-
272- auto weakResolveWrapper = CallbackWrapper::createWeak (args[0 ].getObject (rt).getFunction (rt), rt, jsInvoker);
273- auto weakRejectWrapper = CallbackWrapper::createWeak (args[1 ].getObject (rt).getFunction (rt), rt, jsInvoker);
274-
275- __block BOOL resolveWasCalled = NO ;
276- __block BOOL rejectWasCalled = NO ;
277-
278- RCTBlockGuard *blockGuard = [[RCTBlockGuard alloc ] initWithCleanup: ^() {
279- auto strongResolveWrapper = weakResolveWrapper.lock ();
280- if (strongResolveWrapper) {
281- strongResolveWrapper->destroy ();
282- }
283-
284- auto strongRejectWrapper = weakRejectWrapper.lock ();
285- if (strongRejectWrapper) {
286- strongRejectWrapper->destroy ();
287- }
288- }];
289-
290- RCTPromiseResolveBlock resolveBlock = ^(id result) {
291- if (rejectWasCalled) {
292- RCTLogError (@" %s : Tried to resolve a promise after it's already been rejected." , moduleMethod.c_str ());
293- return ;
294- }
295-
296- if (resolveWasCalled) {
297- RCTLogError (@" %s : Tried to resolve a promise more than once." , moduleMethod.c_str ());
298- return ;
299- }
300-
301- auto strongResolveWrapper = weakResolveWrapper.lock ();
302- auto strongRejectWrapper = weakRejectWrapper.lock ();
303- if (!strongResolveWrapper || !strongRejectWrapper) {
304- return ;
305- }
306-
307- strongResolveWrapper->jsInvoker ().invokeAsync ([weakResolveWrapper, weakRejectWrapper, result, blockGuard]() {
308- auto strongResolveWrapper2 = weakResolveWrapper.lock ();
309- auto strongRejectWrapper2 = weakRejectWrapper.lock ();
310- if (!strongResolveWrapper2 || !strongRejectWrapper2) {
311- return ;
230+ jsi::Function::createFromHostFunction (
231+ runtime,
232+ jsi::PropNameID::forAscii (runtime, " fn" ),
233+ 2 ,
234+ [invokeCopy, jsInvoker = jsInvoker_, moduleName = name_, methodName](
235+ jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) {
236+ std::string moduleMethod = moduleName + " ." + methodName + " ()" ;
237+
238+ if (count != 2 ) {
239+ throw std::invalid_argument (
240+ moduleMethod + " : Promise must pass constructor function two args. Passed " + std::to_string (count) +
241+ " args." );
312242 }
313-
314- jsi::Runtime &rt = strongResolveWrapper2->runtime ();
315- jsi::Value arg = convertObjCObjectToJSIValue (rt, result);
316- strongResolveWrapper2->callback ().call (rt, arg);
317-
318- strongResolveWrapper2->destroy ();
319- strongRejectWrapper2->destroy ();
320- (void )blockGuard;
321- });
322-
323- resolveWasCalled = YES ;
324- };
325-
326- RCTPromiseRejectBlock rejectBlock = ^(NSString *code, NSString *message, NSError *error) {
327- if (resolveWasCalled) {
328- RCTLogError (@" %s : Tried to reject a promise after it's already been resolved." , moduleMethod.c_str ());
329- return ;
330- }
331-
332- if (rejectWasCalled) {
333- RCTLogError (@" %s : Tried to reject a promise more than once." , moduleMethod.c_str ());
334- return ;
335- }
336-
337- auto strongResolveWrapper = weakResolveWrapper.lock ();
338- auto strongRejectWrapper = weakRejectWrapper.lock ();
339- if (!strongResolveWrapper || !strongRejectWrapper) {
340- return ;
341- }
342-
343- NSDictionary *jsError = RCTJSErrorFromCodeMessageAndNSError (code, message, error);
344- strongRejectWrapper->jsInvoker ().invokeAsync ([weakResolveWrapper, weakRejectWrapper, jsError, blockGuard]() {
345- auto strongResolveWrapper2 = weakResolveWrapper.lock ();
346- auto strongRejectWrapper2 = weakRejectWrapper.lock ();
347- if (!strongResolveWrapper2 || !strongRejectWrapper2) {
348- return ;
243+ if (!invokeCopy) {
244+ return jsi::Value::undefined ();
349245 }
350246
351- jsi::Runtime &rt = strongRejectWrapper2->runtime ();
352- jsi::Value arg = convertNSDictionaryToJSIObject (rt, jsError);
353- strongRejectWrapper2->callback ().call (rt, arg);
354-
355- strongResolveWrapper2->destroy ();
356- strongRejectWrapper2->destroy ();
357- (void )blockGuard;
358- });
359-
360- rejectWasCalled = YES ;
361- };
362-
363- invokeCopy (resolveBlock, rejectBlock);
364- return jsi::Value::undefined ();
365- });
366-
367- return Promise.callAsConstructor (runtime, fn);
247+ __block BOOL resolveWasCalled = NO ;
248+ __block std::optional<AsyncCallback<>> resolve (
249+ {rt, args[0 ].getObject (rt).getFunction (rt), std::move (jsInvoker)});
250+ __block std::optional<AsyncCallback<>> reject (
251+ {rt, args[1 ].getObject (rt).getFunction (rt), std::move (jsInvoker)});
252+
253+ RCTPromiseResolveBlock resolveBlock = ^(id result) {
254+ if (!resolve || !reject) {
255+ if (resolveWasCalled) {
256+ RCTLogError (@" %s : Tried to resolve a promise more than once." , moduleMethod.c_str ());
257+ } else {
258+ RCTLogError (
259+ @" %s : Tried to resolve a promise after it's already been rejected." , moduleMethod.c_str ());
260+ }
261+ return ;
262+ }
263+
264+ resolve->call ([result](jsi::Runtime &rt, jsi::Function &jsFunction) {
265+ jsFunction.call (rt, convertObjCObjectToJSIValue (rt, result));
266+ });
267+
268+ resolveWasCalled = YES ;
269+ resolve = std::nullopt ;
270+ reject = std::nullopt ;
271+ };
272+
273+ RCTPromiseRejectBlock rejectBlock = ^(NSString *code, NSString *message, NSError *error) {
274+ if (!resolve || !reject) {
275+ if (resolveWasCalled) {
276+ RCTLogError (@" %s : Tried to reject a promise after it's already been resolved." , moduleMethod.c_str ());
277+ } else {
278+ RCTLogError (@" %s : Tried to reject a promise more than once." , moduleMethod.c_str ());
279+ }
280+ return ;
281+ }
282+
283+ NSDictionary *jsError = RCTJSErrorFromCodeMessageAndNSError (code, message, error);
284+ reject->call ([jsError](jsi::Runtime &rt, jsi::Function &jsFunction) {
285+ jsFunction.call (rt, convertObjCObjectToJSIValue (rt, jsError));
286+ });
287+
288+ resolveWasCalled = NO ;
289+ resolve = std::nullopt ;
290+ reject = std::nullopt ;
291+ };
292+
293+ invokeCopy (resolveBlock, rejectBlock);
294+ return jsi::Value::undefined ();
295+ }));
368296}
369297
370298/* *
0 commit comments