@@ -176,32 +176,40 @@ Napi::Value ClockGetNow(const Napi::CallbackInfo& info) {
176176}
177177
178178struct JumpCallbackData {
179- Napi::ObjectReference ref;
179+ Napi::ThreadSafeFunction tsfn_pre;
180+ Napi::ThreadSafeFunction tsfn_post;
181+ };
182+
183+ struct JumpCallbackContext {
184+ rcl_time_jump_t time_jump;
185+ bool before_jump;
180186};
181187
182188void _rclnodejs_on_time_jump (const rcl_time_jump_t * time_jump, bool before_jump,
183189 void * user_data) {
184190 JumpCallbackData* data = static_cast <JumpCallbackData*>(user_data);
185- Napi::Env env = data->ref .Env ();
186- Napi::HandleScope scope (env);
187191
188- Napi::Object callback_obj = data-> ref . Value () ;
192+ auto context = new JumpCallbackContext{*time_jump, before_jump} ;
189193
190194 if (before_jump) {
191- Napi::Value pre_callback = callback_obj.Get (" _pre_callback" );
192- if (pre_callback.IsFunction ()) {
193- pre_callback.As <Napi::Function>().Call (callback_obj, {});
194- }
195+ auto callback = [](Napi::Env env, Napi::Function js_callback,
196+ JumpCallbackContext* context) {
197+ js_callback.Call ({});
198+ delete context;
199+ };
200+ data->tsfn_pre .NonBlockingCall (context, callback);
195201 } else {
196- Napi::Value post_callback = callback_obj. Get ( " _post_callback " );
197- if (post_callback. IsFunction () ) {
202+ auto callback = []( Napi::Env env, Napi::Function js_callback,
203+ JumpCallbackContext* context ) {
198204 Napi::Object jump_info = Napi::Object::New (env);
199205 jump_info.Set (" clock_change" ,
200- static_cast <int32_t >(time_jump->clock_change ));
201- jump_info.Set (" delta" ,
202- Napi::BigInt::New (env, time_jump->delta .nanoseconds ));
203- post_callback.As <Napi::Function>().Call (callback_obj, {jump_info});
204- }
206+ static_cast <int32_t >(context->time_jump .clock_change ));
207+ jump_info.Set (" delta" , Napi::BigInt::New (
208+ env, context->time_jump .delta .nanoseconds ));
209+ js_callback.Call ({jump_info});
210+ delete context;
211+ };
212+ data->tsfn_post .NonBlockingCall (context, callback);
205213 }
206214}
207215
@@ -212,31 +220,56 @@ Napi::Value ClockAddJumpCallback(const Napi::CallbackInfo& info) {
212220 rcl_clock_t * clock = reinterpret_cast <rcl_clock_t *>(clock_handle->ptr ());
213221
214222 Napi::Object callback_obj = info[1 ].As <Napi::Object>();
223+ Napi::Function pre_callback =
224+ callback_obj.Get (" _pre_callback" ).As <Napi::Function>();
225+ Napi::Function post_callback =
226+ callback_obj.Get (" _post_callback" ).As <Napi::Function>();
227+
215228 bool on_clock_change = info[2 ].As <Napi::Boolean>();
216229
217230 bool lossless;
218231 int64_t min_forward = info[3 ].As <Napi::BigInt>().Int64Value (&lossless);
232+ if (!lossless) {
233+ Napi::TypeError::New (
234+ env, " min_forward BigInt value cannot be represented as int64_t" )
235+ .ThrowAsJavaScriptException ();
236+ return env.Undefined ();
237+ }
219238 int64_t min_backward = info[4 ].As <Napi::BigInt>().Int64Value (&lossless);
239+ if (!lossless) {
240+ Napi::TypeError::New (
241+ env, " min_backward BigInt value cannot be represented as int64_t" )
242+ .ThrowAsJavaScriptException ();
243+ return env.Undefined ();
244+ }
220245
221246 rcl_jump_threshold_t threshold;
222247 threshold.on_clock_change = on_clock_change;
223248 threshold.min_forward .nanoseconds = min_forward;
224249 threshold.min_backward .nanoseconds = min_backward;
225250
226- JumpCallbackData* data = new JumpCallbackData{Napi::Persistent (callback_obj)};
227- callback_obj.Set (" _cpp_handle" ,
228- Napi::External<JumpCallbackData>::New (env, data));
251+ JumpCallbackData* data = new JumpCallbackData ();
252+ data->tsfn_pre = Napi::ThreadSafeFunction::New (
253+ env, pre_callback, " ClockJumpPreCallback" , 10 , 1 , [](Napi::Env) {});
254+ data->tsfn_post =
255+ Napi::ThreadSafeFunction::New (env, post_callback, " ClockJumpPostCallback" ,
256+ 10 , 1 , [data](Napi::Env) { delete data; });
257+
258+ Napi::Object handle_obj = Napi::Object::New (env);
259+ handle_obj.Set (" _cpp_handle" ,
260+ Napi::External<JumpCallbackData>::New (env, data));
229261
230262 rcl_ret_t ret = rcl_clock_add_jump_callback (clock, threshold,
231263 _rclnodejs_on_time_jump, data);
232264
233265 if (ret != RCL_RET_OK ) {
234- data->ref .Reset ();
235- delete data;
236- callback_obj.Set (" _cpp_handle" , env.Undefined ());
266+ data->tsfn_pre .Release ();
267+ data->tsfn_post .Release ();
237268 THROW_ERROR_IF_NOT_EQUAL (RCL_RET_OK , ret, rcl_get_error_string ().str );
238269 }
239270
271+ callback_obj.Set (" _cpp_handle" , handle_obj.Get (" _cpp_handle" ));
272+
240273 return env.Undefined ();
241274}
242275
@@ -246,8 +279,8 @@ Napi::Value ClockRemoveJumpCallback(const Napi::CallbackInfo& info) {
246279 RclHandle* clock_handle = RclHandle::Unwrap (info[0 ].As <Napi::Object>());
247280 rcl_clock_t * clock = reinterpret_cast <rcl_clock_t *>(clock_handle->ptr ());
248281
249- Napi::Object callback_obj = info[1 ].As <Napi::Object>();
250- Napi::Value cpp_handle = callback_obj .Get (" _cpp_handle" );
282+ Napi::Object handle_obj = info[1 ].As <Napi::Object>();
283+ Napi::Value cpp_handle = handle_obj .Get (" _cpp_handle" );
251284
252285 if (cpp_handle.IsUndefined () || !cpp_handle.IsExternal ()) {
253286 Napi::Error::New (env,
@@ -263,9 +296,9 @@ Napi::Value ClockRemoveJumpCallback(const Napi::CallbackInfo& info) {
263296 rcl_clock_remove_jump_callback (clock, _rclnodejs_on_time_jump, data);
264297
265298 if (ret == RCL_RET_OK ) {
266- data->ref . Reset ();
267- delete data;
268- callback_obj .Set (" _cpp_handle" , env.Undefined ());
299+ data->tsfn_pre . Release ();
300+ data-> tsfn_post . Release () ;
301+ handle_obj .Set (" _cpp_handle" , env.Undefined ());
269302 } else {
270303 THROW_ERROR_IF_NOT_EQUAL (RCL_RET_OK , ret, rcl_get_error_string ().str );
271304 }
0 commit comments