Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ let rcl = {
throw new TypeError('argv elements must be strings (and not null).');
}

rclnodejs.init(context.handle, argv);
rclnodejs.init(context.handle, argv, context._domainId);

if (_rosVersionChecked) {
// no further processing required
Expand Down
6 changes: 4 additions & 2 deletions lib/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ class Context {
* Call rcl.init(context) to initialize this context state for
* use in creating nodes, etc.
* @constructor
* @param {bigint} - Optional, The domain ID of this context.
*/
constructor() {
constructor(domainId) {
this._handle = rclnodejs.createContext();
this._isShutdown = false;
this._nodes = [];
this._domainId = domainId;
Context._instances.push(this);
}

Expand Down Expand Up @@ -222,7 +224,7 @@ class Context {

/**
* Get the domain ID of this context.
* @returns {Number} domain ID of this context
* @returns {bigint} domain ID of this context
*/
get domainId() {
return rclnodejs.getDomainId(this.handle);
Expand Down
24 changes: 23 additions & 1 deletion src/rcl_context_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <rcl/rcl.h>

#include <cstdio>
#include <rcpputils/scope_exit.hpp>
#include <string>

#include "macros.h"
Expand All @@ -35,6 +36,15 @@ Napi::Value Init(const Napi::CallbackInfo& info) {
rcl_init_options_init(&init_options, allocator),
rcl_get_error_string().str);

RCPPUTILS_SCOPE_EXIT({
rcl_ret_t fini_ret = rcl_init_options_fini(&init_options);
if (RCL_RET_OK != fini_ret) {
Napi::Error::New(env, rcl_get_error_string().str)
.ThrowAsJavaScriptException();
rcl_reset_error();
}
});

// Preprocess Context
RclHandle* context_handle = RclHandle::Unwrap(info[0].As<Napi::Object>());
rcl_context_t* context =
Expand All @@ -54,6 +64,18 @@ Napi::Value Init(const Napi::CallbackInfo& info) {
snprintf(argv[i], len, "%s", arg.c_str());
}
}
// Set up the domain id.
size_t domain_id = RCL_DEFAULT_DOMAIN_ID;
if (info.Length() > 2 && info[2].IsBigInt()) {
bool lossless;
domain_id = info[2].As<Napi::BigInt>().Uint64Value(&lossless);
Copy link

Copilot AI Jun 16, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider checking if the BigInt conversion was lossless by verifying the 'lossless' boolean value; if the conversion is not lossless, it may be appropriate to throw an error to prevent potential data truncation.

Suggested change
domain_id = info[2].As<Napi::BigInt>().Uint64Value(&lossless);
domain_id = info[2].As<Napi::BigInt>().Uint64Value(&lossless);
if (!lossless) {
Napi::Error::New(env, "BigInt conversion to domain_id was not lossless")
.ThrowAsJavaScriptException();
return env.Undefined();
}

Copilot uses AI. Check for mistakes.
}
rcl_ret_t ret = rcl_init_options_set_domain_id(&init_options, domain_id);
if (RCL_RET_OK != ret) {
Napi::Error::New(env, "failed to set domain id to init options")
.ThrowAsJavaScriptException();
return env.Undefined();
}

THROW_ERROR_IF_NOT_EQUAL(
RCL_RET_OK,
Expand Down Expand Up @@ -141,7 +163,7 @@ Napi::Value GetDomainId(const Napi::CallbackInfo& info) {
return env.Undefined();
}

return Napi::Number::New(env, domain_id);
return Napi::BigInt::New(env, domain_id);
}

Napi::Object InitContextBindings(Napi::Env env, Napi::Object exports) {
Expand Down
11 changes: 9 additions & 2 deletions test/test-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,16 @@ describe('context test suite', function () {
assert.strictEqual(context.nodes.length, 0);
});

it('context number id', async function () {
it('context domain id', async function () {
let context = new rclnodejs.Context(BigInt(123));
await rclnodejs.init(context);
assert.strictEqual(typeof context.domainId, 'bigint');
assert.strictEqual(context.domainId, BigInt(123));
});

it('context with default domain id', async function () {
let context = new rclnodejs.Context();
await rclnodejs.init(context);
assert.strictEqual(typeof context.domainId, 'number');
assert.strictEqual(typeof context.domainId, 'bigint');
});
});
3 changes: 2 additions & 1 deletion test/types/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ expectType<string | undefined>(rclnodejs.DistroUtils.getDistroName(2105));

// ---- Context -----
expectType<rclnodejs.Context>(rclnodejs.Context.defaultContext());
expectType<number>(rclnodejs.Context.defaultContext().domainId());
expectType<rclnodejs.Context>(new rclnodejs.Context(123n));
expectType<bigint>(rclnodejs.Context.defaultContext().domainId());

// ---- NodeOptions ----
const nodeOptions = new rclnodejs.NodeOptions();
Expand Down
5 changes: 3 additions & 2 deletions types/context.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ declare module 'rclnodejs' {
* Create a new instance in uninitialized state.
* Call rcl.init(context) to initialize this context state for
* use in creating nodes, etc.
* @param {bigint} - Optional, The domain ID of this context.
*/
constructor();
constructor(domainId?: bigint);

/**
* Test if this context has not been initialized by rcl.init(context).
Expand Down Expand Up @@ -92,6 +93,6 @@ declare module 'rclnodejs' {
* Get the domain ID of this context.
* @returns domain ID of this context
*/
domainId(): number;
domainId(): bigint;
}
}
Loading