@@ -856,180 +856,513 @@ napi_status ConcludeDeferred(napi_env env,
856
856
return GET_RETURN_STATUS (env);
857
857
}
858
858
859
- } // end of namespace v8impl
860
-
861
- // Intercepts the Node-V8 module registration callback. Converts parameters
862
- // to NAPI equivalents and then calls the registration callback specified
863
- // by the NAPI module.
864
- void napi_module_register_cb (v8::Local<v8::Object> exports,
865
- v8::Local<v8::Value> module,
866
- v8::Local<v8::Context> context,
867
- void * priv) {
868
- napi_module* mod = static_cast <napi_module*>(priv);
859
+ class ThreadSafeFunction : public node ::AsyncResource {
860
+ public:
861
+ ThreadSafeFunction (v8::Local<v8::Function> func,
862
+ v8::Local<v8::Object> resource,
863
+ v8::Local<v8::String> name,
864
+ size_t thread_count_,
865
+ void * context_,
866
+ size_t max_queue_size_,
867
+ napi_env env_,
868
+ void * finalize_data_,
869
+ napi_finalize finalize_cb_,
870
+ napi_threadsafe_function_call_js call_js_cb_):
871
+ AsyncResource (env_->isolate,
872
+ resource,
873
+ *v8::String::Utf8Value (env_->isolate, name)),
874
+ thread_count(thread_count_),
875
+ is_closing(false ),
876
+ context(context_),
877
+ max_queue_size(max_queue_size_),
878
+ env(env_),
879
+ finalize_data(finalize_data_),
880
+ finalize_cb(finalize_cb_),
881
+ call_js_cb(call_js_cb_ == nullptr ? CallJs : call_js_cb_),
882
+ handles_closing(false ) {
883
+ ref.Reset (env->isolate , func);
884
+ node::AddEnvironmentCleanupHook (env->isolate , Cleanup, this );
885
+ }
869
886
870
- if (mod->nm_register_func == nullptr ) {
871
- node::Environment::GetCurrent (context)->ThrowError (
872
- " Module has no declared entry point." );
873
- return ;
887
+ ~ThreadSafeFunction () {
888
+ node::RemoveEnvironmentCleanupHook (env->isolate , Cleanup, this );
889
+ if (ref.IsEmpty ())
890
+ return ;
891
+ ref.ClearWeak ();
892
+ ref.Reset ();
874
893
}
875
894
876
- // Create a new napi_env for this module or reference one if a pre-existing
877
- // one is found.
878
- napi_env env = v8impl::GetEnv (context);
895
+ // These methods can be called from any thread.
879
896
880
- napi_value _exports;
881
- NAPI_CALL_INTO_MODULE_THROW (env,
882
- _exports = mod->nm_register_func (env,
883
- v8impl::JsValueFromV8LocalValue (exports)));
897
+ napi_status Push (void * data, napi_threadsafe_function_call_mode mode) {
898
+ node::Mutex::ScopedLock lock (this ->mutex );
884
899
885
- // If register function returned a non-null exports object different from
886
- // the exports object we passed it, set that as the "exports" property of
887
- // the module.
888
- if (_exports != nullptr &&
889
- _exports != v8impl::JsValueFromV8LocalValue (exports)) {
890
- napi_value _module = v8impl::JsValueFromV8LocalValue (module);
891
- napi_set_named_property (env, _module, " exports" , _exports);
900
+ while (queue.size () >= max_queue_size &&
901
+ max_queue_size > 0 &&
902
+ !is_closing) {
903
+ if (mode == napi_tsfn_nonblocking) {
904
+ return napi_queue_full;
905
+ }
906
+ cond->Wait (lock);
907
+ }
908
+
909
+ if (is_closing) {
910
+ if (thread_count == 0 ) {
911
+ return napi_invalid_arg;
912
+ } else {
913
+ thread_count--;
914
+ return napi_closing;
915
+ }
916
+ } else {
917
+ if (uv_async_send (&async) != 0 ) {
918
+ return napi_generic_failure;
919
+ }
920
+ queue.push (data);
921
+ return napi_ok;
922
+ }
892
923
}
893
- }
894
924
895
- } // end of anonymous namespace
925
+ napi_status Acquire () {
926
+ node::Mutex::ScopedLock lock (this ->mutex );
896
927
897
- // Registers a NAPI module.
898
- void napi_module_register (napi_module* mod) {
899
- node::node_module* nm = new node::node_module {
900
- -1 ,
901
- mod->nm_flags ,
902
- nullptr ,
903
- mod->nm_filename ,
904
- nullptr ,
905
- napi_module_register_cb,
906
- mod->nm_modname ,
907
- mod, // priv
908
- nullptr ,
909
- };
910
- node::node_module_register (nm);
911
- }
928
+ if (is_closing) {
929
+ return napi_closing;
930
+ }
912
931
913
- napi_status napi_add_env_cleanup_hook (napi_env env,
914
- void (*fun)(void * arg),
915
- void * arg) {
916
- CHECK_ENV (env);
917
- CHECK_ARG (env, fun);
932
+ thread_count++;
918
933
919
- node::AddEnvironmentCleanupHook (env->isolate , fun, arg);
934
+ return napi_ok;
935
+ }
920
936
921
- return napi_ok;
922
- }
937
+ napi_status Release (napi_threadsafe_function_release_mode mode) {
938
+ node::Mutex::ScopedLock lock ( this -> mutex );
923
939
924
- napi_status napi_remove_env_cleanup_hook (napi_env env,
925
- void (*fun)(void * arg),
926
- void * arg) {
927
- CHECK_ENV (env);
928
- CHECK_ARG (env, fun);
940
+ if (thread_count == 0 ) {
941
+ return napi_invalid_arg;
942
+ }
929
943
930
- node::RemoveEnvironmentCleanupHook (env-> isolate , fun, arg) ;
944
+ thread_count-- ;
931
945
932
- return napi_ok;
933
- }
946
+ if (thread_count == 0 || mode == napi_tsfn_abort) {
947
+ if (!is_closing) {
948
+ is_closing = (mode == napi_tsfn_abort);
949
+ if (is_closing && max_queue_size > 0 ) {
950
+ cond->Signal (lock);
951
+ }
952
+ if (uv_async_send (&async) != 0 ) {
953
+ return napi_generic_failure;
954
+ }
955
+ }
956
+ }
934
957
935
- // Warning: Keep in-sync with napi_status enum
936
- static
937
- const char * error_messages[] = {nullptr ,
938
- " Invalid argument" ,
939
- " An object was expected" ,
940
- " A string was expected" ,
941
- " A string or symbol was expected" ,
942
- " A function was expected" ,
943
- " A number was expected" ,
944
- " A boolean was expected" ,
945
- " An array was expected" ,
946
- " Unknown failure" ,
947
- " An exception is pending" ,
948
- " The async work item was cancelled" ,
949
- " napi_escape_handle already called on scope" ,
950
- " Invalid handle scope usage" ,
951
- " Invalid callback scope usage" ,
952
- " Thread-safe function queue is full" ,
953
- " Thread-safe function handle is closing"
954
- };
958
+ return napi_ok;
959
+ }
955
960
956
- static inline napi_status napi_clear_last_error (napi_env env) {
957
- env->last_error .error_code = napi_ok;
961
+ void EmptyQueueAndDelete () {
962
+ for (; !queue.empty () ; queue.pop ()) {
963
+ call_js_cb (nullptr , nullptr , context, queue.front ());
964
+ }
965
+ delete this ;
966
+ }
958
967
959
- // TODO(boingoing): Should this be a callback?
960
- env->last_error .engine_error_code = 0 ;
961
- env->last_error .engine_reserved = nullptr ;
962
- return napi_ok;
963
- }
968
+ // These methods must only be called from the loop thread.
964
969
965
- static inline
966
- napi_status napi_set_last_error (napi_env env, napi_status error_code,
967
- uint32_t engine_error_code,
968
- void * engine_reserved) {
969
- env->last_error .error_code = error_code;
970
- env->last_error .engine_error_code = engine_error_code;
971
- env->last_error .engine_reserved = engine_reserved;
972
- return error_code;
973
- }
970
+ napi_status Init () {
971
+ ThreadSafeFunction* ts_fn = this ;
974
972
975
- napi_status napi_get_last_error_info (napi_env env,
976
- const napi_extended_error_info** result) {
977
- CHECK_ENV (env);
978
- CHECK_ARG (env, result);
973
+ if (uv_async_init (env->loop , &async, AsyncCb) == 0 ) {
974
+ if (max_queue_size > 0 ) {
975
+ cond.reset (new node::ConditionVariable);
976
+ }
977
+ if ((max_queue_size == 0 || cond.get () != nullptr ) &&
978
+ uv_idle_init (env->loop , &idle) == 0 ) {
979
+ return napi_ok;
980
+ }
979
981
980
- // you must update this assert to reference the last message
981
- // in the napi_status enum each time a new error message is added.
982
- // We don't have a napi_status_last as this would result in an ABI
983
- // change each time a message was added.
984
- static_assert (
985
- node::arraysize (error_messages) == napi_closing + 1 ,
986
- " Count of error messages must match count of error values" );
987
- CHECK_LE (env->last_error .error_code , napi_callback_scope_mismatch);
982
+ uv_close (reinterpret_cast <uv_handle_t *>(&async),
983
+ [] (uv_handle_t * handle) -> void {
984
+ ThreadSafeFunction* ts_fn =
985
+ node::ContainerOf (&ThreadSafeFunction::async,
986
+ reinterpret_cast <uv_async_t *>(handle));
987
+ delete ts_fn;
988
+ });
988
989
989
- // Wait until someone requests the last error information to fetch the error
990
- // message string
991
- env-> last_error . error_message =
992
- error_messages[env-> last_error . error_code ];
990
+ // Prevent the thread-safe function from being deleted here, because
991
+ // the callback above will delete it.
992
+ ts_fn = nullptr ;
993
+ }
993
994
994
- *result = &(env->last_error );
995
- return napi_ok;
996
- }
995
+ delete ts_fn;
997
996
998
- napi_status napi_fatal_exception (napi_env env, napi_value err) {
999
- NAPI_PREAMBLE (env);
1000
- CHECK_ARG (env, err);
997
+ return napi_generic_failure;
998
+ }
1001
999
1002
- v8::Local<v8::Value> local_err = v8impl::V8LocalValueFromJsValue (err);
1003
- v8impl::trigger_fatal_exception (env, local_err);
1000
+ napi_status Unref () {
1001
+ uv_unref (reinterpret_cast <uv_handle_t *>(&async));
1002
+ uv_unref (reinterpret_cast <uv_handle_t *>(&idle));
1004
1003
1005
- return napi_clear_last_error (env) ;
1006
- }
1004
+ return napi_ok ;
1005
+ }
1007
1006
1008
- NAPI_NO_RETURN void napi_fatal_error (const char * location,
1009
- size_t location_len,
1010
- const char * message,
1011
- size_t message_len) {
1012
- std::string location_string;
1013
- std::string message_string;
1007
+ napi_status Ref () {
1008
+ uv_ref (reinterpret_cast <uv_handle_t *>(&async));
1009
+ uv_ref (reinterpret_cast <uv_handle_t *>(&idle));
1014
1010
1015
- if (location_len != NAPI_AUTO_LENGTH) {
1016
- location_string.assign (
1017
- const_cast <char *>(location), location_len);
1018
- } else {
1019
- location_string.assign (
1020
- const_cast <char *>(location), strlen (location));
1011
+ return napi_ok;
1021
1012
}
1022
1013
1023
- if (message_len != NAPI_AUTO_LENGTH) {
1024
- message_string.assign (
1025
- const_cast <char *>(message), message_len);
1026
- } else {
1027
- message_string.assign (
1028
- const_cast <char *>(message), strlen (message));
1029
- }
1014
+ void DispatchOne () {
1015
+ void * data = nullptr ;
1016
+ bool popped_value = false ;
1017
+ bool idle_stop_failed = false ;
1030
1018
1031
- node::FatalError (location_string.c_str (), message_string.c_str ());
1032
- }
1019
+ {
1020
+ node::Mutex::ScopedLock lock (this ->mutex );
1021
+ if (is_closing) {
1022
+ CloseHandlesAndMaybeDelete ();
1023
+ } else {
1024
+ size_t size = queue.size ();
1025
+ if (size > 0 ) {
1026
+ data = queue.front ();
1027
+ queue.pop ();
1028
+ popped_value = true ;
1029
+ if (size == max_queue_size && max_queue_size > 0 ) {
1030
+ cond->Signal (lock);
1031
+ }
1032
+ size--;
1033
+ }
1034
+
1035
+ if (size == 0 ) {
1036
+ if (thread_count == 0 ) {
1037
+ is_closing = true ;
1038
+ if (max_queue_size > 0 ) {
1039
+ cond->Signal (lock);
1040
+ }
1041
+ CloseHandlesAndMaybeDelete ();
1042
+ } else {
1043
+ if (uv_idle_stop (&idle) != 0 ) {
1044
+ idle_stop_failed = true ;
1045
+ }
1046
+ }
1047
+ }
1048
+ }
1049
+ }
1050
+
1051
+ if (popped_value || idle_stop_failed) {
1052
+ v8::HandleScope scope (env->isolate );
1053
+ CallbackScope cb_scope (this );
1054
+
1055
+ if (idle_stop_failed) {
1056
+ CHECK (napi_throw_error (env,
1057
+ " ERR_NAPI_TSFN_STOP_IDLE_LOOP" ,
1058
+ " Failed to stop the idle loop" ) == napi_ok);
1059
+ } else {
1060
+ v8::Local<v8::Function> js_cb =
1061
+ v8::Local<v8::Function>::New (env->isolate , ref);
1062
+ call_js_cb (env,
1063
+ v8impl::JsValueFromV8LocalValue (js_cb),
1064
+ context,
1065
+ data);
1066
+ }
1067
+ }
1068
+ }
1069
+
1070
+ node::Environment* NodeEnv () {
1071
+ // For some reason grabbing the Node.js environment requires a handle scope.
1072
+ v8::HandleScope scope (env->isolate );
1073
+ return node::Environment::GetCurrent (env->isolate );
1074
+ }
1075
+
1076
+ void MaybeStartIdle () {
1077
+ if (uv_idle_start (&idle, IdleCb) != 0 ) {
1078
+ v8::HandleScope scope (env->isolate );
1079
+ CallbackScope cb_scope (this );
1080
+ CHECK (napi_throw_error (env,
1081
+ " ERR_NAPI_TSFN_START_IDLE_LOOP" ,
1082
+ " Failed to start the idle loop" ) == napi_ok);
1083
+ }
1084
+ }
1085
+
1086
+ void Finalize () {
1087
+ v8::HandleScope scope (env->isolate );
1088
+ if (finalize_cb) {
1089
+ CallbackScope cb_scope (this );
1090
+ finalize_cb (env, finalize_data, context);
1091
+ }
1092
+ EmptyQueueAndDelete ();
1093
+ }
1094
+
1095
+ inline void * Context () {
1096
+ return context;
1097
+ }
1098
+
1099
+ void CloseHandlesAndMaybeDelete (bool set_closing = false ) {
1100
+ if (set_closing) {
1101
+ node::Mutex::ScopedLock lock (this ->mutex );
1102
+ is_closing = true ;
1103
+ if (max_queue_size > 0 ) {
1104
+ cond->Signal (lock);
1105
+ }
1106
+ }
1107
+ if (handles_closing) {
1108
+ return ;
1109
+ }
1110
+ handles_closing = true ;
1111
+ uv_close (
1112
+ reinterpret_cast <uv_handle_t *>(&async),
1113
+ [] (uv_handle_t * handle) -> void {
1114
+ ThreadSafeFunction* ts_fn =
1115
+ node::ContainerOf (&ThreadSafeFunction::async,
1116
+ reinterpret_cast <uv_async_t *>(handle));
1117
+ uv_close (
1118
+ reinterpret_cast <uv_handle_t *>(&ts_fn->idle ),
1119
+ [] (uv_handle_t * handle) -> void {
1120
+ ThreadSafeFunction* ts_fn =
1121
+ node::ContainerOf (&ThreadSafeFunction::idle,
1122
+ reinterpret_cast <uv_idle_t *>(handle));
1123
+ ts_fn->Finalize ();
1124
+ });
1125
+ });
1126
+ }
1127
+
1128
+ // Default way of calling into JavaScript. Used when ThreadSafeFunction is
1129
+ // constructed without a call_js_cb_.
1130
+ static void CallJs (napi_env env, napi_value cb, void * context, void * data) {
1131
+ if (!(env == nullptr || cb == nullptr )) {
1132
+ napi_value recv;
1133
+ napi_status status;
1134
+
1135
+ status = napi_get_undefined (env, &recv);
1136
+ if (status != napi_ok) {
1137
+ napi_throw_error (env, " ERR_NAPI_TSFN_GET_UNDEFINED" ,
1138
+ " Failed to retrieve undefined value" );
1139
+ return ;
1140
+ }
1141
+
1142
+ status = napi_call_function (env, recv, cb, 0 , nullptr , nullptr );
1143
+ if (status != napi_ok && status != napi_pending_exception) {
1144
+ napi_throw_error (env, " ERR_NAPI_TSFN_CALL_JS" ,
1145
+ " Failed to call JS callback" );
1146
+ return ;
1147
+ }
1148
+ }
1149
+ }
1150
+
1151
+ static void IdleCb (uv_idle_t * idle) {
1152
+ ThreadSafeFunction* ts_fn =
1153
+ node::ContainerOf (&ThreadSafeFunction::idle, idle);
1154
+ ts_fn->DispatchOne ();
1155
+ }
1156
+
1157
+ static void AsyncCb (uv_async_t * async) {
1158
+ ThreadSafeFunction* ts_fn =
1159
+ node::ContainerOf (&ThreadSafeFunction::async, async);
1160
+ ts_fn->MaybeStartIdle ();
1161
+ }
1162
+
1163
+ static void Cleanup (void * data) {
1164
+ reinterpret_cast <ThreadSafeFunction*>(data)
1165
+ ->CloseHandlesAndMaybeDelete (true );
1166
+ }
1167
+
1168
+ private:
1169
+ // These are variables protected by the mutex.
1170
+ node::Mutex mutex;
1171
+ std::unique_ptr<node::ConditionVariable> cond;
1172
+ std::queue<void *> queue;
1173
+ uv_async_t async;
1174
+ uv_idle_t idle;
1175
+ size_t thread_count;
1176
+ bool is_closing;
1177
+
1178
+ // These are variables set once, upon creation, and then never again, which
1179
+ // means we don't need the mutex to read them.
1180
+ void * context;
1181
+ size_t max_queue_size;
1182
+
1183
+ // These are variables accessed only from the loop thread.
1184
+ v8::Persistent<v8::Function> ref;
1185
+ napi_env env;
1186
+ void * finalize_data;
1187
+ napi_finalize finalize_cb;
1188
+ napi_threadsafe_function_call_js call_js_cb;
1189
+ bool handles_closing;
1190
+ };
1191
+
1192
+ } // end of namespace v8impl
1193
+
1194
+ // Intercepts the Node-V8 module registration callback. Converts parameters
1195
+ // to NAPI equivalents and then calls the registration callback specified
1196
+ // by the NAPI module.
1197
+ void napi_module_register_cb (v8::Local<v8::Object> exports,
1198
+ v8::Local<v8::Value> module,
1199
+ v8::Local<v8::Context> context,
1200
+ void * priv) {
1201
+ napi_module* mod = static_cast <napi_module*>(priv);
1202
+
1203
+ if (mod->nm_register_func == nullptr ) {
1204
+ node::Environment::GetCurrent (context)->ThrowError (
1205
+ " Module has no declared entry point." );
1206
+ return ;
1207
+ }
1208
+
1209
+ // Create a new napi_env for this module or reference one if a pre-existing
1210
+ // one is found.
1211
+ napi_env env = v8impl::GetEnv (context);
1212
+
1213
+ napi_value _exports;
1214
+ NAPI_CALL_INTO_MODULE_THROW (env,
1215
+ _exports = mod->nm_register_func (env,
1216
+ v8impl::JsValueFromV8LocalValue (exports)));
1217
+
1218
+ // If register function returned a non-null exports object different from
1219
+ // the exports object we passed it, set that as the "exports" property of
1220
+ // the module.
1221
+ if (_exports != nullptr &&
1222
+ _exports != v8impl::JsValueFromV8LocalValue (exports)) {
1223
+ napi_value _module = v8impl::JsValueFromV8LocalValue (module);
1224
+ napi_set_named_property (env, _module, " exports" , _exports);
1225
+ }
1226
+ }
1227
+
1228
+ } // end of anonymous namespace
1229
+
1230
+ // Registers a NAPI module.
1231
+ void napi_module_register (napi_module* mod) {
1232
+ node::node_module* nm = new node::node_module {
1233
+ -1 ,
1234
+ mod->nm_flags ,
1235
+ nullptr ,
1236
+ mod->nm_filename ,
1237
+ nullptr ,
1238
+ napi_module_register_cb,
1239
+ mod->nm_modname ,
1240
+ mod, // priv
1241
+ nullptr ,
1242
+ };
1243
+ node::node_module_register (nm);
1244
+ }
1245
+
1246
+ napi_status napi_add_env_cleanup_hook (napi_env env,
1247
+ void (*fun)(void * arg),
1248
+ void* arg) {
1249
+ CHECK_ENV (env);
1250
+ CHECK_ARG (env, fun);
1251
+
1252
+ node::AddEnvironmentCleanupHook (env->isolate , fun, arg);
1253
+
1254
+ return napi_ok;
1255
+ }
1256
+
1257
+ napi_status napi_remove_env_cleanup_hook (napi_env env,
1258
+ void (*fun)(void * arg),
1259
+ void* arg) {
1260
+ CHECK_ENV (env);
1261
+ CHECK_ARG (env, fun);
1262
+
1263
+ node::RemoveEnvironmentCleanupHook (env->isolate , fun, arg);
1264
+
1265
+ return napi_ok;
1266
+ }
1267
+
1268
+ // Warning: Keep in-sync with napi_status enum
1269
+ static
1270
+ const char * error_messages[] = {nullptr ,
1271
+ " Invalid argument" ,
1272
+ " An object was expected" ,
1273
+ " A string was expected" ,
1274
+ " A string or symbol was expected" ,
1275
+ " A function was expected" ,
1276
+ " A number was expected" ,
1277
+ " A boolean was expected" ,
1278
+ " An array was expected" ,
1279
+ " Unknown failure" ,
1280
+ " An exception is pending" ,
1281
+ " The async work item was cancelled" ,
1282
+ " napi_escape_handle already called on scope" ,
1283
+ " Invalid handle scope usage" ,
1284
+ " Invalid callback scope usage" ,
1285
+ " Thread-safe function queue is full" ,
1286
+ " Thread-safe function handle is closing"
1287
+ };
1288
+
1289
+ static inline napi_status napi_clear_last_error (napi_env env) {
1290
+ env->last_error .error_code = napi_ok;
1291
+
1292
+ // TODO(boingoing): Should this be a callback?
1293
+ env->last_error .engine_error_code = 0 ;
1294
+ env->last_error .engine_reserved = nullptr ;
1295
+ return napi_ok;
1296
+ }
1297
+
1298
+ static inline
1299
+ napi_status napi_set_last_error (napi_env env, napi_status error_code,
1300
+ uint32_t engine_error_code,
1301
+ void * engine_reserved) {
1302
+ env->last_error .error_code = error_code;
1303
+ env->last_error .engine_error_code = engine_error_code;
1304
+ env->last_error .engine_reserved = engine_reserved;
1305
+ return error_code;
1306
+ }
1307
+
1308
+ napi_status napi_get_last_error_info (napi_env env,
1309
+ const napi_extended_error_info** result) {
1310
+ CHECK_ENV (env);
1311
+ CHECK_ARG (env, result);
1312
+
1313
+ // you must update this assert to reference the last message
1314
+ // in the napi_status enum each time a new error message is added.
1315
+ // We don't have a napi_status_last as this would result in an ABI
1316
+ // change each time a message was added.
1317
+ static_assert (
1318
+ node::arraysize (error_messages) == napi_closing + 1 ,
1319
+ " Count of error messages must match count of error values" );
1320
+ CHECK_LE (env->last_error .error_code , napi_callback_scope_mismatch);
1321
+
1322
+ // Wait until someone requests the last error information to fetch the error
1323
+ // message string
1324
+ env->last_error .error_message =
1325
+ error_messages[env->last_error .error_code ];
1326
+
1327
+ *result = &(env->last_error );
1328
+ return napi_ok;
1329
+ }
1330
+
1331
+ napi_status napi_fatal_exception (napi_env env, napi_value err) {
1332
+ NAPI_PREAMBLE (env);
1333
+ CHECK_ARG (env, err);
1334
+
1335
+ v8::Local<v8::Value> local_err = v8impl::V8LocalValueFromJsValue (err);
1336
+ v8impl::trigger_fatal_exception (env, local_err);
1337
+
1338
+ return napi_clear_last_error (env);
1339
+ }
1340
+
1341
+ NAPI_NO_RETURN void napi_fatal_error (const char * location,
1342
+ size_t location_len,
1343
+ const char * message,
1344
+ size_t message_len) {
1345
+ std::string location_string;
1346
+ std::string message_string;
1347
+
1348
+ if (location_len != NAPI_AUTO_LENGTH) {
1349
+ location_string.assign (
1350
+ const_cast <char *>(location), location_len);
1351
+ } else {
1352
+ location_string.assign (
1353
+ const_cast <char *>(location), strlen (location));
1354
+ }
1355
+
1356
+ if (message_len != NAPI_AUTO_LENGTH) {
1357
+ message_string.assign (
1358
+ const_cast <char *>(message), message_len);
1359
+ } else {
1360
+ message_string.assign (
1361
+ const_cast <char *>(message), strlen (message));
1362
+ }
1363
+
1364
+ node::FatalError (location_string.c_str (), message_string.c_str ());
1365
+ }
1033
1366
1034
1367
napi_status napi_create_function (napi_env env,
1035
1368
const char * utf8name,
@@ -3473,456 +3806,126 @@ napi_status napi_create_async_work(napi_env env,
3473
3806
*result = reinterpret_cast <napi_async_work>(work);
3474
3807
3475
3808
return napi_clear_last_error (env);
3476
- }
3477
-
3478
- napi_status napi_delete_async_work (napi_env env, napi_async_work work) {
3479
- CHECK_ENV (env);
3480
- CHECK_ARG (env, work);
3481
-
3482
- uvimpl::Work::Delete (reinterpret_cast <uvimpl::Work*>(work));
3483
-
3484
- return napi_clear_last_error (env);
3485
- }
3486
-
3487
- napi_status napi_get_uv_event_loop (napi_env env, uv_loop_t ** loop) {
3488
- CHECK_ENV (env);
3489
- CHECK_ARG (env, loop);
3490
- *loop = env->loop ;
3491
- return napi_clear_last_error (env);
3492
- }
3493
-
3494
- napi_status napi_queue_async_work (napi_env env, napi_async_work work) {
3495
- CHECK_ENV (env);
3496
- CHECK_ARG (env, work);
3497
-
3498
- napi_status status;
3499
- uv_loop_t * event_loop = nullptr ;
3500
- status = napi_get_uv_event_loop (env, &event_loop);
3501
- if (status != napi_ok)
3502
- return napi_set_last_error (env, status);
3503
-
3504
- uvimpl::Work* w = reinterpret_cast <uvimpl::Work*>(work);
3505
-
3506
- CALL_UV (env, uv_queue_work (event_loop,
3507
- w->Request (),
3508
- uvimpl::Work::ExecuteCallback,
3509
- uvimpl::Work::CompleteCallback));
3510
-
3511
- return napi_clear_last_error (env);
3512
- }
3513
-
3514
- napi_status napi_cancel_async_work (napi_env env, napi_async_work work) {
3515
- CHECK_ENV (env);
3516
- CHECK_ARG (env, work);
3517
-
3518
- uvimpl::Work* w = reinterpret_cast <uvimpl::Work*>(work);
3519
-
3520
- CALL_UV (env, uv_cancel (reinterpret_cast <uv_req_t *>(w->Request ())));
3521
-
3522
- return napi_clear_last_error (env);
3523
- }
3524
-
3525
- napi_status napi_create_promise (napi_env env,
3526
- napi_deferred* deferred,
3527
- napi_value* promise) {
3528
- NAPI_PREAMBLE (env);
3529
- CHECK_ARG (env, deferred);
3530
- CHECK_ARG (env, promise);
3531
-
3532
- auto maybe = v8::Promise::Resolver::New (env->isolate ->GetCurrentContext ());
3533
- CHECK_MAYBE_EMPTY (env, maybe, napi_generic_failure);
3534
-
3535
- auto v8_resolver = maybe.ToLocalChecked ();
3536
- auto v8_deferred = new v8::Persistent<v8::Value>();
3537
- v8_deferred->Reset (env->isolate , v8_resolver);
3538
-
3539
- *deferred = v8impl::JsDeferredFromV8Persistent (v8_deferred);
3540
- *promise = v8impl::JsValueFromV8LocalValue (v8_resolver->GetPromise ());
3541
- return GET_RETURN_STATUS (env);
3542
- }
3543
-
3544
- napi_status napi_resolve_deferred (napi_env env,
3545
- napi_deferred deferred,
3546
- napi_value resolution) {
3547
- return v8impl::ConcludeDeferred (env, deferred, resolution, true );
3548
- }
3549
-
3550
- napi_status napi_reject_deferred (napi_env env,
3551
- napi_deferred deferred,
3552
- napi_value resolution) {
3553
- return v8impl::ConcludeDeferred (env, deferred, resolution, false );
3554
- }
3555
-
3556
- napi_status napi_is_promise (napi_env env,
3557
- napi_value promise,
3558
- bool * is_promise) {
3559
- CHECK_ENV (env);
3560
- CHECK_ARG (env, promise);
3561
- CHECK_ARG (env, is_promise);
3562
-
3563
- *is_promise = v8impl::V8LocalValueFromJsValue (promise)->IsPromise ();
3564
-
3565
- return napi_clear_last_error (env);
3566
- }
3567
-
3568
- napi_status napi_run_script (napi_env env,
3569
- napi_value script,
3570
- napi_value* result) {
3571
- NAPI_PREAMBLE (env);
3572
- CHECK_ARG (env, script);
3573
- CHECK_ARG (env, result);
3574
-
3575
- v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue (script);
3576
-
3577
- if (!v8_script->IsString ()) {
3578
- return napi_set_last_error (env, napi_string_expected);
3579
- }
3580
-
3581
- v8::Local<v8::Context> context = env->isolate ->GetCurrentContext ();
3582
-
3583
- auto maybe_script = v8::Script::Compile (context,
3584
- v8::Local<v8::String>::Cast (v8_script));
3585
- CHECK_MAYBE_EMPTY (env, maybe_script, napi_generic_failure);
3586
-
3587
- auto script_result =
3588
- maybe_script.ToLocalChecked ()->Run (context);
3589
- CHECK_MAYBE_EMPTY (env, script_result, napi_generic_failure);
3590
-
3591
- *result = v8impl::JsValueFromV8LocalValue (script_result.ToLocalChecked ());
3592
- return GET_RETURN_STATUS (env);
3593
- }
3594
-
3595
- class TsFn : public node ::AsyncResource {
3596
- public:
3597
- TsFn (v8::Local<v8::Function> func,
3598
- v8::Local<v8::Object> resource,
3599
- v8::Local<v8::String> name,
3600
- size_t thread_count_,
3601
- void * context_,
3602
- size_t max_queue_size_,
3603
- napi_env env_,
3604
- void * finalize_data_,
3605
- napi_finalize finalize_cb_,
3606
- napi_threadsafe_function_call_js call_js_cb_):
3607
- AsyncResource (env_->isolate,
3608
- resource,
3609
- *v8::String::Utf8Value (env_->isolate, name)),
3610
- thread_count(thread_count_),
3611
- is_closing(false ),
3612
- context(context_),
3613
- max_queue_size(max_queue_size_),
3614
- env(env_),
3615
- finalize_data(finalize_data_),
3616
- finalize_cb(finalize_cb_),
3617
- call_js_cb(call_js_cb_ == nullptr ? CallJs : call_js_cb_),
3618
- handles_closing(false ) {
3619
- ref.Reset (env->isolate , func);
3620
- node::AddEnvironmentCleanupHook (env->isolate , Cleanup, this );
3621
- }
3622
-
3623
- ~TsFn () {
3624
- node::RemoveEnvironmentCleanupHook (env->isolate , Cleanup, this );
3625
- if (ref.IsEmpty ())
3626
- return ;
3627
- ref.ClearWeak ();
3628
- ref.Reset ();
3629
- }
3630
-
3631
- // These methods can be called from any thread.
3632
-
3633
- napi_status Push (void * data, napi_threadsafe_function_call_mode mode) {
3634
- node::Mutex::ScopedLock lock (this ->mutex );
3635
-
3636
- while (queue.size () >= max_queue_size &&
3637
- max_queue_size > 0 &&
3638
- !is_closing) {
3639
- if (mode == napi_tsfn_nonblocking) {
3640
- return napi_queue_full;
3641
- }
3642
- cond->Wait (lock);
3643
- }
3644
-
3645
- if (is_closing) {
3646
- if (thread_count == 0 ) {
3647
- return napi_invalid_arg;
3648
- } else {
3649
- thread_count--;
3650
- return napi_closing;
3651
- }
3652
- } else {
3653
- if (uv_async_send (&async) != 0 ) {
3654
- return napi_generic_failure;
3655
- }
3656
- queue.push (data);
3657
- return napi_ok;
3658
- }
3659
- }
3660
-
3661
- napi_status Acquire () {
3662
- node::Mutex::ScopedLock lock (this ->mutex );
3663
-
3664
- if (is_closing) {
3665
- return napi_closing;
3666
- }
3667
-
3668
- thread_count++;
3669
-
3670
- return napi_ok;
3671
- }
3672
-
3673
- napi_status Release (napi_threadsafe_function_release_mode mode) {
3674
- node::Mutex::ScopedLock lock (this ->mutex );
3675
-
3676
- if (thread_count == 0 ) {
3677
- return napi_invalid_arg;
3678
- }
3679
-
3680
- thread_count--;
3681
-
3682
- if (thread_count == 0 || mode == napi_tsfn_abort) {
3683
- if (!is_closing) {
3684
- is_closing = (mode == napi_tsfn_abort);
3685
- if (is_closing && max_queue_size > 0 ) {
3686
- cond->Signal (lock);
3687
- }
3688
- if (uv_async_send (&async) != 0 ) {
3689
- return napi_generic_failure;
3690
- }
3691
- }
3692
- }
3693
-
3694
- return napi_ok;
3695
- }
3696
-
3697
- void EmptyQueueAndDelete () {
3698
- for (; !queue.empty () ; queue.pop ()) {
3699
- call_js_cb (nullptr , nullptr , context, queue.front ());
3700
- }
3701
- delete this ;
3702
- }
3703
-
3704
- // These methods must only be called from the loop thread.
3705
-
3706
- napi_status Init () {
3707
- TsFn* ts_fn = this ;
3708
-
3709
- if (uv_async_init (env->loop , &async, AsyncCb) == 0 ) {
3710
- if (max_queue_size > 0 ) {
3711
- cond.reset (new node::ConditionVariable);
3712
- }
3713
- if ((max_queue_size == 0 || cond.get () != nullptr ) &&
3714
- uv_idle_init (env->loop , &idle) == 0 ) {
3715
- return napi_ok;
3716
- }
3809
+ }
3717
3810
3718
- uv_close (reinterpret_cast <uv_handle_t *>(&async),
3719
- [] (uv_handle_t * handle) -> void {
3720
- TsFn* ts_fn =
3721
- node::ContainerOf (&TsFn::async,
3722
- reinterpret_cast <uv_async_t *>(handle));
3723
- delete ts_fn;
3724
- });
3811
+ napi_status napi_delete_async_work (napi_env env, napi_async_work work) {
3812
+ CHECK_ENV (env);
3813
+ CHECK_ARG (env, work);
3725
3814
3726
- // Prevent the thread-safe function from being deleted here, because
3727
- // the callback above will delete it.
3728
- ts_fn = nullptr ;
3729
- }
3815
+ uvimpl::Work::Delete (reinterpret_cast <uvimpl::Work*>(work));
3730
3816
3731
- delete ts_fn;
3817
+ return napi_clear_last_error (env);
3818
+ }
3732
3819
3733
- return napi_generic_failure;
3734
- }
3820
+ napi_status napi_get_uv_event_loop (napi_env env, uv_loop_t ** loop) {
3821
+ CHECK_ENV (env);
3822
+ CHECK_ARG (env, loop);
3823
+ *loop = env->loop ;
3824
+ return napi_clear_last_error (env);
3825
+ }
3735
3826
3736
- napi_status Unref ( ) {
3737
- uv_unref ( reinterpret_cast < uv_handle_t *>(&async) );
3738
- uv_unref ( reinterpret_cast < uv_handle_t *>(&idle) );
3827
+ napi_status napi_queue_async_work (napi_env env, napi_async_work work ) {
3828
+ CHECK_ENV (env );
3829
+ CHECK_ARG (env, work );
3739
3830
3740
- return napi_ok;
3741
- }
3831
+ napi_status status;
3832
+ uv_loop_t * event_loop = nullptr ;
3833
+ status = napi_get_uv_event_loop (env, &event_loop);
3834
+ if (status != napi_ok)
3835
+ return napi_set_last_error (env, status);
3742
3836
3743
- napi_status Ref () {
3744
- uv_ref (reinterpret_cast <uv_handle_t *>(&async));
3745
- uv_ref (reinterpret_cast <uv_handle_t *>(&idle));
3837
+ uvimpl::Work* w = reinterpret_cast <uvimpl::Work*>(work);
3746
3838
3747
- return napi_ok;
3748
- }
3839
+ CALL_UV (env, uv_queue_work (event_loop,
3840
+ w->Request (),
3841
+ uvimpl::Work::ExecuteCallback,
3842
+ uvimpl::Work::CompleteCallback));
3749
3843
3750
- void DispatchOne () {
3751
- void * data = nullptr ;
3752
- bool popped_value = false ;
3753
- bool idle_stop_failed = false ;
3844
+ return napi_clear_last_error (env);
3845
+ }
3754
3846
3755
- {
3756
- node::Mutex::ScopedLock lock (this ->mutex );
3757
- if (is_closing) {
3758
- CloseHandlesAndMaybeDelete ();
3759
- } else {
3760
- size_t size = queue.size ();
3761
- if (size > 0 ) {
3762
- data = queue.front ();
3763
- queue.pop ();
3764
- popped_value = true ;
3765
- if (size == max_queue_size && max_queue_size > 0 ) {
3766
- cond->Signal (lock);
3767
- }
3768
- size--;
3769
- }
3847
+ napi_status napi_cancel_async_work (napi_env env, napi_async_work work) {
3848
+ CHECK_ENV (env);
3849
+ CHECK_ARG (env, work);
3770
3850
3771
- if (size == 0 ) {
3772
- if (thread_count == 0 ) {
3773
- is_closing = true ;
3774
- if (max_queue_size > 0 ) {
3775
- cond->Signal (lock);
3776
- }
3777
- CloseHandlesAndMaybeDelete ();
3778
- } else {
3779
- if (uv_idle_stop (&idle) != 0 ) {
3780
- idle_stop_failed = true ;
3781
- }
3782
- }
3783
- }
3784
- }
3785
- }
3851
+ uvimpl::Work* w = reinterpret_cast <uvimpl::Work*>(work);
3786
3852
3787
- if (popped_value || idle_stop_failed) {
3788
- v8::HandleScope scope (env->isolate );
3789
- CallbackScope cb_scope (this );
3853
+ CALL_UV (env, uv_cancel (reinterpret_cast <uv_req_t *>(w->Request ())));
3790
3854
3791
- if (idle_stop_failed) {
3792
- CHECK (napi_throw_error (env,
3793
- " ERR_NAPI_TSFN_STOP_IDLE_LOOP" ,
3794
- " Failed to stop the idle loop" ) == napi_ok);
3795
- } else {
3796
- v8::Local<v8::Function> js_cb =
3797
- v8::Local<v8::Function>::New (env->isolate , ref);
3798
- call_js_cb (env,
3799
- v8impl::JsValueFromV8LocalValue (js_cb),
3800
- context,
3801
- data);
3802
- }
3803
- }
3804
- }
3855
+ return napi_clear_last_error (env);
3856
+ }
3805
3857
3806
- node::Environment* NodeEnv () {
3807
- // For some reason grabbing the Node.js environment requires a handle scope.
3808
- v8::HandleScope scope (env->isolate );
3809
- return node::Environment::GetCurrent (env->isolate );
3810
- }
3858
+ napi_status napi_create_promise (napi_env env,
3859
+ napi_deferred* deferred,
3860
+ napi_value* promise) {
3861
+ NAPI_PREAMBLE (env);
3862
+ CHECK_ARG (env, deferred);
3863
+ CHECK_ARG (env, promise);
3811
3864
3812
- void MaybeStartIdle () {
3813
- if (uv_idle_start (&idle, IdleCb) != 0 ) {
3814
- v8::HandleScope scope (env->isolate );
3815
- CallbackScope cb_scope (this );
3816
- CHECK (napi_throw_error (env,
3817
- " ERR_NAPI_TSFN_START_IDLE_LOOP" ,
3818
- " Failed to start the idle loop" ) == napi_ok);
3819
- }
3820
- }
3865
+ auto maybe = v8::Promise::Resolver::New (env->isolate ->GetCurrentContext ());
3866
+ CHECK_MAYBE_EMPTY (env, maybe, napi_generic_failure);
3821
3867
3822
- void Finalize () {
3823
- v8::HandleScope scope (env->isolate );
3824
- if (finalize_cb) {
3825
- CallbackScope cb_scope (this );
3826
- finalize_cb (env, finalize_data, context);
3827
- }
3828
- EmptyQueueAndDelete ();
3829
- }
3868
+ auto v8_resolver = maybe.ToLocalChecked ();
3869
+ auto v8_deferred = new v8::Persistent<v8::Value>();
3870
+ v8_deferred->Reset (env->isolate , v8_resolver);
3830
3871
3831
- inline void * Context () {
3832
- return context;
3833
- }
3872
+ *deferred = v8impl::JsDeferredFromV8Persistent (v8_deferred);
3873
+ *promise = v8impl::JsValueFromV8LocalValue (v8_resolver->GetPromise ());
3874
+ return GET_RETURN_STATUS (env);
3875
+ }
3834
3876
3835
- void CloseHandlesAndMaybeDelete (bool set_closing = false ) {
3836
- if (set_closing) {
3837
- node::Mutex::ScopedLock lock (this ->mutex );
3838
- is_closing = true ;
3839
- if (max_queue_size > 0 ) {
3840
- cond->Signal (lock);
3841
- }
3842
- }
3843
- if (handles_closing) {
3844
- return ;
3845
- }
3846
- handles_closing = true ;
3847
- uv_close (
3848
- reinterpret_cast <uv_handle_t *>(&async),
3849
- [] (uv_handle_t * handle) -> void {
3850
- TsFn* ts_fn = node::ContainerOf (&TsFn::async,
3851
- reinterpret_cast <uv_async_t *>(handle));
3852
- uv_close (
3853
- reinterpret_cast <uv_handle_t *>(&ts_fn->idle ),
3854
- [] (uv_handle_t * handle) -> void {
3855
- TsFn* ts_fn = node::ContainerOf (&TsFn::idle,
3856
- reinterpret_cast <uv_idle_t *>(handle));
3857
- ts_fn->Finalize ();
3858
- });
3859
- });
3860
- }
3877
+ napi_status napi_resolve_deferred (napi_env env,
3878
+ napi_deferred deferred,
3879
+ napi_value resolution) {
3880
+ return v8impl::ConcludeDeferred (env, deferred, resolution, true );
3881
+ }
3861
3882
3862
- // Default way of calling into JavaScript. Used when TsFn is constructed
3863
- // without a call_js_cb_.
3864
- static void CallJs (napi_env env, napi_value cb, void * context, void * data) {
3865
- if (!(env == nullptr || cb == nullptr )) {
3866
- napi_value recv;
3867
- napi_status status;
3883
+ napi_status napi_reject_deferred (napi_env env,
3884
+ napi_deferred deferred,
3885
+ napi_value resolution) {
3886
+ return v8impl::ConcludeDeferred (env, deferred, resolution, false );
3887
+ }
3868
3888
3869
- status = napi_get_undefined ( env, &recv);
3870
- if (status != napi_ok) {
3871
- napi_throw_error (env, " ERR_NAPI_TSFN_GET_UNDEFINED " ,
3872
- " Failed to retrieve undefined value " );
3873
- return ;
3874
- }
3889
+ napi_status napi_is_promise (napi_env env,
3890
+ napi_value promise,
3891
+ bool * is_promise) {
3892
+ CHECK_ENV (env );
3893
+ CHECK_ARG (env, promise) ;
3894
+ CHECK_ARG (env, is_promise);
3875
3895
3876
- status = napi_call_function (env, recv, cb, 0 , nullptr , nullptr );
3877
- if (status != napi_ok && status != napi_pending_exception) {
3878
- napi_throw_error (env, " ERR_NAPI_TSFN_CALL_JS" ,
3879
- " Failed to call JS callback" );
3880
- return ;
3881
- }
3882
- }
3883
- }
3896
+ *is_promise = v8impl::V8LocalValueFromJsValue (promise)->IsPromise ();
3884
3897
3885
- static void IdleCb (uv_idle_t * idle) {
3886
- TsFn* ts_fn =
3887
- node::ContainerOf (&TsFn::idle, idle);
3888
- ts_fn->DispatchOne ();
3889
- }
3898
+ return napi_clear_last_error (env);
3899
+ }
3890
3900
3891
- static void AsyncCb (uv_async_t * async) {
3892
- TsFn* ts_fn =
3893
- node::ContainerOf (&TsFn::async, async);
3894
- ts_fn->MaybeStartIdle ();
3895
- }
3901
+ napi_status napi_run_script (napi_env env,
3902
+ napi_value script,
3903
+ napi_value* result) {
3904
+ NAPI_PREAMBLE (env);
3905
+ CHECK_ARG (env, script);
3906
+ CHECK_ARG (env, result);
3896
3907
3897
- static void Cleanup (void * data) {
3898
- reinterpret_cast <TsFn*>(data)->CloseHandlesAndMaybeDelete (true );
3908
+ v8::Local<v8::Value> v8_script = v8impl::V8LocalValueFromJsValue (script);
3909
+
3910
+ if (!v8_script->IsString ()) {
3911
+ return napi_set_last_error (env, napi_string_expected);
3899
3912
}
3900
3913
3901
- private:
3902
- // These are variables protected by the mutex.
3903
- node::Mutex mutex;
3904
- std::unique_ptr<node::ConditionVariable> cond;
3905
- std::queue<void *> queue;
3906
- uv_async_t async;
3907
- uv_idle_t idle;
3908
- size_t thread_count;
3909
- bool is_closing;
3914
+ v8::Local<v8::Context> context = env->isolate ->GetCurrentContext ();
3910
3915
3911
- // These are variables set once, upon creation, and then never again, which
3912
- // means we don't need the mutex to read them.
3913
- void * context;
3914
- size_t max_queue_size;
3916
+ auto maybe_script = v8::Script::Compile (context,
3917
+ v8::Local<v8::String>::Cast (v8_script));
3918
+ CHECK_MAYBE_EMPTY (env, maybe_script, napi_generic_failure);
3915
3919
3916
- // These are variables accessed only from the loop thread.
3917
- v8::Persistent<v8::Function> ref;
3918
- napi_env env;
3919
- void * finalize_data;
3920
- napi_finalize finalize_cb;
3921
- napi_threadsafe_function_call_js call_js_cb;
3922
- bool handles_closing;
3923
- };
3920
+ auto script_result =
3921
+ maybe_script.ToLocalChecked ()->Run (context);
3922
+ CHECK_MAYBE_EMPTY (env, script_result, napi_generic_failure);
3923
+
3924
+ *result = v8impl::JsValueFromV8LocalValue (script_result.ToLocalChecked ());
3925
+ return GET_RETURN_STATUS (env);
3926
+ }
3924
3927
3925
- NAPI_EXTERN napi_status
3928
+ napi_status
3926
3929
napi_create_threadsafe_function (napi_env env,
3927
3930
napi_value func,
3928
3931
napi_value async_resource,
@@ -3957,16 +3960,17 @@ napi_create_threadsafe_function(napi_env env,
3957
3960
v8::Local<v8::String> v8_name;
3958
3961
CHECK_TO_STRING (env, v8_context, v8_name, async_resource_name);
3959
3962
3960
- TsFn* ts_fn = new TsFn (v8_func,
3961
- v8_resource,
3962
- v8_name,
3963
- initial_thread_count,
3964
- context,
3965
- max_queue_size,
3966
- env,
3967
- thread_finalize_data,
3968
- thread_finalize_cb,
3969
- call_js_cb);
3963
+ v8impl::ThreadSafeFunction* ts_fn =
3964
+ new v8impl::ThreadSafeFunction (v8_func,
3965
+ v8_resource,
3966
+ v8_name,
3967
+ initial_thread_count,
3968
+ context,
3969
+ max_queue_size,
3970
+ env,
3971
+ thread_finalize_data,
3972
+ thread_finalize_cb,
3973
+ call_js_cb);
3970
3974
3971
3975
if (ts_fn == nullptr ) {
3972
3976
status = napi_generic_failure;
@@ -3981,45 +3985,46 @@ napi_create_threadsafe_function(napi_env env,
3981
3985
return napi_set_last_error (env, status);
3982
3986
}
3983
3987
3984
- NAPI_EXTERN napi_status
3988
+ napi_status
3985
3989
napi_get_threadsafe_function_context (napi_threadsafe_function func,
3986
3990
void ** result) {
3987
3991
CHECK (func != nullptr );
3988
3992
CHECK (result != nullptr );
3989
3993
3990
- *result = reinterpret_cast <TsFn *>(func)->Context ();
3994
+ *result = reinterpret_cast <v8impl::ThreadSafeFunction *>(func)->Context ();
3991
3995
return napi_ok;
3992
3996
}
3993
3997
3994
- NAPI_EXTERN napi_status
3998
+ napi_status
3995
3999
napi_call_threadsafe_function (napi_threadsafe_function func,
3996
4000
void * data,
3997
4001
napi_threadsafe_function_call_mode is_blocking) {
3998
4002
CHECK (func != nullptr );
3999
- return reinterpret_cast <TsFn*>(func)->Push (data, is_blocking);
4003
+ return reinterpret_cast <v8impl::ThreadSafeFunction*>(func)->Push (data,
4004
+ is_blocking);
4000
4005
}
4001
4006
4002
- NAPI_EXTERN napi_status
4007
+ napi_status
4003
4008
napi_acquire_threadsafe_function (napi_threadsafe_function func) {
4004
4009
CHECK (func != nullptr );
4005
- return reinterpret_cast <TsFn *>(func)->Acquire ();
4010
+ return reinterpret_cast <v8impl::ThreadSafeFunction *>(func)->Acquire ();
4006
4011
}
4007
4012
4008
- NAPI_EXTERN napi_status
4013
+ napi_status
4009
4014
napi_release_threadsafe_function (napi_threadsafe_function func,
4010
4015
napi_threadsafe_function_release_mode mode) {
4011
4016
CHECK (func != nullptr );
4012
- return reinterpret_cast <TsFn *>(func)->Release (mode);
4017
+ return reinterpret_cast <v8impl::ThreadSafeFunction *>(func)->Release (mode);
4013
4018
}
4014
4019
4015
- NAPI_EXTERN napi_status
4020
+ napi_status
4016
4021
napi_unref_threadsafe_function (napi_env env, napi_threadsafe_function func) {
4017
4022
CHECK (func != nullptr );
4018
- return reinterpret_cast <TsFn *>(func)->Unref ();
4023
+ return reinterpret_cast <v8impl::ThreadSafeFunction *>(func)->Unref ();
4019
4024
}
4020
4025
4021
- NAPI_EXTERN napi_status
4026
+ napi_status
4022
4027
napi_ref_threadsafe_function (napi_env env, napi_threadsafe_function func) {
4023
4028
CHECK (func != nullptr );
4024
- return reinterpret_cast <TsFn *>(func)->Ref ();
4029
+ return reinterpret_cast <v8impl::ThreadSafeFunction *>(func)->Ref ();
4025
4030
}
0 commit comments