Skip to content

Add timer autostart and TimerInfo callback support#1472

Merged
minggangw merged 2 commits into
RobotWebTools:developfrom
minggangw:fix-1471
Apr 3, 2026
Merged

Add timer autostart and TimerInfo callback support#1472
minggangw merged 2 commits into
RobotWebTools:developfrom
minggangw:fix-1471

Conversation

@minggangw

Copy link
Copy Markdown
Member
  • extend Node.createTimer() to accept { autostart?: boolean } while preserving existing call signatures
  • inject TimerInfo metadata into JS timer callbacks when native support is available, exposing expectedCallTime and actualCallTime
  • wire native timer creation to honor autostart, with a compatible fallback for older ROS distros
  • update timer typings for TimerInfo, TimerOptions, and the optional callback argument
  • add runtime and type tests covering autostart: false, callback metadata, and option validation
  • refresh timer API comments to match the new behavior

Fix: #1471

Copilot AI review requested due to automatic review settings April 3, 2026 02:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the timer API to support delayed start (autostart: false) and to optionally provide timer call metadata (TimerInfo) to JS callbacks when the underlying ROS 2 distro exposes rcl_timer_call_with_info, while keeping backward compatibility for older distros.

Changes:

  • Extend Node.createTimer() to accept an options object (currently { autostart?: boolean }) while preserving the existing “pass a Clock as the 3rd arg” signature.
  • When supported by the native layer, call timers via callTimerWithInfo() and pass { expectedCallTime, actualCallTime } into the timer callback.
  • Update TypeScript typings and add runtime + type tests covering autostart: false, TimerInfo callback injection, and options validation.

Reviewed changes

Copilot reviewed 5 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
types/timer.d.ts Tighten callTimerWithInfo() return type to TimerInfo and update doc comment.
types/node.d.ts Add TimerInfo/TimerOptions, update timer callback type, and extend createTimer signature/docs.
test/types/index.test-d.ts Type-level coverage for TimerInfo callback param and autostart: false options usage.
test/test-timer.js Runtime tests for autostart: false, callback TimerInfo delivery, and option type validation.
src/rcl_timer_bindings.cpp Native support for autostart (using rcl_timer_init2 when available, otherwise init+cancel).
lib/timer.js JSDoc update for callTimerWithInfo() return shape.
lib/node.js Implement options/clock argument parsing for createTimer + inject TimerInfo into callbacks when supported.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@coveralls

coveralls commented Apr 3, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 85.327% (+0.02%) from 85.304%
when pulling 602f5a0 on minggangw:fix-1471
into 5b88d78 on RobotWebTools:develop.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 7 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

lib/timer.js:163

  • The JSDoc return type for callTimerWithInfo() claims it returns a TimerInfo-shaped object, but on Humble and earlier this method warns and returns undefined. Update the JSDoc to reflect the actual return type (e.g., include undefined) so generated docs and editors don’t mislead users.
  /**
   * Call a timer and starts counting again, retrieves actual and expected call time.
   * @return {{expectedCallTime: bigint, actualCallTime: bigint}} - The timer information.
   */
  callTimerWithInfo() {
    if (DistroUtils.getDistroId() <= DistroUtils.getDistroId('humble')) {
      console.warn(
        'callTimerWithInfo is not supported by this version of ROS 2'
      );
      return;
    }
    return rclnodejs.callTimerWithInfo(this._handle);
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/node.js Outdated
Comment on lines +259 to +265
let timerInfo;
if (typeof rclnodejs.callTimerWithInfo === 'function') {
timerInfo = rclnodejs.callTimerWithInfo(timer.handle);
} else {
rclnodejs.callTimer(timer.handle);
}
timer.callback(timerInfo);

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node.execute() now always calls timer.callback(timerInfo) even when timerInfo is undefined (i.e., when callTimerWithInfo is unavailable). That changes observable callback behavior: arguments.length becomes 1 instead of 0, which can break user callbacks that branch on arity. To preserve the existing callback contract, only pass the TimerInfo argument when it is actually available; otherwise invoke the callback with no arguments.

Suggested change
let timerInfo;
if (typeof rclnodejs.callTimerWithInfo === 'function') {
timerInfo = rclnodejs.callTimerWithInfo(timer.handle);
} else {
rclnodejs.callTimer(timer.handle);
}
timer.callback(timerInfo);
if (typeof rclnodejs.callTimerWithInfo === 'function') {
let timerInfo = rclnodejs.callTimerWithInfo(timer.handle);
timer.callback(timerInfo);
} else {
rclnodejs.callTimer(timer.handle);
timer.callback();
}

Copilot uses AI. Check for mistakes.
Comment thread src/rcl_timer_bindings.cpp Outdated
bool lossless;
int64_t period_nsec = info[2].As<Napi::BigInt>().Int64Value(&lossless);
bool autostart = true;
if (info.Length() > 3 && info[3].IsBoolean()) {

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Native CreateTimer silently ignores a non-boolean 4th argument and falls back to autostart = true. Since the JS layer can’t prevent direct calls to rclnodejs.createTimer, it would be safer and more consistent to throw a TypeError when a 4th argument is provided but is not a boolean, rather than silently changing behavior.

Suggested change
if (info.Length() > 3 && info[3].IsBoolean()) {
if (info.Length() > 3) {
if (!info[3].IsBoolean()) {
Napi::TypeError::New(env, "Timer autostart must be a boolean")
.ThrowAsJavaScriptException();
return env.Undefined();
}

Copilot uses AI. Check for mistakes.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 7 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

lib/timer.js:163

  • The JSDoc for Timer.callTimerWithInfo() claims it returns an object with timestamps, but the method returns undefined on Humble and earlier (return; after warning). Please update the @return annotation to include undefined and ideally note the distro gating, so docs match runtime behavior.
  /**
   * Call a timer and starts counting again, retrieves actual and expected call time.
   * @return {{expectedCallTime: bigint, actualCallTime: bigint}} - The timer information.
   */
  callTimerWithInfo() {
    if (DistroUtils.getDistroId() <= DistroUtils.getDistroId('humble')) {
      console.warn(
        'callTimerWithInfo is not supported by this version of ROS 2'
      );
      return;
    }
    return rclnodejs.callTimerWithInfo(this._handle);
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@minggangw minggangw merged commit 601a6a1 into RobotWebTools:develop Apr 3, 2026
20 checks passed
minggangw added a commit that referenced this pull request Apr 3, 2026
- extend `Node.createTimer()` to accept `{ autostart?: boolean }` while preserving existing call signatures
- inject `TimerInfo` metadata into JS timer callbacks when native support is available, exposing `expectedCallTime` and `actualCallTime`
- wire native timer creation to honor `autostart`, with a compatible fallback for older ROS distros
- update timer typings for `TimerInfo`, `TimerOptions`, and the optional callback argument
- add runtime and type tests covering `autostart: false`, callback metadata, and option validation
- refresh timer API comments to match the new behavior

Fix: #1471
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add timer autostart and TimerInfo callback support

3 participants