• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RobotWebTools / rclnodejs / 14823168803

04 May 2025 04:36PM UTC coverage: 85.076% (+0.03%) from 85.042%
14823168803

Pull #1116

github

web-flow
Merge 90459a1e9 into 2d70163e0
Pull Request #1116: Move configure client introspection to binding of client

711 of 928 branches covered (76.62%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

1746 of 1960 relevant lines covered (89.08%)

1108.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.77
/lib/context.js
1
// Copyright (c) 2019 Intel Corporation. All rights reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
'use strict';
16

17
const rclnodejs = require('bindings')('rclnodejs');
78✔
18

19
let defaultContext = null;
78✔
20

21
/**
22
 * Encapsulates the lifecycle of an rcl environment from init to shutdown.
23
 * A Context serves as a container for a ROS2 RCL environment that holds
24
 * nodes and the resources created by the nodes, e.g.,
25
 * publishers, subscriptions, actions, services...v
26
 *
27
 * A context has 3 states:
28
 * ```
29
 * new Context() --> uninitialized -->
30
 * *                                  |
31
 *         ---------------------------
32
 *        |
33
 *        v
34
 * rcl.init(context) --> initialized ->
35
 *                                     |
36
 *         ----------------------------
37
 *        |
38
 *        v
39
 * rcl.shutdown(context)
40
 *        or
41
 * context.shutdown() ---> shutdown
42
 * ```
43
 * Must call rclnodejs.init(context) to initialize the context
44
 * to the usable 'initialized' (valid) state be using.
45
 */
46
class Context {
47
  /**
48
   * Access the list of usable (initialized/valid) contexts.
49
   * @returns {Context[]} Array of valid contexts
50
   */
51
  static get instances() {
52
    let contexts = [];
72✔
53
    for (const ctx of Context._instances) {
72✔
54
      if (ctx.isValid()) {
72!
55
        contexts.push(ctx);
72✔
56
      }
57
    }
58
    return contexts;
72✔
59
  }
60

61
  /**
62
   * Create a new instance in uninitialized state.
63
   * Call rcl.init(context) to initialize this context state for
64
   * use in creating nodes, etc.
65
   * @constructor
66
   */
67
  constructor() {
68
    this._handle = rclnodejs.createContext();
579✔
69
    this._isShutdown = false;
579✔
70
    this._nodes = [];
579✔
71
    Context._instances.push(this);
579✔
72
  }
73

74
  /**
75
   * Access the nodes managed by this context.
76
   * @returns {Node[]} The nodes.
77
   */
78
  get nodes() {
79
    return Array.from(this._nodes);
582✔
80
  }
81

82
  /**
83
   * Get the handle referencing the internal context object. Do not modify it yourself: only pass it to *rclnodejs* functions!
84
   * @returns {undefined} a reference to the internal context object
85
   */
86
  get handle() {
87
    return this._handle;
16,128✔
88
  }
89

90
  /**
91
   * Test if this context has not been initialized by rcl.init(context).
92
   * @returns {boolean} True if context has been initialized; otherwise false
93
   */
94
  isUninitialized() {
95
    return !this.isShutdown() && !this.isValid();
516✔
96
  }
97

98
  /**
99
   * Test if this context has been initialized, i.e., rcl.init(context),
100
   * and not shutdown.
101
   * @returns {boolean} True if context has been initialized; otherwise false
102
   */
103
  isInitialized() {
104
    return !this.isShutdown() && this.isValid();
636✔
105
  }
106

107
  /**
108
   * Test if this context has been shutdown, i.e., context.shutdown().
109
   * @returns {boolean} True if context has been shutdown; otherwise false
110
   */
111
  isShutdown() {
112
    return this._isShutdown;
3,432✔
113
  }
114

115
  /**
116
   * Test if this context is the default one.
117
   * @returns {boolean} whether this is the default context
118
   */
119
  isDefaultContext() {
120
    return this === defaultContext;
600✔
121
  }
122

123
  /**
124
   * Check that the context is in a usable state, i.e., it
125
   * has been initialized and not yet shutdown.
126
   * @returns {boolean} whether this context is (still) valid
127
   */
128
  isValid() {
129
    return rclnodejs.isContextValid(this.handle);
1,254✔
130
  }
131

132
  /**
133
   * Check that the context is valid.
134
   * @returns {boolean} whether this context is (still) valid
135
   *
136
   * @deprecated since 0.18.0, Use Context.isValid()
137
   */
138
  get isOk() {
139
    return this.isValid();
42✔
140
  }
141

142
  /**
143
   * Shut down the context including destroying all nodes.
144
   * @returns {undefined}
145
   * @throws {Error} If there is a problem shutting down the context.
146
   */
147
  shutdown() {
148
    if (this.isShutdown()) return;
570!
149

150
    // shutdown and remove all nodes
151
    for (const node of this.nodes) {
570✔
152
      node.destroy();
285✔
153
    }
154

155
    if (this.isInitialized()) {
570✔
156
      rclnodejs.shutdown(this.handle);
492✔
157
    }
158

159
    this._isShutdown = true;
570✔
160

161
    // remove context from _instances[]
162
    const index = Context._instances.indexOf(this);
570✔
163
    if (index > -1) {
570!
164
      Context._instances.splice(index, 1);
570✔
165
    }
166

167
    if (this.isDefaultContext()) {
570✔
168
      defaultContext = null;
537✔
169
    }
170
  }
171

172
  /**
173
   * Try to shut down the context.
174
   * @returns {undefined}
175
   * @throws {Error} If there is a problem shutting down the context.
176
   */
177
  tryShutdown() {
178
    if (this.isInitialized()) {
×
179
      this.shutdown();
×
180
    }
181
  }
182

183
  onNodeCreated(node) {
184
    if (!node) {
1,701!
185
      throw new Error('Node must be defined to add to Context');
×
186
    }
187

188
    if (this.isShutdown()) {
1,701!
189
      throw new Error('Can not add a Node to a Context that is shutdown');
×
190
    }
191

192
    if (this._nodes.includes(node)) {
1,701!
193
      // do nothing
194
      return;
×
195
    }
196

197
    this._nodes.push(node);
1,701✔
198
  }
199

200
  onNodeDestroyed(node) {
201
    if (!this._nodes) {
1,767!
202
      return;
×
203
    }
204

205
    // remove node from _nodes[]
206
    const index = this._nodes.indexOf(node);
1,767✔
207
    if (index > -1) {
1,767✔
208
      this._nodes.splice(index, 1);
1,701✔
209
    }
210
  }
211

212
  /**
213
   * Get the global default Context object.
214
   * @returns {Context} The default Context
215
   */
216
  static defaultContext() {
217
    if (defaultContext === null) {
2,751✔
218
      defaultContext = new Context();
537✔
219
    }
220
    return defaultContext;
2,751✔
221
  }
222

223
  /**
224
   * Get the domain ID of this context.
225
   * @returns {Number} domain ID of this context
226
   */
227
  get domainId() {
228
    return rclnodejs.getDomainId(this.handle);
3✔
229
  }
230
}
231

232
Context._instances = [];
78✔
233

234
module.exports = Context;
78✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc