Skip to content
Merged
8 changes: 8 additions & 0 deletions lib/subscription.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ class Subscription extends Entity {
return this._serializationMode;
}

/**
* Check if content filtering is supported for this subscription.
* @returns {boolean} True if the subscription instance supports content filtering; otherwise false.
*/
isContentFilterSupported() {
return rclnodejs.isContentFilterSupported(this.handle);
}

/**
* Test if the RMW supports content-filtered topics and that this subscription
* has an active wellformed content-filter.
Expand Down
3 changes: 1 addition & 2 deletions rosidl_parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@ def get_json_object_from_msg_spec_object(msg_spec_object):

if __name__ == '__main__':
if len(sys.argv) < 4:
print('Usage: {} <command> <packageName> <filePath>'.format(sys.argv[0]), file=sys.stderr)
print('Wrong number of argments')

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

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

The argument-count check regresses error reporting: it now prints a generic message to stdout and drops the detailed usage message (previously printed to stderr). This makes failures from rosidl_parser/rosidl_parser.js much harder to diagnose because the Node-side error includes stderr was: ... and will now often be empty. Consider restoring the original Usage: <command> <packageName> <filePath> message and printing it to stderr.

Suggested change
print('Wrong number of argments')
print(f'Usage: {sys.argv[0]} <command> <packageName> <filePath>', file=sys.stderr)

Copilot uses AI. Check for mistakes.

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

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

Typo in the error message: "argments" should be "arguments".

Suggested change
print('Wrong number of argments')
print('Wrong number of arguments')

Copilot uses AI. Check for mistakes.
sys.exit(1)
Comment on lines 49 to 51

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

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

This change in rosidl_parser/parser.py (updating the CLI arg-count error message) doesn’t appear related to the PR’s stated goal of adding a subscription content-filter support check. If it’s not required for the feature, consider reverting it or splitting it into a separate PR to keep changes focused.

Copilot uses AI. Check for mistakes.
try:
parser_method = getattr(parser, sys.argv[1])
spec = parser_method(sys.argv[2], sys.argv[3])

if sys.argv[1] == 'parse_message_file':
json_obj = get_json_object_from_msg_spec_object(spec)
elif sys.argv[1] == 'parse_service_file':
Expand Down
14 changes: 14 additions & 0 deletions src/rcl_subscription_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,18 @@ Napi::Value GetSubscriptionTopic(const Napi::CallbackInfo& info) {
return Napi::String::New(env, topic);
}

Napi::Value IsContentFilterSupported(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();

RclHandle* subscription_handle =
RclHandle::Unwrap(info[0].As<Napi::Object>());
rcl_subscription_t* subscription =
reinterpret_cast<rcl_subscription_t*>(subscription_handle->ptr());

bool is_supported = rcl_subscription_is_cft_supported(subscription);
return Napi::Boolean::New(env, is_supported);
}

Napi::Value HasContentFilter(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();

Expand Down Expand Up @@ -476,6 +488,8 @@ Napi::Object InitSubscriptionBindings(Napi::Env env, Napi::Object exports) {
exports.Set("rclTakeRaw", Napi::Function::New(env, RclTakeRaw));
exports.Set("getSubscriptionTopic",
Napi::Function::New(env, GetSubscriptionTopic));
exports.Set("isContentFilterSupported",
Napi::Function::New(env, IsContentFilterSupported));
exports.Set("hasContentFilter", Napi::Function::New(env, HasContentFilter));
exports.Set("setContentFilter", Napi::Function::New(env, SetContentFilter));
exports.Set("getContentFilter", Napi::Function::New(env, GetContentFilter));
Expand Down
32 changes: 32 additions & 0 deletions test/test-subscription-content-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -480,3 +480,35 @@ describe('subscription content-filtering', function () {
done();
});
});

describe('subscription isContentFilterSupported', function () {
this.timeout(30 * 1000);

beforeEach(async function () {
await rclnodejs.init();
this.node = new Node('cft_support_test_node');
});

afterEach(function () {
this.node.destroy();
rclnodejs.shutdown();
});

it('isContentFilterSupported returns boolean matching RMW capability', function (done) {
const typeclass = 'std_msgs/msg/Int16';
const subscription = this.node.createSubscription(
typeclass,
TOPIC,
(msg) => {}
);

const supported = subscription.isContentFilterSupported();
assert.strictEqual(typeof supported, 'boolean');

// Validate against known RMW capabilities
const expectedSupported = isContentFilteringSupported();
assert.strictEqual(supported, expectedSupported);

done();
});
});
1 change: 1 addition & 0 deletions test/types/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ expectType<rclnodejs.SubscriptionWithRawMessageCallback>(rawMessageCallback);

expectType<string>(subscription.topic);
expectType<boolean>(subscription.isDestroyed());
expectType<boolean>(subscription.isContentFilterSupported());
expectType<boolean>(subscription.setContentFilter(contentFilter));
expectType<rclnodejs.SubscriptionContentFilter | undefined>(
subscription.getContentFilter()
Expand Down
6 changes: 6 additions & 0 deletions types/subscription.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ declare module 'rclnodejs' {
*/
readonly isRaw: boolean;

/**
* Check if content filtering is supported for this subscription.
* @returns True if the subscription instance supports content filtering; otherwise false.
*/
isContentFilterSupported(): boolean;

/**
* Test if the RMW supports content-filtered topics and that this subscription
* is configured with a well formed content-filter.
Expand Down
Loading