@@ -72,7 +72,9 @@ inline ThreadSafeCallback::~ThreadSafeCallback() {
7272
7373inline void ThreadSafeCallback::call (ArgumentFunction argFunction) {
7474 auto argFn = new ArgumentFunction (argFunction);
75- if (threadSafeFunction_.BlockingCall (argFn) != napi_ok) {
75+ // Use NonBlockingCall to avoid hanging if environment is destroyed
76+ // This will queue the callback but not block waiting for it
77+ if (threadSafeFunction_.NonBlockingCall (argFn) != napi_ok) {
7678 delete argFn;
7779 }
7880}
@@ -83,13 +85,50 @@ inline void ThreadSafeCallback::callJsCallback(
8385 Napi::Reference<Napi::Value>* context,
8486 ArgumentFunction* argFn) {
8587
86- if (argFn != nullptr ) {
88+ if (argFn == nullptr ) {
89+ return ;
90+ }
91+
92+ // Check if environment and callback are valid before proceeding
93+ if (env == nullptr || jsCallback == nullptr || context == nullptr ) {
94+ delete argFn;
95+ return ;
96+ }
97+
98+ // Check if context reference is still valid
99+ if (context->IsEmpty ()) {
100+ delete argFn;
101+ return ;
102+ }
103+
104+ try {
87105 ArgumentVector args;
88106 (*argFn)(env, args);
89107 delete argFn;
90108
91- if (env != nullptr && jsCallback != nullptr ) {
92- jsCallback.Call (context->Value (), args);
109+ // Get the receiver value and check if it's valid
110+ Napi::Value receiverValue = context->Value ();
111+ // Check if receiver value is null or undefined (invalid)
112+ if (receiverValue.IsNull () || receiverValue.IsUndefined ()) {
113+ return ;
114+ }
115+
116+ // Attempt to call the callback with error handling
117+ // If the environment is being destroyed, this may fail
118+ // Note: N-API errors don't throw C++ exceptions, so this won't catch
119+ // napi_open_callback_scope failures, but it helps with other cases
120+ try {
121+ jsCallback.Call (receiverValue, args);
122+ } catch (const std::exception&) {
123+ // Silently ignore exceptions - environment might be destroyed
124+ } catch (...) {
125+ // Catch any other exceptions during callback execution
93126 }
127+ } catch (const std::exception&) {
128+ // If argument building fails, just clean up
129+ delete argFn;
130+ } catch (...) {
131+ // Catch any other exceptions and clean up
132+ delete argFn;
94133 }
95134}
0 commit comments