From 8d0b4bf00637da8ba273513d14e96af20bcb6d53 Mon Sep 17 00:00:00 2001 From: Minggang Wang Date: Fri, 14 Feb 2025 15:25:11 +0800 Subject: [PATCH] Levrage BigInt to represent int64/uint64 (#1030) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to [double precision floating point format](https://en.wikipedia.org/wiki/Double_precision_floating-point_format), JavaScript can only safely represent integers [between](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER) -(2^53 – 1) to 2^53 – 1, meanwhile, `Number.MAX_SAFE_INTEGER` is defined to represent the maximum safe integer in JavaScript, which is 9007199254740991. Per ROS2 message types, it has [int64](https://github.com/ros2/common_interfaces/blob/rolling/std_msgs/msg/Int64.msg)/[uint64](https://github.com/ros2/common_interfaces/blob/rolling/std_msgs/msg/UInt64.msg), which may be out of the range above. For current implementation, we leverage [ref](https://github.com/node-ffi-napi/ref-napi) to read/write values from `int64_t` and `uint64_t` data of C++, which can be type of: 1. `number`: when value in [`-Number.MAX_SAFE_INTEGER` `Number.MAX_SAFE_INTEGER`]. 2. `string`: otherwise. This brings the problem that the type of int64/uint64 be ununified in JavaScript. Along with [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) introduced, it becomes possible to make the type consistent. This patch implements to leverage `BigInt` to represent int64/uint64, including: 1. Update `message.dot` to use `BigInt` when hitting int64/uint64. 2. Update `rosidl_parser.js` to convert int64/uint64 to string in JSON object. 3. Update `message_translator.js` to add `bigint` as primitive. 4. Update `parameter.js` to use `BigInt` for integer and its `ts` definition `parameter.d.ts`. 5. Update tests targeting on messages that include int64/uint64. Fix: #836, #1025 --- lib/parameter.js | 62 ++++---- package.json | 1 + rosidl_gen/message_translator.js | 21 ++- rosidl_gen/packages.js | 8 +- rosidl_gen/templates/message.dot | 24 +++- rosidl_parser/rosidl_parser.js | 30 +++- rostsd_gen/index.js | 6 +- test/client_setup.js | 6 +- test/publisher_msg.js | 4 + test/test-bounded-sequences.js | 20 +-- test/test-fixed-array.js | 24 ++-- test/test-interactive.js | 4 +- test/test-message-translator-primitive.js | 168 ++++------------------ test/test-message-type.js | 14 +- test/test-parameter-service.js | 14 +- test/test-parameters.js | 58 ++++---- test/test-primitive-msg-type-check.js | 12 +- test/test-security-related.js | 2 +- test/test-service-introspection.js | 4 +- test/test-service-with-async-callback.js | 8 +- test/test-single-process.js | 46 +++--- test/types/main.ts | 11 ++ types/parameter.d.ts | 13 +- 23 files changed, 264 insertions(+), 296 deletions(-) diff --git a/lib/parameter.js b/lib/parameter.js index a7911cfe..9b938f47 100644 --- a/lib/parameter.js +++ b/lib/parameter.js @@ -34,6 +34,7 @@ const rclnodejs = require('bindings')('rclnodejs'); const DEFAULT_NUMERIC_RANGE_TOLERANCE = 1e-6; const PARAMETER_SEPARATOR = '.'; +const PARAMETER_BYTE = 10; /** * Enum for ParameterType @@ -125,7 +126,9 @@ class Parameter { constructor(name, type, value) { this._name = name; this._type = type; - this._value = value; + // Convert to bigint if it's type of `PARAMETER_INTEGER`. + this._value = + this._type == ParameterType.PARAMETER_INTEGER ? BigInt(value) : value; this._isDirty = true; this.validate(); @@ -240,10 +243,10 @@ class Parameter { msg.double_array_value = this.value; break; case ParameterType.PARAMETER_INTEGER: - msg.integer_value = Math.trunc(this.value); + msg.integer_value = this.value; break; case ParameterType.PARAMETER_INTEGER_ARRAY: - msg.integer_array_value = this.value.map((val) => Math.trunc(val)); + msg.integer_array_value = this.value; break; case ParameterType.PARAMETER_STRING: msg.string_value = this.value; @@ -537,10 +540,10 @@ class Range { /** * Determine if a value is within this range. - * A TypeError is thrown when value is not a number. + * A TypeError is thrown when value is not a number or bigint. * Subclasses should override and call this method for basic type checking. * - * @param {number} value - The number to check. + * @param {number|bigint} value - The number or bigint to check. * @return {boolean} - True if value satisfies the range; false otherwise. */ inRange(value) { @@ -550,8 +553,8 @@ class Range { (inRange, val) => inRange && this.inRange(val), true ); - } else if (typeof value !== 'number') { - throw new TypeError('Value must be a number'); + } else if (typeof value !== 'number' && typeof value !== 'bigint') { + throw new TypeError('Value must be a number or bigint'); } return true; @@ -652,27 +655,16 @@ class FloatingPointRange extends Range { * Defines a range for integer values. * @class */ -class IntegerRange extends FloatingPointRange { +class IntegerRange extends Range { /** * Create a new instance. * @constructor - * @param {number} fromValue - The lowest inclusive value in range - * @param {number} toValue - The highest inclusive value in range - * @param {number} step - The internal unit size. - * @param {number} tolerance - The plus/minus tolerance for number equivalence. + * @param {bigint} fromValue - The lowest inclusive value in range + * @param {bigint} toValue - The highest inclusive value in range + * @param {bigint} step - The internal unit size. */ - constructor( - fromValue, - toValue, - step = 1, - tolerance = DEFAULT_NUMERIC_RANGE_TOLERANCE - ) { - super( - Math.trunc(fromValue), - Math.trunc(toValue), - Math.trunc(step), - tolerance - ); + constructor(fromValue, toValue, step = 1n) { + super(fromValue, toValue, step); } /** @@ -683,12 +675,23 @@ class IntegerRange extends FloatingPointRange { */ isValidType(parameterType) { const result = - parameterType === ParameterType.PARAMETER_BYTE || - parameterType === ParameterType.PARAMETER_BYTE_ARRAY || parameterType === ParameterType.PARAMETER_INTEGER || parameterType === ParameterType.PARAMETER_INTEGER_ARRAY; return result; } + + inRange(value) { + const min = this.fromValue; + const max = this.toValue; + if (value < min || value > max) { + return false; + } + + if (this.step != 0n && (value - min) % this.step !== 0n) { + return false; + } + return true; + } } /** @@ -763,10 +766,13 @@ function validValue(value, type) { case ParameterType.PARAMETER_STRING: result = typeof value === 'string'; break; - case ParameterType.PARAMETER_INTEGER: case ParameterType.PARAMETER_DOUBLE: + case PARAMETER_BYTE: result = typeof value === 'number'; break; + case ParameterType.PARAMETER_INTEGER: + result = typeof value === 'bigint'; + break; case ParameterType.PARAMETER_BOOL_ARRAY: case ParameterType.PARAMETER_BYTE_ARRAY: case ParameterType.PARAMETER_INTEGER_ARRAY: @@ -789,7 +795,7 @@ function _validArray(values, type) { if (type === ParameterType.PARAMETER_BOOL_ARRAY) { arrayElementType = ParameterType.PARAMETER_BOOL; } else if (type === ParameterType.PARAMETER_BYTE_ARRAY) { - arrayElementType = ParameterType.PARAMETER_INTEGER; + arrayElementType = PARAMETER_BYTE; } if (type === ParameterType.PARAMETER_INTEGER_ARRAY) { arrayElementType = ParameterType.PARAMETER_INTEGER; diff --git a/package.json b/package.json index 84691c1b..ce7ff3c2 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "dot": "^1.1.3", "dtslint": "^4.2.1", "fs-extra": "^11.2.0", + "json-bigint": "^1.0.0", "int64-napi": "^1.0.2", "is-close": "^1.3.3", "mkdirp": "^3.0.1", diff --git a/rosidl_gen/message_translator.js b/rosidl_gen/message_translator.js index b8bb048f..7d5417bd 100644 --- a/rosidl_gen/message_translator.js +++ b/rosidl_gen/message_translator.js @@ -27,7 +27,12 @@ function copyMsgObject(msg, obj) { for (let i in obj) { if (msg.hasMember(i)) { const type = typeof obj[i]; - if (type === 'string' || type === 'number' || type === 'boolean') { + if ( + type === 'string' || + type === 'number' || + type === 'boolean' || + type === 'bigint' + ) { // A primitive-type value msg[i] = obj[i]; } else if (Array.isArray(obj[i]) || isTypedArray(obj[i])) { @@ -80,17 +85,20 @@ function verifyMessage(message, obj) { case 'char': case 'int16': case 'int32': - case 'int64': case 'byte': case 'uint16': case 'uint32': - case 'uint64': case 'float32': case 'float64': if (typeof obj[name] != 'number') { return false; } break; + case 'int64': + case 'uint64': + if (typeof obj[name] != 'bigint') { + return false; + } case 'bool': if (typeof obj[name] != 'boolean') { return false; @@ -171,7 +179,12 @@ function toROSMessage(TypeClass, obj) { function constructFromPlanObject(msg, obj) { const type = typeof obj; - if (type === 'string' || type === 'number' || type === 'boolean') { + if ( + type === 'string' || + type === 'number' || + type === 'boolean' || + type === 'bigint' + ) { msg.data = obj; } else if (type === 'object') { copyMsgObject(msg, obj); diff --git a/rosidl_gen/packages.js b/rosidl_gen/packages.js index a7ee7a54..8efefe43 100644 --- a/rosidl_gen/packages.js +++ b/rosidl_gen/packages.js @@ -161,9 +161,7 @@ async function generateMsgForSrv(filePath, interfaceInfo, pkgMap) { async function addInterfaceInfos(filePath, dir, pkgMap) { const interfaceInfo = grabInterfaceInfo(filePath, true); const ignore = pkgFilters.matchesAny(interfaceInfo); - if (ignore) { - console.log('Omitting filtered interface: ', interfaceInfo); - } else { + if (!ignore) { if (path.extname(filePath) === '.msg') { // Some .msg files were generated prior to 0.3.2 for .action files, // which has been disabled. So these files should be ignored here. @@ -232,9 +230,7 @@ async function findPackagesInDirectory(dir) { amentExecuted ); const ignore = pkgFilters.matchesAny(interfaceInfo); - if (ignore) { - console.log('Omitting filtered interface: ', interfaceInfo); - } else { + if (!ignore) { if (path.extname(file.name) === '.msg') { // Some .msg files were generated prior to 0.3.2 for .action files, // which has been disabled. So these files should be ignored here. diff --git a/rosidl_gen/templates/message.dot b/rosidl_gen/templates/message.dot index c43393f2..d9b2ca56 100644 --- a/rosidl_gen/templates/message.dot +++ b/rosidl_gen/templates/message.dot @@ -157,6 +157,10 @@ function isTypedArrayType(type) { return typedArrayType.indexOf(type.type.toLowerCase()) !== -1; } +function isBigInt(type) { + return ['int64', 'uint64'].indexOf(type.type.toLowerCase()) !== -1; +} + const willUseTypedArray = isTypedArrayType(it.spec.baseType); const currentTypedArray = getTypedArrayName(it.spec.baseType); const currentTypedArrayElementType = getTypedArrayElementName(it.spec.baseType); @@ -303,7 +307,13 @@ class {{=objectWrapper}} { this._refObject.{{=field.name}} = {{=field.default_value}}; {{?}} {{?? field.type.isPrimitiveType && !isTypedArrayType(field.type) && field.default_value}} - this._{{=field.name}}Array = {{=JSON.stringify(field.default_value)}}; + {{? isBigInt(field.type)}} + {{/* For non-TypedArray like int64/uint64. */}} + this._{{=field.name}}Array = {{=JSON.stringify(field.default_value)}}.map(num => BigInt(num)); + {{??}} + {{/* For non-TypedArray like bool. */}} + this._{{=field.name}}Array = {{=JSON.stringify(field.default_value)}}; + {{?}} {{?? field.type.isPrimitiveType && isTypedArrayType(field.type) && field.default_value}} this._wrapperFields.{{=field.name}}.fill({{=getTypedArrayName(field.type)}}.from({{=JSON.stringify(field.default_value)}})); {{?}} @@ -376,8 +386,11 @@ class {{=objectWrapper}} { } } } + {{?? isBigInt(field.type)}} + {{/* For non-TypedArray like int64/uint64. */}} + this._refObject.{{=field.name}} = this._{{=field.name}}Array.map(num => num.toString()); {{??}} - {{/* For non-TypedArray like int64/uint64/bool. */}} + {{/* For non-TypedArray like bool. */}} this._refObject.{{=field.name}} = this._{{=field.name}}Array; {{?}} {{?? field.type.isArray && field.type.isPrimitiveType && isTypedArrayType(field.type) && field.type.isFixedSizeArray}} @@ -527,6 +540,8 @@ class {{=objectWrapper}} { return this._wrapperFields.{{=field.name}}; {{?? !field.type.isArray && field.type.type === 'string' && it.spec.msgName !== 'String'}} return this._wrapperFields.{{=field.name}}.data; + {{?? isBigInt(field.type)}} + return BigInt(this._refObject.{{=field.name}}); {{??}} return this._refObject.{{=field.name}}; {{?}} @@ -559,6 +574,11 @@ class {{=objectWrapper}} { } {{?? !field.type.isArray && field.type.type === 'string' && it.spec.msgName !== 'String'}} this._wrapperFields.{{=field.name}}.data = value; + {{?? isBigInt(field.type)}} + if (typeof value !== "bigint") { + throw new TypeError('{{=field.name}} must be type of bigint'); + } + this._refObject.{{=field.name}} = value.toString(); {{??}} {{? it.spec.msgName === 'String'}} this._refObject.size = Buffer.byteLength(value); diff --git a/rosidl_parser/rosidl_parser.js b/rosidl_parser/rosidl_parser.js index 93d19a3a..50a4d672 100644 --- a/rosidl_parser/rosidl_parser.js +++ b/rosidl_parser/rosidl_parser.js @@ -14,11 +14,20 @@ 'use strict'; +const compareVersions = require('compare-versions'); const path = require('path'); const execFile = require('child_process').execFile; const pythonExecutable = require('./py_utils').getPythonExecutable('python3'); +const contextSupportedVersion = '21.0.0.0'; +const currentVersion = process.version; +const isContextSupported = compareVersions.compare( + currentVersion.substring(1, currentVersion.length), + contextSupportedVersion, + '>=' +); + const rosidlParser = { parseMessageFile(packageName, filePath) { return this._parseFile('parse_message_file', packageName, filePath); @@ -32,6 +41,25 @@ const rosidlParser = { return this._parseFile('parse_action_file', packageName, filePath); }, + _parseJSONObject(str) { + // For nodejs >= `contextSupportedVersion`, we leverage context parameter to + // convert unsafe integer to string, otherwise, json-bigint is used. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse + if (isContextSupported) { + return JSON.parse(str, (key, value, context) => { + if ( + Number.isInteger(value) && + !Number.isSafeInteger(Number(context.source)) + ) { + return context.source; + } + return value; + }); + } + const JSONbigString = require('json-bigint')({ storeAsString: true }); + return JSONbigString.parse(str); + }, + _parseFile(command, packageName, filePath) { return new Promise((resolve, reject) => { const args = [ @@ -54,7 +82,7 @@ const rosidlParser = { ) ); } else { - resolve(JSON.parse(stdout)); + resolve(this._parseJSONObject(stdout)); } } ); diff --git a/rostsd_gen/index.js b/rostsd_gen/index.js index 07c0ab7d..2ddbdb10 100644 --- a/rostsd_gen/index.js +++ b/rostsd_gen/index.js @@ -478,7 +478,6 @@ function primitiveType2JSName(type) { case 'int8': case 'int16': case 'int32': - case 'int64': // signed explicit float types case 'float32': @@ -488,7 +487,6 @@ function primitiveType2JSName(type) { case 'uint8': case 'uint16': case 'uint32': - case 'uint64': jsName = 'number'; break; case 'bool': @@ -499,6 +497,10 @@ function primitiveType2JSName(type) { case 'wstring': jsName = 'string'; break; + case 'int64': + case 'uint64': + jsName = 'bigint'; + break; } return jsName; diff --git a/test/client_setup.js b/test/client_setup.js index 5319efd8..03eb2deb 100644 --- a/test/client_setup.js +++ b/test/client_setup.js @@ -24,13 +24,13 @@ rclnodejs const Int8 = 'std_msgs/msg/Int8'; var client = node.createClient(AddTwoInts, 'add_two_ints'); const request = { - a: 1, - b: 2, + a: 1n, + b: 2n, }; var publisher = node.createPublisher(Int8, 'back_add_two_ints'); client.waitForService().then(() => { client.sendRequest(request, (response) => { - publisher.publish(response.sum); + publisher.publish(Number(response.sum)); }); }); diff --git a/test/publisher_msg.js b/test/publisher_msg.js index a263dcc5..e905db7e 100644 --- a/test/publisher_msg.js +++ b/test/publisher_msg.js @@ -19,6 +19,10 @@ const rclnodejs = require('../index.js'); var rclType = process.argv[2]; var rclValue = eval(process.argv[3]); +if (['int64', 'uint64'].indexOf(rclType.toLowerCase()) !== -1) { + rclValue = BigInt(rclValue); +} + rclnodejs .init() .then(() => { diff --git a/test/test-bounded-sequences.js b/test/test-bounded-sequences.js index 3bb655ff..d4ddf146 100644 --- a/test/test-bounded-sequences.js +++ b/test/test-bounded-sequences.js @@ -35,8 +35,8 @@ describe('Test bounded sequeces', function () { uint16_value: 1, int32_value: 1, uint32_value: 1, - int64_value: 2, - uint64_value: 2, + int64_value: 2n, + uint64_value: 2n, }; const msg = { @@ -51,10 +51,10 @@ describe('Test bounded sequeces', function () { uint16_values: Uint16Array.from([1, 2]), int32_values: Int32Array.from([1, 2]), uint32_values: Uint32Array.from([1, 2]), - int64_values: [1, 2], - uint64_values: [1, 2], - int64_values_default: [-1, 2, 3], - uint64_values_default: [1, 2, 3], + int64_values: [1n, 2n], + uint64_values: [1n, 2n], + int64_values_default: [0n, 9223372036854775807n, -9223372036854775808n], + uint64_values_default: [0n, 1n, 18446744073709551615n], string_values: ['hello', 'world'], basic_types_values: [primitives, primitives], alignment_check: 100, @@ -72,10 +72,10 @@ describe('Test bounded sequeces', function () { uint16_values: Uint16Array.from([1, 2]), int32_values: Int32Array.from([1, 2]), uint32_values: Uint32Array.from([1, 2]), - int64_values: [1, 2], - uint64_values: [1, 2], - int64_values_default: [-1, 2, 3], - uint64_values_default: [1, 2, 3], + int64_values: [1n, 2n], + uint64_values: [1n, 2n], + int64_values_default: [0n, 9223372036854775807n, -9223372036854775808n], + uint64_values_default: [0n, 1n, 18446744073709551615n], string_values: ['hello', 'world'], basic_types_values: [primitives, primitives], bool_values_default: [false, true, false], diff --git a/test/test-fixed-array.js b/test/test-fixed-array.js index a8f60caa..647260bd 100644 --- a/test/test-fixed-array.js +++ b/test/test-fixed-array.js @@ -145,8 +145,8 @@ describe('Test message which has a fixed array of 36', function () { uint16_value: 1, int32_value: 1, uint32_value: 1, - int64_value: 2, - uint64_value: 2, + int64_value: 2n, + uint64_value: 2n, }; const defaultValue = { @@ -161,8 +161,8 @@ describe('Test message which has a fixed array of 36', function () { uint16_value: 2000, int32_value: -30000, uint32_value: 60000, - int64_value: -40000000, - uint64_value: 50000000, + int64_value: -40000000n, + uint64_value: 50000000n, }; const msg = { @@ -177,14 +177,12 @@ describe('Test message which has a fixed array of 36', function () { uint16_values: Uint16Array.from([1, 2, 3]), int32_values: Int32Array.from([1, 2, 3]), uint32_values: Uint32Array.from([1, 2, 3]), - int64_values: [1, 2, 3], - uint64_values: [1, 2, 3], + int64_values: [1n, 2n, 3n], + uint64_values: [1n, 2n, 3n], string_values: ['hello', 'world', 'abc'], basic_types_values: [bacicType, bacicType, bacicType], defaults_values: [defaultValue, defaultValue, defaultValue], - // Use a string, '18446744073709551615', representing UINT64_MAX for ref, - // see details https://github.com/node-ffi-napi/ref-napi/blob/latest/test/uint64.js#L17. - uint64_values_default: [0, 1, '18446744073709551615'], + uint64_values_default: [0, 1, 18446744073709551615n], alignment_check: 100, }; @@ -201,8 +199,8 @@ describe('Test message which has a fixed array of 36', function () { uint16_values: Uint16Array.from([1, 2, 3]), int32_values: Int32Array.from([1, 2, 3]), uint32_values: Uint32Array.from([1, 2, 3]), - int64_values: [1, 2, 3], - uint64_values: [1, 2, 3], + int64_values: [1n, 2n, 3n], + uint64_values: [1n, 2n, 3n], string_values: ['hello', 'world', 'abc'], basic_types_values: [bacicType, bacicType, bacicType], defaults_values: [defaultValue, defaultValue, defaultValue], @@ -217,8 +215,8 @@ describe('Test message which has a fixed array of 36', function () { uint16_values_default: Uint16Array.from([0, 1, 65535]), int32_values_default: Int32Array.from([0, 2147483647, -2147483648]), uint32_values_default: Uint32Array.from([0, 1, 4294967295]), - int64_values_default: [0, 9223372036854775807, -9223372036854775808], - uint64_values_default: [0, 1, '18446744073709551615'], + int64_values_default: [0n, 9223372036854775807n, -9223372036854775808n], + uint64_values_default: [0n, 1n, 18446744073709551615n], string_values_default: ['', 'max value', 'min value'], alignment_check: 100, constants_values: [], diff --git a/test/test-interactive.js b/test/test-interactive.js index 20c9a851..a124a768 100644 --- a/test/test-interactive.js +++ b/test/test-interactive.js @@ -61,9 +61,9 @@ describe('rclnodejs interactive testing', function () { 'add_two_ints', (request, response) => { assert.ok('a' in request); - assert.deepStrictEqual(typeof request.a, 'number'); + assert.deepStrictEqual(typeof request.a, 'bigint'); assert.ok('b' in request); - assert.deepStrictEqual(typeof request.b, 'number'); + assert.deepStrictEqual(typeof request.b, 'bigint'); let result = response.template; result.sum = request.a + request.b; response.send(result); diff --git a/test/test-message-translator-primitive.js b/test/test-message-translator-primitive.js index e6646ef9..ab093e4c 100644 --- a/test/test-message-translator-primitive.js +++ b/test/test-message-translator-primitive.js @@ -46,17 +46,16 @@ describe('Rclnodejs message translation: primitive types', function () { { type: 'Int64', values: [ - -32768, - -2, - -1, - 0, - 1, - 2, - 3, - 32767, - 2147483648, - 4294967295, - Number.MAX_SAFE_INTEGER, + -32768n, + -2n, + -1n, + 0n, + 1n, + 2n, + 3n, + 32767n, + 2147483648n, + BigInt(Number.MAX_SAFE_INTEGER) + 1n, ], }, { type: 'Int8', values: [-128, -127, -2, -1, 0, 1, 2, 3, 127] }, @@ -69,15 +68,15 @@ describe('Rclnodejs message translation: primitive types', function () { { type: 'UInt64', values: [ - 0, - 1, - 2, - 3, - 32767, - 65535, - 2147483648, - 4294967295, - Number.MAX_SAFE_INTEGER, + 0n, + 1n, + 2n, + 3n, + 32767n, + 65535n, + 2147483648n, + 4294967295n, + BigInt(Number.MAX_SAFE_INTEGER) + 1n, ], }, { type: 'UInt8', values: [0, 1, 2, 3, 127, 255] }, @@ -187,16 +186,16 @@ describe('Rclnodejs message translation: primitive types array', function () { { type: 'Int64MultiArray', values: [ - -Number.MAX_SAFE_INTEGER, - -32768, - -2, - -1, - 0, - 1, - 2, - 3, - 32767, - Number.MAX_SAFE_INTEGER, + BigInt(-Number.MAX_SAFE_INTEGER), + -32768n, + -2n, + -1n, + 0n, + 1n, + 2n, + 3n, + 32767n, + BigInt(Number.MAX_SAFE_INTEGER), ], }, { type: 'UInt8MultiArray', values: [0, 1, 2, 3, 127, 255] }, @@ -207,7 +206,7 @@ describe('Rclnodejs message translation: primitive types array', function () { }, { type: 'UInt64MultiArray', - values: [0, 1, 2, 3, 32767, 65535, Number.MAX_SAFE_INTEGER], + values: [0n, 1n, 2n, 3n, 32767n, 65535n, BigInt(Number.MAX_SAFE_INTEGER)], }, ].forEach((testData) => { const topic = testData.topic || 'topic' + testData.type; @@ -242,113 +241,6 @@ describe('Rclnodejs message translation: primitive types array', function () { }); }); -// describe('Rclnodejs message translation: primitive types array - exception', function() { -// this.timeout(60 * 1000); - -// before(function() { -// return rclnodejs.init(); -// }); - -// after(function() { -// rclnodejs.shutdown(); -// }); - -// [ -// {type: 'ByteMultiArray', values: [0, 1, 2, 3, 255, 256]}, -// {type: 'ByteMultiArray', values: [-1, 0, 1, 2, 3, 255]}, -// {type: 'ByteMultiArray', values: [-100, 0, 1, 2, 3, 255]}, -// {type: 'ByteMultiArray', values: [0, 1, 2, 3, 32767, Number.MAX_SAFE_INTEGER]}, -// {type: 'ByteMultiArray', values: [0, 1, 2, 3, 32767, Number.POSITIVE_INFINITY]}, - -// {type: 'Int8MultiArray', values: [-128, -127, -2, -1, 0, 1, 2, 3, 127, 128]}, -// {type: 'Int8MultiArray', values: [-128, -127, -2, -1, 0, 1, 2, 3, 127, 129]}, -// {type: 'Int8MultiArray', values: [-128, -127, -2, -1, 0, 1, 2, 3, 127, 1000]}, -// {type: 'Int8MultiArray', values: [-129, -127, -2, -1, 0, 1, 2, 3, 127]}, -// {type: 'Int8MultiArray', values: [-1000, -127, -2, -1, 0, 1, 2, 3, 127]}, -// {type: 'Int8MultiArray', values: [-Number.MAX_SAFE_INTEGER, -2, -1, 0, 1, 2, 3, 32767]}, -// {type: 'Int8MultiArray', values: [Number.NEGATIVE_INFINITY, -2, -1, 0, 1, 2, 3, 32767]}, - -// {type: 'Int16MultiArray', values: [-32768, -2, -1, 0, 1, 2, 3, 32767, 32768]}, -// {type: 'Int16MultiArray', values: [-32768, -2, -1, 0, 1, 2, 3, 32767, 32769]}, -// {type: 'Int16MultiArray', values: [-32768, -2, -1, 0, 1, 2, 3, 32767, 100000]}, -// {type: 'Int16MultiArray', values: [-32768, -2, -1, 0, 1, 2, 3, 32767, 1000000]}, -// {type: 'Int16MultiArray', values: [-32768, -2, -1, 0, 1, 2, 3, 32767, Number.MAX_SAFE_INTEGER]}, -// {type: 'Int16MultiArray', values: [-32768, -2, -1, 0, 1, 2, 3, 32767, Number.POSITIVE_INFINITY]}, -// {type: 'Int16MultiArray', values: [-32769, -2, -1, 0, 1, 2, 3, 32767]}, -// {type: 'Int16MultiArray', values: [-100000, -2, -1, 0, 1, 2, 3, 32767]}, -// {type: 'Int16MultiArray', values: [-Number.MAX_SAFE_INTEGER, -2, -1, 0, 1, 2, 3, 32767]}, -// {type: 'Int16MultiArray', values: [Number.NEGATIVE_INFINITY, -2, -1, 0, 1, 2, 3, 32767]}, - -// {type: 'Int32MultiArray', values: [-3, -2, -1, 0, 1, 2, 3, 32767, 2147483647, 2147483648]}, -// {type: 'Int32MultiArray', values: [-2147483649, -2, -1, 0, 1, 2, 3, 32767, 2147483647]}, -// {type: 'Int32MultiArray', values: [-3, -2, -1, 0, 1, 2, 3, 32767, 2147483647, Number.MAX_SAFE_INTEGER]}, -// {type: 'Int32MultiArray', values: [-3, -2, -1, 0, 1, 2, 3, 32767, 2147483647, Number.POSITIVE_INFINITY]}, -// {type: 'Int32MultiArray', values: [-Number.MAX_SAFE_INTEGER, -2, -1, 0, 1, 2, 3, 32767, 2147483647]}, -// {type: 'Int32MultiArray', values: [Number.NEGATIVE_INFINITY, -2, -1, 0, 1, 2, 3, 32767, 2147483647]}, - -// {type: 'UInt8MultiArray', values: [0, 1, 2, 3, 127, 255, 256]}, -// {type: 'UInt8MultiArray', values: [0, 1, 2, 3, 127, 255, 257]}, -// {type: 'UInt8MultiArray', values: [0, 1, 2, 3, 127, 255, 1000]}, -// {type: 'UInt8MultiArray', values: [0, 1, 2, 3, 127, 255, 10000]}, -// {type: 'UInt8MultiArray', values: [0, 1, 2, 3, 127, 255, Number.MAX_SAFE_INTEGER]}, -// {type: 'UInt8MultiArray', values: [0, 1, 2, 3, 127, 255, Number.POSITIVE_INFINITY]}, -// {type: 'UInt8MultiArray', values: [-1, 1, 2, 3, 127, 255]}, -// {type: 'UInt8MultiArray', values: [-100, 1, 2, 3, 127, 255]}, -// {type: 'UInt8MultiArray', values: [-1000, 1, 2, 3, 127, 255]}, -// {type: 'UInt8MultiArray', values: [-Number.MAX_SAFE_INTEGER, -2, -1, 0, 1, 2, 3]}, -// {type: 'UInt8MultiArray', values: [Number.NEGATIVE_INFINITY, -2, -1, 0, 1, 2, 3]}, - -// {type: 'UInt16MultiArray', values: [0, 1, 2, 3, 32767, 65535, 65536]}, -// {type: 'UInt16MultiArray', values: [0, 1, 2, 3, 32767, 65535, 100000]}, -// {type: 'UInt16MultiArray', values: [0, 1, 2, 3, 32767, 65535, 1000000]}, -// {type: 'UInt16MultiArray', values: [0, 1, 2, 3, 32767, 65535, Number.MAX_SAFE_INTEGER]}, -// {type: 'UInt16MultiArray', values: [0, 1, 2, 3, 32767, 65535, Number.POSITIVE_INFINITY]}, -// {type: 'UInt16MultiArray', values: [-1, 1, 2, 3, 32767, 65535]}, -// {type: 'UInt16MultiArray', values: [-10000, 1, 2, 3, 32767, 65535]}, -// {type: 'UInt16MultiArray', values: [-Number.MAX_SAFE_INTEGER, 1, 2, 3, 32767, 65535]}, -// {type: 'UInt16MultiArray', values: [Number.NEGATIVE_INFINITY, 1, 2, 3, 32767, 65535]}, - -// {type: 'UInt32MultiArray', values: [0, 1, 2, 3, 32767, 65535, 4294967296]}, -// {type: 'UInt32MultiArray', values: [0, 1, 2, 3, 32767, 65535, 4294967297]}, -// {type: 'UInt32MultiArray', values: [0, 1, 2, 3, 32767, 65535, 10000000000]}, -// {type: 'UInt32MultiArray', values: [0, 1, 2, 3, 32767, 65535, 100000000000]}, -// {type: 'UInt32MultiArray', values: [0, 1, 2, 3, 32767, 65535, Number.MAX_SAFE_INTEGER]}, -// {type: 'UInt32MultiArray', values: [0, 1, 2, 3, 32767, 65535, Number.POSITIVE_INFINITY]}, -// {type: 'UInt32MultiArray', values: [-1, 1, 2, 3, 32767, 65535, 4294967295]}, -// {type: 'UInt32MultiArray', values: [-2, 1, 2, 3, 32767, 65535, 4294967295]}, -// {type: 'UInt32MultiArray', values: [-10000, 1, 2, 3, 32767, 65535, 4294967295]}, -// {type: 'UInt32MultiArray', values: [-Number.MAX_SAFE_INTEGER, 1, 2, 3, 32767, 65535, 4294967295]}, -// ].forEach((testData) => { -// const topic = testData.topic || 'topic' + testData.type; -// const testCaseName = 'Test translation of ' + testData.type + -// ' msg, value ' + testData.values + ' (exception)'; -// it(testCaseName, function() { -// const node = rclnodejs.createNode('test_message_translation_node'); -// const MessageType = 'std_msgs/msg/' + testData.type; -// const publisher = node.createPublisher(MessageType, topic); -// return new Promise((resolve, reject) => { -// try { -// publisher.publish({ -// layout: { -// dim: [ -// {label: 'length', size: 0, stride: 0}, -// ], -// data_offset: 0, -// }, -// data: testData.values, -// }); -// node.destroy(); -// reject('Exception is expected for: ' + testData.values); -// } catch (e) { -// node.destroy(); -// resolve(); -// } -// rclnodejs.spin(node); -// }); -// }); -// }); -// }); - describe('Rclnodejs message translation: TypedArray large data', function () { this.timeout(60 * 1000); diff --git a/test/test-message-type.js b/test/test-message-type.js index 5034a35e..2098efcb 100644 --- a/test/test-message-type.js +++ b/test/test-message-type.js @@ -271,11 +271,8 @@ describe('Rclnodejs message type testing', function () { 'Int64_channel', (msg) => { publisher.kill('SIGINT'); - // assert.deepStrictEqual(typeof msg.data, 'string'); - assert.deepStrictEqual( - parseInt(msg.data, 10), - Number.MAX_SAFE_INTEGER - ); + assert.deepStrictEqual(typeof msg.data, 'bigint'); + assert.deepStrictEqual(msg.data, BigInt('0x1fffffffffffff')); done(); } ); @@ -294,11 +291,8 @@ describe('Rclnodejs message type testing', function () { 'UInt64_channel', (msg) => { publisher.kill('SIGINT'); - // assert.deepStrictEqual(typeof msg.data, 'string'); - assert.deepStrictEqual( - parseInt(msg.data, 10), - Number.MAX_SAFE_INTEGER - ); + assert.deepStrictEqual(typeof msg.data, 'bigint'); + assert.deepStrictEqual(msg.data, BigInt('0x1fffffffffffff')); done(); } ); diff --git a/test/test-parameter-service.js b/test/test-parameter-service.js index 507b0a6e..522a9fa5 100644 --- a/test/test-parameter-service.js +++ b/test/test-parameter-service.js @@ -71,7 +71,7 @@ describe('Parameter_server tests', function () { ) ); node.declareParameter( - new Parameter('p2', ParameterType.PARAMETER_INTEGER, 123), + new Parameter('p2', ParameterType.PARAMETER_INTEGER, 123n), new ParameterDescriptor('p2', ParameterType.PARAMETER_INTEGER) ); node.declareParameter( @@ -84,7 +84,11 @@ describe('Parameter_server tests', function () { ) ); node.declareParameter( - new Parameter('A.B.p4', ParameterType.PARAMETER_INTEGER_ARRAY, [1, 2, 3]), + new Parameter('A.B.p4', ParameterType.PARAMETER_INTEGER_ARRAY, [ + 1n, + 2n, + 3n, + ]), new ParameterDescriptor( 'A.B.p4', ParameterType.PARAMETER_INTEGER_ARRAY, @@ -115,7 +119,7 @@ describe('Parameter_server tests', function () { const request = new (rclnodejs.require( 'rcl_interfaces/srv/ListParameters' ).Request)(); - request.depth = 1; + request.depth = 1n; request.prefixes = []; let success = false; @@ -141,7 +145,7 @@ describe('Parameter_server tests', function () { const request = new (rclnodejs.require( 'rcl_interfaces/srv/ListParameters' ).Request)(); - request.depth = 2; + request.depth = 2n; request.prefixes = ['A']; let success = false; @@ -168,7 +172,7 @@ describe('Parameter_server tests', function () { const request = new (rclnodejs.require( 'rcl_interfaces/srv/ListParameters' ).Request)(); - request.depth = 3; + request.depth = 3n; request.prefixes = ['A']; let success = false; diff --git a/test/test-parameters.js b/test/test-parameters.js index 056d4a1a..eaf4892c 100644 --- a/test/test-parameters.js +++ b/test/test-parameters.js @@ -92,12 +92,12 @@ describe('rclnodejs parameters test suite', function () { let param = new Parameter( 'int_param', ParameterType.PARAMETER_INTEGER, - 100 + 100n ); - assert.strictEqual(param.value, 100); + assert.strictEqual(param.value, 100n); - param.value = 101; - assert.strictEqual(param.value, 101); + param.value = 101n; + assert.strictEqual(param.value, 101n); assertThrowsError(() => (param.value = 'hello world'), TypeError); }); @@ -211,7 +211,7 @@ describe('rclnodejs parameters test suite', function () { ))(); param_msg.name = 'integer_param'; param_msg.value.type = ParameterType.PARAMETER_INTEGER; - param_msg.value.integer_value = 123; + param_msg.value.integer_value = 123n; let param; assert.doesNotThrow(() => { @@ -219,7 +219,7 @@ describe('rclnodejs parameters test suite', function () { }); assert.strictEqual(param.name, 'integer_param'); assert.strictEqual(param.type, ParameterType.PARAMETER_INTEGER); - assert.strictEqual(param.value, 123); + assert.strictEqual(param.value, 123n); }); it('should convert PARAMETER_INTEGER_ARRAY type', function () { @@ -228,7 +228,7 @@ describe('rclnodejs parameters test suite', function () { ))(); param_msg.name = 'integer_array_param'; param_msg.value.type = ParameterType.PARAMETER_INTEGER_ARRAY; - param_msg.value.integer_array_value = [1, 2, 3, 4, 5]; + param_msg.value.integer_array_value = [1n, 2n, 3n, 4n, 5n]; let param; assert.doesNotThrow(() => { @@ -236,7 +236,7 @@ describe('rclnodejs parameters test suite', function () { }); assert.strictEqual(param.name, 'integer_array_param'); assert.strictEqual(param.type, ParameterType.PARAMETER_INTEGER_ARRAY); - assert.deepStrictEqual(param.value, [1, 2, 3, 4, 5]); + assert.deepStrictEqual(param.value, [1n, 2n, 3n, 4n, 5n]); }); it('should convert PARAMETER_STRING type', function () { @@ -282,25 +282,25 @@ describe('rclnodejs parameters test suite', function () { }); it('IntegerRange test', function () { - const range = new IntegerRange(0, 100, 1); + const range = new IntegerRange(0n, 100n, 1n); // test property accessors - assert.equal(range.fromValue, 0); - assert.equal(range.toValue, 100); - assert.equal(range.step, 1); + assert.equal(range.fromValue, 0n); + assert.equal(range.toValue, 100n); + assert.equal(range.step, 1n); // test midpoint - assert.ok(range.inRange(50)); + assert.ok(range.inRange(50n)); // test lower boundary - assert.ok(range.inRange(1)); - assert.ok(range.inRange(0)); - assert.ok(!range.inRange(-1)); + assert.ok(range.inRange(1n)); + assert.ok(range.inRange(0n)); + assert.ok(!range.inRange(-1n)); // test upper boundary - assert.ok(range.inRange(99)); - assert.ok(range.inRange(100)); - assert.ok(!range.inRange(101)); + assert.ok(range.inRange(99n)); + assert.ok(range.inRange(100n)); + assert.ok(!range.inRange(101n)); }); it('FloatingPointRange test', function () { @@ -345,22 +345,22 @@ describe('rclnodejs parameters test suite', function () { 'int_param', ParameterType.PARAMETER_INTEGER ); - descriptor.range = new IntegerRange(0, 255); + descriptor.range = new IntegerRange(0n, 255n); const param = new Parameter( 'int_param', ParameterType.PARAMETER_INTEGER, - 100 + 100n ); assert.ifError(descriptor.validateParameter(param)); - param.value = 255; + param.value = 255n; assert.ifError(descriptor.validateParameter(param)); - param.value = -1; + param.value = -1n; assertThrowsError(() => descriptor.validateParameter(param), RangeError); - param.value = 256; + param.value = 256n; assertThrowsError(() => descriptor.validateParameter(param), RangeError); }); @@ -369,22 +369,22 @@ describe('rclnodejs parameters test suite', function () { 'int_param', ParameterType.PARAMETER_INTEGER ); - descriptor.range = new IntegerRange(0, 255, 5); + descriptor.range = new IntegerRange(0n, 255n, 5n); const param = new Parameter( 'int_param', ParameterType.PARAMETER_INTEGER, - 100 + 100n ); assert.ifError(descriptor.validateParameter(param)); - param.value = 255; + param.value = 255n; assert.ifError(descriptor.validateParameter(param)); - param.value = 1; + param.value = 1n; assertThrowsError(() => descriptor.validateParameter(param), RangeError); - param.value = 256; + param.value = 256n; assertThrowsError(() => descriptor.validateParameter(param), RangeError); }); }); diff --git a/test/test-primitive-msg-type-check.js b/test/test-primitive-msg-type-check.js index ea112f24..800cb34c 100644 --- a/test/test-primitive-msg-type-check.js +++ b/test/test-primitive-msg-type-check.js @@ -301,9 +301,9 @@ describe('Rclnodejs message type data testing', function () { var msgInt64 = rclnodejs.require('std_msgs').msg.Int64; var msg = new msgInt64(); - msg.data = 0x1fffffffffffff; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, Number.MAX_SAFE_INTEGER); + msg.data = BigInt('0x1fffffffffffff'); + assert.deepStrictEqual(typeof msg.data, 'bigint'); + assert.deepStrictEqual(msg.data, BigInt(Number.MAX_SAFE_INTEGER)); }); it('UInt64 data checking', function () { @@ -311,9 +311,9 @@ describe('Rclnodejs message type data testing', function () { var msgUInt64 = rclnodejs.require('std_msgs').msg.UInt64; var msg = new msgUInt64(); - msg.data = 0x1fffffffffffff; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, Number.MAX_SAFE_INTEGER); + msg.data = BigInt('0x1fffffffffffff'); + assert.deepStrictEqual(typeof msg.data, 'bigint'); + assert.deepStrictEqual(msg.data, BigInt(Number.MAX_SAFE_INTEGER)); }); it('Float32 data checking', function () { diff --git a/test/test-security-related.js b/test/test-security-related.js index 319238d4..670920db 100644 --- a/test/test-security-related.js +++ b/test/test-security-related.js @@ -276,7 +276,7 @@ describe('Fuzzing API calls testing', function () { done(); }); - let request = { a: 1, b: 2 }; + let request = { a: 1n, b: 2n }; client.sendRequest(request, (response) => { throw new Error('never reached'); }); diff --git a/test/test-service-introspection.js b/test/test-service-introspection.js index f6801393..60de54f0 100644 --- a/test/test-service-introspection.js +++ b/test/test-service-introspection.js @@ -86,8 +86,8 @@ describe('service introspection', function () { } this.request = { - a: Math.floor(Math.random() * 100), - b: Math.floor(Math.random() * 100), + a: BigInt(Math.floor(Math.random() * 100)), + b: BigInt(Math.floor(Math.random() * 100)), }; this.eventQueue = []; diff --git a/test/test-service-with-async-callback.js b/test/test-service-with-async-callback.js index ad549bbe..7c01a5b0 100644 --- a/test/test-service-with-async-callback.js +++ b/test/test-service-with-async-callback.js @@ -38,8 +38,8 @@ describe('Test creating a service with an async callback', function () { AddTwoInts, 'single_ps_channel2', async (request, response) => { - assert.deepStrictEqual(request.a, 1); - assert.deepStrictEqual(request.b, 2); + assert.deepStrictEqual(request.a, 1n); + assert.deepStrictEqual(request.b, 2n); let result = response.template; result.sum = request.a + request.b; // to trigger the bug, two conditions must hold: @@ -53,12 +53,12 @@ describe('Test creating a service with an async callback', function () { } ); var client = clientNode.createClient(AddTwoInts, 'single_ps_channel2'); - const request = { a: 1, b: 2 }; + const request = { a: 1n, b: 2n }; var timer = clientNode.createTimer(100, () => { client.sendRequest(request, (response) => { timer.cancel(); - assert.deepStrictEqual(response.sum, 3); + assert.deepStrictEqual(response.sum, 3n); serviceNode.destroy(); clientNode.destroy(); done(); diff --git a/test/test-single-process.js b/test/test-single-process.js index 223a64eb..ac68e9ea 100644 --- a/test/test-single-process.js +++ b/test/test-single-process.js @@ -91,20 +91,20 @@ describe('Test rclnodejs nodes in a single process', function () { AddTwoInts, 'single_ps_channel2', (request, response) => { - assert.deepStrictEqual(request.a, 1); - assert.deepStrictEqual(request.b, 2); + assert.deepStrictEqual(request.a, 1n); + assert.deepStrictEqual(request.b, 2n); let result = response.template; result.sum = request.a + request.b; return result; } ); var client = clientNode.createClient(AddTwoInts, 'single_ps_channel2'); - const request = { a: 1, b: 2 }; + const request = { a: 1n, b: 2n }; var timer = clientNode.createTimer(100, () => { client.sendRequest(request, (response) => { timer.cancel(); - assert.deepStrictEqual(response.sum, 3); + assert.deepStrictEqual(response.sum, 3n); serviceNode.destroy(); clientNode.destroy(); done(); @@ -123,20 +123,20 @@ describe('Test rclnodejs nodes in a single process', function () { AddTwoInts, 'single_ps_channel2_2', (request, response) => { - assert.deepStrictEqual(request.a, 1); - assert.deepStrictEqual(request.b, 2); + assert.deepStrictEqual(request.a, 1n); + assert.deepStrictEqual(request.b, 2n); let result = response.template; result.sum = request.a + request.b; response.send(result); } ); var client = clientNode.createClient(AddTwoInts, 'single_ps_channel2_2'); - const request = { a: 1, b: 2 }; + const request = { a: 1n, b: 2n }; var timer = clientNode.createTimer(100, () => { client.sendRequest(request, (response) => { timer.cancel(); - assert.deepStrictEqual(response.sum, 3); + assert.deepStrictEqual(response.sum, 3n); serviceNode.destroy(); clientNode.destroy(); done(); @@ -155,18 +155,18 @@ describe('Test rclnodejs nodes in a single process', function () { AddTwoInts, 'single_ps_channel2_3', (request, response) => { - assert.deepStrictEqual(request.a, 1); - assert.deepStrictEqual(request.b, 2); + assert.deepStrictEqual(request.a, 1n); + assert.deepStrictEqual(request.b, 2n); response.send({ sum: request.a + request.b }); } ); var client = clientNode.createClient(AddTwoInts, 'single_ps_channel2_3'); - const request = { a: 1, b: 2 }; + const request = { a: 1n, b: 2n }; var timer = clientNode.createTimer(100, () => { client.sendRequest(request, (response) => { timer.cancel(); - assert.deepStrictEqual(response.sum, 3); + assert.deepStrictEqual(response.sum, 3n); serviceNode.destroy(); clientNode.destroy(); done(); @@ -184,8 +184,8 @@ describe('Test rclnodejs nodes in a single process', function () { AddTwoInts, 'new_style_require2', (request, response) => { - assert.deepStrictEqual(request.a, 1); - assert.deepStrictEqual(request.b, 2); + assert.deepStrictEqual(request.a, 1n); + assert.deepStrictEqual(request.b, 2n); let result = response.template; result.sum = request.a + request.b; return result; @@ -193,13 +193,13 @@ describe('Test rclnodejs nodes in a single process', function () { ); var client = node.createClient(AddTwoInts, 'new_style_require2'); let request = new AddTwoInts.Request(); - request.a = 1; - request.b = 2; + request.a = 1n; + request.b = 2n; var timer = node.createTimer(100, () => { client.sendRequest(request, (response) => { timer.cancel(); - assert.deepStrictEqual(response.sum, 3); + assert.deepStrictEqual(response.sum, 3n); node.destroy(); done(); }); @@ -225,11 +225,11 @@ describe('Test rclnodejs nodes in a single process', function () { ); var client = node.createClient(AddTwoInts, 'multi_request_service'); let request = new AddTwoInts.Request(); - request.a = 1; - request.b = 2; + request.a = 1n; + request.b = 2n; let request2 = new AddTwoInts.Request(); - request2.a = 3; - request2.b = 4; + request2.a = 3n; + request2.b = 4n; let pendingRequests = 2; let request1Succeeded = false; @@ -241,7 +241,7 @@ describe('Test rclnodejs nodes in a single process', function () { logger.info( `[Callback 1] received response: ${response.sum}, pending requests: ${pendingRequests}` ); - assert.deepStrictEqual(response.sum, 3); + assert.deepStrictEqual(response.sum, 3n); request1Succeeded = true; if (pendingRequests == 0 && request1Succeeded && request2Succeeded) { logger.info( @@ -257,7 +257,7 @@ describe('Test rclnodejs nodes in a single process', function () { logger.info( `[Callback 2] received response: ${response.sum}, pending requests: ${pendingRequests}` ); - assert.deepStrictEqual(response.sum, 7); + assert.deepStrictEqual(response.sum, 7n); request2Succeeded = true; if (pendingRequests == 0 && request1Succeeded && request2Succeeded) { logger.info( diff --git a/test/types/main.ts b/test/types/main.ts index ae1ccf97..4a0a518e 100644 --- a/test/types/main.ts +++ b/test/types/main.ts @@ -680,3 +680,14 @@ actionUuid.toMessage(); // $ExpectType UUID rclnodejs.ActionUuid.randomMessage(); + +// ---- Parameter ----- +// $ExpectType Parameter +const param = rclnodejs.createMessageObject('rcl_interfaces/msg/Parameter'); +param.name = 'integer_param'; +param.value.type = rclnodejs.ParameterType.PARAMETER_INTEGER; +param.value.integer_value = BigInt(123); + +param.name = 'byte_array_param'; +param.value.type = rclnodejs.ParameterType.PARAMETER_BYTE_ARRAY; +param.value.byte_array_value = [1, 2, 3]; diff --git a/types/parameter.d.ts b/types/parameter.d.ts index 6f02905a..f0dde114 100644 --- a/types/parameter.d.ts +++ b/types/parameter.d.ts @@ -45,7 +45,7 @@ declare module 'rclnodejs' { * * @param name - The parameter name, must be a valid name. * @param type - The type identifier. - * @param {value - The parameter value. + * @param value - The parameter value. */ constructor(name: string, type: ParameterType, value?: any); @@ -261,16 +261,15 @@ declare module 'rclnodejs' { /** * */ - class IntegerRange extends FloatingPointRange { + class IntegerRange extends Range { /** * Create a new instance. * @constructor - * @param {number} fromValue - The lowest inclusive value in range - * @param {number} toValue - The highest inclusive value in range - * @param {number} step - The internal unit size. - * @param {number} tolerance - The plus/minus tolerance for number equivalence. + * @param {bigint} fromValue - The lowest inclusive value in range + * @param {bigint} toValue - The highest inclusive value in range + * @param {bigint} step - The internal unit size. */ - constructor(from: number, to: number, step?: number, tolerance?: number); + constructor(from: bigint, to: bigint, step?: bigint); /** * Determine if a ParameterType is compatible.