222222Napi::Promise AskForContactsAccess (const Napi::CallbackInfo &info) {
223223 Napi::Env env = info.Env ();
224224 Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New (env);
225- Napi::ThreadSafeFunction ts_fn =
226- Napi::ThreadSafeFunction::New (env, Napi::Function::New (env, NoOp),
227- " contactsCallback" , 0 , 1 );
225+ Napi::ThreadSafeFunction ts_fn = Napi::ThreadSafeFunction::New (
226+ env, Napi::Function::New (env, NoOp), " contactsCallback" , 0 , 1 );
228227
228+ __block Napi::ThreadSafeFunction tsfn = ts_fn;
229229 if (@available (macOS 10.11 , *)) {
230230 CNContactStore *store = [CNContactStore new ];
231231 [store requestAccessForEntityType: CNEntityTypeContacts
234234 const char *granted) {
235235 deferred.Resolve (Napi::String::New (env, granted));
236236 };
237- ts_fn.BlockingCall (granted ? " authorized" : " denied" ,
238- callback);
237+ tsfn.BlockingCall (granted ? " authorized" : " denied" ,
238+ callback);
239+ tsfn.Release ();
239240 }];
240241 } else {
241242 deferred.Resolve (Napi::String::New (env, " authorized" ));
248249Napi::Promise AskForCalendarAccess (const Napi::CallbackInfo &info) {
249250 Napi::Env env = info.Env ();
250251 Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New (env);
251- Napi::ThreadSafeFunction ts_fn =
252- Napi::ThreadSafeFunction::New (env, Napi::Function::New (env, NoOp),
253- " calendarCallback" , 0 , 1 );
252+ Napi::ThreadSafeFunction ts_fn = Napi::ThreadSafeFunction::New (
253+ env, Napi::Function::New (env, NoOp), " calendarCallback" , 0 , 1 );
254254
255+ __block Napi::ThreadSafeFunction tsfn = ts_fn;
255256 [[EKEventStore new ]
256257 requestAccessToEntityType: EKEntityTypeEvent
257258 completion: ^(BOOL granted, NSError *error) {
258259 auto callback = [=](Napi::Env env, Napi::Function js_cb,
259260 const char *granted) {
260261 deferred.Resolve (Napi::String::New (env, granted));
261262 };
262- ts_fn.BlockingCall (granted ? " authorized" : " denied" ,
263- callback);
263+ tsfn.BlockingCall (granted ? " authorized" : " denied" ,
264+ callback);
265+ tsfn.Release ();
264266 }];
265267
266268 return deferred.Promise ();
273275 Napi::ThreadSafeFunction ts_fn = Napi::ThreadSafeFunction::New (
274276 env, Napi::Function::New (env, NoOp), " remindersCallback" , 0 , 1 );
275277
278+ __block Napi::ThreadSafeFunction tsfn = ts_fn;
276279 [[EKEventStore new ]
277280 requestAccessToEntityType: EKEntityTypeReminder
278281 completion: ^(BOOL granted, NSError *error) {
281284 const char *granted) {
282285 deferred.Resolve (Napi::String::New (env, granted));
283286 };
284- ts_fn.BlockingCall (granted ? " authorized" : " denied" ,
285- callback);
287+ tsfn.BlockingCall (granted ? " authorized" : " denied" ,
288+ callback);
289+ tsfn.Release ();
286290 }];
287291
288292 return deferred.Promise ();
@@ -307,6 +311,7 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
307311 std::string auth_status = MediaAuthStatus (" camera" );
308312
309313 if (auth_status == " not determined" ) {
314+ __block Napi::ThreadSafeFunction tsfn = ts_fn;
310315 [AVCaptureDevice
311316 requestAccessForMediaType: AVMediaTypeVideo
312317 completionHandler: ^(BOOL granted) {
@@ -315,8 +320,9 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
315320 deferred.Resolve (Napi::String::New (env, granted));
316321 };
317322
318- ts_fn.BlockingCall (granted ? " authorized" : " denied" ,
319- callback);
323+ tsfn.BlockingCall (granted ? " authorized" : " denied" ,
324+ callback);
325+ tsfn.Release ();
320326 }];
321327 } else if (auth_status == " denied" ) {
322328 NSWorkspace *workspace = [[NSWorkspace alloc ] init ];
@@ -347,6 +353,7 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
347353 std::string auth_status = MediaAuthStatus (" microphone" );
348354
349355 if (auth_status == " not determined" ) {
356+ __block Napi::ThreadSafeFunction tsfn = ts_fn;
350357 [AVCaptureDevice
351358 requestAccessForMediaType: AVMediaTypeAudio
352359 completionHandler: ^(BOOL granted) {
@@ -355,8 +362,9 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
355362 deferred.Resolve (Napi::String::New (env, granted));
356363 };
357364
358- ts_fn.BlockingCall (granted ? " authorized" : " denied" ,
359- callback);
365+ tsfn.BlockingCall (granted ? " authorized" : " denied" ,
366+ callback);
367+ tsfn.Release ();
360368 }];
361369 } else if (auth_status == " denied" ) {
362370 NSWorkspace *workspace = [[NSWorkspace alloc ] init ];
@@ -379,7 +387,7 @@ void AskForFullDiskAccess(const Napi::CallbackInfo &info) {
379387// Request Screen Capture Access.
380388void AskForScreenCaptureAccess (const Napi::CallbackInfo &info) {
381389 if (@available (macOS 10.15 , *)) {
382- // Tries to create a capture stream. This is necessary to add the app back
390+ // Tries to create a capture stream. This is necessary to add the app back
383391 // to the list in sysprefs if the user previously denied.
384392 // https://stackoverflow.com/questions/56597221/detecting-screen-recording-settings-on-macos-catalina
385393 CGDisplayStreamRef stream = CGDisplayStreamCreate (
0 commit comments