objc-js 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
package/package.json
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"format": "prettier --write \"**/*.{ts,js,json,md}\"",
|
|
40
40
|
"preinstall-disabled": "npm run build-scripts && npm run make-clangd-config"
|
|
41
41
|
},
|
|
42
|
-
"version": "0.0.
|
|
42
|
+
"version": "0.0.11",
|
|
43
43
|
"description": "Objective-C bridge for Node.js",
|
|
44
44
|
"main": "dist/index.js",
|
|
45
45
|
"dependencies": {
|
|
@@ -551,7 +551,15 @@ void ForwardInvocation(id self, SEL _cmd, NSInvocation *invocation) {
|
|
|
551
551
|
js_thread = it->second.js_thread;
|
|
552
552
|
|
|
553
553
|
// Get the ThreadSafeFunction - this is thread-safe by design
|
|
554
|
+
// IMPORTANT: We must Acquire() to increment the ref count, because copying
|
|
555
|
+
// a ThreadSafeFunction does NOT increment it. If DeallocImplementation runs
|
|
556
|
+
// and calls Release() on the original, our copy would become invalid.
|
|
554
557
|
tsfn = callbackIt->second;
|
|
558
|
+
napi_status acq_status = tsfn.Acquire();
|
|
559
|
+
if (acq_status != napi_ok) {
|
|
560
|
+
NSLog(@"Warning: Failed to acquire ThreadSafeFunction for selector %s", selectorName.c_str());
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
555
563
|
|
|
556
564
|
// Get the type encoding for return value handling
|
|
557
565
|
auto encIt = it->second.typeEncodings.find(selectorName);
|
|
@@ -571,9 +579,14 @@ void ForwardInvocation(id self, SEL _cmd, NSInvocation *invocation) {
|
|
|
571
579
|
|
|
572
580
|
if (is_js_thread) {
|
|
573
581
|
// We're on the JS thread, so it's safe to access N-API values directly
|
|
582
|
+
// Release the TSFN we acquired - we don't need it on this path
|
|
583
|
+
tsfn.Release();
|
|
584
|
+
|
|
574
585
|
// Do a second lookup to get the JS callback
|
|
586
|
+
// IMPORTANT: We must call .Value() while holding the lock to prevent
|
|
587
|
+
// DeallocImplementation from erasing the entry while we're using it
|
|
575
588
|
napi_env stored_env;
|
|
576
|
-
Napi::
|
|
589
|
+
Napi::Function jsFn;
|
|
577
590
|
{
|
|
578
591
|
std::lock_guard<std::mutex> lock(g_implementations_mutex);
|
|
579
592
|
auto it = g_implementations.find(ptr);
|
|
@@ -591,12 +604,13 @@ void ForwardInvocation(id self, SEL _cmd, NSInvocation *invocation) {
|
|
|
591
604
|
}
|
|
592
605
|
|
|
593
606
|
stored_env = it->second.env;
|
|
594
|
-
|
|
607
|
+
// Get the function value WHILE HOLDING THE LOCK
|
|
608
|
+
// This prevents a race with DeallocImplementation clearing the jsCallbacks map
|
|
609
|
+
jsFn = jsCallbackIt->second.Value();
|
|
595
610
|
}
|
|
596
611
|
|
|
597
|
-
// Now
|
|
612
|
+
// Now jsFn is a local Napi::Function (napi_value), safe to use after lock release
|
|
598
613
|
Napi::Env env(stored_env);
|
|
599
|
-
Napi::Function jsFn = jsCallbackPtr->Value(); // Safe: on JS thread with valid HandleScope
|
|
600
614
|
CallJSCallback(env, jsFn, data);
|
|
601
615
|
// Data is deleted in CallJSCallback
|
|
602
616
|
} else {
|
|
@@ -604,6 +618,10 @@ void ForwardInvocation(id self, SEL _cmd, NSInvocation *invocation) {
|
|
|
604
618
|
// Use ThreadSafeFunction to marshal to JS thread
|
|
605
619
|
napi_status status = tsfn.BlockingCall(data, CallJSCallback);
|
|
606
620
|
|
|
621
|
+
// Release our acquired reference to the TSFN
|
|
622
|
+
// This balances the Acquire() call above
|
|
623
|
+
tsfn.Release();
|
|
624
|
+
|
|
607
625
|
if (status != napi_ok) {
|
|
608
626
|
NSLog(@"Error: Failed to call ThreadSafeFunction for selector %s (status: %d)",
|
|
609
627
|
selectorName.c_str(), status);
|