8
8
#include " node_buffer.h"
9
9
#include " node_errors.h"
10
10
#include " node_internals.h"
11
+ #include " node_process.h"
11
12
#include " threadpoolwork-inl.h"
12
13
#include " tracing/traced_value.h"
13
14
#include " util-inl.h"
@@ -21,6 +22,8 @@ struct node_napi_env__ : public napi_env__ {
21
22
CHECK_NOT_NULL (node_env ());
22
23
}
23
24
25
+ ~node_napi_env__ () { FinalizeAll (); }
26
+
24
27
inline node::Environment* node_env () const {
25
28
return node::Environment::GetCurrent (context ());
26
29
}
@@ -37,15 +40,54 @@ struct node_napi_env__ : public napi_env__ {
37
40
v8::True (isolate));
38
41
}
39
42
43
+ inline void trigger_fatal_exception (v8::Local<v8::Value> local_err) {
44
+ v8::Local<v8::Message> local_msg =
45
+ v8::Exception::CreateMessage (isolate, local_err);
46
+ node::errors::TriggerUncaughtException (isolate, local_err, local_msg);
47
+ }
48
+
49
+ // option enforceUncaughtExceptionPolicy is added for not breaking existing
50
+ // running n-api add-ons, and should be deprecated in the next major Node.js
51
+ // release.
52
+ template <typename T>
53
+ inline void CallbackIntoModule (T&& call,
54
+ bool enforceUncaughtExceptionPolicy = false ) {
55
+ CallIntoModule (
56
+ call,
57
+ [enforceUncaughtExceptionPolicy](napi_env env_,
58
+ v8::Local<v8::Value> local_err) {
59
+ node_napi_env__* env = static_cast <node_napi_env__*>(env_);
60
+ node::Environment* node_env = env->node_env ();
61
+ if (!node_env->options ()->force_node_api_uncaught_exceptions_policy &&
62
+ !enforceUncaughtExceptionPolicy) {
63
+ ProcessEmitDeprecationWarning (
64
+ node_env,
65
+ " Uncaught N-API callback exception detected, please run node "
66
+ " with option --force-node-api-uncaught-exceptions-policy to handle "
67
+ " those exceptions properly." ,
68
+ " DEP0XXX" );
69
+ return ;
70
+ }
71
+ // If there was an unhandled exception in the complete callback,
72
+ // report it as a fatal exception. (There is no JavaScript on the
73
+ // callstack that can possibly handle it.)
74
+ env->trigger_fatal_exception (local_err);
75
+ });
76
+ }
77
+
40
78
void CallFinalizer (napi_finalize cb, void * data, void * hint) override {
79
+ CallFinalizer (cb, data, hint, true );
80
+ }
81
+
82
+ inline void CallFinalizer (napi_finalize cb,
83
+ void * data,
84
+ void * hint,
85
+ bool enforceUncaughtExceptionPolicy) {
41
86
napi_env env = static_cast <napi_env>(this );
42
- node_env ()->SetImmediate ([=](node::Environment* node_env) {
43
- v8::HandleScope handle_scope (env->isolate );
44
- v8::Context::Scope context_scope (env->context ());
45
- env->CallIntoModule ([&](napi_env env) {
46
- cb (env, data, hint);
47
- });
48
- });
87
+ v8::HandleScope handle_scope (env->isolate );
88
+ v8::Context::Scope context_scope (env->context ());
89
+ CallbackIntoModule ([&](napi_env env) { cb (env, data, hint); },
90
+ enforceUncaughtExceptionPolicy);
49
91
}
50
92
51
93
const char * GetFilename () const { return filename.c_str (); }
@@ -76,12 +118,9 @@ class BufferFinalizer : private Finalizer {
76
118
v8::HandleScope handle_scope (finalizer->_env ->isolate );
77
119
v8::Context::Scope context_scope (finalizer->_env ->context ());
78
120
79
- finalizer->_env ->CallIntoModule ([&](napi_env env) {
80
- finalizer->_finalize_callback (
81
- env,
82
- finalizer->_finalize_data ,
83
- finalizer->_finalize_hint );
84
- });
121
+ finalizer->_env ->CallFinalizer (finalizer->_finalize_callback ,
122
+ finalizer->_finalize_data ,
123
+ finalizer->_finalize_hint );
85
124
});
86
125
}
87
126
@@ -113,13 +152,6 @@ NewEnv(v8::Local<v8::Context> context, const std::string& module_filename) {
113
152
return result;
114
153
}
115
154
116
- static inline void trigger_fatal_exception (
117
- napi_env env, v8::Local<v8::Value> local_err) {
118
- v8::Local<v8::Message> local_msg =
119
- v8::Exception::CreateMessage (env->isolate , local_err);
120
- node::errors::TriggerUncaughtException (env->isolate , local_err, local_msg);
121
- }
122
-
123
155
class ThreadSafeFunction : public node ::AsyncResource {
124
156
public:
125
157
ThreadSafeFunction (v8::Local<v8::Function> func,
@@ -318,19 +350,16 @@ class ThreadSafeFunction : public node::AsyncResource {
318
350
v8::Local<v8::Function>::New (env->isolate , ref);
319
351
js_callback = v8impl::JsValueFromV8LocalValue (js_cb);
320
352
}
321
- env->CallIntoModule ([&](napi_env env) {
322
- call_js_cb (env, js_callback, context, data);
323
- });
353
+ env->CallbackIntoModule (
354
+ [&](napi_env env) { call_js_cb (env, js_callback, context, data); });
324
355
}
325
356
}
326
357
327
358
void Finalize () {
328
359
v8::HandleScope scope (env->isolate );
329
360
if (finalize_cb) {
330
361
CallbackScope cb_scope (this );
331
- env->CallIntoModule ([&](napi_env env) {
332
- finalize_cb (env, finalize_data, context);
333
- });
362
+ env->CallFinalizer (finalize_cb, finalize_data, context, false );
334
363
}
335
364
EmptyQueueAndDelete ();
336
365
}
@@ -718,7 +747,7 @@ napi_status napi_fatal_exception(napi_env env, napi_value err) {
718
747
CHECK_ARG (env, err);
719
748
720
749
v8::Local<v8::Value> local_err = v8impl::V8LocalValueFromJsValue (err);
721
- v8impl::trigger_fatal_exception (env, local_err);
750
+ static_cast <node_napi_env> (env)-> trigger_fatal_exception ( local_err);
722
751
723
752
return napi_clear_last_error (env);
724
753
}
@@ -1068,14 +1097,11 @@ class Work : public node::AsyncResource, public node::ThreadPoolWork {
1068
1097
1069
1098
CallbackScope callback_scope (this );
1070
1099
1071
- _env->CallIntoModule ([&](napi_env env) {
1072
- _complete (env, ConvertUVErrorCode (status), _data);
1073
- }, [](napi_env env, v8::Local<v8::Value> local_err) {
1074
- // If there was an unhandled exception in the complete callback,
1075
- // report it as a fatal exception. (There is no JavaScript on the
1076
- // callstack that can possibly handle it.)
1077
- v8impl::trigger_fatal_exception (env, local_err);
1078
- });
1100
+ _env->CallbackIntoModule (
1101
+ [&](napi_env env) {
1102
+ _complete (env, ConvertUVErrorCode (status), _data);
1103
+ },
1104
+ true );
1079
1105
1080
1106
// Note: Don't access `work` after this point because it was
1081
1107
// likely deleted by the complete callback.
0 commit comments