Skip to content

Commit 2c0ac64

Browse files
authored
Fix Node creation crash when using plain object as options (#1424)
When a plain object (e.g., `{ enableRosout: false }`) is passed as options instead of a `NodeOptions` instance, `options.parameterOverrides` is `undefined`, causing `TypeError: Cannot read properties of undefined (reading 'length')`. Added `Node._normalizeOptions()` to merge plain objects with `NodeOptions.defaultOptions` defaults using nullish coalescing (`??`), ensuring all documented defaults are preserved for unspecified fields while respecting explicitly set values (including `false`). **Files:** - `lib/node.js` — added `static _normalizeOptions()`, called at the top of `_init()` - `test/test-node.js` — added tests for node creation with plain object options and empty object options Fix: #1423
1 parent 574cc35 commit 2c0ac64

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

lib/node.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,30 @@ class Node extends rclnodejs.ShadowNode {
9797
);
9898
}
9999

100+
static _normalizeOptions(options) {
101+
if (options instanceof NodeOptions) {
102+
return options;
103+
}
104+
const defaults = NodeOptions.defaultOptions;
105+
return {
106+
startParameterServices:
107+
options.startParameterServices ?? defaults.startParameterServices,
108+
parameterOverrides:
109+
options.parameterOverrides ?? defaults.parameterOverrides,
110+
automaticallyDeclareParametersFromOverrides:
111+
options.automaticallyDeclareParametersFromOverrides ??
112+
defaults.automaticallyDeclareParametersFromOverrides,
113+
startTypeDescriptionService:
114+
options.startTypeDescriptionService ??
115+
defaults.startTypeDescriptionService,
116+
enableRosout: options.enableRosout ?? defaults.enableRosout,
117+
rosoutQos: options.rosoutQos ?? defaults.rosoutQos,
118+
};
119+
}
120+
100121
_init(name, namespace, options, context, args, useGlobalArguments) {
122+
options = Node._normalizeOptions(options);
123+
101124
this.handle = rclnodejs.createNode(
102125
name,
103126
namespace,

test/test-node.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,25 @@ describe('rclnodejs node test suite', function () {
143143
);
144144
});
145145
});
146+
147+
it('Create a node with a plain object as options', function () {
148+
const node = new rclnodejs.Node('plain_opts_node', '/ns', undefined, {
149+
enableRosout: false,
150+
});
151+
assert.strictEqual(node.name(), 'plain_opts_node');
152+
node.destroy();
153+
});
154+
155+
it('Create a node with options missing parameterOverrides', function () {
156+
const node = new rclnodejs.Node(
157+
'partial_opts_node',
158+
'/ns',
159+
undefined,
160+
{}
161+
);
162+
assert.strictEqual(node.name(), 'partial_opts_node');
163+
node.destroy();
164+
});
146165
});
147166
});
148167

0 commit comments

Comments
 (0)