22#import < Foundation/Foundation.h>
33#include < cstdint>
44#include < cstring>
5+ #include < mutex>
56#include < unordered_map>
67#include " Interop.h"
78#include " ObjCBridge.h"
3738constexpr int kBlockRefCountOne = (1 << 1 );
3839constexpr int kBlockHasSignature = (1 << 30 );
3940std::unordered_map<void *, napi_ref> g_blockToJsFunction;
41+ std::mutex g_blockToJsFunctionMutex;
4042
4143void block_copy (void * dest, void * src) {
4244 auto dst = static_cast <Block_literal_1*>(dest);
4345 auto source = static_cast <Block_literal_1*>(src);
4446 dst->closure = source->closure ;
47+ if (dst->closure != nullptr ) {
48+ dst->closure ->retain ();
49+ }
4550}
4651
4752void block_release (void * src) {
@@ -51,28 +56,32 @@ void block_release(void* src) {
5156 }
5257
5358 if (block->closure != nullptr && block->closure ->env != nullptr ) {
59+ std::lock_guard<std::mutex> lock (g_blockToJsFunctionMutex);
5460 auto it = g_blockToJsFunction.find (block);
5561 if (it != g_blockToJsFunction.end ()) {
56- napi_delete_reference (block->closure ->env , it->second );
62+ if (std::this_thread::get_id () == block->closure ->jsThreadId ) {
63+ napi_delete_reference (block->closure ->env , it->second );
64+ }
5765 g_blockToJsFunction.erase (it);
5866 }
5967 }
6068
6169 if (block->closure != nullptr ) {
62- delete block->closure ;
63- block->closure = nullptr ;
70+ block->closure ->release ();
6471 }
72+ block->closure = nullptr ;
6573}
6674
6775Block_descriptor_1 kBlockDescriptor = {
6876 .reserved = 0 ,
6977 .size = sizeof (Block_literal_1),
7078 .copy_helper = block_copy,
7179 .dispose_helper = block_release,
72- .signature = nullptr ,
80+ .signature = " v@? " ,
7381};
7482
7583inline napi_value getCachedBlockJsFunction (napi_env env, void * blockPtr) {
84+ std::lock_guard<std::mutex> lock (g_blockToJsFunctionMutex);
7685 auto it = g_blockToJsFunction.find (blockPtr);
7786 if (it == g_blockToJsFunction.end ()) {
7887 return nullptr ;
@@ -89,6 +98,7 @@ inline void cacheBlockJsFunction(napi_env env, void* blockPtr, napi_value jsFunc
8998 if (blockPtr == nullptr || jsFunction == nullptr ) {
9099 return ;
91100 }
101+ std::lock_guard<std::mutex> lock (g_blockToJsFunctionMutex);
92102 if (g_blockToJsFunction.find (blockPtr) != g_blockToJsFunction.end ()) {
93103 return ;
94104 }
@@ -104,16 +114,19 @@ void block_finalize(napi_env env, void* data, void* hint) {
104114 return ;
105115 }
106116
107- auto it = g_blockToJsFunction.find (block);
108- if (it != g_blockToJsFunction.end ()) {
109- napi_delete_reference (env, it->second );
110- g_blockToJsFunction.erase (it);
117+ {
118+ std::lock_guard<std::mutex> lock (g_blockToJsFunctionMutex);
119+ auto it = g_blockToJsFunction.find (block);
120+ if (it != g_blockToJsFunction.end ()) {
121+ napi_delete_reference (env, it->second );
122+ g_blockToJsFunction.erase (it);
123+ }
111124 }
112125
113126 if (block->closure != nullptr ) {
114- delete block->closure ;
115- block->closure = nullptr ;
127+ block->closure ->release ();
116128 }
129+ block->closure = nullptr ;
117130
118131 free (block);
119132}
@@ -136,7 +149,7 @@ id registerBlock(napi_env env, Closure* closure, napi_value callback) {
136149 }
137150
138151 block->isa = mallocBlockISA != nullptr ? mallocBlockISA : stackBlockISA;
139- block->flags = kBlockNeedsFree | kBlockHasCopyDispose | kBlockRefCountOne ;
152+ block->flags = kBlockNeedsFree | kBlockHasCopyDispose | kBlockRefCountOne | kBlockHasSignature ;
140153 block->reserved = 0 ;
141154 block->invoke = closure->fnptr ;
142155 block->descriptor = &kBlockDescriptor ;
0 commit comments